@mcoda/agents 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/codex/CodexAdapter.d.ts.map +1 -1
- package/dist/adapters/codex/CodexAdapter.js +16 -2
- package/dist/adapters/codex/CodexCliRunner.d.ts +2 -2
- package/dist/adapters/codex/CodexCliRunner.d.ts.map +1 -1
- package/dist/adapters/codex/CodexCliRunner.js +195 -142
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodexAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/CodexAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"CodexAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/CodexAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAmBtG,qBAAa,YAAa,YAAW,YAAY;IACnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEnC,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIpC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAYnC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwB5D,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,OAAO,CAAC;CAyBjG"}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { cliHealthy, runCodexExec, runCodexExecStream } from "./CodexCliRunner.js";
|
|
2
|
+
const extractOutputSchema = (request) => {
|
|
3
|
+
const candidate = request.metadata?.outputSchema;
|
|
4
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
return candidate;
|
|
8
|
+
};
|
|
9
|
+
const extractTimeoutMs = (request) => {
|
|
10
|
+
const candidate = request.metadata?.timeoutMs;
|
|
11
|
+
if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate <= 0) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return Math.floor(candidate);
|
|
15
|
+
};
|
|
2
16
|
export class CodexAdapter {
|
|
3
17
|
constructor(config) {
|
|
4
18
|
this.config = config;
|
|
@@ -20,7 +34,7 @@ export class CodexAdapter {
|
|
|
20
34
|
async invoke(request) {
|
|
21
35
|
const health = cliHealthy(true);
|
|
22
36
|
const cliDetails = health.details;
|
|
23
|
-
const result = await runCodexExec(request.input, this.config.model);
|
|
37
|
+
const result = await runCodexExec(request.input, this.config.model, extractOutputSchema(request), extractTimeoutMs(request));
|
|
24
38
|
return {
|
|
25
39
|
output: result.output,
|
|
26
40
|
adapter: this.config.adapter ?? "codex-cli",
|
|
@@ -38,7 +52,7 @@ export class CodexAdapter {
|
|
|
38
52
|
async *invokeStream(request) {
|
|
39
53
|
const health = cliHealthy(true);
|
|
40
54
|
const cliDetails = health.details;
|
|
41
|
-
for await (const chunk of runCodexExecStream(request.input, this.config.model)) {
|
|
55
|
+
for await (const chunk of runCodexExecStream(request.input, this.config.model, extractOutputSchema(request), extractTimeoutMs(request))) {
|
|
42
56
|
yield {
|
|
43
57
|
output: chunk.output,
|
|
44
58
|
adapter: this.config.adapter ?? "codex-cli",
|
|
@@ -2,11 +2,11 @@ export declare const cliHealthy: (throwOnError?: boolean) => {
|
|
|
2
2
|
ok: boolean;
|
|
3
3
|
details?: Record<string, unknown>;
|
|
4
4
|
};
|
|
5
|
-
export declare const runCodexExec: (prompt: string, model?: string) => Promise<{
|
|
5
|
+
export declare const runCodexExec: (prompt: string, model?: string, outputSchema?: Record<string, unknown>, timeoutMs?: number) => Promise<{
|
|
6
6
|
output: string;
|
|
7
7
|
raw: string;
|
|
8
8
|
}>;
|
|
9
|
-
export declare function runCodexExecStream(prompt: string, model?: string): AsyncGenerator<{
|
|
9
|
+
export declare function runCodexExecStream(prompt: string, model?: string, outputSchema?: Record<string, unknown>, timeoutMs?: number): AsyncGenerator<{
|
|
10
10
|
output: string;
|
|
11
11
|
raw: string;
|
|
12
12
|
}, void, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodexCliRunner.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/CodexCliRunner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CodexCliRunner.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/CodexCliRunner.ts"],"names":[],"mappings":"AAk1BA,eAAO,MAAM,UAAU,GAAI,sBAAoB,KAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CA+BjG,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,QAAQ,MAAM,EACd,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,YAAY,MAAM,KACjB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CASzC,CAAC;AAEF,wBAAuB,kBAAkB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAmFhE"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
2
5
|
const CODEX_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
3
6
|
const CODEX_REASONING_ENV = "MCODA_CODEX_REASONING_EFFORT";
|
|
4
7
|
const CODEX_REASONING_ENV_FALLBACK = "CODEX_REASONING_EFFORT";
|
|
@@ -208,6 +211,7 @@ const parseCodexOutput = (raw) => {
|
|
|
208
211
|
}
|
|
209
212
|
return message;
|
|
210
213
|
};
|
|
214
|
+
const normalizeComparableAssistantText = (value) => value.replace(/\r\n/g, "\n").trim();
|
|
211
215
|
const normalizeValue = (value) => {
|
|
212
216
|
if (typeof value !== "string")
|
|
213
217
|
return value;
|
|
@@ -635,12 +639,35 @@ const extractAssistantText = (parsed) => {
|
|
|
635
639
|
}
|
|
636
640
|
return null;
|
|
637
641
|
};
|
|
638
|
-
const
|
|
642
|
+
const materializeOutputSchema = async (outputSchema) => {
|
|
643
|
+
if (!outputSchema || typeof outputSchema !== "object" || Array.isArray(outputSchema)) {
|
|
644
|
+
return undefined;
|
|
645
|
+
}
|
|
646
|
+
const tempDir = await mkdtemp(path.join(os.tmpdir(), "mcoda-codex-schema-"));
|
|
647
|
+
const schemaPath = path.join(tempDir, "output-schema.json");
|
|
648
|
+
await writeFile(schemaPath, `${JSON.stringify(outputSchema, null, 2)}\n`, "utf8");
|
|
649
|
+
return {
|
|
650
|
+
schemaPath,
|
|
651
|
+
cleanup: async () => {
|
|
652
|
+
try {
|
|
653
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
654
|
+
}
|
|
655
|
+
catch {
|
|
656
|
+
/* ignore cleanup errors */
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
};
|
|
661
|
+
const invokeCodexProcess = async (prompt, model, options) => {
|
|
639
662
|
const resolvedModel = model ?? "gpt-5.1-codex-max";
|
|
640
663
|
const sandboxArgs = resolveSandboxArgs();
|
|
641
664
|
const reasoningEffort = resolveReasoningEffort(resolvedModel);
|
|
642
665
|
const codexCommand = resolveCodexCommand();
|
|
643
666
|
const args = [...codexCommand.preArgs, ...sandboxArgs.args, "exec", "--model", resolvedModel, "--json"];
|
|
667
|
+
const schemaFile = await materializeOutputSchema(options?.outputSchema);
|
|
668
|
+
if (schemaFile) {
|
|
669
|
+
args.push("--output-schema", schemaFile.schemaPath);
|
|
670
|
+
}
|
|
644
671
|
if (!sandboxArgs.bypass) {
|
|
645
672
|
args.push("--full-auto");
|
|
646
673
|
}
|
|
@@ -648,141 +675,148 @@ const invokeCodexProcess = async (prompt, model, hooks) => {
|
|
|
648
675
|
args.push("-c", `model_reasoning_effort=${reasoningEffort}`);
|
|
649
676
|
}
|
|
650
677
|
args.push("-");
|
|
651
|
-
const timeoutMs =
|
|
678
|
+
const timeoutMs = typeof options?.timeoutMs === "number" && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0
|
|
679
|
+
? Math.floor(options.timeoutMs)
|
|
680
|
+
: resolveCodexTimeoutMs();
|
|
652
681
|
const exitGraceMs = resolveCodexExitGraceMs();
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
682
|
+
try {
|
|
683
|
+
return await new Promise((resolve, reject) => {
|
|
684
|
+
const child = spawn(codexCommand.command, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
685
|
+
let raw = "";
|
|
686
|
+
let stderr = "";
|
|
687
|
+
let lineBuffer = "";
|
|
688
|
+
let message = "";
|
|
689
|
+
let protocolError;
|
|
690
|
+
let settled = false;
|
|
691
|
+
let forcedExit = false;
|
|
692
|
+
let completionTimer;
|
|
693
|
+
const clearTimers = () => {
|
|
694
|
+
if (completionTimer) {
|
|
695
|
+
clearTimeout(completionTimer);
|
|
696
|
+
completionTimer = undefined;
|
|
697
|
+
}
|
|
698
|
+
clearTimeout(timeoutHandle);
|
|
699
|
+
};
|
|
700
|
+
const finalizeOutput = () => {
|
|
701
|
+
const parsedOutput = parseCodexOutput(raw).trim();
|
|
702
|
+
return parsedOutput || message.trim();
|
|
703
|
+
};
|
|
704
|
+
const finishResolve = () => {
|
|
705
|
+
if (settled)
|
|
706
|
+
return;
|
|
707
|
+
settled = true;
|
|
708
|
+
clearTimers();
|
|
709
|
+
resolve({ output: finalizeOutput(), raw, forcedExit });
|
|
710
|
+
};
|
|
711
|
+
const finishReject = (error) => {
|
|
712
|
+
if (settled)
|
|
713
|
+
return;
|
|
714
|
+
settled = true;
|
|
715
|
+
clearTimers();
|
|
716
|
+
reject(error);
|
|
717
|
+
};
|
|
718
|
+
const scheduleCompletionGrace = () => {
|
|
719
|
+
if (settled)
|
|
720
|
+
return;
|
|
721
|
+
if (completionTimer) {
|
|
722
|
+
clearTimeout(completionTimer);
|
|
723
|
+
}
|
|
724
|
+
completionTimer = setTimeout(() => {
|
|
725
|
+
if (settled)
|
|
726
|
+
return;
|
|
727
|
+
forcedExit = true;
|
|
728
|
+
safeKill(child, "SIGTERM");
|
|
729
|
+
scheduleHardKill(child);
|
|
730
|
+
finishResolve();
|
|
731
|
+
}, exitGraceMs);
|
|
732
|
+
completionTimer.unref();
|
|
733
|
+
};
|
|
734
|
+
const handleLine = (line) => {
|
|
735
|
+
const normalized = line.replace(/\r$/, "");
|
|
736
|
+
options?.hooks?.onLine?.(normalized);
|
|
737
|
+
const parsed = safeJsonParse(normalized);
|
|
738
|
+
const event = extractAssistantText(parsed);
|
|
739
|
+
if (event) {
|
|
740
|
+
if (event.kind === "delta") {
|
|
741
|
+
message += event.text;
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
message = event.text;
|
|
745
|
+
scheduleCompletionGrace();
|
|
746
|
+
}
|
|
747
|
+
options?.hooks?.onAssistantEvent?.(event, normalized);
|
|
748
|
+
}
|
|
749
|
+
const parsedError = extractProtocolError(parsed);
|
|
750
|
+
if (parsedError) {
|
|
751
|
+
protocolError = parsedError;
|
|
752
|
+
}
|
|
753
|
+
if (isCompletionEvent(parsed)) {
|
|
754
|
+
scheduleCompletionGrace();
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
const timeoutHandle = setTimeout(() => {
|
|
695
758
|
if (settled)
|
|
696
759
|
return;
|
|
697
760
|
forcedExit = true;
|
|
698
761
|
safeKill(child, "SIGTERM");
|
|
699
762
|
scheduleHardKill(child);
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
763
|
+
const detail = stderr.trim().length > 0 ? `: ${stderr.trim()}` : "";
|
|
764
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI timed out after ${timeoutMs}ms${detail}`));
|
|
765
|
+
}, timeoutMs);
|
|
766
|
+
timeoutHandle.unref();
|
|
767
|
+
child.stdout?.setEncoding("utf8");
|
|
768
|
+
child.stdout?.on("data", (chunk) => {
|
|
769
|
+
const text = chunk.toString();
|
|
770
|
+
raw += text;
|
|
771
|
+
lineBuffer += text;
|
|
772
|
+
let idx;
|
|
773
|
+
while ((idx = lineBuffer.indexOf("\n")) !== -1) {
|
|
774
|
+
const line = lineBuffer.slice(0, idx);
|
|
775
|
+
lineBuffer = lineBuffer.slice(idx + 1);
|
|
776
|
+
handleLine(line);
|
|
712
777
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
778
|
+
});
|
|
779
|
+
child.stderr?.setEncoding("utf8");
|
|
780
|
+
child.stderr?.on("data", (chunk) => {
|
|
781
|
+
stderr += chunk.toString();
|
|
782
|
+
});
|
|
783
|
+
child.stdin?.on("error", (error) => {
|
|
784
|
+
if (settled || isIgnorableStdinError(error))
|
|
785
|
+
return;
|
|
786
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI stdin failed (${error.message})`));
|
|
787
|
+
});
|
|
788
|
+
child.on("error", (error) => {
|
|
789
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI failed (${error.message})`));
|
|
790
|
+
});
|
|
791
|
+
child.on("close", (code) => {
|
|
792
|
+
if (lineBuffer.trim()) {
|
|
793
|
+
handleLine(lineBuffer);
|
|
794
|
+
lineBuffer = "";
|
|
716
795
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
scheduleHardKill(child);
|
|
733
|
-
const detail = stderr.trim().length > 0 ? `: ${stderr.trim()}` : "";
|
|
734
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI timed out after ${timeoutMs}ms${detail}`));
|
|
735
|
-
}, timeoutMs);
|
|
736
|
-
timeoutHandle.unref();
|
|
737
|
-
child.stdout?.setEncoding("utf8");
|
|
738
|
-
child.stdout?.on("data", (chunk) => {
|
|
739
|
-
const text = chunk.toString();
|
|
740
|
-
raw += text;
|
|
741
|
-
lineBuffer += text;
|
|
742
|
-
let idx;
|
|
743
|
-
while ((idx = lineBuffer.indexOf("\n")) !== -1) {
|
|
744
|
-
const line = lineBuffer.slice(0, idx);
|
|
745
|
-
lineBuffer = lineBuffer.slice(idx + 1);
|
|
746
|
-
handleLine(line);
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
child.stderr?.setEncoding("utf8");
|
|
750
|
-
child.stderr?.on("data", (chunk) => {
|
|
751
|
-
stderr += chunk.toString();
|
|
752
|
-
});
|
|
753
|
-
child.stdin?.on("error", (error) => {
|
|
754
|
-
if (settled || isIgnorableStdinError(error))
|
|
755
|
-
return;
|
|
756
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI stdin failed (${error.message})`));
|
|
757
|
-
});
|
|
758
|
-
child.on("error", (error) => {
|
|
759
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI failed (${error.message})`));
|
|
760
|
-
});
|
|
761
|
-
child.on("close", (code) => {
|
|
762
|
-
if (lineBuffer.trim()) {
|
|
763
|
-
handleLine(lineBuffer);
|
|
764
|
-
lineBuffer = "";
|
|
765
|
-
}
|
|
766
|
-
if (settled)
|
|
767
|
-
return;
|
|
768
|
-
if ((code ?? 0) !== 0) {
|
|
769
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI failed (exit ${code ?? 0}): ${stderr || protocolError || "no output"}`));
|
|
770
|
-
return;
|
|
796
|
+
if (settled)
|
|
797
|
+
return;
|
|
798
|
+
if ((code ?? 0) !== 0) {
|
|
799
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI failed (exit ${code ?? 0}): ${stderr || protocolError || "no output"}`));
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (protocolError && !finalizeOutput()) {
|
|
803
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI failed (${protocolError})`));
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
finishResolve();
|
|
807
|
+
});
|
|
808
|
+
try {
|
|
809
|
+
child.stdin?.write(prompt);
|
|
810
|
+
child.stdin?.end();
|
|
771
811
|
}
|
|
772
|
-
|
|
773
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI failed (${
|
|
774
|
-
return;
|
|
812
|
+
catch (error) {
|
|
813
|
+
finishReject(new Error(`AUTH_ERROR: codex CLI stdin failed (${error.message})`));
|
|
775
814
|
}
|
|
776
|
-
finishResolve();
|
|
777
815
|
});
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
catch (error) {
|
|
783
|
-
finishReject(new Error(`AUTH_ERROR: codex CLI stdin failed (${error.message})`));
|
|
784
|
-
}
|
|
785
|
-
});
|
|
816
|
+
}
|
|
817
|
+
finally {
|
|
818
|
+
await schemaFile?.cleanup();
|
|
819
|
+
}
|
|
786
820
|
};
|
|
787
821
|
export const cliHealthy = (throwOnError = false) => {
|
|
788
822
|
if (process.env.MCODA_CLI_STUB === "1") {
|
|
@@ -816,17 +850,17 @@ export const cliHealthy = (throwOnError = false) => {
|
|
|
816
850
|
}
|
|
817
851
|
return { ok: true, details: { version: result.stdout?.toString().trim() } };
|
|
818
852
|
};
|
|
819
|
-
export const runCodexExec = async (prompt, model) => {
|
|
853
|
+
export const runCodexExec = async (prompt, model, outputSchema, timeoutMs) => {
|
|
820
854
|
if (process.env.MCODA_CLI_STUB === "1") {
|
|
821
855
|
const output = `qa-stub:${prompt}`;
|
|
822
856
|
const raw = JSON.stringify({ type: "item.completed", item: { type: "agent_message", text: output } });
|
|
823
857
|
return { output, raw };
|
|
824
858
|
}
|
|
825
859
|
cliHealthy(true);
|
|
826
|
-
const result = await invokeCodexProcess(prompt, model);
|
|
860
|
+
const result = await invokeCodexProcess(prompt, model, { outputSchema, timeoutMs });
|
|
827
861
|
return { output: result.output, raw: result.raw };
|
|
828
862
|
};
|
|
829
|
-
export async function* runCodexExecStream(prompt, model) {
|
|
863
|
+
export async function* runCodexExecStream(prompt, model, outputSchema, timeoutMs) {
|
|
830
864
|
if (process.env.MCODA_CLI_STUB === "1") {
|
|
831
865
|
const output = `qa-stub:${prompt}\n`;
|
|
832
866
|
const raw = JSON.stringify({ type: "item.delta", item: { type: "agent_message", text: output } });
|
|
@@ -841,28 +875,47 @@ export async function* runCodexExecStream(prompt, model) {
|
|
|
841
875
|
let done = false;
|
|
842
876
|
let failure;
|
|
843
877
|
let sawDelta = false;
|
|
878
|
+
let assistantDeltaBuffer = "";
|
|
844
879
|
const notify = () => {
|
|
845
880
|
while (waiters.length) {
|
|
846
881
|
waiters.shift()?.();
|
|
847
882
|
}
|
|
848
883
|
};
|
|
849
884
|
void invokeCodexProcess(prompt, model, {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
885
|
+
outputSchema,
|
|
886
|
+
timeoutMs,
|
|
887
|
+
hooks: {
|
|
888
|
+
onLine: (line) => {
|
|
889
|
+
formatter.handleLine(line);
|
|
890
|
+
},
|
|
891
|
+
onAssistantEvent: (event, rawLine) => {
|
|
892
|
+
if (event.kind === "delta") {
|
|
893
|
+
sawDelta = true;
|
|
894
|
+
assistantDeltaBuffer += event.text;
|
|
895
|
+
queue.push({ output: event.text, raw: rawLine });
|
|
896
|
+
notify();
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
const finalText = event.text;
|
|
900
|
+
const bufferedText = assistantDeltaBuffer;
|
|
901
|
+
assistantDeltaBuffer = "";
|
|
902
|
+
if (!sawDelta) {
|
|
903
|
+
const output = finalText.endsWith("\n") ? finalText : `${finalText}\n`;
|
|
904
|
+
queue.push({ output, raw: rawLine });
|
|
905
|
+
notify();
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
sawDelta = false;
|
|
909
|
+
const normalizedFinal = normalizeComparableAssistantText(finalText);
|
|
910
|
+
const normalizedBuffered = normalizeComparableAssistantText(bufferedText);
|
|
911
|
+
if (!normalizedFinal || normalizedFinal === normalizedBuffered) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const suffix = finalText.startsWith(bufferedText) ? finalText.slice(bufferedText.length) : finalText;
|
|
915
|
+
const output = suffix.endsWith("\n") ? suffix : `${suffix}\n`;
|
|
862
916
|
queue.push({ output, raw: rawLine });
|
|
863
917
|
notify();
|
|
864
|
-
}
|
|
865
|
-
sawDelta = false;
|
|
918
|
+
},
|
|
866
919
|
},
|
|
867
920
|
})
|
|
868
921
|
.catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcoda/agents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.37",
|
|
4
4
|
"description": "Agent registry and capabilities for mcoda.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@mcoda/shared": "0.1.
|
|
34
|
-
"@mcoda/db": "0.1.
|
|
33
|
+
"@mcoda/shared": "0.1.37",
|
|
34
|
+
"@mcoda/db": "0.1.37"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsc -p tsconfig.json",
|