fix: honor audio_as_voice streaming + parse tests (#490) (thanks @jarvis-medmatic)
This commit is contained in:
@@ -776,6 +776,7 @@ export async function compactEmbeddedPiSession(params: {
|
||||
const enqueueGlobal =
|
||||
params.enqueue ??
|
||||
((task, opts) => enqueueCommandInLane(globalLane, task, opts));
|
||||
const runAbortController = new AbortController();
|
||||
return enqueueCommandInLane(sessionLane, () =>
|
||||
enqueueGlobal(async () => {
|
||||
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
||||
|
||||
@@ -651,7 +651,9 @@ export function createClawdbotCodingTools(options?: {
|
||||
// Without this, some providers (notably OpenAI) will reject root-level union schemas.
|
||||
const normalized = subagentFiltered.map(normalizeToolParameters);
|
||||
const withAbort = options?.abortSignal
|
||||
? normalized.map((tool) => wrapToolWithAbortSignal(tool, options.abortSignal))
|
||||
? normalized.map((tool) =>
|
||||
wrapToolWithAbortSignal(tool, options.abortSignal),
|
||||
)
|
||||
: normalized;
|
||||
|
||||
// Anthropic blocks specific lowercase tool names (bash, read, write, edit) with OAuth tokens.
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
resolveStorePath,
|
||||
type SessionEntry,
|
||||
saveSessionStore,
|
||||
} from "../../config/sessions.js";
|
||||
import {
|
||||
@@ -35,7 +36,7 @@ export function setAbortMemory(key: string, value: boolean): void {
|
||||
}
|
||||
|
||||
function resolveSessionEntryForKey(
|
||||
store: Record<string, { sessionId: string; updatedAt: number }> | undefined,
|
||||
store: Record<string, SessionEntry> | undefined,
|
||||
sessionKey: string | undefined,
|
||||
) {
|
||||
if (!store || !sessionKey) return {};
|
||||
|
||||
@@ -7,7 +7,10 @@ import type { ReplyDispatcher } from "./reply-dispatcher.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
routeReply: vi.fn(async () => ({ ok: true, messageId: "mock" })),
|
||||
tryFastAbortFromMessage: vi.fn(async () => ({ handled: false, aborted: false })),
|
||||
tryFastAbortFromMessage: vi.fn(async () => ({
|
||||
handled: false,
|
||||
aborted: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("./route-reply.js", () => ({
|
||||
|
||||
19
src/media/parse.test.ts
Normal file
19
src/media/parse.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { splitMediaFromOutput } from "./parse.js";
|
||||
|
||||
describe("splitMediaFromOutput", () => {
|
||||
it("detects audio_as_voice tag and strips it", () => {
|
||||
const result = splitMediaFromOutput("Hello [[audio_as_voice]] world");
|
||||
expect(result.audioAsVoice).toBe(true);
|
||||
expect(result.text).toBe("Hello world");
|
||||
});
|
||||
|
||||
it("keeps audio_as_voice detection stable across calls", () => {
|
||||
const input = "Hello [[audio_as_voice]]";
|
||||
const first = splitMediaFromOutput(input);
|
||||
const second = splitMediaFromOutput(input);
|
||||
expect(first.audioAsVoice).toBe(true);
|
||||
expect(second.audioAsVoice).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -34,6 +34,7 @@ function isInsideFence(
|
||||
|
||||
// Regex to detect [[audio_as_voice]] tag
|
||||
const AUDIO_AS_VOICE_RE = /\[\[audio_as_voice\]\]/gi;
|
||||
const AUDIO_AS_VOICE_TEST_RE = /\[\[audio_as_voice\]\]/i;
|
||||
|
||||
export function splitMediaFromOutput(raw: string): {
|
||||
text: string;
|
||||
@@ -123,7 +124,7 @@ export function splitMediaFromOutput(raw: string): {
|
||||
.trim();
|
||||
|
||||
// Detect and strip [[audio_as_voice]] tag
|
||||
const hasAudioAsVoice = AUDIO_AS_VOICE_RE.test(cleanedText);
|
||||
const hasAudioAsVoice = AUDIO_AS_VOICE_TEST_RE.test(cleanedText);
|
||||
if (hasAudioAsVoice) {
|
||||
cleanedText = cleanedText
|
||||
.replace(AUDIO_AS_VOICE_RE, "")
|
||||
|
||||
Reference in New Issue
Block a user