@wrongstack/core 0.313.0 → 0.316.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chronicle/index.js +84 -6391
- package/dist/chronicle/legacy-journal-import.d.ts +0 -6
- package/dist/chronicle/metrics-ingest.d.ts +14 -0
- package/dist/chronicle/metrics-schema.d.ts +10 -1
- package/dist/chronicle/metrics-store.d.ts +20 -2
- package/dist/chronicle/project-server.js +98 -4874
- package/dist/chronicle/sink.d.ts +13 -0
- package/dist/chronicle/sqlite-journal.d.ts +20 -2
- package/dist/chunk-25LSLC3G.js +334 -0
- package/dist/chunk-27QIURLN.js +1073 -0
- package/dist/chunk-2FK4WTFF.js +207 -0
- package/dist/chunk-2YU4WVBW.js +134 -0
- package/dist/chunk-3AGWVSS7.js +4608 -0
- package/dist/chunk-3BDV7RL3.js +211 -0
- package/dist/chunk-3ECENVHL.js +325 -0
- package/dist/chunk-3XPVB7BA.js +135 -0
- package/dist/chunk-45WI72ZB.js +16884 -0
- package/dist/chunk-4BMVPOHO.js +3748 -0
- package/dist/chunk-4I7HGVVA.js +363 -0
- package/dist/chunk-4LCZVJVF.js +317 -0
- package/dist/chunk-4SJNS7OB.js +217 -0
- package/dist/chunk-4VWO3ZXL.js +342 -0
- package/dist/chunk-57GEWK5X.js +26 -0
- package/dist/chunk-5BMIE7QG.js +46 -0
- package/dist/chunk-5S437PRC.js +50 -0
- package/dist/chunk-5XDUGTKN.js +511 -0
- package/dist/chunk-5YPSXQXM.js +1443 -0
- package/dist/chunk-6FHWXLPT.js +10 -0
- package/dist/chunk-6H5GEOET.js +2406 -0
- package/dist/chunk-6NWEVFEL.js +151 -0
- package/dist/chunk-AYW5YINX.js +58 -0
- package/dist/chunk-B4AMLZPB.js +9 -0
- package/dist/chunk-B7F4WVP4.js +65 -0
- package/dist/chunk-BJHVULHO.js +55 -0
- package/dist/chunk-BPBKKBUK.js +2085 -0
- package/dist/chunk-BYD345OX.js +589 -0
- package/dist/chunk-C27KDLOX.js +279 -0
- package/dist/chunk-CU546ESW.js +597 -0
- package/dist/chunk-DLHHXUAM.js +172 -0
- package/dist/chunk-DOTHQSJ2.js +429 -0
- package/dist/chunk-DYLPMV4Q.js +711 -0
- package/dist/chunk-EODDVJBM.js +82 -0
- package/dist/chunk-F3JWNST7.js +361 -0
- package/dist/chunk-FC2ZGRF3.js +140 -0
- package/dist/chunk-FCBTO76Z.js +5786 -0
- package/dist/chunk-FHZVFYSL.js +396 -0
- package/dist/chunk-FNXVT7HF.js +52 -0
- package/dist/chunk-FWNLEZYG.js +259 -0
- package/dist/chunk-FXQLIX3K.js +211 -0
- package/dist/chunk-G5S3S5ZN.js +38 -0
- package/dist/chunk-GDQ7CZRQ.js +116 -0
- package/dist/chunk-GJJGJB2R.js +1374 -0
- package/dist/chunk-GTCU6DZ3.js +1 -0
- package/dist/chunk-HA4ZYA6T.js +178 -0
- package/dist/chunk-HI3JGZR2.js +188 -0
- package/dist/chunk-HMLIGAU7.js +395 -0
- package/dist/chunk-HXKZ7OBQ.js +303 -0
- package/dist/chunk-I7DALG7J.js +292 -0
- package/dist/chunk-IRUTEHCE.js +960 -0
- package/dist/chunk-IYFBFX34.js +86 -0
- package/dist/chunk-J2WRWR37.js +1104 -0
- package/dist/chunk-JFPJ6LLQ.js +129 -0
- package/dist/chunk-JMULFFLN.js +9 -0
- package/dist/chunk-JO4MGB6Z.js +1264 -0
- package/dist/chunk-JVKB2TBL.js +48 -0
- package/dist/chunk-JX7VBZDK.js +31 -0
- package/dist/chunk-K6BXGITA.js +931 -0
- package/dist/chunk-KDQJCT2J.js +45 -0
- package/dist/chunk-KJ2ZTQSL.js +47 -0
- package/dist/chunk-KZMSZV32.js +187 -0
- package/dist/chunk-LA7CLDRW.js +129 -0
- package/dist/chunk-LHOA5DWA.js +28 -0
- package/dist/chunk-LSMMOS2Z.js +119 -0
- package/dist/chunk-LX5QWLBL.js +27 -0
- package/dist/chunk-LXWCMQNJ.js +789 -0
- package/dist/chunk-M27LIEKV.js +2829 -0
- package/dist/chunk-MJPHJRAL.js +663 -0
- package/dist/chunk-MTL4O5YR.js +228 -0
- package/dist/chunk-NDBIPFNY.js +102 -0
- package/dist/chunk-NEMIWEXC.js +1199 -0
- package/dist/chunk-NHJ75HXY.js +1 -0
- package/dist/chunk-NIOAGFPB.js +1510 -0
- package/dist/chunk-NS52ISWS.js +355 -0
- package/dist/chunk-NSOFPKGT.js +5352 -0
- package/dist/chunk-NVIZG63R.js +757 -0
- package/dist/chunk-O37BQ65S.js +21 -0
- package/dist/chunk-OOYZPOXM.js +308 -0
- package/dist/chunk-OSGLYW5J.js +28 -0
- package/dist/chunk-PFCMSSUF.js +1640 -0
- package/dist/chunk-PFZO3C6H.js +14 -0
- package/dist/chunk-PGRVXIMY.js +158 -0
- package/dist/chunk-PHH7LD45.js +113 -0
- package/dist/chunk-PISBFBJN.js +109 -0
- package/dist/chunk-POOOIWE5.js +9 -0
- package/dist/chunk-PQNS3U7Z.js +1240 -0
- package/dist/chunk-QSTSJOCK.js +402 -0
- package/dist/chunk-RFQMOKWK.js +282 -0
- package/dist/chunk-RJIZEJ42.js +30 -0
- package/dist/chunk-RTOTNK3P.js +484 -0
- package/dist/chunk-RXKSDUAU.js +1172 -0
- package/dist/chunk-S45JPKQN.js +3317 -0
- package/dist/chunk-SAFHACFA.js +152 -0
- package/dist/chunk-SQJVFEBV.js +41 -0
- package/dist/chunk-SVT4RNTR.js +49 -0
- package/dist/chunk-SWUFN7XM.js +43 -0
- package/dist/chunk-SXMVYC5H.js +174 -0
- package/dist/chunk-SZ6AYUIZ.js +23 -0
- package/dist/chunk-TBRL2RCC.js +9 -0
- package/dist/chunk-TCCHINEF.js +655 -0
- package/dist/chunk-THEGTRAG.js +316 -0
- package/dist/chunk-TR4LQE7L.js +2256 -0
- package/dist/chunk-TRT2HRWZ.js +18 -0
- package/dist/chunk-TWJMGXCI.js +900 -0
- package/dist/chunk-U45AXT5D.js +1023 -0
- package/dist/chunk-U4FWBSO3.js +509 -0
- package/dist/chunk-UBGDX6FI.js +147 -0
- package/dist/chunk-UJILKYES.js +75 -0
- package/dist/chunk-ULMAQV3T.js +234 -0
- package/dist/chunk-VVBP6KGT.js +9 -0
- package/dist/chunk-W5VITDM2.js +168 -0
- package/dist/chunk-WAHQVNWT.js +194 -0
- package/dist/chunk-WBPVKEEE.js +227 -0
- package/dist/chunk-WGGYRBXH.js +5434 -0
- package/dist/chunk-WLYKU45P.js +5770 -0
- package/dist/chunk-WP7BVANJ.js +53 -0
- package/dist/chunk-WQQON3SV.js +473 -0
- package/dist/chunk-WQTOVMGV.js +119 -0
- package/dist/chunk-XBDP4QPW.js +7 -0
- package/dist/chunk-XEBHSJLT.js +103 -0
- package/dist/chunk-XF4VUMKW.js +231 -0
- package/dist/chunk-XQ2ECNK3.js +1 -0
- package/dist/chunk-Y5YXDM7D.js +74 -0
- package/dist/chunk-YOPAUVU4.js +2588 -0
- package/dist/chunk-YPT4A46F.js +362 -0
- package/dist/chunk-YWXT3JNM.js +425 -0
- package/dist/chunk-YY6APYUM.js +49 -0
- package/dist/chunk-Z2IJUO45.js +691 -0
- package/dist/chunk-ZHZ2Y2DH.js +1643 -0
- package/dist/chunk-ZT7JNIGX.js +152 -0
- package/dist/coordination/agent-monitor.d.ts +9 -1
- package/dist/coordination/agent-subagent-runner.d.ts +1 -1
- package/dist/coordination/agents/agent-prompts.d.ts +8 -0
- package/dist/coordination/agents/index.d.ts +33 -1
- package/dist/coordination/agents/index.js +184 -6269
- package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
- package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
- package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
- package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
- package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
- package/dist/coordination/agents/types.d.ts +13 -2
- package/dist/coordination/brain-monitor.d.ts +30 -7
- package/dist/coordination/collab-debug.d.ts +1 -1
- package/dist/coordination/collab-pause.d.ts +1 -1
- package/dist/coordination/delegate-tool.d.ts +7 -5
- package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
- package/dist/coordination/director-options.d.ts +7 -0
- package/dist/coordination/director-spawn-model.d.ts +17 -0
- package/dist/coordination/director-tools.d.ts +2 -2
- package/dist/coordination/director.d.ts +12 -0
- package/dist/coordination/dispatcher.d.ts +8 -0
- package/dist/coordination/fleet-bus.d.ts +35 -4
- package/dist/coordination/fleet-supervisor.d.ts +10 -2
- package/dist/coordination/fleet.d.ts +16 -7
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +402 -34324
- package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
- package/dist/coordination/mailbox-http-router.d.ts +4 -3
- package/dist/coordination/mailbox-http-validation.d.ts +1 -1
- package/dist/coordination/mailbox-project-server.js +48 -3276
- package/dist/coordination/mailbox-types.d.ts +24 -6
- package/dist/coordination/model-tier-leader.d.ts +122 -0
- package/dist/coordination/model-tier.d.ts +122 -0
- package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
- package/dist/coordination/origin-session.d.ts +16 -0
- package/dist/coordination/provider-status-tracker.d.ts +41 -5
- package/dist/coordination/session-note-hub.d.ts +44 -0
- package/dist/coordination/session-note-tool.d.ts +10 -0
- package/dist/core/agent.d.ts +15 -2
- package/dist/core/context.d.ts +22 -3
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +239 -12360
- package/dist/core/model-ref.js +5 -23
- package/dist/core/provider-runner.d.ts +36 -1
- package/dist/core/request-conversation-binding.d.ts +37 -0
- package/dist/core/session-notes.d.ts +25 -0
- package/dist/core/system-prompt-builder.d.ts +11 -2
- package/dist/core/system-prompt-variants.d.ts +78 -0
- package/dist/design/index.js +50 -1087
- package/dist/execution/auto-compaction-middleware.d.ts +11 -0
- package/dist/execution/autonomy-brain.d.ts +2 -1
- package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
- package/dist/execution/compaction-core.d.ts +4 -4
- package/dist/execution/eternal-autonomy.d.ts +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.js +1615 -21895
- package/dist/execution/model-runtime.d.ts +0 -7
- package/dist/execution/parallel-eternal-engine.d.ts +7 -7
- package/dist/execution/prompt-enhancer.js +16 -535
- package/dist/execution/retry-policy.d.ts +31 -1
- package/dist/extension/index.js +7 -311
- package/dist/goal/index.js +33 -3435
- package/dist/hooks/index.js +14 -1138
- package/dist/hq/index.js +114 -5139
- package/dist/hq/persistence/event-log.d.ts +0 -1
- package/dist/hq/persistence.d.ts +4 -4
- package/dist/hq/protocol.js +21 -668
- package/dist/hq/publisher.d.ts +2 -0
- package/dist/index.d.ts +14 -11
- package/dist/index.js +1502 -92655
- package/dist/infrastructure/index.d.ts +4 -4
- package/dist/infrastructure/index.js +504 -5230
- package/dist/infrastructure/token-counter.d.ts +9 -0
- package/dist/kernel/events/agent-events.d.ts +77 -3
- package/dist/kernel/events/brain-events.d.ts +12 -0
- package/dist/kernel/events/provider-events.d.ts +22 -1
- package/dist/kernel/events/session-events.d.ts +14 -0
- package/dist/kernel/events/tool-events.d.ts +13 -0
- package/dist/kernel/index.js +14 -992
- package/dist/mailbox-attach.d.ts +1 -1
- package/dist/models/index.js +41 -1117
- package/dist/notifications/index.js +3 -108
- package/dist/observability/event-bridge.d.ts +25 -5
- package/dist/observability/index.d.ts +9 -8
- package/dist/observability/index.js +477 -631
- package/dist/observability/tool-usage-source.d.ts +65 -0
- package/dist/plugin/index.d.ts +5 -0
- package/dist/plugin/index.js +600 -14835
- package/dist/plugins/auto-review-plugin.d.ts +3 -2
- package/dist/plugins/review-finding-commands.d.ts +0 -8
- package/dist/plugins/review-finding-store.js +22 -0
- package/dist/plugins/review-finding-types.js +19 -0
- package/dist/plugins/review-report-integration.js +21 -0
- package/dist/plugins/review-report-store.js +20 -0
- package/dist/plugins/review-report-types.js +13 -0
- package/dist/prompts/index.js +14 -948
- package/dist/registry/index.js +9 -822
- package/dist/registry/tool-registry.d.ts +59 -9
- package/dist/registry-7N4O3E7W.js +14 -0
- package/dist/replay/index.js +6 -84
- package/dist/security/capabilities.d.ts +6 -0
- package/dist/security/file-permissions.d.ts +1 -1
- package/dist/security/index.js +161 -2235
- package/dist/security/permission-policy.d.ts +12 -1
- package/dist/security/secret-scrubber.d.ts +15 -0
- package/dist/session-catalog/index.d.ts +1 -0
- package/dist/session-catalog/index.js +41 -2103
- package/dist/session-catalog/project-server.js +59 -1435
- package/dist/session-catalog/protocol.d.ts +32 -1
- package/dist/session-catalog/registry.d.ts +17 -1
- package/dist/session-catalog/session-agents.d.ts +56 -0
- package/dist/session-catalog/store-rebuild.d.ts +14 -0
- package/dist/session-catalog/store-schema.d.ts +26 -0
- package/dist/session-catalog/store.d.ts +27 -1
- package/dist/session-note-attach.d.ts +9 -0
- package/dist/skills/index.js +35 -1578
- package/dist/statusline/index.d.ts +43 -0
- package/dist/statusline/index.js +102 -0
- package/dist/storage/board-store-port.d.ts +2 -2
- package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
- package/dist/storage/config-loader.d.ts +3 -2
- package/dist/storage/file-session-writer.d.ts +4 -2
- package/dist/storage/goal-coordination.d.ts +6 -1
- package/dist/storage/goal-kanban.d.ts +4 -1
- package/dist/storage/index.d.ts +12 -4
- package/dist/storage/index.js +198 -15601
- package/dist/storage/input-history-store.d.ts +2 -4
- package/dist/storage/memory-curator.d.ts +133 -0
- package/dist/storage/session-agent-attribution.d.ts +39 -0
- package/dist/storage/session-doctor.d.ts +109 -0
- package/dist/storage/session-event-bridge.d.ts +5 -7
- package/dist/storage/session-outcome.d.ts +42 -0
- package/dist/storage/session-recovery.d.ts +55 -0
- package/dist/storage/session-store/load-session-data.d.ts +11 -0
- package/dist/storage/session-store/prune-helpers.d.ts +1 -1
- package/dist/storage/session-store/resume-session.d.ts +0 -2
- package/dist/storage/session-store/types.d.ts +8 -0
- package/dist/storage/session-store.d.ts +3 -3
- package/dist/storage/session-summary-tracker.d.ts +8 -1
- package/dist/storage/session-write-buffer.d.ts +18 -0
- package/dist/storage/session-writer-truncate.d.ts +2 -0
- package/dist/tasking/index.js +10 -676
- package/dist/tools/fallback-manage-tools.d.ts +6 -4
- package/dist/tools/index.js +52 -9590
- package/dist/tools/model-tier-set-tool.d.ts +66 -0
- package/dist/types/agent-bridge.d.ts +2 -1
- package/dist/types/config/autonomy.d.ts +5 -0
- package/dist/types/config/mcp-features.d.ts +7 -0
- package/dist/types/config/model-tiers.d.ts +148 -0
- package/dist/types/config/root.d.ts +9 -0
- package/dist/types/config/tools.d.ts +73 -0
- package/dist/types/config/ui.d.ts +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/context.d.ts +2 -0
- package/dist/types/default-config.d.ts +6 -0
- package/dist/types/errors.d.ts +20 -1
- package/dist/types/index.d.ts +11 -9
- package/dist/types/index.js +131 -1342
- package/dist/types/multi-agent.d.ts +43 -0
- package/dist/types/plugin.d.ts +1 -1
- package/dist/types/provider-runner.d.ts +8 -0
- package/dist/types/provider.d.ts +15 -0
- package/dist/types/runtime-capability-manifest.d.ts +1 -1
- package/dist/types/secret-scrubber.d.ts +15 -0
- package/dist/types/session-markers.d.ts +37 -10
- package/dist/types/session-markers.js +8 -144
- package/dist/types/session-timeline.d.ts +197 -0
- package/dist/types/session-timeline.js +12 -0
- package/dist/types/session.d.ts +172 -11
- package/dist/types/system-prompt.d.ts +27 -0
- package/dist/utils/config-backup.d.ts +9 -1
- package/dist/utils/error.js +3 -4
- package/dist/utils/expect-defined.js +3 -9
- package/dist/utils/heap-watchdog.js +6 -706
- package/dist/utils/index.js +271 -5685
- package/dist/utils/message-invariants.d.ts +4 -1
- package/dist/utils/regex-guard.d.ts +1 -1
- package/dist/utils/sage-output-block.js +5 -42
- package/dist/utils/socket-path.d.ts +1 -1
- package/dist/utils/token-estimate.d.ts +6 -2
- package/dist/utils/wstack-paths.d.ts +2 -0
- package/dist/wiring/proxy-rewrite.d.ts +46 -0
- package/dist/wiring/proxy-rewrite.js +24 -121
- package/dist/worktree/index.js +6 -887
- package/instructions/agents/explore-companion.md +45 -18
- package/instructions/agents/memory-curator.md +34 -22
- package/instructions/coordination/director-preamble.md +12 -7
- package/instructions/coordination/subagent-baseline.md +26 -5
- package/instructions/leader-after-task.md +4 -1
- package/instructions/llm/chimera-review.md +30 -9
- package/instructions/llm/memory-curator.md +31 -0
- package/instructions/sections/tool/delegation-compact.md +2 -0
- package/instructions/sections/tool/delegation-full.md +5 -1
- package/instructions/sections/tool/mailbox-compact.md +5 -1
- package/instructions/sections/tool/mailbox-full.md +3 -0
- package/instructions/sections/tool/session-note-compact.md +3 -0
- package/instructions/sections/tool/session-note-full.md +15 -0
- package/instructions/system-lite.md +9 -4
- package/instructions/system-pro.md +66 -143
- package/instructions/system.md +73 -175
- package/package.json +32 -4
- package/dist/coordination/agents.d.ts +0 -8
- package/dist/coordination/transport.d.ts +0 -2
- package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHRONICLE_MAX_APPEND_BATCH
|
|
3
|
+
} from "./chunk-4BMVPOHO.js";
|
|
4
|
+
import {
|
|
5
|
+
mapWithConcurrency
|
|
6
|
+
} from "./chunk-SZ6AYUIZ.js";
|
|
7
|
+
import {
|
|
8
|
+
DEFAULT_WALK_IGNORE_DIRS,
|
|
9
|
+
watchProjectTree
|
|
10
|
+
} from "./chunk-J2WRWR37.js";
|
|
11
|
+
|
|
12
|
+
// src/chronicle/context.ts
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
function createChronicleContext(scope, traceId = randomUUID()) {
|
|
15
|
+
return {
|
|
16
|
+
scope: { ...scope },
|
|
17
|
+
correlation: { traceId, spanId: randomUUID() }
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function childChronicleContext(parent, overrides = {}) {
|
|
21
|
+
return {
|
|
22
|
+
scope: { ...parent.scope, ...overrides.scope },
|
|
23
|
+
correlation: {
|
|
24
|
+
...parent.correlation,
|
|
25
|
+
...overrides.correlation,
|
|
26
|
+
traceId: parent.correlation.traceId,
|
|
27
|
+
parentSpanId: parent.correlation.spanId,
|
|
28
|
+
spanId: overrides.correlation?.spanId ?? randomUUID()
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/chronicle/file-observer.ts
|
|
34
|
+
import { createHash } from "node:crypto";
|
|
35
|
+
import * as fsp from "node:fs/promises";
|
|
36
|
+
import * as path from "node:path";
|
|
37
|
+
var DEFAULT_EXCLUDED = [
|
|
38
|
+
...DEFAULT_WALK_IGNORE_DIRS,
|
|
39
|
+
".wrongstack",
|
|
40
|
+
".claude",
|
|
41
|
+
".temp_files"
|
|
42
|
+
];
|
|
43
|
+
var SCAN_HASH_CONCURRENCY = 32;
|
|
44
|
+
var DEFAULT_FULL_RESCAN_MIN_INTERVAL_MS = 3e4;
|
|
45
|
+
var MAX_RECENT_TOOL_MUTATIONS = 500;
|
|
46
|
+
var JOURNAL_FLUSH_CHUNK = CHRONICLE_MAX_APPEND_BATCH;
|
|
47
|
+
async function startChronicleFileObserver(options) {
|
|
48
|
+
const root = path.resolve(options.projectRoot);
|
|
49
|
+
const excluded = new Set(options.excludedDirectories ?? DEFAULT_EXCLUDED);
|
|
50
|
+
const excludedPaths = normalizeExcludedPaths(root, options.excludedPaths ?? []);
|
|
51
|
+
const debounceMs = options.debounceMs ?? 120;
|
|
52
|
+
const maxHashBytes = options.maxHashBytes ?? 8 * 1024 * 1024;
|
|
53
|
+
const known = (await scanProject(root, excluded, excludedPaths, maxHashBytes, options.onError)).files;
|
|
54
|
+
const recentToolMutations = /* @__PURE__ */ new Map();
|
|
55
|
+
const noteToolMutation = (hint) => {
|
|
56
|
+
const absolute = path.isAbsolute(hint.path) ? path.normalize(hint.path) : path.resolve(root, hint.path);
|
|
57
|
+
const relative2 = normalizeRelative(path.relative(root, absolute));
|
|
58
|
+
if (relative2.startsWith("../") || isExcluded(relative2, excluded, excludedPaths)) return;
|
|
59
|
+
recentToolMutations.set(relative2, {
|
|
60
|
+
at: hint.at ?? Date.now(),
|
|
61
|
+
toolUseId: hint.toolUseId,
|
|
62
|
+
toolName: hint.toolName,
|
|
63
|
+
agentId: hint.agentId,
|
|
64
|
+
sessionId: hint.sessionId
|
|
65
|
+
});
|
|
66
|
+
if (recentToolMutations.size > MAX_RECENT_TOOL_MUTATIONS) {
|
|
67
|
+
const overflow = recentToolMutations.size - MAX_RECENT_TOOL_MUTATIONS;
|
|
68
|
+
const keys = [...recentToolMutations.keys()];
|
|
69
|
+
for (let i = 0; i < overflow && i < keys.length; i++) {
|
|
70
|
+
recentToolMutations.delete(keys[i]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const offToolProgress = options.events?.on("tool.progress", (event) => {
|
|
75
|
+
if (event.event.type !== "file_changed" || !event.event.path) return;
|
|
76
|
+
noteToolMutation({
|
|
77
|
+
path: event.event.path,
|
|
78
|
+
toolUseId: event.id,
|
|
79
|
+
toolName: event.name,
|
|
80
|
+
agentId: event.agentId,
|
|
81
|
+
sessionId: event.sessionId
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
const pending = /* @__PURE__ */ new Set();
|
|
85
|
+
let timer;
|
|
86
|
+
let closed = false;
|
|
87
|
+
let flushTail = null;
|
|
88
|
+
let drainFailure;
|
|
89
|
+
const minFullRescanIntervalMs = options.minFullRescanIntervalMs ?? DEFAULT_FULL_RESCAN_MIN_INTERVAL_MS;
|
|
90
|
+
let lastFullScanAt = Date.now();
|
|
91
|
+
let fullRescanTimer;
|
|
92
|
+
const bumpDebounce = () => {
|
|
93
|
+
if (timer) clearTimeout(timer);
|
|
94
|
+
timer = setTimeout(() => {
|
|
95
|
+
timer = void 0;
|
|
96
|
+
drainPending();
|
|
97
|
+
}, debounceMs);
|
|
98
|
+
};
|
|
99
|
+
const requestFullRescan = () => {
|
|
100
|
+
if (closed) return;
|
|
101
|
+
const since = Date.now() - lastFullScanAt;
|
|
102
|
+
if (since >= minFullRescanIntervalMs) {
|
|
103
|
+
pending.add("*");
|
|
104
|
+
bumpDebounce();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (fullRescanTimer) return;
|
|
108
|
+
fullRescanTimer = setTimeout(() => {
|
|
109
|
+
fullRescanTimer = void 0;
|
|
110
|
+
if (closed) return;
|
|
111
|
+
pending.add("*");
|
|
112
|
+
bumpDebounce();
|
|
113
|
+
}, minFullRescanIntervalMs - since);
|
|
114
|
+
if (typeof fullRescanTimer.unref === "function") fullRescanTimer.unref();
|
|
115
|
+
};
|
|
116
|
+
const schedule = (filename) => {
|
|
117
|
+
if (closed) return;
|
|
118
|
+
if (filename === null) {
|
|
119
|
+
requestFullRescan();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const relative2 = normalizeRelative(String(filename));
|
|
123
|
+
if (!relative2 || isExcluded(relative2, excluded, excludedPaths)) return;
|
|
124
|
+
pending.add(relative2);
|
|
125
|
+
bumpDebounce();
|
|
126
|
+
};
|
|
127
|
+
const reconcile = async (changedPaths) => {
|
|
128
|
+
const wantsFullScan = changedPaths.includes("*");
|
|
129
|
+
if (wantsFullScan) lastFullScanAt = Date.now();
|
|
130
|
+
const fullScan = wantsFullScan ? await scanProject(root, excluded, excludedPaths, maxHashBytes, options.onError, known) : void 0;
|
|
131
|
+
const candidates = (fullScan ? unionKeys(known, fullScan.files) : changedPaths).filter(
|
|
132
|
+
(relative2) => !isExcluded(relative2, excluded, excludedPaths)
|
|
133
|
+
);
|
|
134
|
+
const changes = [];
|
|
135
|
+
for (const relative2 of candidates) {
|
|
136
|
+
const before = known.get(relative2);
|
|
137
|
+
const cached = fullScan?.files.get(relative2);
|
|
138
|
+
const after = cached ?? (fullScan?.complete ? void 0 : await fingerprint(path.join(root, relative2), maxHashBytes));
|
|
139
|
+
if (sameFingerprint(before, after)) continue;
|
|
140
|
+
changes.push({ relative: relative2, before, after });
|
|
141
|
+
}
|
|
142
|
+
const deleted = changes.filter((change) => change.before && !change.after);
|
|
143
|
+
const created = changes.filter((change) => !change.before && change.after);
|
|
144
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
145
|
+
const pendingEvents = [];
|
|
146
|
+
const pushPending = (eventType, relativePath, state, attributes, stateWrites) => {
|
|
147
|
+
const attribution = peekAttribution(relativePath, recentToolMutations);
|
|
148
|
+
const { input, emitActivity } = buildMutation(
|
|
149
|
+
options,
|
|
150
|
+
eventType,
|
|
151
|
+
relativePath,
|
|
152
|
+
state,
|
|
153
|
+
attributes,
|
|
154
|
+
attribution
|
|
155
|
+
);
|
|
156
|
+
pendingEvents.push({
|
|
157
|
+
input,
|
|
158
|
+
state: stateWrites,
|
|
159
|
+
emitActivity,
|
|
160
|
+
attribution,
|
|
161
|
+
attributionKey: attribution ? relativePath : void 0
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const createdByHash = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const to of created) {
|
|
166
|
+
const hash = to.after?.hash;
|
|
167
|
+
if (hash === void 0) continue;
|
|
168
|
+
const bucket = createdByHash.get(hash);
|
|
169
|
+
if (bucket) bucket.entries.push(to);
|
|
170
|
+
else createdByHash.set(hash, { entries: [to], cursor: 0 });
|
|
171
|
+
}
|
|
172
|
+
const claimCreated = (hash) => {
|
|
173
|
+
const bucket = createdByHash.get(hash);
|
|
174
|
+
if (!bucket) return void 0;
|
|
175
|
+
return bucket.cursor < bucket.entries.length ? bucket.entries[bucket.cursor++] : void 0;
|
|
176
|
+
};
|
|
177
|
+
for (const from of deleted) {
|
|
178
|
+
const fromHash = from.before?.hash;
|
|
179
|
+
if (fromHash === void 0) continue;
|
|
180
|
+
const match = claimCreated(fromHash);
|
|
181
|
+
if (!match) continue;
|
|
182
|
+
consumed.add(from.relative);
|
|
183
|
+
consumed.add(match.relative);
|
|
184
|
+
pushPending(
|
|
185
|
+
"file.external.renamed",
|
|
186
|
+
match.relative,
|
|
187
|
+
match.after,
|
|
188
|
+
{
|
|
189
|
+
operation: "rename",
|
|
190
|
+
previousPath: from.relative,
|
|
191
|
+
previousResourceId: resourceId(from.relative),
|
|
192
|
+
actor: "external"
|
|
193
|
+
},
|
|
194
|
+
[
|
|
195
|
+
[from.relative, void 0],
|
|
196
|
+
[match.relative, match.after]
|
|
197
|
+
]
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
for (const change of changes) {
|
|
201
|
+
if (consumed.has(change.relative)) continue;
|
|
202
|
+
if (!change.after) {
|
|
203
|
+
pushPending(
|
|
204
|
+
"file.external.deleted",
|
|
205
|
+
change.relative,
|
|
206
|
+
change.before,
|
|
207
|
+
{
|
|
208
|
+
operation: "delete",
|
|
209
|
+
actor: "external",
|
|
210
|
+
previousHash: change.before?.hash,
|
|
211
|
+
previousSize: change.before?.size
|
|
212
|
+
},
|
|
213
|
+
[[change.relative, void 0]]
|
|
214
|
+
);
|
|
215
|
+
} else if (!change.before) {
|
|
216
|
+
pushPending(
|
|
217
|
+
"file.external.created",
|
|
218
|
+
change.relative,
|
|
219
|
+
change.after,
|
|
220
|
+
{
|
|
221
|
+
operation: "write",
|
|
222
|
+
actor: "external"
|
|
223
|
+
},
|
|
224
|
+
[[change.relative, change.after]]
|
|
225
|
+
);
|
|
226
|
+
} else {
|
|
227
|
+
pushPending(
|
|
228
|
+
"file.external.modified",
|
|
229
|
+
change.relative,
|
|
230
|
+
change.after,
|
|
231
|
+
{
|
|
232
|
+
operation: "edit",
|
|
233
|
+
actor: "external",
|
|
234
|
+
previousHash: change.before.hash,
|
|
235
|
+
previousSize: change.before.size
|
|
236
|
+
},
|
|
237
|
+
[[change.relative, change.after]]
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
await flushJournalInputs(options, pendingEvents, (committed) => {
|
|
243
|
+
for (const event of committed) {
|
|
244
|
+
for (const [relative2, after] of event.state) {
|
|
245
|
+
if (after) known.set(relative2, after);
|
|
246
|
+
else known.delete(relative2);
|
|
247
|
+
}
|
|
248
|
+
if (event.attributionKey && recentToolMutations.get(event.attributionKey) === event.attribution) {
|
|
249
|
+
recentToolMutations.delete(event.attributionKey);
|
|
250
|
+
}
|
|
251
|
+
event.emitActivity?.();
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
} catch (error) {
|
|
255
|
+
for (const event of pendingEvents) {
|
|
256
|
+
if (!event.attribution || !event.attributionKey) continue;
|
|
257
|
+
const held = recentToolMutations.get(event.attributionKey);
|
|
258
|
+
if (held !== event.attribution) continue;
|
|
259
|
+
recentToolMutations.set(event.attributionKey, { ...event.attribution, at: Date.now() });
|
|
260
|
+
}
|
|
261
|
+
requestFullRescan();
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const drainPending = () => {
|
|
266
|
+
if (flushTail) return flushTail;
|
|
267
|
+
const drain = (async () => {
|
|
268
|
+
while (pending.size > 0) {
|
|
269
|
+
const paths = [...pending];
|
|
270
|
+
pending.clear();
|
|
271
|
+
try {
|
|
272
|
+
await reconcile(paths);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
drainFailure = error;
|
|
275
|
+
options.onError?.(error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
})().finally(() => {
|
|
279
|
+
if (flushTail === drain) flushTail = null;
|
|
280
|
+
if (!closed && pending.size > 0) drainPending();
|
|
281
|
+
});
|
|
282
|
+
flushTail = drain;
|
|
283
|
+
return drain;
|
|
284
|
+
};
|
|
285
|
+
let watcher;
|
|
286
|
+
try {
|
|
287
|
+
watcher = watchProjectTree(root, (event) => schedule(event.filename), {
|
|
288
|
+
onError: (error) => options.onError?.(error)
|
|
289
|
+
});
|
|
290
|
+
} catch (error) {
|
|
291
|
+
options.onError?.(error);
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
get watchedFiles() {
|
|
296
|
+
return known.size;
|
|
297
|
+
},
|
|
298
|
+
noteToolMutation,
|
|
299
|
+
/**
|
|
300
|
+
* Shut down the observer. If the final drain (an in-flight drain plus
|
|
301
|
+
* anything still pending at close time) fails, close() REJECTS with
|
|
302
|
+
* that error — a failed shutdown flush is surfaced, not silently
|
|
303
|
+
* dropped. The failure is still not retried after close returns:
|
|
304
|
+
* `requestFullRescan()` no-ops once `closed` is set, and `known` is
|
|
305
|
+
* in-memory state that dies here, so uncommitted changes are not
|
|
306
|
+
* re-derived by a future boot (the startup scan builds fresh
|
|
307
|
+
* fingerprints without diffing against this process's history). The
|
|
308
|
+
* journal remains authoritative for everything that did commit. A
|
|
309
|
+
* second close() call is a no-op and does not re-throw.
|
|
310
|
+
*/
|
|
311
|
+
async close() {
|
|
312
|
+
if (closed) return;
|
|
313
|
+
closed = true;
|
|
314
|
+
drainFailure = void 0;
|
|
315
|
+
offToolProgress?.();
|
|
316
|
+
watcher.close();
|
|
317
|
+
if (timer) {
|
|
318
|
+
clearTimeout(timer);
|
|
319
|
+
timer = void 0;
|
|
320
|
+
}
|
|
321
|
+
if (fullRescanTimer) {
|
|
322
|
+
clearTimeout(fullRescanTimer);
|
|
323
|
+
fullRescanTimer = void 0;
|
|
324
|
+
pending.add("*");
|
|
325
|
+
}
|
|
326
|
+
if (pending.size > 0) drainPending();
|
|
327
|
+
await flushTail;
|
|
328
|
+
recentToolMutations.clear();
|
|
329
|
+
if (drainFailure !== void 0) throw drainFailure;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function buildMutation(options, eventType, relativePath, state, attributes, attribution) {
|
|
334
|
+
const context = typeof options.context === "function" ? options.context() : options.context;
|
|
335
|
+
const operation = attributes["operation"];
|
|
336
|
+
const bus = options.events;
|
|
337
|
+
const activity = {
|
|
338
|
+
filePath: path.join(options.projectRoot, relativePath),
|
|
339
|
+
operation,
|
|
340
|
+
phase: "changed",
|
|
341
|
+
source: attribution ? "tool" : "external",
|
|
342
|
+
at: Date.now(),
|
|
343
|
+
sessionId: context.scope.sessionId,
|
|
344
|
+
traceId: context.correlation.traceId,
|
|
345
|
+
agentId: attribution?.agentId ?? context.scope.agentId,
|
|
346
|
+
...attribution ? { toolUseId: attribution.toolUseId, toolName: attribution.toolName } : {}
|
|
347
|
+
};
|
|
348
|
+
const emitActivity = bus ? () => {
|
|
349
|
+
bus.emit("file.activity", activity);
|
|
350
|
+
} : void 0;
|
|
351
|
+
const input = {
|
|
352
|
+
eventType: attribution ? eventType.replace(".external.", ".tool.") : eventType,
|
|
353
|
+
scope: {
|
|
354
|
+
...context.scope,
|
|
355
|
+
...attribution?.sessionId ? { sessionId: attribution.sessionId } : {},
|
|
356
|
+
...attribution?.agentId ? { agentId: attribution.agentId } : {}
|
|
357
|
+
},
|
|
358
|
+
correlation: {
|
|
359
|
+
...context.correlation,
|
|
360
|
+
...attribution ? { toolCallId: attribution.toolUseId } : {}
|
|
361
|
+
},
|
|
362
|
+
outcome: "success",
|
|
363
|
+
resource: {
|
|
364
|
+
kind: "file",
|
|
365
|
+
id: resourceId(relativePath),
|
|
366
|
+
path: normalizeRelative(relativePath),
|
|
367
|
+
...state?.hash ? { contentHashAfter: state.hash } : {}
|
|
368
|
+
},
|
|
369
|
+
attributes: {
|
|
370
|
+
...attributes,
|
|
371
|
+
actor: attribution ? "agent" : attributes["actor"],
|
|
372
|
+
source: attribution ? "tool" : "external",
|
|
373
|
+
toolName: attribution?.toolName,
|
|
374
|
+
size: state?.size,
|
|
375
|
+
mtimeMs: state?.mtimeMs,
|
|
376
|
+
observedBy: "fs.watch"
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
return { input, emitActivity };
|
|
380
|
+
}
|
|
381
|
+
async function flushJournalInputs(options, events, onCommitted) {
|
|
382
|
+
if (events.length === 0) return;
|
|
383
|
+
const batch = options.journal.appendBatch?.bind(options.journal);
|
|
384
|
+
if (!batch) {
|
|
385
|
+
const settled = await Promise.allSettled(
|
|
386
|
+
events.map(async (event) => {
|
|
387
|
+
await options.journal.append(event.input);
|
|
388
|
+
onCommitted([event]);
|
|
389
|
+
})
|
|
390
|
+
);
|
|
391
|
+
const failure = settled.find((result) => result.status === "rejected");
|
|
392
|
+
if (failure) throw failure.reason;
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
for (let index = 0; index < events.length; index += JOURNAL_FLUSH_CHUNK) {
|
|
396
|
+
const chunk = events.slice(index, index + JOURNAL_FLUSH_CHUNK);
|
|
397
|
+
await batch(chunk.map((event) => event.input));
|
|
398
|
+
onCommitted(chunk);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function peekAttribution(relativePath, recent) {
|
|
402
|
+
const value = recent.get(relativePath);
|
|
403
|
+
if (!value) return void 0;
|
|
404
|
+
return Date.now() - value.at <= 2e3 ? value : void 0;
|
|
405
|
+
}
|
|
406
|
+
async function scanProject(root, excluded, excludedPaths, maxHashBytes, onError, previous) {
|
|
407
|
+
const result = /* @__PURE__ */ new Map();
|
|
408
|
+
const dirs = [""];
|
|
409
|
+
let complete = true;
|
|
410
|
+
while (dirs.length > 0) {
|
|
411
|
+
const relativeDir = dirs.pop();
|
|
412
|
+
try {
|
|
413
|
+
const entries = await fsp.readdir(path.join(root, relativeDir), { withFileTypes: true });
|
|
414
|
+
const filePaths = [];
|
|
415
|
+
for (const entry of entries) {
|
|
416
|
+
const relative2 = normalizeRelative(path.join(relativeDir, entry.name));
|
|
417
|
+
if (isExcluded(relative2, excluded, excludedPaths)) continue;
|
|
418
|
+
if (entry.isDirectory()) {
|
|
419
|
+
dirs.push(relative2);
|
|
420
|
+
} else if (entry.isFile()) {
|
|
421
|
+
filePaths.push(relative2);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const fingerprints = await mapWithConcurrency(
|
|
425
|
+
filePaths,
|
|
426
|
+
SCAN_HASH_CONCURRENCY,
|
|
427
|
+
async (relative2) => {
|
|
428
|
+
try {
|
|
429
|
+
const value = await fingerprint(
|
|
430
|
+
path.join(root, relative2),
|
|
431
|
+
maxHashBytes,
|
|
432
|
+
previous?.get(relative2)
|
|
433
|
+
);
|
|
434
|
+
return value ? [relative2, value] : null;
|
|
435
|
+
} catch (error) {
|
|
436
|
+
complete = false;
|
|
437
|
+
onError?.(error);
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
for (const entry of fingerprints) {
|
|
443
|
+
if (entry) result.set(entry[0], entry[1]);
|
|
444
|
+
}
|
|
445
|
+
} catch (error) {
|
|
446
|
+
complete = false;
|
|
447
|
+
onError?.(error);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return { files: result, complete };
|
|
451
|
+
}
|
|
452
|
+
async function fingerprint(filePath, maxHashBytes, previous) {
|
|
453
|
+
try {
|
|
454
|
+
const stat2 = await fsp.stat(filePath);
|
|
455
|
+
if (!stat2.isFile()) return void 0;
|
|
456
|
+
const base = { size: stat2.size, mtimeMs: stat2.mtimeMs };
|
|
457
|
+
if (previous?.hash !== void 0 && previous.size === stat2.size && previous.mtimeMs === stat2.mtimeMs) {
|
|
458
|
+
base.hash = previous.hash;
|
|
459
|
+
return base;
|
|
460
|
+
}
|
|
461
|
+
if (stat2.size <= maxHashBytes) {
|
|
462
|
+
base.hash = createHash("sha256").update(await fsp.readFile(filePath)).digest("hex");
|
|
463
|
+
}
|
|
464
|
+
return base;
|
|
465
|
+
} catch (error) {
|
|
466
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
|
|
467
|
+
return void 0;
|
|
468
|
+
throw error;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function sameFingerprint(a, b) {
|
|
472
|
+
if (!a || !b) return a === b;
|
|
473
|
+
if (a.hash !== void 0 && b.hash !== void 0) return a.hash === b.hash;
|
|
474
|
+
return a.size === b.size && a.mtimeMs === b.mtimeMs;
|
|
475
|
+
}
|
|
476
|
+
function isExcluded(relative2, excluded, excludedPaths) {
|
|
477
|
+
const normalized = normalizeRelative(relative2);
|
|
478
|
+
if (normalized.split("/").some((segment) => excluded.has(segment))) return true;
|
|
479
|
+
for (const prefix of excludedPaths) {
|
|
480
|
+
if (normalized === prefix || normalized.startsWith(`${prefix}/`)) return true;
|
|
481
|
+
}
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
function normalizeExcludedPaths(root, values) {
|
|
485
|
+
const result = /* @__PURE__ */ new Set();
|
|
486
|
+
for (const value of values) {
|
|
487
|
+
const relative2 = path.isAbsolute(value) ? path.relative(root, path.resolve(value)) : value;
|
|
488
|
+
const normalized = normalizeRelative(relative2).replace(/\/+$/u, "");
|
|
489
|
+
if (!normalized || normalized === "." || normalized.startsWith("../")) continue;
|
|
490
|
+
result.add(normalized);
|
|
491
|
+
}
|
|
492
|
+
return result;
|
|
493
|
+
}
|
|
494
|
+
function normalizeRelative(value) {
|
|
495
|
+
return value.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
496
|
+
}
|
|
497
|
+
function resourceId(relativePath) {
|
|
498
|
+
return `file_${createHash("sha256").update(normalizeRelative(relativePath)).digest("hex").slice(0, 24)}`;
|
|
499
|
+
}
|
|
500
|
+
function unionKeys(a, b) {
|
|
501
|
+
return [.../* @__PURE__ */ new Set([...a.keys(), ...b.keys()])];
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
export {
|
|
505
|
+
createChronicleContext,
|
|
506
|
+
childChronicleContext,
|
|
507
|
+
startChronicleFileObserver
|
|
508
|
+
};
|
|
509
|
+
//# sourceMappingURL=chunk-U4FWBSO3.js.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// src/security/capabilities.ts
|
|
2
|
+
var ToolCapabilities = {
|
|
3
|
+
/** Can execute arbitrary commands in the user's shell (the `bash` tool). */
|
|
4
|
+
SHELL_ARBITRARY: "shell.arbitrary",
|
|
5
|
+
/**
|
|
6
|
+
* Can execute the `exec` tool's allowlisted commands.
|
|
7
|
+
*
|
|
8
|
+
* "Restricted" describes the command NAME check, not the resulting power.
|
|
9
|
+
* Treat this as equivalent to {@link SHELL_ARBITRARY} when deciding what to
|
|
10
|
+
* grant: the allowlist includes general-purpose interpreters (`node`,
|
|
11
|
+
* `python`, `perl`, `ruby`) and, on Windows, the platform shells (`cmd`,
|
|
12
|
+
* `powershell`, `pwsh`) — deliberately, since without them `exec` cannot run
|
|
13
|
+
* `dir`/`type`/any cmdlet. `node -e …` or `cmd /c …` therefore reaches
|
|
14
|
+
* arbitrary execution, and per-argument denylisting cannot close that while
|
|
15
|
+
* the shells remain (blocking `node -e` still leaves `cmd /c node -e`).
|
|
16
|
+
*
|
|
17
|
+
* What actually bounds this is downstream, not the name check: the permission
|
|
18
|
+
* policy reconstructs the full command line and runs it through the
|
|
19
|
+
* destructive classifier, so destructive calls still require confirmation.
|
|
20
|
+
*
|
|
21
|
+
* Granting `shell.restricted` while withholding `shell.arbitrary` therefore
|
|
22
|
+
* buys no meaningful reduction in blast radius. Documented rather than
|
|
23
|
+
* silently implied, because the two read as a narrow/wide pair (WS-083).
|
|
24
|
+
*/
|
|
25
|
+
SHELL_RESTRICTED: "shell.restricted",
|
|
26
|
+
/** Can run a restricted project formatter/linter-style command. */
|
|
27
|
+
SHELL_EXEC: "shell.exec",
|
|
28
|
+
/** Can read files inside the project (and possibly outside via symlinks if not guarded). */
|
|
29
|
+
FS_READ: "fs.read",
|
|
30
|
+
/** Can write / modify / delete files inside the project. */
|
|
31
|
+
FS_WRITE: "fs.write",
|
|
32
|
+
/** Can write files outside the current project root (very high risk). */
|
|
33
|
+
FS_WRITE_OUTSIDE_PROJECT: "fs.write.outside-project",
|
|
34
|
+
/** Can perform outbound network requests. */
|
|
35
|
+
NET_OUTBOUND: "net.outbound",
|
|
36
|
+
/** Can mutate in-memory session todos only. */
|
|
37
|
+
SESSION_TODO: "session.todo",
|
|
38
|
+
/**
|
|
39
|
+
* Can post an ephemeral same-session note to the leader or a peer
|
|
40
|
+
* (`session_note` / `session.note`). In-process only — not the durable
|
|
41
|
+
* cross-session mailbox (`coordination.mail`).
|
|
42
|
+
*/
|
|
43
|
+
SESSION_NOTE: "session.note",
|
|
44
|
+
/** Can park after-task `<nextsteps>` suggestions for the current turn. */
|
|
45
|
+
SESSION_NEXTSTEPS: "session.nextsteps",
|
|
46
|
+
/** Can mutate in-memory session mode only. */
|
|
47
|
+
SESSION_MODE: "session.mode",
|
|
48
|
+
/** Can inspect registered tool metadata. */
|
|
49
|
+
TOOL_META: "tool.meta",
|
|
50
|
+
/** Can invoke arbitrary registered tools through a meta-tool. */
|
|
51
|
+
TOOL_MUTATE_ANY: "tool.mutate.any",
|
|
52
|
+
/** Can read persistent memory. */
|
|
53
|
+
MEMORY_READ: "memory.read",
|
|
54
|
+
/** Can write persistent memory. */
|
|
55
|
+
MEMORY_WRITE: "memory.write",
|
|
56
|
+
/** Can delete persistent memory. */
|
|
57
|
+
MEMORY_DELETE: "memory.delete",
|
|
58
|
+
/** Proxies tools from external MCP servers (unknown capability). */
|
|
59
|
+
MCP_PROXY: "mcp.proxy",
|
|
60
|
+
/** Can spawn or manage subagents / multi-agent tasks. */
|
|
61
|
+
SUBAGENT_SPAWN: "subagent.spawn",
|
|
62
|
+
/** Can inspect fleet/subagent coordination state without mutating it. */
|
|
63
|
+
COORDINATION_FLEET_READ: "coordination.fleet.read",
|
|
64
|
+
/** Can publish attributed, schema-checked events onto the fleet bus. */
|
|
65
|
+
COORDINATION_FLEET_EMIT: "coordination.fleet.emit",
|
|
66
|
+
/** Can submit a task-local structured result to the parent Director. */
|
|
67
|
+
COORDINATION_RESULT_SUBMIT: "coordination.result.submit",
|
|
68
|
+
/** Can read or write inter-agent mailbox messages. */
|
|
69
|
+
COORDINATION_MAIL: "coordination.mail",
|
|
70
|
+
/** Can schedule, inspect, or cancel in-session cron jobs. */
|
|
71
|
+
COORDINATION_CRON: "coordination.cron",
|
|
72
|
+
/** Can mutate global or session configuration / trust state. */
|
|
73
|
+
CONFIG_MUTATE: "config.mutate",
|
|
74
|
+
/** Can install packages or run package managers with side effects. */
|
|
75
|
+
PACKAGE_INSTALL: "package.install"
|
|
76
|
+
};
|
|
77
|
+
var DANGEROUS_FOR_SUBAGENTS = [
|
|
78
|
+
ToolCapabilities.SHELL_ARBITRARY,
|
|
79
|
+
ToolCapabilities.SHELL_RESTRICTED,
|
|
80
|
+
ToolCapabilities.SHELL_EXEC,
|
|
81
|
+
ToolCapabilities.FS_WRITE,
|
|
82
|
+
ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,
|
|
83
|
+
ToolCapabilities.TOOL_MUTATE_ANY,
|
|
84
|
+
ToolCapabilities.MEMORY_WRITE,
|
|
85
|
+
ToolCapabilities.MEMORY_DELETE,
|
|
86
|
+
ToolCapabilities.MCP_PROXY,
|
|
87
|
+
ToolCapabilities.SUBAGENT_SPAWN,
|
|
88
|
+
ToolCapabilities.CONFIG_MUTATE,
|
|
89
|
+
ToolCapabilities.PACKAGE_INSTALL
|
|
90
|
+
];
|
|
91
|
+
var WIDE_SUBAGENT_CAPABILITIES = [
|
|
92
|
+
ToolCapabilities.FS_READ,
|
|
93
|
+
ToolCapabilities.FS_WRITE,
|
|
94
|
+
ToolCapabilities.NET_OUTBOUND,
|
|
95
|
+
ToolCapabilities.SESSION_TODO,
|
|
96
|
+
ToolCapabilities.SESSION_NOTE,
|
|
97
|
+
ToolCapabilities.TOOL_META,
|
|
98
|
+
ToolCapabilities.MEMORY_READ,
|
|
99
|
+
ToolCapabilities.SHELL_ARBITRARY,
|
|
100
|
+
ToolCapabilities.SHELL_RESTRICTED,
|
|
101
|
+
ToolCapabilities.SHELL_EXEC,
|
|
102
|
+
ToolCapabilities.PACKAGE_INSTALL,
|
|
103
|
+
// Read-only fleet visibility (fleet_status) — peer awareness has no blast
|
|
104
|
+
// radius and every fleet worker should coordinate around its peers.
|
|
105
|
+
ToolCapabilities.COORDINATION_FLEET_READ,
|
|
106
|
+
ToolCapabilities.COORDINATION_RESULT_SUBMIT
|
|
107
|
+
];
|
|
108
|
+
function clampSubagentCapabilities(requested, ceiling = WIDE_SUBAGENT_CAPABILITIES) {
|
|
109
|
+
const ceilingSet = new Set(ceiling);
|
|
110
|
+
const requestedSet = new Set(requested);
|
|
111
|
+
return {
|
|
112
|
+
granted: ceiling.filter((capability) => requestedSet.has(capability)),
|
|
113
|
+
dropped: [...requestedSet].filter((capability) => !ceilingSet.has(capability))
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function hasDangerousCapabilityForSubagents(toolOrCaps) {
|
|
117
|
+
if (!toolOrCaps) return false;
|
|
118
|
+
const input = toolOrCaps;
|
|
119
|
+
const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
|
|
120
|
+
return caps.some((c) => DANGEROUS_FOR_SUBAGENTS.includes(c));
|
|
121
|
+
}
|
|
122
|
+
function hasCapability(toolOrCaps, capability) {
|
|
123
|
+
if (!toolOrCaps) return false;
|
|
124
|
+
const input = toolOrCaps;
|
|
125
|
+
const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
|
|
126
|
+
const toCheck = Array.isArray(capability) ? capability : [capability];
|
|
127
|
+
return toCheck.some((c) => caps.includes(c));
|
|
128
|
+
}
|
|
129
|
+
function getDangerousCapabilities(toolOrCaps) {
|
|
130
|
+
if (!toolOrCaps) return [];
|
|
131
|
+
const input = toolOrCaps;
|
|
132
|
+
const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
|
|
133
|
+
return caps.filter(
|
|
134
|
+
(c) => DANGEROUS_FOR_SUBAGENTS.includes(c)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
ToolCapabilities,
|
|
140
|
+
DANGEROUS_FOR_SUBAGENTS,
|
|
141
|
+
WIDE_SUBAGENT_CAPABILITIES,
|
|
142
|
+
clampSubagentCapabilities,
|
|
143
|
+
hasDangerousCapabilityForSubagents,
|
|
144
|
+
hasCapability,
|
|
145
|
+
getDangerousCapabilities
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=chunk-UBGDX6FI.js.map
|