@tea-agent/loop-agent 0.39.0-next.3 → 0.39.0-next.30
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/AGENTS.md +4 -1
- package/CHANGELOG.md +267 -65
- package/README.md +11 -5
- package/bin/loop-agent.js +7 -3
- package/dist/application/dag/generate-task-dag.js +9 -0
- package/dist/application/task-lifecycle/advance.js +4 -0
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +16 -5
- package/dist/cli/program.js +16 -2
- package/dist/cli/update/notifier.js +2 -2
- package/dist/cli.js +2 -1
- package/dist/commands/dag-rerun.js +55 -1
- package/dist/commands/init-model-catalog.js +464 -0
- package/dist/commands/init-upgrade.js +265 -97
- package/dist/commands/init.js +428 -27
- package/dist/commands/inspect-next.js +8 -0
- package/dist/commands/task-advance.js +31 -0
- package/dist/executors/dag-pi-executor.js +118 -14
- package/dist/executors/pi-event-serializer.js +42 -1
- package/dist/executors/pi-executor.js +51 -0
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-playwright-cli-tool.js +8 -1
- package/dist/executors/pi-sdk-executor.js +187 -59
- package/dist/executors/shell-executor.js +533 -29
- package/dist/executors/shell-write-guard.js +7 -0
- package/dist/shared/dag-prompt-override.js +28 -0
- package/dist/shared/operator/capabilities.js +181 -27
- package/dist/shared/update/console-notifier.js +100 -0
- package/dist/{cli → shared}/update/npm-client.js +41 -8
- package/dist/{cli → shared}/update/state.js +41 -13
- package/dist/task/config-types.js +22 -0
- package/dist/task/contract/constants.js +1 -0
- package/dist/task/contract/diff.js +26 -0
- package/dist/task/contract/project.js +5 -0
- package/dist/task/contract/schema.js +6 -1
- package/dist/task/source-prepare/build-draft.js +15 -0
- package/dist/worker/cli.js +31 -1
- package/dist/worker/console/chat/deferred-turn.js +91 -0
- package/dist/worker/console/chat/mcp-inventory.js +221 -0
- package/dist/worker/console/chat/pi-runtime.js +165 -83
- package/dist/worker/console/chat/repo-walk.js +10 -1
- package/dist/worker/console/chat/routes.js +478 -55
- package/dist/worker/console/chat/semantic-activity.js +20 -8
- package/dist/worker/console/chat/session-store.js +146 -2
- package/dist/worker/console/chat/turn-process.js +17 -30
- package/dist/worker/console/harness-pi-model-matrix.js +137 -0
- package/dist/worker/console/operator-actions.js +244 -4
- package/dist/worker/console/operator-user-error.js +19 -0
- package/dist/worker/console/pi-readiness.js +12 -5
- package/dist/worker/console/recovery-cta.js +4 -4
- package/dist/worker/console/recovery-error-copy.js +4 -4
- package/dist/worker/console/routes.js +43 -2
- package/dist/worker/console/security.js +83 -10
- package/dist/worker/console/server.js +42 -6
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DSvF6RXQ.js → abnfDiagram-N423BO3Z-CiGOV5eG.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DuI4ogtJ.js → arc-Ds9Gyfd8.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DdBbgD4y.js → architectureDiagram-T3A2C74G-C6V6uC98.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-xQC2HELm.js → blockDiagram-VBNYF7ZC-DezF7Ol9.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DPMSgwIZ.js → c4Diagram-5PPSVZJV-BCWk3gCT.js} +1 -1
- package/dist/worker/console/static/assets/channel-DMvu1nmi.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-WTEKTxin.js → chunk-2GRJ4B5K-DbYr-Cxy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B6vZ0Pv_.js → chunk-2Q5K7J3B-XSlusW4G.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BrerNAix.js → chunk-5RXB4S5H-BtcKAj9i.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-D_ch2aaI.js → chunk-5VM5RSS4-BF57lhXj.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-VvfacNrq.js → chunk-6Q2QTUOP-DJIlR25o.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-B-uGFIg2.js → chunk-GF5L2VYU-DklNc7dm.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BlysCtod.js → chunk-JWPE2WC7-fZNtEdQZ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BjAUAfcT.js → chunk-KBJHAD2P-BBgLqV4h.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BeZnBmb-.js → chunk-RYQCIY6F-Dl9e5n_J.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Bbfe3UJG.js → chunk-XXDRQBXY-B0JK51NT.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DVzM-02m.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DVzM-02m.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BKJQnYVM.js → cose-bilkent-JH36ORCC-Ch-ajv4O.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-B1wtI3hU.js → cynefin-VYW2F7L2-xn_NxcfB.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DCF6DBSu.js → cynefinDiagram-MW4NZA55-DRD0fyga.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJyNGRlP.js → dagre-VZM6K2ZE-COtnKp4B.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B7j1-VsZ.js → diagram-7IWD3JNH-BQp_CAqG.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BREJ140a.js → diagram-B4RE2ZJO-x0y-vNgq.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CDPHmHGH.js → diagram-LBJQPF4R-N2ezwL31.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BtZLrez1.js → diagram-Q27KOJAE-CSaxRH6Q.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-mzybu8oU.js → diagram-UB23O5K3-6Ro7Kpbd.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Dk3I2uO6.js → ebnfDiagram-BXEA7PRR-CrIIQEAI.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BT97u_tQ.js → erDiagram-JOGREHBK-DivKcq8g.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CMOtYzui.js → flowDiagram-UKHOOZJN-BXrfDo8y.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DiNydkuY.js → ganttDiagram-PKOTCBZU-LTTQmMRJ.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Cwt6fLkl.js → gitGraphDiagram-DS77QQ5N-DP3o_5qd.js} +1 -1
- package/dist/worker/console/static/assets/index-C2jmYBfu.js +404 -0
- package/dist/worker/console/static/assets/index-C8rOIAJr.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-AsGIGKKB.js → infoDiagram-6WML65LV-wVfSY1WH.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BL8ITZh3.js → ishikawaDiagram-WSZJBQD7-BRKfFL0I.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-VPKAUX8M.js → journeyDiagram-NVQOT4AX-DEml3jLb.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BL56hfGp.js → kanban-definition-27J2QSJJ-DTzBmOqN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BmSG3nIZ.js → linear-Cpy1d873.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DWGK9kwP.js → mermaid.core-C1cSavOy.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS--vvKLjo0.js → mindmap-definition-FAOFIHXS-BEBSKvYM.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-B41mxb2-.js → pegDiagram-VL7TDLO6-BrLs4Oac.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DTlu77sw.js → pieDiagram-7S7Q4E2Y-B47AZcLa.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Bk5A7alv.js → quadrantDiagram-CIZ2JOQS-s0dVeYR2.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Csf9jzQy.js → railroadDiagram-AXF67PYL-lW8aJ7Q6.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CeptoSNx.js → requirementDiagram-LRYGKXZP-BcHJPf6Q.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-A-DLCLer.js → sankeyDiagram-W5VNT64P-DdegpUUf.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-22VbPdOI.js → sequenceDiagram-SI44F4Z6-BxFWqNv8.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DWvAyBC9.js → sizeCapture-X5ZJPWSS-cOdUDPbR.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-qICZ75yT.js → stateDiagram-OKZ733FA-DpxlYl8P.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BwecGAkM.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-xi7lcMyp.js → swimlanes-SLNWSIFB-DQOfurE0.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D5WW_LbN.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Bu6Nl6O2.js → timeline-definition-Z64GVDOM-CIp3tC6V.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BzMz4Bn9.js → vennDiagram-T6HMQDX7-C-adIPKn.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CxaJnzc5.js → wardleyDiagram-T6FBY63Y-CiYrar9M.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-5JK-omQK.js → xychartDiagram-ELKLHX3M-WHrdTV0-.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +39 -0
- package/dist/worker/console/static-src/app/useOperatorActions.js +1 -1
- package/dist/worker/console/static-src/app/useRecoveryActions.js +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +82 -22
- package/dist/worker/console/static-src/operator-chat/mutation-gate.js +45 -0
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +328 -0
- package/dist/worker/console/static-src/operator-chat/resource-diagnostics.js +204 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +8 -1
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +42 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +18 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +216 -10
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +50 -22
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +26 -1
- package/dist/worker/observe/node-input.js +74 -3
- package/dist/worker/observe/node-process.js +377 -0
- package/dist/worker/observe/routes.js +36 -3
- package/dist/worker/observe/shell-handler-keys.js +34 -0
- package/dist/worker/observe/static/api.js +66 -0
- package/dist/worker/observe/static/constants.js +8 -1
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/format.js +23 -0
- package/dist/worker/observe/static/markdown-render.js +20 -1
- package/dist/worker/observe/static/operator-chrome.js +4 -0
- package/dist/worker/observe/static/state.js +13 -2
- package/dist/worker/observe/static/styles.css +73 -0
- package/dist/worker/observe/static/views/dag-inspector.js +612 -8
- package/dist/worker/observe/static/views/dag.js +8 -1
- package/dist/worker/observe/static/views/session-timeline.js +78 -9
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +827 -53
- package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
- package/dist/workflows/dag/backend-test-execution-contract.js +18 -9
- package/dist/workflows/dag/backend-test-gap-fill.js +205 -0
- package/dist/workflows/dag/backend-test-intake-context.js +32 -0
- package/dist/workflows/dag/backend-test-layout.js +133 -0
- package/dist/workflows/dag/backend-test-markdown-workflow.js +167 -32
- package/dist/workflows/dag/backend-test-module-stem.js +5 -0
- package/dist/workflows/dag/backend-test-pytest-collection.js +368 -33
- package/dist/workflows/dag/backend-test-result-contract.js +1 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +884 -140
- package/dist/workflows/dag/backend-test-scenario-partitions.js +321 -0
- package/dist/workflows/dag/backend-test-writer-completeness.js +100 -56
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/contract-validator-registrations.js +3 -1
- package/dist/workflows/dag/convergence/controller.js +141 -0
- package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
- package/dist/workflows/dag/dynamic-runtime/shared.js +1 -1
- package/dist/workflows/dag/failure-category.js +12 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +493 -2
- package/dist/workflows/dag/frontend-plan-render.js +90 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +221 -31
- package/dist/workflows/dag/frontend-test-case-quality.js +5 -13
- package/dist/workflows/dag/frontend-test-environment-probe.js +227 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +10 -18
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +68 -0
- package/dist/workflows/dag/init-hybrid.js +805 -113
- package/dist/workflows/dag/node-execution.js +194 -6
- package/dist/workflows/dag/prompt.js +60 -1
- package/dist/workflows/dag/rerun-feedback.js +212 -0
- package/dist/workflows/dag/rerun-plan.js +224 -27
- package/dist/workflows/dag/rerun-run.js +61 -6
- package/dist/workflows/dag/rerun-task.js +61 -2
- package/dist/workflows/dag/retry-policy.js +113 -0
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +157 -1
- package/dist/workflows/dag/validate.js +41 -1
- package/docs/init-surface.manifest.json +5 -0
- package/docs/operations/README.md +1 -1
- package/docs/operations/local-development-environment.md +1 -5
- package/docs/skills/vetted-skill-registry.md +14 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +44 -0
- package/docs/templates/backend-test-dag.json +60 -35
- package/docs/templates/frontend-implementation-contract.schema.json +9 -2
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/docs/templates/init-managed-agents.md +13 -3
- package/harness.json +3 -1
- package/package.json +12 -4
- package/scripts/next-info.mjs +356 -0
- package/scripts/next-publish-gate.mjs +238 -0
- package/scripts/release-source-binding.mjs +251 -0
- package/skills/analyze-product-requirements/SKILL.md +8 -5
- package/skills/analyze-product-requirements/references/acceptance-criteria.md +1 -1
- package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +10 -6
- package/skills/analyze-product-requirements/references/example.md +50 -0
- package/skills/analyze-product-requirements/references/forward-test-cases.md +11 -7
- package/skills/analyze-product-requirements/references/kb-integration.md +5 -5
- package/skills/analyze-product-requirements/references/product-analysis-schema.md +8 -4
- package/skills/analyze-product-requirements/references/product-requirement-schema.md +2 -2
- package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +1 -1
- package/skills/analyze-product-requirements/scripts/test-validators.mjs +11 -1
- package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +20 -1
- package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +9 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/frontend-design-review/references/review-checklist.md +2 -0
- package/skills/frontend-implementation/references/design-spec.md +16 -19
- package/skills/frontend-implementation/references/node-contracts.md +9 -6
- package/skills/improve-codebase-architecture/SKILL.md +81 -0
- package/skills/improve-codebase-architecture/deepening.md +37 -0
- package/skills/improve-codebase-architecture/html-report.md +123 -0
- package/skills/improve-codebase-architecture/interface-design.md +44 -0
- package/skills/improve-codebase-architecture/language.md +53 -0
- package/skills/loop-agent/references/command-reference.md +11 -4
- package/dist/worker/console/static/assets/channel-DLVz9TYW.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/index-DQxiso1w.js +0 -325
- package/dist/worker/console/static/assets/index-_j0Hzo69.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DzKvfHTX.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cxqr_qM1.js +0 -8
|
@@ -1,24 +1,78 @@
|
|
|
1
|
-
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
1
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { isLoopbackHost } from "./loopback.js";
|
|
3
|
+
/** Prefix for instance-scoped Cookie names; not a lookup name. */
|
|
3
4
|
export const BOOT_CAPABILITY_COOKIE = "loop_console_capability";
|
|
4
5
|
/** Custom mutation confirmation header (design §9). JS-readable; not the HttpOnly boot cookie. */
|
|
5
6
|
export const CONFIRMATION_TOKEN_HEADER = "x-loop-console-confirmation";
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
function normalizeInstanceScope(scope) {
|
|
8
|
+
const repoFingerprint = scope.repoFingerprint.trim();
|
|
9
|
+
if (!repoFingerprint) {
|
|
10
|
+
throw new Error("console instance scope requires a non-empty repoFingerprint");
|
|
11
|
+
}
|
|
12
|
+
const bindHost = scope.bindHost.trim();
|
|
13
|
+
if (!bindHost) {
|
|
14
|
+
throw new Error("console instance scope requires a non-empty bindHost");
|
|
15
|
+
}
|
|
16
|
+
if (!Number.isInteger(scope.configuredPort) || scope.configuredPort < 0) {
|
|
17
|
+
throw new Error(`console instance scope configuredPort must be an integer >= 0, got ${String(scope.configuredPort)}`);
|
|
18
|
+
}
|
|
19
|
+
const instanceNonce = scope.instanceNonce?.trim();
|
|
20
|
+
if (scope.configuredPort === 0) {
|
|
21
|
+
if (!instanceNonce) {
|
|
22
|
+
throw new Error("console instance scope requires a non-empty instanceNonce when configuredPort is 0");
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
repoFingerprint,
|
|
26
|
+
bindHost,
|
|
27
|
+
configuredPort: 0,
|
|
28
|
+
instanceNonce,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
repoFingerprint,
|
|
33
|
+
bindHost,
|
|
34
|
+
configuredPort: scope.configuredPort,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Deterministic Cookie name for one Console instance; never includes repo path or token. */
|
|
38
|
+
export function deriveBootCapabilityCookieName(scope, variant) {
|
|
39
|
+
const normalized = normalizeInstanceScope(scope);
|
|
40
|
+
const digest = createHash("sha256")
|
|
41
|
+
.update("loop-console-capability-v1\0", "utf8")
|
|
42
|
+
.update(normalized.repoFingerprint, "utf8")
|
|
43
|
+
.update("\0", "utf8")
|
|
44
|
+
.update(normalized.bindHost, "utf8")
|
|
45
|
+
.update("\0", "utf8")
|
|
46
|
+
.update(String(normalized.configuredPort), "utf8")
|
|
47
|
+
.update("\0", "utf8")
|
|
48
|
+
.update(normalized.instanceNonce ?? "", "utf8")
|
|
49
|
+
.update("\0", "utf8")
|
|
50
|
+
.update(variant ?? "", "utf8")
|
|
51
|
+
.digest("hex")
|
|
52
|
+
.slice(0, 32);
|
|
53
|
+
return `${BOOT_CAPABILITY_COOKIE}_${digest}`;
|
|
54
|
+
}
|
|
55
|
+
/** Issue per-process unguessable boot capability + confirmation tokens.
|
|
56
|
+
* `variant` (e.g. "inspect") derives a separate cookie name so scoped
|
|
57
|
+
* credentials cannot be replayed against the general mutation surface. */
|
|
58
|
+
export function issueBootCapabilityToken(scope, options = {}) {
|
|
59
|
+
const cookieName = deriveBootCapabilityCookieName(scope, options.variant);
|
|
8
60
|
const value = randomBytes(32).toString("base64url");
|
|
9
61
|
const confirmationToken = randomBytes(32).toString("base64url");
|
|
10
62
|
const setCookieHeader = [
|
|
11
|
-
`${
|
|
63
|
+
`${cookieName}=${value}`,
|
|
12
64
|
"HttpOnly",
|
|
13
65
|
"SameSite=Strict",
|
|
14
66
|
"Path=/",
|
|
15
67
|
].join("; ");
|
|
16
|
-
return { value, setCookieHeader, confirmationToken };
|
|
68
|
+
return { cookieName, value, setCookieHeader, confirmationToken };
|
|
17
69
|
}
|
|
18
|
-
/** Inject confirmation token into HTML so the SPA can send the mutation
|
|
19
|
-
|
|
70
|
+
/** Inject confirmation token into HTML so the SPA can send the mutation
|
|
71
|
+
* header. `varName` separates the general Console token from the scoped
|
|
72
|
+
* inspect token on the read-only /inspect surface. */
|
|
73
|
+
export function injectConfirmationTokenScript(html, confirmationToken, varName = "__CONSOLE_CONFIRMATION_TOKEN__") {
|
|
20
74
|
const source = typeof html === "string" ? html : html.toString("utf8");
|
|
21
|
-
const script = `<script>window
|
|
75
|
+
const script = `<script>window.${varName}=${JSON.stringify(confirmationToken)};</script>`;
|
|
22
76
|
if (source.includes("</head>")) {
|
|
23
77
|
return Buffer.from(source.replace("</head>", `${script}</head>`), "utf8");
|
|
24
78
|
}
|
|
@@ -54,8 +108,27 @@ function safeEqualToken(a, b) {
|
|
|
54
108
|
* cookie boot token AND custom confirmation header/token + Host/Origin checks +
|
|
55
109
|
* Sec-Fetch-Site not cross-site.
|
|
56
110
|
*/
|
|
111
|
+
/**
|
|
112
|
+
* Loopback origin equivalence: a Console bound to a loopback host accepts
|
|
113
|
+
* page Origins that resolve to the same loopback server — localhost,
|
|
114
|
+
* 127.0.0.1 and [::1] on the SAME port are interchangeable aliases (browsers
|
|
115
|
+
* treat them as distinct sites, so a third-party page can never spoof one).
|
|
116
|
+
* This keeps bookmarks / autocomplete on `localhost:port` working against a
|
|
117
|
+
* Console bound to `127.0.0.1:port` (and vice versa).
|
|
118
|
+
*/
|
|
119
|
+
function loopbackOriginMatches(origin, consoleOrigin) {
|
|
120
|
+
if (origin === consoleOrigin)
|
|
121
|
+
return true;
|
|
122
|
+
const parseLoopback = (value) => {
|
|
123
|
+
const match = /^http:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/i.exec(value);
|
|
124
|
+
return match ? `${match[1].toLowerCase()}${match[2] ?? ""}` : null;
|
|
125
|
+
};
|
|
126
|
+
const originKey = parseLoopback(origin);
|
|
127
|
+
const consoleKey = parseLoopback(consoleOrigin);
|
|
128
|
+
return originKey !== null && consoleKey !== null && originKey === consoleKey;
|
|
129
|
+
}
|
|
57
130
|
export function evaluateMutationGate(req, ctx) {
|
|
58
|
-
const cookieToken = parseCookieHeader(req.headers.cookie,
|
|
131
|
+
const cookieToken = parseCookieHeader(req.headers.cookie, ctx.cookieName);
|
|
59
132
|
if (!cookieToken) {
|
|
60
133
|
return {
|
|
61
134
|
status: 403,
|
|
@@ -127,7 +200,7 @@ export function evaluateMutationGate(req, ctx) {
|
|
|
127
200
|
}
|
|
128
201
|
else if (typeof origin !== "string" ||
|
|
129
202
|
origin.length === 0 ||
|
|
130
|
-
origin
|
|
203
|
+
!loopbackOriginMatches(origin, ctx.consoleOrigin)) {
|
|
131
204
|
return {
|
|
132
205
|
status: 403,
|
|
133
206
|
code: "origin-mismatch",
|
|
@@ -16,13 +16,14 @@ import { ChatSessionStore } from "./chat/session-store.js";
|
|
|
16
16
|
import { createChatEventStore, createChatOperationLinker, } from "./chat/chat-event-store.js";
|
|
17
17
|
import { createChatTurnExecutionRegistry } from "./chat/turn-execution-registry.js";
|
|
18
18
|
import { ConsolePiRuntime } from "./chat/pi-runtime.js";
|
|
19
|
-
import { handleChatRequest } from "./chat/routes.js";
|
|
19
|
+
import { handleChatRequest, recoverDeferredTurns, } from "./chat/routes.js";
|
|
20
20
|
import { createOperationEventStore, } from "./operation-sse.js";
|
|
21
21
|
import { OperationStore } from "./operation-store.js";
|
|
22
22
|
import { probePiReadiness, } from "./pi-readiness.js";
|
|
23
23
|
import { handleConsoleHealthRequest, handleConsoleOperatorRequest, sendJson, serveConsoleStatic, } from "./routes.js";
|
|
24
|
-
import { issueBootCapabilityToken } from "./security.js";
|
|
24
|
+
import { issueBootCapabilityToken, injectConfirmationTokenScript, } from "./security.js";
|
|
25
25
|
import { resolveSiblingLoopAgentBin } from "./sibling-controller.js";
|
|
26
|
+
import { isDagRerunPromptOverrideEnabled } from "../../shared/dag-prompt-override.js";
|
|
26
27
|
import { NightAuxTicker } from "./night-aux-ticker.js";
|
|
27
28
|
import { deriveObserveRouteCapabilities } from "../observe/health.js";
|
|
28
29
|
import { createObserveRouteContext, defaultObserveStaticDir, handleMatchedObserveRoute, matchObserveGetRoute, ROUTES, serveObserveStatic, } from "../observe/routes.js";
|
|
@@ -66,7 +67,7 @@ export async function createConsoleServer(options) {
|
|
|
66
67
|
process.stderr.write(`console: binding non-loopback host ${host} (Operator mutations enabled; no network auth — expose only on trusted networks)\n`);
|
|
67
68
|
}
|
|
68
69
|
const repoRoot = path.resolve(options.repoRoot);
|
|
69
|
-
const
|
|
70
|
+
const configuredPort = options.port ?? 8790;
|
|
70
71
|
const debug = options.debug === true;
|
|
71
72
|
const keepAliveTimeoutMs = options.keepAliveTimeoutMs ?? 65_000;
|
|
72
73
|
const staticDir = options.staticDir ?? defaultConsoleStaticDir();
|
|
@@ -74,12 +75,27 @@ export async function createConsoleServer(options) {
|
|
|
74
75
|
const observeRouteContext = createObserveRouteContext(repoRoot, {
|
|
75
76
|
staticDir: inspectStaticDir,
|
|
76
77
|
});
|
|
77
|
-
const bootToken = issueBootCapabilityToken();
|
|
78
78
|
const operatorSessionId = `sess_${randomBytes(16).toString("hex")}`;
|
|
79
79
|
const appData = openConsoleAppData({
|
|
80
80
|
repoRoot,
|
|
81
81
|
appDataRoot: options.appDataRoot,
|
|
82
82
|
});
|
|
83
|
+
const instanceNonce = configuredPort === 0 ? randomBytes(16).toString("hex") : undefined;
|
|
84
|
+
const bootToken = issueBootCapabilityToken({
|
|
85
|
+
repoFingerprint: appData.fingerprint,
|
|
86
|
+
bindHost: host,
|
|
87
|
+
configuredPort,
|
|
88
|
+
...(instanceNonce ? { instanceNonce } : {}),
|
|
89
|
+
});
|
|
90
|
+
// Scoped credentials for the experimental /inspect prompt-override rerun:
|
|
91
|
+
// separate cookie name + confirmation token so the read-only inspect page
|
|
92
|
+
// can never replay them against the general Console mutation surface.
|
|
93
|
+
const inspectBootToken = issueBootCapabilityToken({
|
|
94
|
+
repoFingerprint: appData.fingerprint,
|
|
95
|
+
bindHost: host,
|
|
96
|
+
configuredPort,
|
|
97
|
+
...(instanceNonce ? { instanceNonce } : {}),
|
|
98
|
+
}, { variant: "inspect" });
|
|
83
99
|
const operations = new OperationStore(appData);
|
|
84
100
|
const events = createOperationEventStore({
|
|
85
101
|
persistenceDir: path.join(appData.operations, "events"),
|
|
@@ -137,7 +153,7 @@ export async function createConsoleServer(options) {
|
|
|
137
153
|
getConsoleOrigin: () => `http://${boundHost}:${boundPort}`,
|
|
138
154
|
};
|
|
139
155
|
let boundHost = host;
|
|
140
|
-
let boundPort =
|
|
156
|
+
let boundPort = configuredPort;
|
|
141
157
|
const getConsoleOrigin = () => `http://${boundHost}:${boundPort}`;
|
|
142
158
|
// Phase 4: General Operator Chat runtime. The actionContext is forwarded so
|
|
143
159
|
// custom-tool execute() calls dispatch into the operator action layer (Gate 3).
|
|
@@ -175,6 +191,11 @@ export async function createConsoleServer(options) {
|
|
|
175
191
|
getConsoleOrigin,
|
|
176
192
|
allowNonLoopbackAccess: !loopbackBind,
|
|
177
193
|
};
|
|
194
|
+
// Durable single-slot follow-ups are server-owned. Recover them at boot even
|
|
195
|
+
// when no browser currently has the Session open.
|
|
196
|
+
void recoverDeferredTurns(chatRouteDeps).catch((error) => {
|
|
197
|
+
console.error(`[console] deferred Turn recovery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
198
|
+
});
|
|
178
199
|
const nightAuxTicker = new NightAuxTicker({
|
|
179
200
|
repoRoot,
|
|
180
201
|
client,
|
|
@@ -183,6 +204,7 @@ export async function createConsoleServer(options) {
|
|
|
183
204
|
repoRoot,
|
|
184
205
|
staticDir,
|
|
185
206
|
bootToken,
|
|
207
|
+
inspectBootToken,
|
|
186
208
|
getConsoleOrigin,
|
|
187
209
|
allowNonLoopbackAccess: !loopbackBind,
|
|
188
210
|
inspect: {
|
|
@@ -272,8 +294,22 @@ export async function createConsoleServer(options) {
|
|
|
272
294
|
}
|
|
273
295
|
}
|
|
274
296
|
if (pathname.startsWith("/inspect")) {
|
|
297
|
+
// Experimental prompt-override rerun: only while the internal switch
|
|
298
|
+
// is enabled do we hand the inspect page SCOPED mutation
|
|
299
|
+
// credentials (separate cookie + token, only strong enough for
|
|
300
|
+
// INSPECT_MUTATION_ALLOWED_ACTIONS — see routes.ts). Default stays
|
|
301
|
+
// strictly read-only: no token, no cookie, no tab.
|
|
302
|
+
const htmlEnhancer = isDagRerunPromptOverrideEnabled()
|
|
303
|
+
? (html) => ({
|
|
304
|
+
content: injectConfirmationTokenScript(html, routeContext.inspectBootToken?.confirmationToken ??
|
|
305
|
+
routeContext.bootToken.confirmationToken, "__INSPECT_MUTATION_TOKEN__"),
|
|
306
|
+
setCookie: routeContext.inspectBootToken?.setCookieHeader ??
|
|
307
|
+
routeContext.bootToken.setCookieHeader,
|
|
308
|
+
})
|
|
309
|
+
: undefined;
|
|
275
310
|
await serveObserveStatic(req, res, inspectStaticDir, {
|
|
276
311
|
urlPrefix: "/inspect",
|
|
312
|
+
...(htmlEnhancer ? { htmlEnhancer } : {}),
|
|
277
313
|
});
|
|
278
314
|
return;
|
|
279
315
|
}
|
|
@@ -284,7 +320,7 @@ export async function createConsoleServer(options) {
|
|
|
284
320
|
await serveConsoleStatic(req, res, routeContext);
|
|
285
321
|
}
|
|
286
322
|
server.on("error", reject);
|
|
287
|
-
server.listen(
|
|
323
|
+
server.listen(configuredPort, host, () => {
|
|
288
324
|
const addr = server.address();
|
|
289
325
|
if (!addr || typeof addr === "string") {
|
|
290
326
|
reject(new Error("Failed to get console server address"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-DJIlR25o.js";import{p as f}from"./chunk-JWPE2WC7-fZNtEdQZ.js";import{_ as n,l as o}from"./mermaid.core-C1cSavOy.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-xn_NxcfB.js";import"./index-C2jmYBfu.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-C1cSavOy.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|