@tea-agent/loop-agent 0.44.0-next.12 → 0.44.0-next.14
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/CHANGELOG.md +27 -2
- package/README.md +12 -12
- package/dist/adapters/loop-agent.js +34 -0
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +5 -5
- package/dist/cli/program.js +1 -4
- package/dist/commands/init-legacy-audit.js +330 -0
- package/dist/commands/init-upgrade.js +644 -104
- package/dist/commands/init.js +686 -330
- package/dist/commands/operator-guide.js +99 -0
- package/dist/commands/operator.js +16 -3
- package/dist/executors/dag-pi-executor.js +11 -6
- package/dist/executors/pi-sdk-executor.js +3 -1
- package/dist/executors/pi-writer-tool-policy.js +60 -4
- package/dist/executors/playwright-cli-launcher.js +31 -45
- package/dist/executors/shell-write-guard.js +24 -67
- package/dist/governance/exec-plans.js +10 -1
- package/dist/governance/harness.js +2 -7
- package/dist/governance/manifest-types.js +28 -9
- package/dist/governance/project-capability-scanner.js +263 -0
- package/dist/governance/project-config.js +96 -0
- package/dist/governance/resource-catalog.js +151 -0
- package/dist/infrastructure/console/app-data.js +6 -2
- package/dist/shared/operator/capabilities.js +2 -2
- package/dist/shared/package-metadata.js +23 -7
- package/dist/shared/pi-context-pressure/extension.js +23 -0
- package/dist/shared/pi-context-pressure/index.js +1 -0
- package/dist/shared/pi-context-pressure/telemetry.js +4 -0
- package/dist/shared/pi-context-pressure/tool-result-pruner.js +98 -0
- package/dist/shared/update/npm-client.js +49 -1
- package/dist/task/config-types.js +4 -2
- package/dist/task/source-prepare/build-draft.js +1 -0
- package/dist/task/source-prepare/path-policy.js +17 -7
- package/dist/worker/cli.js +3 -5
- package/dist/worker/console/chat/browser-automation.js +455 -41
- package/dist/worker/console/chat/browser-content.js +74 -0
- package/dist/worker/console/chat/browser-diagnostics.js +250 -0
- package/dist/worker/console/chat/browser-evaluation.js +58 -0
- package/dist/worker/console/chat/browser-operation-queue.js +19 -0
- package/dist/worker/console/chat/browser-pick.js +113 -0
- package/dist/worker/console/chat/browser-routes.js +54 -5
- package/dist/worker/console/chat/browser-screenshot-result.js +47 -0
- package/dist/worker/console/chat/browser-storage.js +89 -0
- package/dist/worker/console/chat/chat-event-store.js +7 -6
- package/dist/worker/console/chat/context-insights.js +84 -19
- package/dist/worker/console/chat/pet/pet-affinity.js +169 -0
- package/dist/worker/console/chat/pet/pet-persist.js +109 -0
- package/dist/worker/console/chat/pet/pet-registry.js +142 -0
- package/dist/worker/console/chat/pet/pet-remarks.js +48 -0
- package/dist/worker/console/chat/pet/pet-routes.js +125 -0
- package/dist/worker/console/chat/pet/pet-service.js +262 -0
- package/dist/worker/console/chat/pet/pet-state.js +99 -0
- package/dist/worker/console/chat/pi-mode-loop-isolation.js +17 -2
- package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +125 -174
- package/dist/worker/console/chat/pi-runtime.js +8 -3
- package/dist/worker/console/chat/repo-browser.js +80 -2
- package/dist/worker/console/chat/repo-preview-kind.js +155 -0
- package/dist/worker/console/chat/routes.js +43 -7
- package/dist/worker/console/chat/scheduled-goal-request.js +14 -6
- package/dist/worker/console/chat/session-mode.js +1 -1
- package/dist/worker/console/chat/session-store.js +24 -5
- package/dist/worker/console/chat/tools.js +12 -0
- package/dist/worker/console/console-shutdown.js +34 -0
- package/dist/worker/console/server.js +2 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-r1NAPU_5.js → abnfDiagram-N423BO3Z-DASc69AM.js} +1 -1
- package/dist/worker/console/static/assets/{arc-dT5T4sVL.js → arc-h09p-LAc.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CP_cOq46.js → architectureDiagram-T3A2C74G-CZ3dtLkh.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-sToEZxEf.js → blockDiagram-VBNYF7ZC-DMrRhMXG.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DSxwwi2m.js → c4Diagram-5PPSVZJV-DQxisHV6.js} +1 -1
- package/dist/worker/console/static/assets/channel-D1zgKZfg.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-B9fh0IkF.js → chunk-2GRJ4B5K-CefVN9zh.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CAUNl-A6.js → chunk-2Q5K7J3B-DmR1Koq2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BomeqbNX.js → chunk-5RXB4S5H-NlzrSW7L.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BNAuTOLE.js → chunk-5VM5RSS4-DfelJv-0.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DfzjRD5y.js → chunk-6Q2QTUOP-BK6RFy58.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C3uE-yc2.js → chunk-GF5L2VYU-BAeh9lz4.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-C3sQMMYr.js → chunk-JWPE2WC7-ChPS5WzG.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D_AtEYQL.js → chunk-KBJHAD2P-BoVe5IM6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DW4TwhKv.js → chunk-RYQCIY6F-C4q_0Lw9.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CTQDmJcp.js → chunk-XXDRQBXY-Bb9TvjeY.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CXNNsY2M.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CXNNsY2M.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-iMqPuBsL.js → cose-bilkent-JH36ORCC-DmNnL8Ff.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DktIuDWs.js → cynefin-VYW2F7L2-Contvx58.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BgVnjyEs.js → cynefinDiagram-MW4NZA55-Cigq7cjk.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CR25E4bu.js → dagre-VZM6K2ZE-dEbC0nxb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CPM2h5HY.js → diagram-7IWD3JNH-CzIztESV.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DqF0x2g1.js → diagram-B4RE2ZJO-Bo14zbaY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-G8BYp2eb.js → diagram-LBJQPF4R-C4xUyil6.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BbC4kT_D.js → diagram-Q27KOJAE-CaBY_uYa.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CKZwZ-G5.js → diagram-UB23O5K3-ClUXUeiu.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-kJDmheia.js → ebnfDiagram-BXEA7PRR-BbGCgjC6.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DFTVHyxB.js → erDiagram-JOGREHBK-Dr-AcwSl.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BqdN5_os.js → flowDiagram-UKHOOZJN-BG8Gcfyc.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-SYDjVakh.js → ganttDiagram-PKOTCBZU-CFVaPs5r.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bf8bNpGA.js → gitGraphDiagram-DS77QQ5N-ChJ8pm-O.js} +1 -1
- package/dist/worker/console/static/assets/index-B_5GhVIO.js +488 -0
- package/dist/worker/console/static/assets/index-C7YMBluX.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DIeAmJ45.js → infoDiagram-6WML65LV-C5J9-uCZ.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-oikqUAlo.js → ishikawaDiagram-WSZJBQD7-BcfjqzDv.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-mKEF_xYT.js → journeyDiagram-NVQOT4AX-BzzCO-rD.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BdWJHPnN.js → kanban-definition-27J2QSJJ-NCHUZ46h.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DGRlieMH.js → linear-BKZlWCUU.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-4P9yPC9c.js → mermaid.core-DbTaQjFE.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-5PTSkos6.js → mindmap-definition-FAOFIHXS-CroYl5xQ.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DONIFpG5.js → pegDiagram-VL7TDLO6-DgMBx-9k.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-D_Z4S70M.js → pieDiagram-7S7Q4E2Y-CyWDmbq1.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CAsjh8iY.js → quadrantDiagram-CIZ2JOQS-BgGEOqSP.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Cx4Dd6ac.js → railroadDiagram-AXF67PYL-BMZ7oeeV.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-cQb7mwyH.js → requirementDiagram-LRYGKXZP-DxqyGhcc.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cd-DhUdf.js → sankeyDiagram-W5VNT64P-DnSvNCG8.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-AlKYRgIk.js → sequenceDiagram-SI44F4Z6-BiZh6f-R.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CUy_ET4e.js → sizeCapture-X5ZJPWSS-BKXSI8WB.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-CTuVe6Sa.js → stateDiagram-OKZ733FA-CfSgoYFm.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DgHi3vjb.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-ChFLJb-v.js → swimlanes-SLNWSIFB-CyGADcHe.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bgvdt1Y0.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DZZeiAPr.js → timeline-definition-Z64GVDOM-HmPaSPOK.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-t4O91cZU.js → vennDiagram-T6HMQDX7-VA2VBbez.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CV5qGHZu.js → wardleyDiagram-T6FBY63Y-BxjiBPZa.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DyXbytUI.js → xychartDiagram-ELKLHX3M--hUY-qFj.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static/pets/ember/pet.json +167 -0
- package/dist/worker/console/static/pets/ember/spritesheet.png +0 -0
- package/dist/worker/console/static-src/operator-chat/details-rail-surfaces.js +4 -3
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +57 -9
- package/dist/worker/console/static-src/operator-chat/use-stat-dialog.js +95 -0
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +6 -0
- package/dist/worker/console/workspace-context.js +15 -0
- package/dist/worker/console/workspace-initialization.js +25 -16
- package/dist/worker/delivery/package.js +4 -1
- package/dist/worker/materialize/harness-task-lineage.js +4 -2
- package/dist/worker/observe/static/console-theme.css +33 -29
- package/dist/worker/observe/static/operator-chrome.js +1 -42
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +3 -1
- package/dist/workflows/dag/backend-test-layout.js +27 -7
- package/dist/workflows/dag/backend-test-markdown-workflow.js +3 -1
- package/dist/workflows/dag/backend-test-pytest-collection.js +4 -1
- package/dist/workflows/dag/final-verification.js +45 -10
- package/dist/workflows/dag/frontend-test-case-checklist.js +12 -3
- package/dist/workflows/dag/frontend-test-environment-probe.js +0 -2
- package/dist/workflows/dag/frontend-test-layout.js +41 -12
- package/dist/workflows/dag/hybrid/sources.js +35 -16
- package/dist/workflows/dag/hybrid/templates/backend-test.js +70 -55
- package/dist/workflows/dag/hybrid/templates/frontend-test.js +62 -41
- package/dist/workflows/dag/hybrid/templates/kg-bootstrap.js +6 -6
- package/dist/workflows/dag/hybrid/templates/knowledge-sync.js +5 -5
- package/dist/workflows/dag/skill-instructions.js +102 -32
- package/dist/workflows/dag/skill-snapshot.js +3 -0
- package/dist/workflows/dag/skills.js +7 -7
- package/dist/workflows/dag/test-artifact-namespace.js +73 -0
- package/dist/workflows/dag/validate.js +24 -5
- package/dist/workflows/dag/workspace-checkpoint.js +13 -1
- package/docs/architecture/runtime-boundaries.md +28 -22
- package/docs/init-surface.manifest.json +43 -295
- package/docs/templates/README.md +4 -4
- package/docs/templates/agent-dag.base.json +9 -9
- package/docs/templates/agent-dag.final-verification.json +6 -6
- package/docs/templates/agent-dag.supervised-implementation.json +12 -12
- package/docs/templates/backend-test-dag.generate-pytest.prompt.md +3 -3
- package/docs/templates/backend-test-dag.json +708 -708
- package/docs/templates/backend-test-dag.review-cases.prompt.md +3 -3
- package/docs/templates/frontend-implementation-dag.json +2 -2
- package/docs/templates/frontend-test-case-checklist.md +2 -2
- package/docs/templates/frontend-test-dag.generate-cases.prompt.md +7 -7
- package/docs/templates/frontend-test-dag.json +48 -39
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +2 -2
- package/docs/templates/frontend-test-dag.retrospect.prompt.md +1 -1
- package/docs/templates/frontend-test-dag.review-cases.prompt.md +1 -1
- package/docs/templates/hybrid-dag.json +9 -9
- package/docs/templates/knowledge-sync-dag.json +8 -8
- package/package.json +12 -3
- package/resource-catalog.v1.json +1973 -0
- package/resources/agent-bridge/loop-agent/SKILL.md +40 -0
- package/resources/init-history/legacy-surface.v1.json +33 -0
- package/skills/fe-test-ui-scout/SKILL.md +4 -4
- package/skills/fe-test-ui-scout/references/ledger-schema.md +1 -1
- package/skills/init-update/SKILL.md +34 -0
- package/skills/init-update/agents/openai.yaml +6 -0
- package/skills/playwright-cli/SKILL.md +1 -1
- package/skills/playwright-cli-case-generator/SKILL.md +4 -4
- package/dist/worker/console/static/assets/channel-CyBY_yGk.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D5lN4E_E.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D5lN4E_E.js +0 -1
- package/dist/worker/console/static/assets/index-B28Onmfy.css +0 -1
- package/dist/worker/console/static/assets/index-CTMZsDmh.js +0 -486
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BsWhs8O7.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CJcioYGH.js +0 -8
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { shouldRewriteAssistantTransientProviderError } from "../pi-provider-recovery.js";
|
|
2
2
|
import { buildOverflowCheckpoint } from "./checkpoint.js";
|
|
3
|
+
import { prunePiToolResultMessages, } from "./tool-result-pruner.js";
|
|
3
4
|
import { shouldRewriteAssistantOverflow } from "./overflow.js";
|
|
4
5
|
import { clearRetrieveBypass, compressProviderPayload, createSiftRetrieveToolDefinition, SIFT_RETRIEVE_TOOL_NAME, } from "./sift-bridge.js";
|
|
5
6
|
import { emptyContextPressureCounters, incrementCounter, } from "./telemetry.js";
|
|
6
7
|
export function createCompactionController() {
|
|
7
8
|
return {
|
|
8
9
|
proactiveCompaction: false,
|
|
10
|
+
pruneArmed: false,
|
|
9
11
|
counters: emptyContextPressureCounters(),
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
14
|
export function createContextPressureExtension(options) {
|
|
13
15
|
const l2 = options.policy.mode !== "off";
|
|
14
16
|
const l1 = Boolean(options.sift);
|
|
17
|
+
const pruner = l2 && options.prune !== undefined;
|
|
15
18
|
const transientRecovery = options.normalizeTransientProviderErrors === true;
|
|
16
19
|
if (!l2 && !l1 && !transientRecovery)
|
|
17
20
|
return undefined;
|
|
@@ -54,6 +57,8 @@ export function createContextPressureExtension(options) {
|
|
|
54
57
|
const reason = event.reason;
|
|
55
58
|
if (reason === "overflow") {
|
|
56
59
|
incrementCounter(options.controller.counters, "overflow");
|
|
60
|
+
if (pruner)
|
|
61
|
+
options.controller.pruneArmed = true;
|
|
57
62
|
}
|
|
58
63
|
if (reason === "manual") {
|
|
59
64
|
incrementCounter(options.controller.counters, "manual");
|
|
@@ -79,6 +84,24 @@ export function createContextPressureExtension(options) {
|
|
|
79
84
|
};
|
|
80
85
|
});
|
|
81
86
|
}
|
|
87
|
+
if (pruner) {
|
|
88
|
+
api.on("context", (event) => {
|
|
89
|
+
if (!options.controller.pruneArmed)
|
|
90
|
+
return undefined;
|
|
91
|
+
const messages = Array.isArray(event.messages) ? event.messages : [];
|
|
92
|
+
try {
|
|
93
|
+
const result = prunePiToolResultMessages(messages, options.prune);
|
|
94
|
+
if (!result.changed)
|
|
95
|
+
return undefined;
|
|
96
|
+
options.controller.counters.toolResultPruned += result.messagesPruned;
|
|
97
|
+
options.controller.counters.charsPrunedEstimate += result.charsRemoved;
|
|
98
|
+
return { messages: result.messages };
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
82
105
|
if (l1 && options.sift) {
|
|
83
106
|
const sift = options.sift;
|
|
84
107
|
api.on("before_provider_request", (event) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { isContextOverflow, CONTEXT_OVERFLOW_PHRASES, OVERFLOW_FIXTURES, NORMALIZED_OVERFLOW_PREFIX, shouldRewriteAssistantOverflow, normalizeOverflowErrorMessage, buildGeneratedOverflowClassifierSource, } from "./overflow.js";
|
|
2
2
|
export { parseCompactionPolicy, deriveEffectiveWindow, conservativeTokenEstimate, projectPromptPressure, applyProcessCompactionOverride, inMemoryCompactionSettings, PI_DEFAULT_RESERVE_TOKENS, DEFAULT_KEEP_RECENT_TOKENS, } from "./compaction-policy.js";
|
|
3
3
|
export { buildOverflowCheckpoint } from "./checkpoint.js";
|
|
4
|
+
export { PI_TOOL_RESULT_PRUNE_MARKER, DEFAULT_PI_TOOL_RESULT_PRUNE_CONFIG, resolvePiToolResultPruneConfig, parsePiToolResultPruneConfig, piCodePointLength, prunePiToolResultMessages, } from "./tool-result-pruner.js";
|
|
4
5
|
export { createContextPressureExtension, createCompactionController, } from "./extension.js";
|
|
5
6
|
export { createSiftBridgeState, parseSiftBridgeConfig, compressProviderPayload, executeSiftRetrieve, housekeepSiftStash, createSiftRetrieveToolDefinition, SIFT_RETRIEVE_TOOL_NAME, SIFT_POLICY_VERSION, } from "./sift-bridge.js";
|
|
6
7
|
export { isConsoleSiftEnabled, isDagSiftEnabled, readContextPressureMode, parseEnabledFlag, parseContextPressureMode, } from "./env.js";
|
|
@@ -9,6 +9,8 @@ export function emptyContextPressureCounters() {
|
|
|
9
9
|
l0CompactFailed: 0,
|
|
10
10
|
tokensSavedEstimate: 0,
|
|
11
11
|
blocksCompressed: 0,
|
|
12
|
+
toolResultPruned: 0,
|
|
13
|
+
charsPrunedEstimate: 0,
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
16
|
export function incrementCounter(counters, reason, amount = 1) {
|
|
@@ -47,5 +49,7 @@ export function projectSafeTelemetry(counters) {
|
|
|
47
49
|
failOpen: counters.failOpen,
|
|
48
50
|
tokensSavedEstimate: counters.tokensSavedEstimate,
|
|
49
51
|
blocksCompressed: counters.blocksCompressed,
|
|
52
|
+
toolResultPruned: counters.toolResultPruned,
|
|
53
|
+
charsPrunedEstimate: counters.charsPrunedEstimate,
|
|
50
54
|
};
|
|
51
55
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Deterministic, model-free pruning of Pi tool-result messages. */
|
|
2
|
+
import { parseBoundedNumber, parseEnabledFlag } from "./env.js";
|
|
3
|
+
export const PI_TOOL_RESULT_PRUNE_MARKER = "\n\n[... tool result middle pruned ...]\n\n";
|
|
4
|
+
export const DEFAULT_PI_TOOL_RESULT_PRUNE_CONFIG = Object.freeze({ thresholdChars: 8192, headChars: 4096, tailChars: 1024 });
|
|
5
|
+
export function parsePiToolResultPruneConfig(env = process.env) {
|
|
6
|
+
const enabled = parseEnabledFlag(env.HARNESS_TOOL_RESULT_PRUNE, true);
|
|
7
|
+
const diagnostics = enabled.diagnostic ? [enabled.diagnostic] : [];
|
|
8
|
+
const threshold = parseBoundedNumber(env.HARNESS_TOOL_RESULT_PRUNE_THRESHOLD_CHARS, 8192, 1, 1_000_000);
|
|
9
|
+
const head = parseBoundedNumber(env.HARNESS_TOOL_RESULT_PRUNE_HEAD_CHARS, 4096, 0, 1_000_000);
|
|
10
|
+
const tail = parseBoundedNumber(env.HARNESS_TOOL_RESULT_PRUNE_TAIL_CHARS, 1024, 0, 1_000_000);
|
|
11
|
+
for (const item of [threshold, head, tail])
|
|
12
|
+
if (item.diagnostic)
|
|
13
|
+
diagnostics.push(item.diagnostic);
|
|
14
|
+
try {
|
|
15
|
+
return { enabled: enabled.enabled, config: resolvePiToolResultPruneConfig({ thresholdChars: Math.floor(threshold.value), headChars: Math.floor(head.value), tailChars: Math.floor(tail.value) }), diagnostics };
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
diagnostics.push(error instanceof Error ? error.message : String(error));
|
|
19
|
+
return { enabled: false, config: DEFAULT_PI_TOOL_RESULT_PRUNE_CONFIG, diagnostics };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function resolvePiToolResultPruneConfig(config = {}) {
|
|
23
|
+
const keys = new Set(["thresholdChars", "headChars", "tailChars"]);
|
|
24
|
+
for (const key of Object.keys(config))
|
|
25
|
+
if (!keys.has(key))
|
|
26
|
+
throw new Error(`PiToolResultPruneConfig: unknown key "${key}"`);
|
|
27
|
+
const out = { thresholdChars: config.thresholdChars ?? 8192, headChars: config.headChars ?? 4096, tailChars: config.tailChars ?? 1024 };
|
|
28
|
+
if (!Number.isInteger(out.thresholdChars) || out.thresholdChars <= 0)
|
|
29
|
+
throw new Error("thresholdChars must be positive integer");
|
|
30
|
+
if (!Number.isInteger(out.headChars) || out.headChars < 0)
|
|
31
|
+
throw new Error("headChars must be non-negative integer");
|
|
32
|
+
if (!Number.isInteger(out.tailChars) || out.tailChars < 0)
|
|
33
|
+
throw new Error("tailChars must be non-negative integer");
|
|
34
|
+
if (out.headChars + Array.from(PI_TOOL_RESULT_PRUNE_MARKER).length + out.tailChars > out.thresholdChars)
|
|
35
|
+
throw new Error("prune budgets exceed threshold");
|
|
36
|
+
return Object.freeze(out);
|
|
37
|
+
}
|
|
38
|
+
export function piCodePointLength(text) { return Array.from(text).length; }
|
|
39
|
+
function textBlock(value) { return value && typeof value === "object" && value.type === "text" && typeof value.text === "string"; }
|
|
40
|
+
function isToolResult(message) { return message.role === "tool" || message.role === "toolResult" || message.type === "tool_result" || message.role === "tool_result"; }
|
|
41
|
+
function pruneBlocks(input, cfg) {
|
|
42
|
+
const before = input.reduce((n, b) => n + (textBlock(b) ? piCodePointLength(b.text) : 0), 0);
|
|
43
|
+
if (before <= cfg.thresholdChars)
|
|
44
|
+
return { blocks: null, before, after: before };
|
|
45
|
+
const cutStart = cfg.headChars, cutEnd = before - cfg.tailChars;
|
|
46
|
+
let consumed = 0, inserted = false;
|
|
47
|
+
const out = [];
|
|
48
|
+
for (const block of input) {
|
|
49
|
+
if (!textBlock(block)) {
|
|
50
|
+
out.push(block);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const points = Array.from(block.text);
|
|
54
|
+
const bs = consumed, be = bs + points.length;
|
|
55
|
+
const headEnd = Math.min(points.length, Math.max(0, cutStart - bs));
|
|
56
|
+
const tailStart = Math.min(points.length, Math.max(0, cutEnd - bs));
|
|
57
|
+
const marker = !inserted && bs < cutEnd && be > cutStart ? PI_TOOL_RESULT_PRUNE_MARKER : "";
|
|
58
|
+
if (marker)
|
|
59
|
+
inserted = true;
|
|
60
|
+
const text = points.slice(0, headEnd).join("") + marker + points.slice(tailStart).join("");
|
|
61
|
+
if (text)
|
|
62
|
+
out.push({ ...block, text });
|
|
63
|
+
consumed = be;
|
|
64
|
+
}
|
|
65
|
+
const after = out.reduce((n, b) => n + (textBlock(b) ? piCodePointLength(b.text) : 0), 0);
|
|
66
|
+
if (!inserted || after > cfg.thresholdChars || after >= before)
|
|
67
|
+
throw new Error("Pi tool-result prune invariant failed");
|
|
68
|
+
return { blocks: out, before, after };
|
|
69
|
+
}
|
|
70
|
+
/** Returns a new transcript; input/full originals are never mutated or persisted. */
|
|
71
|
+
export function prunePiToolResultMessages(messages, config) {
|
|
72
|
+
const cfg = resolvePiToolResultPruneConfig(config);
|
|
73
|
+
const output = messages.slice();
|
|
74
|
+
let charsRemoved = 0, messagesPruned = 0;
|
|
75
|
+
for (let i = 0; i < output.length; i++) {
|
|
76
|
+
const message = output[i];
|
|
77
|
+
if (!message || !isToolResult(message))
|
|
78
|
+
continue;
|
|
79
|
+
if (typeof message.content === "string") {
|
|
80
|
+
const r = pruneBlocks([{ type: "text", text: message.content }], cfg);
|
|
81
|
+
if (r.blocks) {
|
|
82
|
+
output[i] = { ...message, content: r.blocks[0].text };
|
|
83
|
+
charsRemoved += r.before - r.after;
|
|
84
|
+
messagesPruned++;
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!Array.isArray(message.content))
|
|
89
|
+
continue;
|
|
90
|
+
const r = pruneBlocks(message.content, cfg);
|
|
91
|
+
if (r.blocks) {
|
|
92
|
+
output[i] = { ...message, content: r.blocks };
|
|
93
|
+
charsRemoved += r.before - r.after;
|
|
94
|
+
messagesPruned++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { messages: output, changed: messagesPruned > 0, charsRemoved, messagesPruned };
|
|
98
|
+
}
|
|
@@ -4,6 +4,39 @@ import path from "node:path";
|
|
|
4
4
|
import semver from "semver";
|
|
5
5
|
const PACKAGE_NAME = "@tea-agent/loop-agent";
|
|
6
6
|
export const DEFAULT_NPM_QUERY_TIMEOUT_MS = 15_000;
|
|
7
|
+
function quoteWindowsCommandArgument(value) {
|
|
8
|
+
if (/[%!^&|<>]/.test(value)) {
|
|
9
|
+
throw new Error("unsafe Windows update command argument");
|
|
10
|
+
}
|
|
11
|
+
return /^[A-Za-z0-9_@./:\\=,+-]+$/.test(value)
|
|
12
|
+
? value
|
|
13
|
+
: `"${value.replaceAll('"', '""')}"`;
|
|
14
|
+
}
|
|
15
|
+
export function resolveUpdateCommandLaunch(command, args, platform = process.platform, comspec = process.env.ComSpec ?? "cmd.exe") {
|
|
16
|
+
if (platform !== "win32") {
|
|
17
|
+
return { command, args: [...args], windowsVerbatimArguments: false };
|
|
18
|
+
}
|
|
19
|
+
const isExplicitPath = command.includes("/") || command.includes("\\");
|
|
20
|
+
const isKnownBareShim = !isExplicitPath &&
|
|
21
|
+
path.win32.extname(command) === "" &&
|
|
22
|
+
new Set(["npm", "npx", "loop-agent"]).has(command.toLowerCase());
|
|
23
|
+
const isCommandShim = isKnownBareShim || /\.(?:cmd|bat)$/i.test(command);
|
|
24
|
+
if (!isCommandShim) {
|
|
25
|
+
return { command, args: [...args], windowsVerbatimArguments: false };
|
|
26
|
+
}
|
|
27
|
+
const windowsCommand = isKnownBareShim ? `${command}.cmd` : command;
|
|
28
|
+
const commandLine = [windowsCommand, ...args]
|
|
29
|
+
.map(quoteWindowsCommandArgument)
|
|
30
|
+
.join(" ");
|
|
31
|
+
const commandPayload = commandLine.startsWith('"')
|
|
32
|
+
? `"${commandLine}"`
|
|
33
|
+
: commandLine;
|
|
34
|
+
return {
|
|
35
|
+
command: comspec,
|
|
36
|
+
args: [`/d /s /c ${commandPayload}`],
|
|
37
|
+
windowsVerbatimArguments: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
7
40
|
export function createNpmUpdateClient(options) {
|
|
8
41
|
const npmCommand = options.npmCommand ?? "npm";
|
|
9
42
|
const loopAgentCommand = options.loopAgentCommand ?? "loop-agent";
|
|
@@ -166,11 +199,26 @@ function isAllowedChannelVersion(version, channel) {
|
|
|
166
199
|
}
|
|
167
200
|
async function runCommand(command, args, options) {
|
|
168
201
|
return new Promise((resolve) => {
|
|
169
|
-
|
|
202
|
+
let launch;
|
|
203
|
+
try {
|
|
204
|
+
launch = resolveUpdateCommandLaunch(command, args);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
resolve({
|
|
208
|
+
exitCode: null,
|
|
209
|
+
stdout: "",
|
|
210
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
211
|
+
timedOut: false,
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const child = spawn(launch.command, launch.args, {
|
|
170
216
|
cwd: options.cwd,
|
|
171
217
|
env: options.env ? { ...process.env, ...options.env } : process.env,
|
|
172
218
|
stdio: ["ignore", "pipe", "pipe"],
|
|
173
219
|
shell: false,
|
|
220
|
+
windowsHide: true,
|
|
221
|
+
windowsVerbatimArguments: launch.windowsVerbatimArguments,
|
|
174
222
|
});
|
|
175
223
|
let stdout = "";
|
|
176
224
|
let stderr = "";
|
|
@@ -126,7 +126,8 @@ export const frontendOpenspecConfigSchema = z.object({
|
|
|
126
126
|
export const frontendTestConfigSchema = z.object({
|
|
127
127
|
/**
|
|
128
128
|
* Repository-relative frontend-test artifact root.
|
|
129
|
-
* Default "testcase/frontend"
|
|
129
|
+
* Default ".harness/testcase/frontend" (canonical harness test-artifact
|
|
130
|
+
* namespace). Semantic validation lives in
|
|
130
131
|
* resolveFrontendTestLayout (fail-closed), not in this schema.
|
|
131
132
|
*/
|
|
132
133
|
testRoot: z.string().min(1).optional(),
|
|
@@ -239,7 +240,8 @@ const backendTestModuleLayoutSchema = z
|
|
|
239
240
|
/** Backend-test artifact layout and pipeline mode configuration (plan A/B/D). */
|
|
240
241
|
export const backendTestConfigSchema = z
|
|
241
242
|
.object({
|
|
242
|
-
/** Repository-relative test root. Default "testcase"
|
|
243
|
+
/** Repository-relative test root. Default ".harness/testcase" (canonical
|
|
244
|
+
* harness test-artifact namespace). */
|
|
243
245
|
testRoot: z.string().min(1).optional(),
|
|
244
246
|
/** Markdown subdirectory relative to testRoot. Default "md". */
|
|
245
247
|
markdownRel: z.string().min(1).optional(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { canonicalizePath } from "../contract/canonicalize.js";
|
|
2
2
|
import { PREPARE_DEFAULT_FORBIDDEN_PATHS } from "./types.js";
|
|
3
|
+
import { isAnyTestArtifactPath, isTestArtifactTaskKind, } from "../../workflows/dag/test-artifact-namespace.js";
|
|
3
4
|
function hasNul(value) {
|
|
4
5
|
return value.includes("\0");
|
|
5
6
|
}
|
|
@@ -133,6 +134,7 @@ export function assessPreparePaths(input) {
|
|
|
133
134
|
forbidden.push(result.value);
|
|
134
135
|
}
|
|
135
136
|
const allowedSet = new Set(allowed);
|
|
137
|
+
const testArtifactTaskKind = isTestArtifactTaskKind(input.taskKind);
|
|
136
138
|
for (const f of forbidden) {
|
|
137
139
|
if (allowedSet.has(f)) {
|
|
138
140
|
blocking.push({
|
|
@@ -145,14 +147,22 @@ export function assessPreparePaths(input) {
|
|
|
145
147
|
}
|
|
146
148
|
for (const a of allowed) {
|
|
147
149
|
for (const f of forbidden) {
|
|
148
|
-
if (forbiddenAncestorCoversAllowed(a, f))
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
if (!forbiddenAncestorCoversAllowed(a, f))
|
|
151
|
+
continue;
|
|
152
|
+
// D3 test-artifact exception: a dedicated test task may allow exactly
|
|
153
|
+
// the canonical `.harness/testcase` roots under the default `.harness/**`
|
|
154
|
+
// forbidden ancestor; every other overlap stays blocking.
|
|
155
|
+
if (testArtifactTaskKind &&
|
|
156
|
+
f === ".harness/**" &&
|
|
157
|
+
isAnyTestArtifactPath(a)) {
|
|
158
|
+
continue;
|
|
155
159
|
}
|
|
160
|
+
blocking.push({
|
|
161
|
+
code: "ALLOWED_UNDER_FORBIDDEN_ANCESTOR",
|
|
162
|
+
level: "blocking",
|
|
163
|
+
message: `allowed path ${a} is fully covered by forbidden ancestor ${f}`,
|
|
164
|
+
path: a,
|
|
165
|
+
});
|
|
156
166
|
}
|
|
157
167
|
}
|
|
158
168
|
for (const a of allowed) {
|
package/dist/worker/cli.js
CHANGED
|
@@ -873,12 +873,10 @@ export async function runConsoleServe(options) {
|
|
|
873
873
|
await server.close();
|
|
874
874
|
return;
|
|
875
875
|
}
|
|
876
|
-
await
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
process.once("SIGTERM", shutdown);
|
|
876
|
+
const { holdConsoleUntilSignal } = await import("./console/console-shutdown.js");
|
|
877
|
+
await holdConsoleUntilSignal({
|
|
878
|
+
close: () => server.close(),
|
|
880
879
|
});
|
|
881
|
-
await server.close();
|
|
882
880
|
}
|
|
883
881
|
catch (error) {
|
|
884
882
|
const detail = error instanceof Error ? error.message : String(error);
|