@covro/covro 0.5.1-dev.3 → 0.5.1-dev.4
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/README.md +9 -1
- package/README.zh-CN.md +9 -1
- package/dist/codex/adapter.js +62 -4
- package/dist/codex/adapter.js.map +2 -2
- package/dist/codex/collaboration.js +28 -0
- package/dist/codex/collaboration.js.map +7 -0
- package/dist/codex/guardian-denials.js +67 -0
- package/dist/codex/guardian-denials.js.map +7 -0
- package/dist/codex/thread-goals.js +15 -0
- package/dist/codex/thread-goals.js.map +7 -0
- package/dist/codex/thread-titles.js +135 -60
- package/dist/codex/thread-titles.js.map +2 -2
- package/dist/server/http.js +37 -0
- package/dist/server/http.js.map +2 -2
- package/dist/server/project-init.js +28 -0
- package/dist/server/project-init.js.map +7 -0
- package/dist/server/projection.js +1 -0
- package/dist/server/projection.js.map +2 -2
- package/dist/server/service.js +181 -3
- package/dist/server/service.js.map +2 -2
- package/dist/server/thread-recap.js +34 -0
- package/dist/server/thread-recap.js.map +7 -0
- package/dist/server/workspace-diff.js +149 -0
- package/dist/server/workspace-diff.js.map +7 -0
- package/dist/shared/guardian-denials.js +1 -0
- package/dist/shared/guardian-denials.js.map +7 -0
- package/dist/shared/thread-goal.js +1 -0
- package/dist/shared/thread-goal.js.map +7 -0
- package/dist/shared/validation.js +51 -3
- package/dist/shared/validation.js.map +2 -2
- package/dist/shared/workspace-diff.js +1 -0
- package/dist/shared/workspace-diff.js.map +7 -0
- package/dist/web/assets/{abnfDiagram-WEYOIA3C-ATf52olP.js → abnfDiagram-WEYOIA3C-2_00Zp4O.js} +1 -1
- package/dist/web/assets/{arc-ChLnTnZI.js → arc-DAyuVDVU.js} +1 -1
- package/dist/web/assets/{architecture-WOLXFQ4H-B2oEg329.js → architecture-WOLXFQ4H-CgR1C4gR.js} +1 -1
- package/dist/web/assets/{architectureDiagram-ZHVYKT53-BzSXU9d0.js → architectureDiagram-ZHVYKT53-Dkb6AWjz.js} +1 -1
- package/dist/web/assets/{blockDiagram-RJAE7QA3-xhCZ7iUm.js → blockDiagram-RJAE7QA3-NtOGZdkX.js} +1 -1
- package/dist/web/assets/{c4Diagram-XDPPPE54-DZ8j79Mx.js → c4Diagram-XDPPPE54-C1dqWKb1.js} +1 -1
- package/dist/web/assets/channel-Co9_v2dk.js +1 -0
- package/dist/web/assets/{chunk-2E7WHVMD-y5rSOViW.js → chunk-2E7WHVMD-ClzuEiGk.js} +1 -1
- package/dist/web/assets/{chunk-4EMNKR2T-B7WVoonr.js → chunk-4EMNKR2T-DyTpkWag.js} +1 -1
- package/dist/web/assets/{chunk-55XCU76K-D-tlN44X.js → chunk-55XCU76K-DXBA4ib1.js} +1 -1
- package/dist/web/assets/{chunk-7S6XSTFO-31xOZx-Y.js → chunk-7S6XSTFO-DA_aq0zc.js} +1 -1
- package/dist/web/assets/{chunk-AQDTSKZB-CeCjUBmu.js → chunk-AQDTSKZB-BWTN3SC_.js} +1 -1
- package/dist/web/assets/{chunk-DSNLSHJZ-DgzXTo3_.js → chunk-DSNLSHJZ-DJnLTeE9.js} +1 -1
- package/dist/web/assets/{chunk-HAGFOTED-Dm22rez0.js → chunk-HAGFOTED-cDP-g1Eh.js} +1 -1
- package/dist/web/assets/{chunk-HNE4Q36P-CnFLQjbZ.js → chunk-HNE4Q36P-B3TTIYd_.js} +1 -1
- package/dist/web/assets/{chunk-NQOKRVIF-7DXXp2d_.js → chunk-NQOKRVIF-D8mmhZHq.js} +1 -1
- package/dist/web/assets/{chunk-UHW7PFBP-Bw9-oVzV.js → chunk-UHW7PFBP-DWIIg_jq.js} +1 -1
- package/dist/web/assets/{chunk-VQ5W62QI-C9PHAHIJ.js → chunk-VQ5W62QI-Bu3R2cpS.js} +1 -1
- package/dist/web/assets/{chunk-WQQL4CDK-C9nKxc0i.js → chunk-WQQL4CDK-BxsR1mXs.js} +1 -1
- package/dist/web/assets/{chunk-XXDRQBXY-DjdTeNXE.js → chunk-XXDRQBXY-Ds0JNdm-.js} +1 -1
- package/dist/web/assets/{chunk-YZO67HFG-C1z77_dC.js → chunk-YZO67HFG-COpqyQaD.js} +1 -1
- package/dist/web/assets/{chunk-ZAUX2LTX-C7e41NBP.js → chunk-ZAUX2LTX-BUrGjDuS.js} +1 -1
- package/dist/web/assets/{chunk-ZCHMQSOR-Gv41Qgvd.js → chunk-ZCHMQSOR-DYMM9mEK.js} +1 -1
- package/dist/web/assets/{classDiagram-v2-4MYWR3UA-PjZDyaSs.js → classDiagram-v2-4MYWR3UA-DfJvks0C.js} +1 -1
- package/dist/web/assets/{cose-bilkent-JH36ORCC-CvwZK3HN.js → cose-bilkent-JH36ORCC-CN5mpYIb.js} +1 -1
- package/dist/web/assets/{cynefin-EF2NZ3EQ-Yn6p93cE.js → cynefin-EF2NZ3EQ-DmlCHkY-.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-WF24UDRP-BXa5Guxe.js → cynefinDiagram-WF24UDRP-C0aUblC2.js} +1 -1
- package/dist/web/assets/{dagre-NK4GIZVX-Cnskqb30.js → dagre-NK4GIZVX-Ba7RcAgP.js} +1 -1
- package/dist/web/assets/{diagram-CBK3MWTC-K8WEazkZ.js → diagram-CBK3MWTC-BYQDjB9i.js} +1 -1
- package/dist/web/assets/{diagram-I5XIIV2D-CLzouqUh.js → diagram-I5XIIV2D-EV79hoob.js} +1 -1
- package/dist/web/assets/{diagram-ODIL2UCW-B_9ysyHU.js → diagram-ODIL2UCW-BvQdwmgA.js} +1 -1
- package/dist/web/assets/{diagram-PFBEJUXE-D1ge5Ebx.js → diagram-PFBEJUXE-hxwI3F00.js} +1 -1
- package/dist/web/assets/{diagram-RJA3I4VV-DWF6V26r.js → diagram-RJA3I4VV-DwaHE2iB.js} +1 -1
- package/dist/web/assets/{diagram-TYUNFSNR-BNM1pCS4.js → diagram-TYUNFSNR-BxiOemA0.js} +1 -1
- package/dist/web/assets/{dist-_uWZFvFF.js → dist-nfRX7L9k.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-V4P3TTPT-Cge9YHFL.js → ebnfDiagram-V4P3TTPT-CzQv5iDM.js} +1 -1
- package/dist/web/assets/{elk-QONTBCTQ-CY_393oL.js → elk-QONTBCTQ-DNR9HWcl.js} +1 -1
- package/dist/web/assets/{erDiagram-KYQIGQAA-CCOr67SS.js → erDiagram-KYQIGQAA-aJlTdb9w.js} +1 -1
- package/dist/web/assets/{eventmodeling-K75KTNOO-BzNNWwRQ.js → eventmodeling-K75KTNOO-D4J-ujy-.js} +1 -1
- package/dist/web/assets/flowDiagram-IUGLLWBU-Bq7dmPlS.js +1 -0
- package/dist/web/assets/{ganttDiagram-R7GPNTJY-8BewtZrJ.js → ganttDiagram-R7GPNTJY-DgytSfqO.js} +1 -1
- package/dist/web/assets/{gitGraph-VSP46ZUC-CrqJbic_.js → gitGraph-VSP46ZUC-BtjueFHB.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PDYL7XHY-Ddr5Q6Is.js → gitGraphDiagram-PDYL7XHY-WP0Hjdh9.js} +1 -1
- package/dist/web/assets/index-BesPYgjq.js +156 -0
- package/dist/web/assets/{index-C_i_PNi6.css → index-qYBdGqKM.css} +1 -1
- package/dist/web/assets/{info-OHQRW6UA-DgPvuC2J.js → info-OHQRW6UA-iuP0WTfn.js} +1 -1
- package/dist/web/assets/{infoDiagram-MVDRKAX5-zlubFwKS.js → infoDiagram-MVDRKAX5-CpAtMyKS.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-HPEHV2GE-DdQfvqVi.js → ishikawaDiagram-HPEHV2GE-JTnItv7N.js} +1 -1
- package/dist/web/assets/{journeyDiagram-BOSHW7O7-DZ4XswBd.js → journeyDiagram-BOSHW7O7-B333k1QJ.js} +1 -1
- package/dist/web/assets/{kanban-definition-FNSA4HC5-B1BQdpKc.js → kanban-definition-FNSA4HC5-DpCk5ZH0.js} +1 -1
- package/dist/web/assets/{line-jQDqs207.js → line-CLs-qFxt.js} +1 -1
- package/dist/web/assets/{linear-DbYz4fU8.js → linear-E9AWqBNs.js} +1 -1
- package/dist/web/assets/{mermaid-parser.core-CY5CVNe8.js → mermaid-parser.core-D1rEzlb-.js} +3 -3
- package/dist/web/assets/{mermaid.core-mETL7nBW.js → mermaid.core-D6TNGGsX.js} +4 -4
- package/dist/web/assets/{mindmap-definition-6OY57UG3-CxgWFLxa.js → mindmap-definition-6OY57UG3-DrpuGWuc.js} +1 -1
- package/dist/web/assets/{packet-JDAUHWVQ-Czsr9kk7.js → packet-JDAUHWVQ-BpBr3aKk.js} +1 -1
- package/dist/web/assets/{pegDiagram-ECIUJNBX-BqYq-SA-.js → pegDiagram-ECIUJNBX-BrZX1cdv.js} +1 -1
- package/dist/web/assets/{pie-XZMESJXO-CRpxJzCy.js → pie-XZMESJXO-CcTpis-K.js} +1 -1
- package/dist/web/assets/{pieDiagram-GNMPY74T-Bt2wKk8z.js → pieDiagram-GNMPY74T-CR2em875.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-D57K4MC3-VOKqYTgn.js → quadrantDiagram-D57K4MC3-D-ET5xbH.js} +1 -1
- package/dist/web/assets/{radar-ABXABTNO-wXmArQH-.js → radar-ABXABTNO-CTFFPCi_.js} +1 -1
- package/dist/web/assets/{railroad-I3PHUGI6-CKPK4tQV.js → railroad-I3PHUGI6-S6MHolw_.js} +1 -1
- package/dist/web/assets/{railroad-abnf-LNEFI6M7-BLEs3xqV.js → railroad-abnf-LNEFI6M7-NWxYLYMN.js} +1 -1
- package/dist/web/assets/{railroad-ebnf-DWYD2UWJ-DS5QZgky.js → railroad-ebnf-DWYD2UWJ-CRnaPl26.js} +1 -1
- package/dist/web/assets/{railroad-peg-JR7BVNR7-DHWXNOSl.js → railroad-peg-JR7BVNR7-CB85ffhO.js} +1 -1
- package/dist/web/assets/{railroadDiagram-Y72NRBL7-Cy4eWKH1.js → railroadDiagram-Y72NRBL7-Ba2xIF7q.js} +1 -1
- package/dist/web/assets/{requirementDiagram-EQYSW5RA-Bvbk8wwe.js → requirementDiagram-EQYSW5RA-B7faqgDT.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-SY24JHO5-B4jGjMzu.js → sankeyDiagram-SY24JHO5-IjJVI58S.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-BLEHNHQU-BpgUogv_.js → sequenceDiagram-BLEHNHQU-D-h5jxwQ.js} +1 -1
- package/dist/web/assets/{src-DigPeGm7.js → src-hBdSvoFJ.js} +1 -1
- package/dist/web/assets/{stateDiagram-v2-A6IESKWZ-tHq7e40Q.js → stateDiagram-v2-A6IESKWZ-rlZaPFqZ.js} +1 -1
- package/dist/web/assets/{swimlanes-B3ENRKFQ-DVUPAaDR.js → swimlanes-B3ENRKFQ-CqgKwSbP.js} +1 -1
- package/dist/web/assets/swimlanesDiagram-AYQRV4AK-BGvWQ2Hp.js +8 -0
- package/dist/web/assets/{timeline-definition-JXYKGLGB-BHMM9AHV.js → timeline-definition-JXYKGLGB-DD76ZtY0.js} +1 -1
- package/dist/web/assets/{treeView-D4JQ5SDB-DZ7k_TTS.js → treeView-D4JQ5SDB-CcwWh4Bw.js} +1 -1
- package/dist/web/assets/{treemap-SAJKECNS-C1wGfVb4.js → treemap-SAJKECNS-8lde6V5O.js} +1 -1
- package/dist/web/assets/{usecaseDiagram-WPOLBNNX-BTg0K_GO.js → usecaseDiagram-WPOLBNNX-CWowobZv.js} +1 -1
- package/dist/web/assets/{vennDiagram-Q3Y3IDCW-BTKShPx1.js → vennDiagram-Q3Y3IDCW-U11W8pHe.js} +1 -1
- package/dist/web/assets/{wardley-7MLQ67FV-DnYPM5OB.js → wardley-7MLQ67FV-Dp2EaBmo.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-IVAIDKWA-Dzb67Boa.js → wardleyDiagram-IVAIDKWA-7Qnos8ak.js} +1 -1
- package/dist/web/assets/{xychartDiagram-4URNHDU4-qijltKIO.js → xychartDiagram-4URNHDU4-BwfHNtsG.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/web/assets/channel-COC5jFhc.js +0 -1
- package/dist/web/assets/flowDiagram-IUGLLWBU-C8dLq0uV.js +0 -1
- package/dist/web/assets/index-DHENTsqN.js +0 -148
- package/dist/web/assets/swimlanesDiagram-AYQRV4AK-jJ6zDGAv.js +0 -8
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
const PROJECT_INIT_PROMPT = `Create AGENTS.md in the current working directory as a concise contributor guide for this repository.
|
|
5
|
+
First check whether any AGENTS.md entry already exists. If it does, stop without modifying or replacing it.
|
|
6
|
+
Inspect the repository before writing. Describe its layout, actual build/test/development commands, coding conventions, testing expectations, and commit/pull-request practices. Adapt the content to the project, use concrete examples, and do not invent commands or policies. Aim for 200\u2013400 words with clear Markdown headings. Respect the current permissions and approval policy. Report what was created, or why initialization could not be completed.`;
|
|
7
|
+
async function assertProjectInstructionsMissing(cwd) {
|
|
8
|
+
try {
|
|
9
|
+
await lstat(join(cwd, "AGENTS.md"));
|
|
10
|
+
} catch (error) {
|
|
11
|
+
if (error.code === "ENOENT") return;
|
|
12
|
+
throw new AppError(
|
|
13
|
+
"AGENTS_CHECK_FAILED",
|
|
14
|
+
"Cannot verify whether AGENTS.md already exists",
|
|
15
|
+
409
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
throw new AppError(
|
|
19
|
+
"AGENTS_EXISTS",
|
|
20
|
+
"AGENTS.md already exists; the existing entry was preserved",
|
|
21
|
+
409
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
PROJECT_INIT_PROMPT,
|
|
26
|
+
assertProjectInstructionsMissing
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=project-init.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/server/project-init.ts"],
|
|
4
|
+
"sourcesContent": ["import { lstat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { AppError } from '../shared/errors.js';\n\n/** A normal agent task, following the native CLI /init contract. */\nexport const PROJECT_INIT_PROMPT = `Create AGENTS.md in the current working directory as a concise contributor guide for this repository.\nFirst check whether any AGENTS.md entry already exists. If it does, stop without modifying or replacing it.\nInspect the repository before writing. Describe its layout, actual build/test/development commands, coding conventions, testing expectations, and commit/pull-request practices. Adapt the content to the project, use concrete examples, and do not invent commands or policies. Aim for 200\u2013400 words with clear Markdown headings. Respect the current permissions and approval policy. Report what was created, or why initialization could not be completed.`;\n\nexport async function assertProjectInstructionsMissing(cwd: string): Promise<void> {\n try {\n await lstat(join(cwd, 'AGENTS.md'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw new AppError(\n 'AGENTS_CHECK_FAILED',\n 'Cannot verify whether AGENTS.md already exists',\n 409,\n );\n }\n throw new AppError(\n 'AGENTS_EXISTS',\n 'AGENTS.md already exists; the existing entry was preserved',\n 409,\n );\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,gBAAgB;AAGlB,MAAM,sBAAsB;AAAA;AAAA;AAInC,eAAsB,iCAAiC,KAA4B;AACjF,MAAI;AACF,UAAM,MAAM,KAAK,KAAK,WAAW,CAAC;AAAA,EACpC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU;AACxD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -249,6 +249,7 @@ class Projection {
|
|
|
249
249
|
this.resolveAction(action.actionId, "expired");
|
|
250
250
|
}
|
|
251
251
|
runtimeReset() {
|
|
252
|
+
for (const thread of this.values()) delete thread.goal;
|
|
252
253
|
for (const action of this.actions.values())
|
|
253
254
|
if (action.status === "pending" || action.status === "responding")
|
|
254
255
|
this.resolveAction(action.actionId, "expired");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/server/projection.ts"],
|
|
4
|
-
"sourcesContent": ["import { endCompactions, mergeCompaction, settleCompactions } from './compaction.js';\nimport type {\n AutoReviewView,\n ItemView,\n PendingAction,\n RunStatus,\n ThreadView,\n TurnView,\n TurnErrorMetadata,\n} from '../shared/types.js';\n\nexport const isActive = (status: RunStatus): boolean =>\n status === 'running' || status === 'waitingApproval' || status === 'waitingInput';\nexport const isTerminal = (status: RunStatus): boolean =>\n status === 'completed' || status === 'failed' || status === 'interrupted';\n\nexport class Projection {\n private readonly threads = new Map<string, ThreadView>();\n readonly actions = new Map<string, PendingAction>();\n private readonly revisions = new Map<string, number>();\n // Notifications may precede thread/turn history. Keep only a bounded, per-thread inbox.\n private readonly earlyAutoReviews = new Map<\n string,\n { threadId: string; turnId: string; item: ItemView; bytes: number }\n >();\n private earlyAutoReviewBytes = 0;\n constructor(private readonly maxItemBytes = 2 * 1024 * 1024) {}\n\n get(threadId: string): ThreadView | undefined {\n return this.threads.get(threadId);\n }\n values(): ThreadView[] {\n return [...this.threads.values()];\n }\n revision(threadId: string): number {\n return this.revisions.get(threadId) ?? 0;\n }\n touch(threadId: string): void {\n this.revisions.set(threadId, this.revision(threadId) + 1);\n }\n\n thread(\n incoming: ThreadView,\n preserveCurrent = false,\n preserveRuntimeSettings = preserveCurrent,\n ): ThreadView {\n const current = this.threads.get(incoming.id);\n if (!current) {\n const thread = structuredClone(incoming);\n for (const turn of thread.turns) turn.items = turn.items.map((item) => this.limit(item));\n thread.actions = [...this.actions.values()].filter((action) => action.threadId === thread.id);\n this.threads.set(thread.id, thread);\n for (const turn of thread.turns) {\n this.flushAutoReviews(thread.id, turn.id);\n this.finishReconnect(turn);\n settleCompactions(turn);\n if (isTerminal(turn.status)) this.finishAutoReviews(turn);\n }\n } else {\n const oldTurns = current.turns;\n const oldStatus = current.status;\n const oldRuntimeSettings = current.runtimeSettings;\n const oldTitle = current.title;\n Object.assign(current, incoming, { turns: oldTurns, actions: current.actions });\n if (oldRuntimeSettings && incoming.runtimeSettings)\n current.runtimeSettings = { ...oldRuntimeSettings, ...incoming.runtimeSettings };\n if (preserveCurrent) {\n current.status = oldStatus;\n current.title = oldTitle;\n }\n if (preserveRuntimeSettings) current.runtimeSettings = oldRuntimeSettings;\n for (const turn of incoming.turns) this.turn(incoming.id, turn, preserveCurrent);\n }\n this.touch(incoming.id);\n return this.threads.get(incoming.id)!;\n }\n\n turn(threadId: string, incoming: TurnView, preserveCurrent = false): void {\n const thread = this.threads.get(threadId);\n if (!thread) return;\n thread.hasMessages = true;\n const current = thread.turns.find((turn) => turn.id === incoming.id);\n if (!current)\n thread.turns.push({\n ...structuredClone(incoming),\n items: incoming.items.map((item) => this.limit(item)),\n });\n else {\n const items = current.items;\n if (!preserveCurrent) Object.assign(current, incoming, { items });\n for (const item of incoming.items) this.item(threadId, incoming.id, item, preserveCurrent);\n }\n // Tool cancellation can finish after a new turn starts. Only the latest\n // turn owns the thread status; older events still update their own history.\n if (!preserveCurrent && thread.turns.at(-1)?.id === incoming.id)\n thread.status = incoming.status;\n this.flushAutoReviews(threadId, incoming.id);\n const updated = thread.turns.find((turn) => turn.id === incoming.id)!;\n this.finishReconnect(updated);\n settleCompactions(updated);\n if (isTerminal(updated.status)) this.finishAutoReviews(updated);\n this.touch(threadId);\n }\n\n turnError(\n threadId: string,\n turnId: string,\n message: string,\n willRetry: boolean,\n metadata: TurnErrorMetadata = {},\n ): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !isActive(turn.status)) return false;\n // Keep display-only diagnostics bounded, without changing the execution reservation.\n const detail = message.slice(0, 4096);\n const info = {\n ...(metadata.errorCode ? { errorCode: metadata.errorCode.slice(0, 100) } : {}),\n ...(metadata.errorDetails ? { errorDetails: metadata.errorDetails.slice(0, 4096) } : {}),\n };\n if (willRetry) turn.reconnect = { status: 'retrying', message: detail, ...info };\n else {\n turn.error = detail;\n Object.assign(turn, info);\n endCompactions(turn, 'failed', detail);\n if (turn.reconnect)\n turn.reconnect = { ...turn.reconnect, ...info, status: 'failed', message: detail };\n }\n this.touch(threadId);\n return true;\n }\n\n compactionCompleted(threadId: string, turnId: string): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !endCompactions(turn, 'completed')) return false;\n this.touch(threadId);\n return true;\n }\n\n endThreadCompactions(threadId: string): void {\n for (const turn of this.threads.get(threadId)?.turns ?? []) endCompactions(turn, 'unknown');\n this.touch(threadId);\n }\n\n turnProgress(threadId: string, turnId: string): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !isActive(turn.status) || turn.reconnect?.status !== 'retrying') return false;\n delete turn.reconnect;\n this.touch(threadId);\n return true;\n }\n\n private finishReconnect(turn: TurnView): void {\n if (!turn.reconnect || !isTerminal(turn.status)) return;\n if (turn.status === 'failed') {\n turn.reconnect = {\n ...turn.reconnect,\n status: 'failed',\n message: (turn.error ?? turn.reconnect.message).slice(0, 4096),\n };\n } else delete turn.reconnect;\n }\n\n autoReview(threadId: string, turnId: string, review: AutoReviewView): boolean {\n const item = this.limit({\n id: `auto-review:${review.reviewId}`,\n type: 'autoApprovalReview',\n status: review.status,\n autoReview: review,\n });\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (turn) return this.applyAutoReview(threadId, turn, item);\n const key = JSON.stringify([threadId, turnId, review.reviewId]);\n const current = this.earlyAutoReviews.get(key);\n if (current && !this.reviewCanReplace(current.item, item)) return false;\n const bytes = Buffer.byteLength(JSON.stringify({ threadId, turnId, item }));\n if (current) this.earlyAutoReviewBytes -= current.bytes;\n this.earlyAutoReviews.set(key, { threadId, turnId, item, bytes });\n this.earlyAutoReviewBytes += bytes;\n while (this.earlyAutoReviews.size > 128 || this.earlyAutoReviewBytes > 4 * 1024 * 1024) {\n const oldest = this.earlyAutoReviews.keys().next().value!;\n this.earlyAutoReviewBytes -= this.earlyAutoReviews.get(oldest)!.bytes;\n this.earlyAutoReviews.delete(oldest);\n }\n return false;\n }\n\n private reviewCanReplace(current: ItemView, incoming: ItemView): boolean {\n const previous = current.autoReview!;\n const next = incoming.autoReview!;\n if (previous.status !== 'inProgress' && next.status === 'inProgress') return false;\n if (\n previous.completedAtMs !== undefined &&\n (next.completedAtMs === undefined || previous.completedAtMs > next.completedAtMs)\n )\n return false;\n return JSON.stringify(current) !== JSON.stringify(incoming);\n }\n\n private applyAutoReview(threadId: string, turn: TurnView, item: ItemView): boolean {\n const index = turn.items.findIndex(\n (entry) =>\n entry.type === 'autoApprovalReview' &&\n entry.autoReview?.reviewId === item.autoReview!.reviewId,\n );\n // Check the original event before converting an unfinished late review to unknown.\n if (index >= 0 && !this.reviewCanReplace(turn.items[index]!, item)) return false;\n if (isTerminal(turn.status) && item.autoReview!.status === 'inProgress') {\n item.autoReview!.status = 'unknown';\n item.status = 'unknown';\n }\n if (index < 0) turn.items.push(item);\n else {\n turn.items[index] = item;\n }\n this.touch(threadId);\n return true;\n }\n\n private flushAutoReviews(threadId: string, turnId: string): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n for (const [key, entry] of this.earlyAutoReviews) {\n if (entry.threadId !== threadId || entry.turnId !== turnId) continue;\n this.earlyAutoReviews.delete(key);\n this.earlyAutoReviewBytes -= entry.bytes;\n this.applyAutoReview(threadId, turn, entry.item);\n }\n }\n\n private finishAutoReviews(turn: TurnView): void {\n for (const item of turn.items) {\n if (item.autoReview?.status !== 'inProgress') continue;\n item.autoReview.status = 'unknown';\n item.status = 'unknown';\n }\n }\n\n item(threadId: string, turnId: string, item: ItemView, preserveCurrent = false): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n const index = turn.items.findIndex((entry) => entry.id === item.id);\n if (index < 0) turn.items.push(this.limit(item));\n else if (!preserveCurrent)\n turn.items[index] = this.limit(mergeCompaction(item, turn.items[index]));\n settleCompactions(turn);\n this.touch(threadId);\n }\n\n delta(\n threadId: string,\n turnId: string,\n itemId: string,\n field: 'text' | 'output',\n delta: string,\n itemType?: string,\n ): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n let item = turn.items.find((entry) => entry.id === itemId);\n if (!item) {\n item = {\n id: itemId,\n type: itemType ?? (field === 'text' ? 'agentMessage' : 'commandExecution'),\n };\n turn.items.push(item);\n }\n if (item.truncated) return;\n item[field] = (item[field] ?? '') + delta;\n Object.assign(item, this.limit(item));\n this.touch(threadId);\n }\n\n diff(threadId: string, turnId: string, diff: string): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (turn) turn.diff = this.clip(diff).value;\n this.touch(threadId);\n }\n\n action(action: PendingAction): void {\n const owner = action.threadId\n ? this.threads.get(action.threadId)?.turns.find((turn) => turn.id === action.turnId)\n : undefined;\n if (owner && isTerminal(owner.status) && ['pending', 'responding'].includes(action.status))\n action = { ...action, status: 'expired' };\n this.actions.set(action.actionId, action);\n const thread = action.threadId ? this.threads.get(action.threadId) : undefined;\n if (thread) {\n thread.actions = [...this.actions.values()].filter((entry) => entry.threadId === thread.id);\n this.updateActionStatus(thread);\n this.touch(thread.id);\n }\n }\n\n resolveAction(actionId: string, status: PendingAction['status']): PendingAction | undefined {\n const action = this.actions.get(actionId);\n if (!action) return undefined;\n action.status = status;\n const thread = action.threadId ? this.threads.get(action.threadId) : undefined;\n if (thread) {\n this.updateActionStatus(thread);\n this.touch(thread.id);\n }\n return action;\n }\n\n expireTurn(threadId: string, turnId: string): void {\n for (const action of this.actions.values())\n if (\n action.threadId === threadId &&\n action.turnId === turnId &&\n (action.status === 'pending' || action.status === 'responding')\n )\n this.resolveAction(action.actionId, 'expired');\n }\n\n runtimeReset(): void {\n for (const action of this.actions.values())\n if (action.status === 'pending' || action.status === 'responding')\n this.resolveAction(action.actionId, 'expired');\n for (const thread of this.threads.values()) {\n thread.managed = false;\n delete thread.resumeError;\n if (thread.runtimeSettings) {\n const { model, reasoningEffort } = thread.runtimeSettings;\n thread.runtimeSettings = { model, reasoningEffort };\n }\n if (isActive(thread.status)) thread.status = 'unknown';\n for (const turn of thread.turns) {\n if (turn.reconnect?.status === 'retrying') delete turn.reconnect;\n if (isActive(turn.status)) turn.status = 'unknown';\n endCompactions(turn, 'unknown');\n this.finishAutoReviews(turn);\n }\n this.touch(thread.id);\n }\n for (const entry of this.earlyAutoReviews.values()) {\n if (entry.item.autoReview?.status === 'inProgress') {\n this.earlyAutoReviewBytes -= entry.bytes;\n entry.item.autoReview.status = 'unknown';\n entry.item.status = 'unknown';\n entry.bytes = Buffer.byteLength(\n JSON.stringify({ threadId: entry.threadId, turnId: entry.turnId, item: entry.item }),\n );\n this.earlyAutoReviewBytes += entry.bytes;\n }\n }\n }\n\n private updateActionStatus(thread: ThreadView): void {\n const active = thread.actions.filter(\n (action) =>\n action.blocking !== false &&\n (action.status === 'pending' || action.status === 'responding'),\n );\n const turn = [...thread.turns].reverse().find((entry) => isActive(entry.status));\n if (!turn) return;\n const status = active.some(\n (action) => action.kind === 'questions' || action.kind === 'elicitation',\n )\n ? 'waitingInput'\n : active.length > 0\n ? 'waitingApproval'\n : 'running';\n thread.status = status;\n turn.status = status;\n }\n\n private limit(item: ItemView): ItemView {\n const result = structuredClone(item);\n if (result.images) {\n let bytes = 0;\n result.imageCount ??= result.images.length;\n result.images = result.images.filter((image) => {\n bytes += Buffer.byteLength(image);\n return bytes <= this.maxItemBytes;\n });\n }\n for (const field of ['text', 'output', 'command'] as const) {\n const value = result[field];\n if (value) {\n const clipped = this.clip(value);\n result[field] = clipped.value;\n if (clipped.truncated) result.truncated = true;\n }\n }\n if (result.changes)\n result.changes = result.changes.map((change) => {\n const clipped = this.clip(change.diff);\n if (clipped.truncated) result.truncated = true;\n return { ...change, diff: clipped.value };\n });\n if (result.details !== undefined) {\n const clipped = this.clip(JSON.stringify(result.details));\n if (clipped.truncated) {\n result.details = clipped.value;\n result.truncated = true;\n }\n }\n if (result.autoReview) {\n for (const field of ['actionLabel', 'actionSummary', 'cwd', 'rationale'] as const) {\n const value = result.autoReview[field];\n if (value === undefined) continue;\n const clipped = this.clip(value);\n result.autoReview[field] = clipped.value;\n if (clipped.truncated) result.truncated = true;\n }\n }\n return result;\n }\n\n private clip(value: string): { value: string; truncated: boolean } {\n if (Buffer.byteLength(value) <= this.maxItemBytes) return { value, truncated: false };\n // Iterating code points avoids a half UTF-8 character at the truncation boundary.\n let kept = '';\n let bytes = 0;\n for (const point of value) {\n bytes += Buffer.byteLength(point);\n if (bytes > this.maxItemBytes) break;\n kept += point;\n }\n return { value: `${kept}\\n[\u8F93\u51FA\u5DF2\u622A\u65AD]`, truncated: true };\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { endCompactions, mergeCompaction, settleCompactions } from './compaction.js';\nimport type {\n AutoReviewView,\n ItemView,\n PendingAction,\n RunStatus,\n ThreadView,\n TurnView,\n TurnErrorMetadata,\n} from '../shared/types.js';\n\nexport const isActive = (status: RunStatus): boolean =>\n status === 'running' || status === 'waitingApproval' || status === 'waitingInput';\nexport const isTerminal = (status: RunStatus): boolean =>\n status === 'completed' || status === 'failed' || status === 'interrupted';\n\nexport class Projection {\n private readonly threads = new Map<string, ThreadView>();\n readonly actions = new Map<string, PendingAction>();\n private readonly revisions = new Map<string, number>();\n // Notifications may precede thread/turn history. Keep only a bounded, per-thread inbox.\n private readonly earlyAutoReviews = new Map<\n string,\n { threadId: string; turnId: string; item: ItemView; bytes: number }\n >();\n private earlyAutoReviewBytes = 0;\n constructor(private readonly maxItemBytes = 2 * 1024 * 1024) {}\n\n get(threadId: string): ThreadView | undefined {\n return this.threads.get(threadId);\n }\n values(): ThreadView[] {\n return [...this.threads.values()];\n }\n revision(threadId: string): number {\n return this.revisions.get(threadId) ?? 0;\n }\n touch(threadId: string): void {\n this.revisions.set(threadId, this.revision(threadId) + 1);\n }\n\n thread(\n incoming: ThreadView,\n preserveCurrent = false,\n preserveRuntimeSettings = preserveCurrent,\n ): ThreadView {\n const current = this.threads.get(incoming.id);\n if (!current) {\n const thread = structuredClone(incoming);\n for (const turn of thread.turns) turn.items = turn.items.map((item) => this.limit(item));\n thread.actions = [...this.actions.values()].filter((action) => action.threadId === thread.id);\n this.threads.set(thread.id, thread);\n for (const turn of thread.turns) {\n this.flushAutoReviews(thread.id, turn.id);\n this.finishReconnect(turn);\n settleCompactions(turn);\n if (isTerminal(turn.status)) this.finishAutoReviews(turn);\n }\n } else {\n const oldTurns = current.turns;\n const oldStatus = current.status;\n const oldRuntimeSettings = current.runtimeSettings;\n const oldTitle = current.title;\n Object.assign(current, incoming, { turns: oldTurns, actions: current.actions });\n if (oldRuntimeSettings && incoming.runtimeSettings)\n current.runtimeSettings = { ...oldRuntimeSettings, ...incoming.runtimeSettings };\n if (preserveCurrent) {\n current.status = oldStatus;\n current.title = oldTitle;\n }\n if (preserveRuntimeSettings) current.runtimeSettings = oldRuntimeSettings;\n for (const turn of incoming.turns) this.turn(incoming.id, turn, preserveCurrent);\n }\n this.touch(incoming.id);\n return this.threads.get(incoming.id)!;\n }\n\n turn(threadId: string, incoming: TurnView, preserveCurrent = false): void {\n const thread = this.threads.get(threadId);\n if (!thread) return;\n thread.hasMessages = true;\n const current = thread.turns.find((turn) => turn.id === incoming.id);\n if (!current)\n thread.turns.push({\n ...structuredClone(incoming),\n items: incoming.items.map((item) => this.limit(item)),\n });\n else {\n const items = current.items;\n if (!preserveCurrent) Object.assign(current, incoming, { items });\n for (const item of incoming.items) this.item(threadId, incoming.id, item, preserveCurrent);\n }\n // Tool cancellation can finish after a new turn starts. Only the latest\n // turn owns the thread status; older events still update their own history.\n if (!preserveCurrent && thread.turns.at(-1)?.id === incoming.id)\n thread.status = incoming.status;\n this.flushAutoReviews(threadId, incoming.id);\n const updated = thread.turns.find((turn) => turn.id === incoming.id)!;\n this.finishReconnect(updated);\n settleCompactions(updated);\n if (isTerminal(updated.status)) this.finishAutoReviews(updated);\n this.touch(threadId);\n }\n\n turnError(\n threadId: string,\n turnId: string,\n message: string,\n willRetry: boolean,\n metadata: TurnErrorMetadata = {},\n ): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !isActive(turn.status)) return false;\n // Keep display-only diagnostics bounded, without changing the execution reservation.\n const detail = message.slice(0, 4096);\n const info = {\n ...(metadata.errorCode ? { errorCode: metadata.errorCode.slice(0, 100) } : {}),\n ...(metadata.errorDetails ? { errorDetails: metadata.errorDetails.slice(0, 4096) } : {}),\n };\n if (willRetry) turn.reconnect = { status: 'retrying', message: detail, ...info };\n else {\n turn.error = detail;\n Object.assign(turn, info);\n endCompactions(turn, 'failed', detail);\n if (turn.reconnect)\n turn.reconnect = { ...turn.reconnect, ...info, status: 'failed', message: detail };\n }\n this.touch(threadId);\n return true;\n }\n\n compactionCompleted(threadId: string, turnId: string): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !endCompactions(turn, 'completed')) return false;\n this.touch(threadId);\n return true;\n }\n\n endThreadCompactions(threadId: string): void {\n for (const turn of this.threads.get(threadId)?.turns ?? []) endCompactions(turn, 'unknown');\n this.touch(threadId);\n }\n\n turnProgress(threadId: string, turnId: string): boolean {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn || !isActive(turn.status) || turn.reconnect?.status !== 'retrying') return false;\n delete turn.reconnect;\n this.touch(threadId);\n return true;\n }\n\n private finishReconnect(turn: TurnView): void {\n if (!turn.reconnect || !isTerminal(turn.status)) return;\n if (turn.status === 'failed') {\n turn.reconnect = {\n ...turn.reconnect,\n status: 'failed',\n message: (turn.error ?? turn.reconnect.message).slice(0, 4096),\n };\n } else delete turn.reconnect;\n }\n\n autoReview(threadId: string, turnId: string, review: AutoReviewView): boolean {\n const item = this.limit({\n id: `auto-review:${review.reviewId}`,\n type: 'autoApprovalReview',\n status: review.status,\n autoReview: review,\n });\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (turn) return this.applyAutoReview(threadId, turn, item);\n const key = JSON.stringify([threadId, turnId, review.reviewId]);\n const current = this.earlyAutoReviews.get(key);\n if (current && !this.reviewCanReplace(current.item, item)) return false;\n const bytes = Buffer.byteLength(JSON.stringify({ threadId, turnId, item }));\n if (current) this.earlyAutoReviewBytes -= current.bytes;\n this.earlyAutoReviews.set(key, { threadId, turnId, item, bytes });\n this.earlyAutoReviewBytes += bytes;\n while (this.earlyAutoReviews.size > 128 || this.earlyAutoReviewBytes > 4 * 1024 * 1024) {\n const oldest = this.earlyAutoReviews.keys().next().value!;\n this.earlyAutoReviewBytes -= this.earlyAutoReviews.get(oldest)!.bytes;\n this.earlyAutoReviews.delete(oldest);\n }\n return false;\n }\n\n private reviewCanReplace(current: ItemView, incoming: ItemView): boolean {\n const previous = current.autoReview!;\n const next = incoming.autoReview!;\n if (previous.status !== 'inProgress' && next.status === 'inProgress') return false;\n if (\n previous.completedAtMs !== undefined &&\n (next.completedAtMs === undefined || previous.completedAtMs > next.completedAtMs)\n )\n return false;\n return JSON.stringify(current) !== JSON.stringify(incoming);\n }\n\n private applyAutoReview(threadId: string, turn: TurnView, item: ItemView): boolean {\n const index = turn.items.findIndex(\n (entry) =>\n entry.type === 'autoApprovalReview' &&\n entry.autoReview?.reviewId === item.autoReview!.reviewId,\n );\n // Check the original event before converting an unfinished late review to unknown.\n if (index >= 0 && !this.reviewCanReplace(turn.items[index]!, item)) return false;\n if (isTerminal(turn.status) && item.autoReview!.status === 'inProgress') {\n item.autoReview!.status = 'unknown';\n item.status = 'unknown';\n }\n if (index < 0) turn.items.push(item);\n else {\n turn.items[index] = item;\n }\n this.touch(threadId);\n return true;\n }\n\n private flushAutoReviews(threadId: string, turnId: string): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n for (const [key, entry] of this.earlyAutoReviews) {\n if (entry.threadId !== threadId || entry.turnId !== turnId) continue;\n this.earlyAutoReviews.delete(key);\n this.earlyAutoReviewBytes -= entry.bytes;\n this.applyAutoReview(threadId, turn, entry.item);\n }\n }\n\n private finishAutoReviews(turn: TurnView): void {\n for (const item of turn.items) {\n if (item.autoReview?.status !== 'inProgress') continue;\n item.autoReview.status = 'unknown';\n item.status = 'unknown';\n }\n }\n\n item(threadId: string, turnId: string, item: ItemView, preserveCurrent = false): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n const index = turn.items.findIndex((entry) => entry.id === item.id);\n if (index < 0) turn.items.push(this.limit(item));\n else if (!preserveCurrent)\n turn.items[index] = this.limit(mergeCompaction(item, turn.items[index]));\n settleCompactions(turn);\n this.touch(threadId);\n }\n\n delta(\n threadId: string,\n turnId: string,\n itemId: string,\n field: 'text' | 'output',\n delta: string,\n itemType?: string,\n ): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (!turn) return;\n let item = turn.items.find((entry) => entry.id === itemId);\n if (!item) {\n item = {\n id: itemId,\n type: itemType ?? (field === 'text' ? 'agentMessage' : 'commandExecution'),\n };\n turn.items.push(item);\n }\n if (item.truncated) return;\n item[field] = (item[field] ?? '') + delta;\n Object.assign(item, this.limit(item));\n this.touch(threadId);\n }\n\n diff(threadId: string, turnId: string, diff: string): void {\n const turn = this.threads.get(threadId)?.turns.find((entry) => entry.id === turnId);\n if (turn) turn.diff = this.clip(diff).value;\n this.touch(threadId);\n }\n\n action(action: PendingAction): void {\n const owner = action.threadId\n ? this.threads.get(action.threadId)?.turns.find((turn) => turn.id === action.turnId)\n : undefined;\n if (owner && isTerminal(owner.status) && ['pending', 'responding'].includes(action.status))\n action = { ...action, status: 'expired' };\n this.actions.set(action.actionId, action);\n const thread = action.threadId ? this.threads.get(action.threadId) : undefined;\n if (thread) {\n thread.actions = [...this.actions.values()].filter((entry) => entry.threadId === thread.id);\n this.updateActionStatus(thread);\n this.touch(thread.id);\n }\n }\n\n resolveAction(actionId: string, status: PendingAction['status']): PendingAction | undefined {\n const action = this.actions.get(actionId);\n if (!action) return undefined;\n action.status = status;\n const thread = action.threadId ? this.threads.get(action.threadId) : undefined;\n if (thread) {\n this.updateActionStatus(thread);\n this.touch(thread.id);\n }\n return action;\n }\n\n expireTurn(threadId: string, turnId: string): void {\n for (const action of this.actions.values())\n if (\n action.threadId === threadId &&\n action.turnId === turnId &&\n (action.status === 'pending' || action.status === 'responding')\n )\n this.resolveAction(action.actionId, 'expired');\n }\n\n runtimeReset(): void {\n for (const thread of this.values()) delete thread.goal;\n for (const action of this.actions.values())\n if (action.status === 'pending' || action.status === 'responding')\n this.resolveAction(action.actionId, 'expired');\n for (const thread of this.threads.values()) {\n thread.managed = false;\n delete thread.resumeError;\n if (thread.runtimeSettings) {\n const { model, reasoningEffort } = thread.runtimeSettings;\n thread.runtimeSettings = { model, reasoningEffort };\n }\n if (isActive(thread.status)) thread.status = 'unknown';\n for (const turn of thread.turns) {\n if (turn.reconnect?.status === 'retrying') delete turn.reconnect;\n if (isActive(turn.status)) turn.status = 'unknown';\n endCompactions(turn, 'unknown');\n this.finishAutoReviews(turn);\n }\n this.touch(thread.id);\n }\n for (const entry of this.earlyAutoReviews.values()) {\n if (entry.item.autoReview?.status === 'inProgress') {\n this.earlyAutoReviewBytes -= entry.bytes;\n entry.item.autoReview.status = 'unknown';\n entry.item.status = 'unknown';\n entry.bytes = Buffer.byteLength(\n JSON.stringify({ threadId: entry.threadId, turnId: entry.turnId, item: entry.item }),\n );\n this.earlyAutoReviewBytes += entry.bytes;\n }\n }\n }\n\n private updateActionStatus(thread: ThreadView): void {\n const active = thread.actions.filter(\n (action) =>\n action.blocking !== false &&\n (action.status === 'pending' || action.status === 'responding'),\n );\n const turn = [...thread.turns].reverse().find((entry) => isActive(entry.status));\n if (!turn) return;\n const status = active.some(\n (action) => action.kind === 'questions' || action.kind === 'elicitation',\n )\n ? 'waitingInput'\n : active.length > 0\n ? 'waitingApproval'\n : 'running';\n thread.status = status;\n turn.status = status;\n }\n\n private limit(item: ItemView): ItemView {\n const result = structuredClone(item);\n if (result.images) {\n let bytes = 0;\n result.imageCount ??= result.images.length;\n result.images = result.images.filter((image) => {\n bytes += Buffer.byteLength(image);\n return bytes <= this.maxItemBytes;\n });\n }\n for (const field of ['text', 'output', 'command'] as const) {\n const value = result[field];\n if (value) {\n const clipped = this.clip(value);\n result[field] = clipped.value;\n if (clipped.truncated) result.truncated = true;\n }\n }\n if (result.changes)\n result.changes = result.changes.map((change) => {\n const clipped = this.clip(change.diff);\n if (clipped.truncated) result.truncated = true;\n return { ...change, diff: clipped.value };\n });\n if (result.details !== undefined) {\n const clipped = this.clip(JSON.stringify(result.details));\n if (clipped.truncated) {\n result.details = clipped.value;\n result.truncated = true;\n }\n }\n if (result.autoReview) {\n for (const field of ['actionLabel', 'actionSummary', 'cwd', 'rationale'] as const) {\n const value = result.autoReview[field];\n if (value === undefined) continue;\n const clipped = this.clip(value);\n result.autoReview[field] = clipped.value;\n if (clipped.truncated) result.truncated = true;\n }\n }\n return result;\n }\n\n private clip(value: string): { value: string; truncated: boolean } {\n if (Buffer.byteLength(value) <= this.maxItemBytes) return { value, truncated: false };\n // Iterating code points avoids a half UTF-8 character at the truncation boundary.\n let kept = '';\n let bytes = 0;\n for (const point of value) {\n bytes += Buffer.byteLength(point);\n if (bytes > this.maxItemBytes) break;\n kept += point;\n }\n return { value: `${kept}\\n[\u8F93\u51FA\u5DF2\u622A\u65AD]`, truncated: true };\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,gBAAgB,iBAAiB,yBAAyB;AAW5D,MAAM,WAAW,CAAC,WACvB,WAAW,aAAa,WAAW,qBAAqB,WAAW;AAC9D,MAAM,aAAa,CAAC,WACzB,WAAW,eAAe,WAAW,YAAY,WAAW;AAEvD,MAAM,WAAW;AAAA,EAUtB,YAA6B,eAAe,IAAI,OAAO,MAAM;AAAhC;AAAA,EAAiC;AAAA,EAAjC;AAAA,EATZ,UAAU,oBAAI,IAAwB;AAAA,EAC9C,UAAU,oBAAI,IAA2B;AAAA,EACjC,YAAY,oBAAI,IAAoB;AAAA;AAAA,EAEpC,mBAAmB,oBAAI,IAGtC;AAAA,EACM,uBAAuB;AAAA,EAG/B,IAAI,UAA0C;AAC5C,WAAO,KAAK,QAAQ,IAAI,QAAQ;AAAA,EAClC;AAAA,EACA,SAAuB;AACrB,WAAO,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC;AAAA,EAClC;AAAA,EACA,SAAS,UAA0B;AACjC,WAAO,KAAK,UAAU,IAAI,QAAQ,KAAK;AAAA,EACzC;AAAA,EACA,MAAM,UAAwB;AAC5B,SAAK,UAAU,IAAI,UAAU,KAAK,SAAS,QAAQ,IAAI,CAAC;AAAA,EAC1D;AAAA,EAEA,OACE,UACA,kBAAkB,OAClB,0BAA0B,iBACd;AACZ,UAAM,UAAU,KAAK,QAAQ,IAAI,SAAS,EAAE;AAC5C,QAAI,CAAC,SAAS;AACZ,YAAM,SAAS,gBAAgB,QAAQ;AACvC,iBAAW,QAAQ,OAAO,MAAO,MAAK,QAAQ,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAAC;AACvF,aAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,OAAO,aAAa,OAAO,EAAE;AAC5F,WAAK,QAAQ,IAAI,OAAO,IAAI,MAAM;AAClC,iBAAW,QAAQ,OAAO,OAAO;AAC/B,aAAK,iBAAiB,OAAO,IAAI,KAAK,EAAE;AACxC,aAAK,gBAAgB,IAAI;AACzB,0BAAkB,IAAI;AACtB,YAAI,WAAW,KAAK,MAAM,EAAG,MAAK,kBAAkB,IAAI;AAAA,MAC1D;AAAA,IACF,OAAO;AACL,YAAM,WAAW,QAAQ;AACzB,YAAM,YAAY,QAAQ;AAC1B,YAAM,qBAAqB,QAAQ;AACnC,YAAM,WAAW,QAAQ;AACzB,aAAO,OAAO,SAAS,UAAU,EAAE,OAAO,UAAU,SAAS,QAAQ,QAAQ,CAAC;AAC9E,UAAI,sBAAsB,SAAS;AACjC,gBAAQ,kBAAkB,EAAE,GAAG,oBAAoB,GAAG,SAAS,gBAAgB;AACjF,UAAI,iBAAiB;AACnB,gBAAQ,SAAS;AACjB,gBAAQ,QAAQ;AAAA,MAClB;AACA,UAAI,wBAAyB,SAAQ,kBAAkB;AACvD,iBAAW,QAAQ,SAAS,MAAO,MAAK,KAAK,SAAS,IAAI,MAAM,eAAe;AAAA,IACjF;AACA,SAAK,MAAM,SAAS,EAAE;AACtB,WAAO,KAAK,QAAQ,IAAI,SAAS,EAAE;AAAA,EACrC;AAAA,EAEA,KAAK,UAAkB,UAAoB,kBAAkB,OAAa;AACxE,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ;AACb,WAAO,cAAc;AACrB,UAAM,UAAU,OAAO,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,SAAS,EAAE;AACnE,QAAI,CAAC;AACH,aAAO,MAAM,KAAK;AAAA,QAChB,GAAG,gBAAgB,QAAQ;AAAA,QAC3B,OAAO,SAAS,MAAM,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,MACtD,CAAC;AAAA,SACE;AACH,YAAM,QAAQ,QAAQ;AACtB,UAAI,CAAC,gBAAiB,QAAO,OAAO,SAAS,UAAU,EAAE,MAAM,CAAC;AAChE,iBAAW,QAAQ,SAAS,MAAO,MAAK,KAAK,UAAU,SAAS,IAAI,MAAM,eAAe;AAAA,IAC3F;AAGA,QAAI,CAAC,mBAAmB,OAAO,MAAM,GAAG,EAAE,GAAG,OAAO,SAAS;AAC3D,aAAO,SAAS,SAAS;AAC3B,SAAK,iBAAiB,UAAU,SAAS,EAAE;AAC3C,UAAM,UAAU,OAAO,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,SAAS,EAAE;AACnE,SAAK,gBAAgB,OAAO;AAC5B,sBAAkB,OAAO;AACzB,QAAI,WAAW,QAAQ,MAAM,EAAG,MAAK,kBAAkB,OAAO;AAC9D,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,UACE,UACA,QACA,SACA,WACA,WAA8B,CAAC,GACtB;AACT,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,MAAM,EAAG,QAAO;AAE5C,UAAM,SAAS,QAAQ,MAAM,GAAG,IAAI;AACpC,UAAM,OAAO;AAAA,MACX,GAAI,SAAS,YAAY,EAAE,WAAW,SAAS,UAAU,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;AAAA,MAC5E,GAAI,SAAS,eAAe,EAAE,cAAc,SAAS,aAAa,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC;AAAA,IACxF;AACA,QAAI,UAAW,MAAK,YAAY,EAAE,QAAQ,YAAY,SAAS,QAAQ,GAAG,KAAK;AAAA,SAC1E;AACH,WAAK,QAAQ;AACb,aAAO,OAAO,MAAM,IAAI;AACxB,qBAAe,MAAM,UAAU,MAAM;AACrC,UAAI,KAAK;AACP,aAAK,YAAY,EAAE,GAAG,KAAK,WAAW,GAAG,MAAM,QAAQ,UAAU,SAAS,OAAO;AAAA,IACrF;AACA,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,oBAAoB,UAAkB,QAAyB;AAC7D,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,QAAQ,CAAC,eAAe,MAAM,WAAW,EAAG,QAAO;AACxD,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,qBAAqB,UAAwB;AAC3C,eAAW,QAAQ,KAAK,QAAQ,IAAI,QAAQ,GAAG,SAAS,CAAC,EAAG,gBAAe,MAAM,SAAS;AAC1F,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,aAAa,UAAkB,QAAyB;AACtD,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,MAAM,KAAK,KAAK,WAAW,WAAW,WAAY,QAAO;AACrF,WAAO,KAAK;AACZ,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,MAAsB;AAC5C,QAAI,CAAC,KAAK,aAAa,CAAC,WAAW,KAAK,MAAM,EAAG;AACjD,QAAI,KAAK,WAAW,UAAU;AAC5B,WAAK,YAAY;AAAA,QACf,GAAG,KAAK;AAAA,QACR,QAAQ;AAAA,QACR,UAAU,KAAK,SAAS,KAAK,UAAU,SAAS,MAAM,GAAG,IAAI;AAAA,MAC/D;AAAA,IACF,MAAO,QAAO,KAAK;AAAA,EACrB;AAAA,EAEA,WAAW,UAAkB,QAAgB,QAAiC;AAC5E,UAAM,OAAO,KAAK,MAAM;AAAA,MACtB,IAAI,eAAe,OAAO,QAAQ;AAAA,MAClC,MAAM;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,YAAY;AAAA,IACd,CAAC;AACD,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,KAAM,QAAO,KAAK,gBAAgB,UAAU,MAAM,IAAI;AAC1D,UAAM,MAAM,KAAK,UAAU,CAAC,UAAU,QAAQ,OAAO,QAAQ,CAAC;AAC9D,UAAM,UAAU,KAAK,iBAAiB,IAAI,GAAG;AAC7C,QAAI,WAAW,CAAC,KAAK,iBAAiB,QAAQ,MAAM,IAAI,EAAG,QAAO;AAClE,UAAM,QAAQ,OAAO,WAAW,KAAK,UAAU,EAAE,UAAU,QAAQ,KAAK,CAAC,CAAC;AAC1E,QAAI,QAAS,MAAK,wBAAwB,QAAQ;AAClD,SAAK,iBAAiB,IAAI,KAAK,EAAE,UAAU,QAAQ,MAAM,MAAM,CAAC;AAChE,SAAK,wBAAwB;AAC7B,WAAO,KAAK,iBAAiB,OAAO,OAAO,KAAK,uBAAuB,IAAI,OAAO,MAAM;AACtF,YAAM,SAAS,KAAK,iBAAiB,KAAK,EAAE,KAAK,EAAE;AACnD,WAAK,wBAAwB,KAAK,iBAAiB,IAAI,MAAM,EAAG;AAChE,WAAK,iBAAiB,OAAO,MAAM;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,SAAmB,UAA6B;AACvE,UAAM,WAAW,QAAQ;AACzB,UAAM,OAAO,SAAS;AACtB,QAAI,SAAS,WAAW,gBAAgB,KAAK,WAAW,aAAc,QAAO;AAC7E,QACE,SAAS,kBAAkB,WAC1B,KAAK,kBAAkB,UAAa,SAAS,gBAAgB,KAAK;AAEnE,aAAO;AACT,WAAO,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,QAAQ;AAAA,EAC5D;AAAA,EAEQ,gBAAgB,UAAkB,MAAgB,MAAyB;AACjF,UAAM,QAAQ,KAAK,MAAM;AAAA,MACvB,CAAC,UACC,MAAM,SAAS,wBACf,MAAM,YAAY,aAAa,KAAK,WAAY;AAAA,IACpD;AAEA,QAAI,SAAS,KAAK,CAAC,KAAK,iBAAiB,KAAK,MAAM,KAAK,GAAI,IAAI,EAAG,QAAO;AAC3E,QAAI,WAAW,KAAK,MAAM,KAAK,KAAK,WAAY,WAAW,cAAc;AACvE,WAAK,WAAY,SAAS;AAC1B,WAAK,SAAS;AAAA,IAChB;AACA,QAAI,QAAQ,EAAG,MAAK,MAAM,KAAK,IAAI;AAAA,SAC9B;AACH,WAAK,MAAM,KAAK,IAAI;AAAA,IACtB;AACA,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,UAAkB,QAAsB;AAC/D,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,KAAM;AACX,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,kBAAkB;AAChD,UAAI,MAAM,aAAa,YAAY,MAAM,WAAW,OAAQ;AAC5D,WAAK,iBAAiB,OAAO,GAAG;AAChC,WAAK,wBAAwB,MAAM;AACnC,WAAK,gBAAgB,UAAU,MAAM,MAAM,IAAI;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,kBAAkB,MAAsB;AAC9C,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,YAAY,WAAW,aAAc;AAC9C,WAAK,WAAW,SAAS;AACzB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,KAAK,UAAkB,QAAgB,MAAgB,kBAAkB,OAAa;AACpF,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,KAAK,MAAM,UAAU,CAAC,UAAU,MAAM,OAAO,KAAK,EAAE;AAClE,QAAI,QAAQ,EAAG,MAAK,MAAM,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,aACtC,CAAC;AACR,WAAK,MAAM,KAAK,IAAI,KAAK,MAAM,gBAAgB,MAAM,KAAK,MAAM,KAAK,CAAC,CAAC;AACzE,sBAAkB,IAAI;AACtB,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,MACE,UACA,QACA,QACA,OACA,OACA,UACM;AACN,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,CAAC,KAAM;AACX,QAAI,OAAO,KAAK,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AACzD,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM,aAAa,UAAU,SAAS,iBAAiB;AAAA,MACzD;AACA,WAAK,MAAM,KAAK,IAAI;AAAA,IACtB;AACA,QAAI,KAAK,UAAW;AACpB,SAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM;AACpC,WAAO,OAAO,MAAM,KAAK,MAAM,IAAI,CAAC;AACpC,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,KAAK,UAAkB,QAAgB,MAAoB;AACzD,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAClF,QAAI,KAAM,MAAK,OAAO,KAAK,KAAK,IAAI,EAAE;AACtC,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,OAAO,QAA6B;AAClC,UAAM,QAAQ,OAAO,WACjB,KAAK,QAAQ,IAAI,OAAO,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,OAAO,MAAM,IACjF;AACJ,QAAI,SAAS,WAAW,MAAM,MAAM,KAAK,CAAC,WAAW,YAAY,EAAE,SAAS,OAAO,MAAM;AACvF,eAAS,EAAE,GAAG,QAAQ,QAAQ,UAAU;AAC1C,SAAK,QAAQ,IAAI,OAAO,UAAU,MAAM;AACxC,UAAM,SAAS,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,QAAQ,IAAI;AACrE,QAAI,QAAQ;AACV,aAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,MAAM,aAAa,OAAO,EAAE;AAC1F,WAAK,mBAAmB,MAAM;AAC9B,WAAK,MAAM,OAAO,EAAE;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,cAAc,UAAkB,QAA4D;AAC1F,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,SAAS;AAChB,UAAM,SAAS,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,QAAQ,IAAI;AACrE,QAAI,QAAQ;AACV,WAAK,mBAAmB,MAAM;AAC9B,WAAK,MAAM,OAAO,EAAE;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,UAAkB,QAAsB;AACjD,eAAW,UAAU,KAAK,QAAQ,OAAO;AACvC,UACE,OAAO,aAAa,YACpB,OAAO,WAAW,WACjB,OAAO,WAAW,aAAa,OAAO,WAAW;AAElD,aAAK,cAAc,OAAO,UAAU,SAAS;AAAA,EACnD;AAAA,EAEA,eAAqB;AACnB,eAAW,UAAU,KAAK,OAAO,EAAG,QAAO,OAAO;AAClD,eAAW,UAAU,KAAK,QAAQ,OAAO;AACvC,UAAI,OAAO,WAAW,aAAa,OAAO,WAAW;AACnD,aAAK,cAAc,OAAO,UAAU,SAAS;AACjD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,aAAO,UAAU;AACjB,aAAO,OAAO;AACd,UAAI,OAAO,iBAAiB;AAC1B,cAAM,EAAE,OAAO,gBAAgB,IAAI,OAAO;AAC1C,eAAO,kBAAkB,EAAE,OAAO,gBAAgB;AAAA,MACpD;AACA,UAAI,SAAS,OAAO,MAAM,EAAG,QAAO,SAAS;AAC7C,iBAAW,QAAQ,OAAO,OAAO;AAC/B,YAAI,KAAK,WAAW,WAAW,WAAY,QAAO,KAAK;AACvD,YAAI,SAAS,KAAK,MAAM,EAAG,MAAK,SAAS;AACzC,uBAAe,MAAM,SAAS;AAC9B,aAAK,kBAAkB,IAAI;AAAA,MAC7B;AACA,WAAK,MAAM,OAAO,EAAE;AAAA,IACtB;AACA,eAAW,SAAS,KAAK,iBAAiB,OAAO,GAAG;AAClD,UAAI,MAAM,KAAK,YAAY,WAAW,cAAc;AAClD,aAAK,wBAAwB,MAAM;AACnC,cAAM,KAAK,WAAW,SAAS;AAC/B,cAAM,KAAK,SAAS;AACpB,cAAM,QAAQ,OAAO;AAAA,UACnB,KAAK,UAAU,EAAE,UAAU,MAAM,UAAU,QAAQ,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AAAA,QACrF;AACA,aAAK,wBAAwB,MAAM;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBAAmB,QAA0B;AACnD,UAAM,SAAS,OAAO,QAAQ;AAAA,MAC5B,CAAC,WACC,OAAO,aAAa,UACnB,OAAO,WAAW,aAAa,OAAO,WAAW;AAAA,IACtD;AACA,UAAM,OAAO,CAAC,GAAG,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,SAAS,MAAM,MAAM,CAAC;AAC/E,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,OAAO;AAAA,MACpB,CAAC,WAAW,OAAO,SAAS,eAAe,OAAO,SAAS;AAAA,IAC7D,IACI,iBACA,OAAO,SAAS,IACd,oBACA;AACN,WAAO,SAAS;AAChB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,MAAM,MAA0B;AACtC,UAAM,SAAS,gBAAgB,IAAI;AACnC,QAAI,OAAO,QAAQ;AACjB,UAAI,QAAQ;AACZ,aAAO,eAAe,OAAO,OAAO;AACpC,aAAO,SAAS,OAAO,OAAO,OAAO,CAAC,UAAU;AAC9C,iBAAS,OAAO,WAAW,KAAK;AAChC,eAAO,SAAS,KAAK;AAAA,MACvB,CAAC;AAAA,IACH;AACA,eAAW,SAAS,CAAC,QAAQ,UAAU,SAAS,GAAY;AAC1D,YAAM,QAAQ,OAAO,KAAK;AAC1B,UAAI,OAAO;AACT,cAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,eAAO,KAAK,IAAI,QAAQ;AACxB,YAAI,QAAQ,UAAW,QAAO,YAAY;AAAA,MAC5C;AAAA,IACF;AACA,QAAI,OAAO;AACT,aAAO,UAAU,OAAO,QAAQ,IAAI,CAAC,WAAW;AAC9C,cAAM,UAAU,KAAK,KAAK,OAAO,IAAI;AACrC,YAAI,QAAQ,UAAW,QAAO,YAAY;AAC1C,eAAO,EAAE,GAAG,QAAQ,MAAM,QAAQ,MAAM;AAAA,MAC1C,CAAC;AACH,QAAI,OAAO,YAAY,QAAW;AAChC,YAAM,UAAU,KAAK,KAAK,KAAK,UAAU,OAAO,OAAO,CAAC;AACxD,UAAI,QAAQ,WAAW;AACrB,eAAO,UAAU,QAAQ;AACzB,eAAO,YAAY;AAAA,MACrB;AAAA,IACF;AACA,QAAI,OAAO,YAAY;AACrB,iBAAW,SAAS,CAAC,eAAe,iBAAiB,OAAO,WAAW,GAAY;AACjF,cAAM,QAAQ,OAAO,WAAW,KAAK;AACrC,YAAI,UAAU,OAAW;AACzB,cAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,eAAO,WAAW,KAAK,IAAI,QAAQ;AACnC,YAAI,QAAQ,UAAW,QAAO,YAAY;AAAA,MAC5C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,KAAK,OAAsD;AACjE,QAAI,OAAO,WAAW,KAAK,KAAK,KAAK,aAAc,QAAO,EAAE,OAAO,WAAW,MAAM;AAEpF,QAAI,OAAO;AACX,QAAI,QAAQ;AACZ,eAAW,SAAS,OAAO;AACzB,eAAS,OAAO,WAAW,KAAK;AAChC,UAAI,QAAQ,KAAK,aAAc;AAC/B,cAAQ;AAAA,IACV;AACA,WAAO,EAAE,OAAO,GAAG,IAAI;AAAA,mCAAa,WAAW,KAAK;AAAA,EACtD;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/server/service.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { CapacityRetries } from "./capacity-retry.js";
|
|
2
2
|
import { isModelCapacityError } from "../shared/turn-errors.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { attentionKey, pendingAttention } from "../shared/thread-attention.js";
|
|
4
5
|
import { ShellService } from "./shell.js";
|
|
6
|
+
import { assertProjectInstructionsMissing, PROJECT_INIT_PROMPT } from "./project-init.js";
|
|
7
|
+
import { recapInput } from "./thread-recap.js";
|
|
5
8
|
import { readGithubRepository } from "./github-repository.js";
|
|
9
|
+
import { readWorkspaceDiff } from "./workspace-diff.js";
|
|
6
10
|
import { realpathSync } from "node:fs";
|
|
7
11
|
import { cp } from "node:fs/promises";
|
|
8
12
|
import { WorkspaceRegistry } from "./workspaces.js";
|
|
@@ -15,6 +19,7 @@ import {
|
|
|
15
19
|
} from "../shared/elicitation.js";
|
|
16
20
|
import { toThreadSummary } from "../shared/thread-summary.js";
|
|
17
21
|
import {
|
|
22
|
+
requestDigest,
|
|
18
23
|
StoreConflict
|
|
19
24
|
} from "./db/operations.js";
|
|
20
25
|
import { EventHub } from "./events.js";
|
|
@@ -81,6 +86,7 @@ class GatewayService {
|
|
|
81
86
|
archiveRevisions = /* @__PURE__ */ new Map();
|
|
82
87
|
turnBaselines = /* @__PURE__ */ new Map();
|
|
83
88
|
renameChanges = /* @__PURE__ */ new Set();
|
|
89
|
+
goalWrites = /* @__PURE__ */ new Set();
|
|
84
90
|
reads = /* @__PURE__ */ new Map();
|
|
85
91
|
resumes = /* @__PURE__ */ new Map();
|
|
86
92
|
executionReads = /* @__PURE__ */ new Map();
|
|
@@ -103,6 +109,29 @@ class GatewayService {
|
|
|
103
109
|
this.projects.get(projectId);
|
|
104
110
|
return { url };
|
|
105
111
|
}
|
|
112
|
+
async getProjectDiff(projectId) {
|
|
113
|
+
const project = this.projects.get(projectId);
|
|
114
|
+
const result = await readWorkspaceDiff(
|
|
115
|
+
project.canonicalRoot,
|
|
116
|
+
this.workspaces.allocations().map((row) => row.canonicalRoot)
|
|
117
|
+
);
|
|
118
|
+
this.projects.get(projectId);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
async getThreadDiff(threadId) {
|
|
122
|
+
let link = this.store.getThreadLink(threadId);
|
|
123
|
+
if (!link) {
|
|
124
|
+
this.normalize(await this.codex.readThreadMetadata(threadId));
|
|
125
|
+
link = this.store.getThreadLink(threadId);
|
|
126
|
+
}
|
|
127
|
+
const { cwd } = this.workspaces.assertOwnership(link.projectId, link.cwd, threadId);
|
|
128
|
+
const result = await readWorkspaceDiff(
|
|
129
|
+
cwd,
|
|
130
|
+
this.workspaces.allocations().filter((row) => row.threadId !== threadId).map((row) => row.canonicalRoot)
|
|
131
|
+
);
|
|
132
|
+
this.workspaces.assertOwnership(link.projectId, link.cwd, threadId);
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
106
135
|
async getThreadGithubRepository(threadId) {
|
|
107
136
|
let link = this.store.getThreadLink(threadId);
|
|
108
137
|
if (!link) {
|
|
@@ -470,15 +499,27 @@ class GatewayService {
|
|
|
470
499
|
this.projection.touch(threadId);
|
|
471
500
|
if (!this.archiveChanges.has(threadId)) this.publishThread(threadId);
|
|
472
501
|
}
|
|
502
|
+
async refreshGoal(thread) {
|
|
503
|
+
if (thread.goal !== void 0 || !this.codex.ready || !this.codex.getGoal) return;
|
|
504
|
+
try {
|
|
505
|
+
const goal = await this.codex.getGoal(thread.id);
|
|
506
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
507
|
+
if (thread.goal === void 0) thread.goal = goal;
|
|
508
|
+
} catch {
|
|
509
|
+
}
|
|
510
|
+
}
|
|
473
511
|
async getThreadMetadata(threadId) {
|
|
474
512
|
const cached = this.projection.get(threadId);
|
|
475
513
|
if (cached) {
|
|
476
514
|
this.workspaces.assertOwnership(cached.projectId, cached.cwd, cached.id);
|
|
477
515
|
if (this.codex.ready) await this.refreshThreadMetadata(threadId);
|
|
478
516
|
this.workspaces.assertOwnership(cached.projectId, cached.cwd, cached.id);
|
|
517
|
+
await this.refreshGoal(cached);
|
|
479
518
|
return { ...this.threadView(cached), turns: [], actions: [] };
|
|
480
519
|
}
|
|
481
520
|
const metadata = this.threadView(this.normalize(await this.codex.readThreadMetadata(threadId)));
|
|
521
|
+
await this.refreshGoal(metadata);
|
|
522
|
+
metadata.historyVisible = this.historyVisible(metadata);
|
|
482
523
|
return { ...metadata, turns: [], actions: [] };
|
|
483
524
|
}
|
|
484
525
|
async getThread(threadId) {
|
|
@@ -487,6 +528,7 @@ class GatewayService {
|
|
|
487
528
|
if (cached && this.codex.ready) await this.refreshThreadMetadata(threadId);
|
|
488
529
|
const thread = this.projection.get(threadId);
|
|
489
530
|
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
531
|
+
await this.refreshGoal(thread);
|
|
490
532
|
return this.threadView(thread);
|
|
491
533
|
}
|
|
492
534
|
getThreadAttention(threadId) {
|
|
@@ -755,6 +797,7 @@ class GatewayService {
|
|
|
755
797
|
if (isActive(this.projection.get(threadId)?.status ?? thread.status))
|
|
756
798
|
throw new AppError("THREAD_BUSY", "\u4F1A\u8BDD\u5DF2\u6709\u6D3B\u52A8\u4EFB\u52A1\uFF0C\u8BF7\u8FFD\u52A0\u8981\u6C42\u6216\u4E2D\u65AD", 409, { threadId });
|
|
757
799
|
this.ensureCompatibilityConfirmed();
|
|
800
|
+
if (input.taskKind === "init") await assertProjectInstructionsMissing(ownership.cwd);
|
|
758
801
|
this.store.dispatch(input.clientOperationId, {
|
|
759
802
|
threadId,
|
|
760
803
|
workspaceKey: ownership.workspaceKey,
|
|
@@ -775,7 +818,7 @@ class GatewayService {
|
|
|
775
818
|
const turn = await this.codex.startTurn(
|
|
776
819
|
threadId,
|
|
777
820
|
ownership.cwd,
|
|
778
|
-
input.text,
|
|
821
|
+
input.taskKind === "init" ? PROJECT_INIT_PROMPT : input.text,
|
|
779
822
|
input.settings,
|
|
780
823
|
input.images
|
|
781
824
|
);
|
|
@@ -843,6 +886,109 @@ class GatewayService {
|
|
|
843
886
|
async retryTurn(threadId, input) {
|
|
844
887
|
return this.dispatchTurn(threadId, { ...input, text: "" }, void 0, input.expectedTurnId);
|
|
845
888
|
}
|
|
889
|
+
async getGoal(threadId) {
|
|
890
|
+
const thread = await this.loadThread(threadId);
|
|
891
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
892
|
+
this.ensureReady();
|
|
893
|
+
if (!this.codex.getGoal) throw new AppError("GOAL_UNAVAILABLE", "\u5F53\u524D Codex \u4E0D\u652F\u6301\u76EE\u6807", 409);
|
|
894
|
+
const goal = await this.codex.getGoal(threadId);
|
|
895
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
896
|
+
const current = this.projection.get(threadId);
|
|
897
|
+
if (current) {
|
|
898
|
+
current.goal = goal;
|
|
899
|
+
this.projection.touch(threadId);
|
|
900
|
+
this.publishThread(threadId);
|
|
901
|
+
}
|
|
902
|
+
return { goal, version: requestDigest(goal) };
|
|
903
|
+
}
|
|
904
|
+
async mutateGoal(threadId, input) {
|
|
905
|
+
return this.perform("goal.update", threadId, input, async () => {
|
|
906
|
+
if (this.goalWrites.has(threadId))
|
|
907
|
+
throw new AppError("GOAL_BUSY", "\u76EE\u6807\u66F4\u65B0\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u7B49\u5F85\u56DE\u6267", 409);
|
|
908
|
+
this.goalWrites.add(threadId);
|
|
909
|
+
try {
|
|
910
|
+
const thread = await this.loadThread(threadId);
|
|
911
|
+
this.ensureManaged(thread);
|
|
912
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
913
|
+
const stopping = input.action === "clear" || input.action === "set" && input.status !== "active" && input.status !== void 0 && input.objective === void 0 && input.tokenBudget === void 0;
|
|
914
|
+
if (!stopping && (thread.status === "unknown" || isActive(thread.status) || thread.turns.some((turn) => isActive(turn.status)) || this.store.activeForThread(threadId)))
|
|
915
|
+
throw new AppError("THREAD_BUSY", "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u5E76\u6838\u5BF9\u72B6\u6001\u540E\u518D\u4FEE\u6539\u6216\u6062\u590D\u76EE\u6807", 409);
|
|
916
|
+
this.ensureCompatibilityConfirmed();
|
|
917
|
+
if (!this.codex.getGoal || !this.codex.mutateGoal)
|
|
918
|
+
throw new AppError("GOAL_UNAVAILABLE", "\u5F53\u524D Codex \u4E0D\u652F\u6301\u76EE\u6807", 409);
|
|
919
|
+
const before = await this.getGoal(threadId);
|
|
920
|
+
if (before.version !== input.expectedVersion)
|
|
921
|
+
throw new AppError("GOAL_CONFLICT", "\u76EE\u6807\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u540E\u64CD\u4F5C", 409);
|
|
922
|
+
this.store.dispatch(input.clientOperationId);
|
|
923
|
+
const mutation = input.action === "clear" ? { action: "clear" } : {
|
|
924
|
+
action: "set",
|
|
925
|
+
...input.objective === void 0 ? {} : { objective: input.objective },
|
|
926
|
+
...input.status === void 0 ? {} : { status: input.status },
|
|
927
|
+
...input.tokenBudget === void 0 ? {} : { tokenBudget: input.tokenBudget }
|
|
928
|
+
};
|
|
929
|
+
const previousGoal = this.projection.get(threadId)?.goal;
|
|
930
|
+
const goal = await this.codex.mutateGoal(threadId, mutation);
|
|
931
|
+
const current = this.projection.get(threadId);
|
|
932
|
+
if (current && current.goal === previousGoal) {
|
|
933
|
+
current.goal = goal;
|
|
934
|
+
this.projection.touch(threadId);
|
|
935
|
+
this.publishThread(threadId);
|
|
936
|
+
}
|
|
937
|
+
return { result: { goal } };
|
|
938
|
+
} finally {
|
|
939
|
+
this.goalWrites.delete(threadId);
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
async recapThread(threadId, input) {
|
|
944
|
+
return this.perform("thread.recap", threadId, input, async () => {
|
|
945
|
+
const thread = await this.loadThread(threadId);
|
|
946
|
+
this.ensureManaged(thread);
|
|
947
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
948
|
+
if (thread.status === "unknown" || isActive(thread.status) || thread.turns.some((turn) => isActive(turn.status)))
|
|
949
|
+
throw new AppError("THREAD_BUSY", "\u8BF7\u7B49\u5F85\u4EFB\u52A1\u7ED3\u675F\u5E76\u6838\u5BF9\u72B6\u6001\u540E\u518D\u751F\u6210\u6458\u8981", 409);
|
|
950
|
+
this.ensureCompatibilityConfirmed();
|
|
951
|
+
if (!this.codex.recapThread)
|
|
952
|
+
throw new AppError("METHOD_UNAVAILABLE", "Codex \u4E0D\u652F\u6301\u4F1A\u8BDD\u6458\u8981", 409);
|
|
953
|
+
const history = await (this.codex.readThreadPage?.(threadId) ?? this.codex.readThread(threadId));
|
|
954
|
+
this.workspaces.assertOwnership(thread.projectId, history.cwd, history.id);
|
|
955
|
+
const { prompt, partial } = recapInput(history, input.language);
|
|
956
|
+
if (!history.turns.some(
|
|
957
|
+
(turn) => turn.items.some(
|
|
958
|
+
(item) => (item.type === "userMessage" || item.type === "agentMessage") && item.text?.trim()
|
|
959
|
+
)
|
|
960
|
+
))
|
|
961
|
+
throw new AppError("EMPTY_THREAD", "\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u53EF\u751F\u6210\u6458\u8981\u7684\u6D88\u606F", 409);
|
|
962
|
+
this.store.dispatch(input.clientOperationId);
|
|
963
|
+
const summary = await this.codex.recapThread(threadId, prompt);
|
|
964
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
965
|
+
return { result: { summary, partial, readAt: Date.now() } };
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
async getGuardianDenials(threadId) {
|
|
969
|
+
const thread = await this.loadThread(threadId);
|
|
970
|
+
this.ensureManaged(thread);
|
|
971
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
972
|
+
if (!this.codex.listGuardianDenials)
|
|
973
|
+
throw new AppError("METHOD_UNAVAILABLE", "Codex \u4E0D\u652F\u6301\u62D2\u7EDD\u8BB0\u5F55\u8BFB\u53D6", 409);
|
|
974
|
+
return { data: this.codex.listGuardianDenials(threadId) };
|
|
975
|
+
}
|
|
976
|
+
async approveGuardianDenial(threadId, input) {
|
|
977
|
+
return this.perform("guardian.approve", threadId, input, async () => {
|
|
978
|
+
const thread = await this.loadThread(threadId);
|
|
979
|
+
this.ensureManaged(thread);
|
|
980
|
+
this.workspaces.assertOwnership(thread.projectId, thread.cwd, thread.id);
|
|
981
|
+
if (thread.status === "unknown" || isActive(thread.status) || thread.turns.some((turn) => isActive(turn.status)))
|
|
982
|
+
throw new AppError("THREAD_BUSY", "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u5E76\u786E\u8BA4\u72B6\u6001\u540E\u518D\u6388\u6743\u91CD\u8BD5", 409);
|
|
983
|
+
this.ensureCompatibilityConfirmed();
|
|
984
|
+
if (!this.codex.approveGuardianDenial || !this.codex.listGuardianDenials?.(threadId).some((entry) => entry.id === input.denialId))
|
|
985
|
+
throw new AppError("DENIAL_EXPIRED", "\u62D2\u7EDD\u8BB0\u5F55\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u67E5\u770B\u5F53\u524D\u4F1A\u8BDD", 409);
|
|
986
|
+
this.store.dispatch(input.clientOperationId);
|
|
987
|
+
await this.codex.approveGuardianDenial(threadId, input.denialId);
|
|
988
|
+
this.publishThread(threadId);
|
|
989
|
+
return { result: { threadId } };
|
|
990
|
+
});
|
|
991
|
+
}
|
|
846
992
|
async compactThread(threadId, input) {
|
|
847
993
|
return this.perform("thread.compact", threadId, input, async () => {
|
|
848
994
|
this.capacityRetries.clear(threadId);
|
|
@@ -888,7 +1034,7 @@ class GatewayService {
|
|
|
888
1034
|
});
|
|
889
1035
|
const revision = this.projection.revision(threadId);
|
|
890
1036
|
this.turnBaselines.set(input.clientOperationId, new Set(thread.turns.map((turn2) => turn2.id)));
|
|
891
|
-
const turn = await this.codex.startReview(threadId);
|
|
1037
|
+
const turn = await this.codex.startReview(threadId, input.target);
|
|
892
1038
|
this.store.attachTurn(input.clientOperationId, turn.id);
|
|
893
1039
|
this.turnBaselines.delete(input.clientOperationId);
|
|
894
1040
|
this.projection.turn(threadId, turn, this.projection.revision(threadId) !== revision);
|
|
@@ -1282,7 +1428,7 @@ class GatewayService {
|
|
|
1282
1428
|
}
|
|
1283
1429
|
historyVisible(thread) {
|
|
1284
1430
|
return Boolean(
|
|
1285
|
-
thread.hasMessages || thread.archived || thread.turns.length || this.store.activeForThread(thread.id) || isActive(thread.status) || thread.actions.some((action) => ["pending", "responding"].includes(action.status))
|
|
1431
|
+
thread.hasMessages || thread.archived || thread.goal || thread.turns.length || this.store.activeForThread(thread.id) || isActive(thread.status) || thread.actions.some((action) => ["pending", "responding"].includes(action.status))
|
|
1286
1432
|
);
|
|
1287
1433
|
}
|
|
1288
1434
|
retryLinks(threadId) {
|
|
@@ -1418,6 +1564,12 @@ class GatewayService {
|
|
|
1418
1564
|
}
|
|
1419
1565
|
const thread = this.projection.get(event.threadId);
|
|
1420
1566
|
if (!thread) return;
|
|
1567
|
+
if (event.type === "goal") {
|
|
1568
|
+
thread.goal = event.goal;
|
|
1569
|
+
this.projection.touch(thread.id);
|
|
1570
|
+
this.publishThread(thread.id);
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1421
1573
|
const previousAttention = new Set(
|
|
1422
1574
|
event.type === "item" || event.type === "turn" ? pendingAttention(thread).map(attentionKey) : []
|
|
1423
1575
|
);
|
|
@@ -1453,6 +1605,32 @@ class GatewayService {
|
|
|
1453
1605
|
this.projection.touch(thread.id);
|
|
1454
1606
|
} else if (event.type === "turn") {
|
|
1455
1607
|
const previous = thread.turns.find((turn) => turn.id === event.turn.id);
|
|
1608
|
+
if (thread.goal && !isTerminal(event.turn.status) && (!previous || !isTerminal(previous.status)) && !this.store.activeForThread(thread.id) && this.store.getThreadLink(thread.id)?.managedEpoch === this.codex.epoch) {
|
|
1609
|
+
try {
|
|
1610
|
+
const ownership = this.workspaces.assertOwnership(
|
|
1611
|
+
thread.projectId,
|
|
1612
|
+
thread.cwd,
|
|
1613
|
+
thread.id
|
|
1614
|
+
);
|
|
1615
|
+
const operationId = randomUUID();
|
|
1616
|
+
this.store.accept(operationId, "goal.continue", thread.id, {
|
|
1617
|
+
turnId: event.turn.id,
|
|
1618
|
+
codexEpoch: this.codex.epoch
|
|
1619
|
+
});
|
|
1620
|
+
this.store.dispatch(operationId, {
|
|
1621
|
+
threadId: thread.id,
|
|
1622
|
+
workspaceKey: ownership.workspaceKey,
|
|
1623
|
+
codexEpoch: this.codex.epoch
|
|
1624
|
+
});
|
|
1625
|
+
this.store.attachTurn(operationId, event.turn.id);
|
|
1626
|
+
this.store.acknowledge(
|
|
1627
|
+
operationId,
|
|
1628
|
+
{ threadId: thread.id, turnId: event.turn.id },
|
|
1629
|
+
event.turn.id
|
|
1630
|
+
);
|
|
1631
|
+
} catch {
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1456
1634
|
const newCompletion = !previous || !isTerminal(previous.status);
|
|
1457
1635
|
if (isTerminal(event.turn.status)) this.turnUsage.save(thread.id, event.turn);
|
|
1458
1636
|
this.projection.turn(thread.id, event.turn);
|