@runcore-sh/runcore 0.4.0 → 0.5.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/dictionary.json +2 -2
- package/dist/activity/log.js +2 -2
- package/dist/activity/log.js.map +1 -1
- package/dist/agents/governed-spawn.d.ts.map +1 -1
- package/dist/cli.js +101 -11
- package/dist/cli.js.map +1 -1
- package/dist/extensions/cache.d.ts +57 -0
- package/dist/extensions/cache.d.ts.map +1 -0
- package/dist/extensions/cache.js +173 -0
- package/dist/extensions/cache.js.map +1 -0
- package/dist/extensions/client.d.ts +55 -0
- package/dist/extensions/client.d.ts.map +1 -0
- package/dist/extensions/client.js +120 -0
- package/dist/extensions/client.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +50 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +166 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/manifest.d.ts +38 -0
- package/dist/extensions/manifest.d.ts.map +1 -0
- package/dist/extensions/manifest.js +17 -0
- package/dist/extensions/manifest.js.map +1 -0
- package/dist/extensions/stubs.d.ts +27 -0
- package/dist/extensions/stubs.d.ts.map +1 -0
- package/dist/extensions/stubs.js +45 -0
- package/dist/extensions/stubs.js.map +1 -0
- package/dist/lib/audit.js +2 -2
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/brain-migrate.d.ts +21 -0
- package/dist/lib/brain-migrate.d.ts.map +1 -0
- package/dist/lib/brain-migrate.js +137 -0
- package/dist/lib/brain-migrate.js.map +1 -0
- package/dist/lib/paths.d.ts +27 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +65 -0
- package/dist/lib/paths.js.map +1 -1
- package/dist/llm/call-log.d.ts +40 -0
- package/dist/llm/call-log.d.ts.map +1 -0
- package/dist/llm/call-log.js +35 -0
- package/dist/llm/call-log.js.map +1 -0
- package/dist/llm/complete.d.ts +6 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +27 -0
- package/dist/llm/complete.js.map +1 -1
- package/dist/mcp-server.js +118 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/memory/file-backed.d.ts +4 -0
- package/dist/memory/file-backed.d.ts.map +1 -1
- package/dist/memory/file-backed.js +4 -0
- package/dist/memory/file-backed.js.map +1 -1
- package/dist/memory/vector-index.d.ts +4 -12
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +11 -93
- package/dist/memory/vector-index.js.map +1 -1
- package/dist/search/brain-docs.d.ts +17 -7
- package/dist/search/brain-docs.d.ts.map +1 -1
- package/dist/search/brain-docs.js +170 -52
- package/dist/search/brain-docs.js.map +1 -1
- package/dist/search/brain-rag.d.ts +45 -0
- package/dist/search/brain-rag.d.ts.map +1 -0
- package/dist/search/brain-rag.js +275 -0
- package/dist/search/brain-rag.js.map +1 -0
- package/dist/search/chunker.d.ts +24 -0
- package/dist/search/chunker.d.ts.map +1 -0
- package/dist/search/chunker.js +95 -0
- package/dist/search/chunker.js.map +1 -0
- package/dist/search/embedder.d.ts +16 -0
- package/dist/search/embedder.d.ts.map +1 -0
- package/dist/search/embedder.js +108 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/file-watcher.d.ts +11 -0
- package/dist/search/file-watcher.d.ts.map +1 -0
- package/dist/search/file-watcher.js +86 -0
- package/dist/search/file-watcher.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +814 -472
- package/dist/server.js.map +1 -1
- package/dist/sessions/store.d.ts +9 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +78 -2
- package/dist/settings.js.map +1 -1
- package/dist/tracing/init.d.ts +1 -1
- package/dist/tracing/init.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/module-tiers.json +164 -0
- package/package.json +9 -13
- package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
- package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
- package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
- package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
- package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
- package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
- package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
- package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
- package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
- package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
- package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
- package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
- package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
- package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
- package/public/index.html +379 -59
- package/dist/agents/autonomous.js +0 -749
- package/dist/agents/autonomous.js.map +0 -1
- package/dist/agents/commit.js +0 -113
- package/dist/agents/commit.js.map +0 -1
- package/dist/agents/continue.js +0 -158
- package/dist/agents/continue.js.map +0 -1
- package/dist/agents/cooldown.js +0 -397
- package/dist/agents/cooldown.js.map +0 -1
- package/dist/agents/dedup-guard.js +0 -131
- package/dist/agents/dedup-guard.js.map +0 -1
- package/dist/agents/feed.js +0 -176
- package/dist/agents/feed.js.map +0 -1
- package/dist/agents/governance.js +0 -292
- package/dist/agents/governance.js.map +0 -1
- package/dist/agents/governed-spawn.js +0 -192
- package/dist/agents/governed-spawn.js.map +0 -1
- package/dist/agents/heartbeat.js +0 -324
- package/dist/agents/heartbeat.js.map +0 -1
- package/dist/agents/instance-manager.js +0 -850
- package/dist/agents/instance-manager.js.map +0 -1
- package/dist/agents/issue-reporter.js +0 -123
- package/dist/agents/issue-reporter.js.map +0 -1
- package/dist/agents/issues.js +0 -141
- package/dist/agents/issues.js.map +0 -1
- package/dist/agents/locks.js +0 -234
- package/dist/agents/locks.js.map +0 -1
- package/dist/agents/memory.js +0 -93
- package/dist/agents/memory.js.map +0 -1
- package/dist/agents/monitor.js +0 -235
- package/dist/agents/monitor.js.map +0 -1
- package/dist/agents/orchestration.js +0 -715
- package/dist/agents/orchestration.js.map +0 -1
- package/dist/agents/recover.js +0 -166
- package/dist/agents/recover.js.map +0 -1
- package/dist/agents/reflection.js +0 -199
- package/dist/agents/reflection.js.map +0 -1
- package/dist/agents/runtime/bus.js +0 -174
- package/dist/agents/runtime/bus.js.map +0 -1
- package/dist/agents/runtime/config.js +0 -101
- package/dist/agents/runtime/config.js.map +0 -1
- package/dist/agents/runtime/driver.js +0 -214
- package/dist/agents/runtime/driver.js.map +0 -1
- package/dist/agents/runtime/errors.js +0 -40
- package/dist/agents/runtime/errors.js.map +0 -1
- package/dist/agents/runtime/index.js +0 -54
- package/dist/agents/runtime/index.js.map +0 -1
- package/dist/agents/runtime/lifecycle.js +0 -116
- package/dist/agents/runtime/lifecycle.js.map +0 -1
- package/dist/agents/runtime/manager.js +0 -948
- package/dist/agents/runtime/manager.js.map +0 -1
- package/dist/agents/runtime/registry.js +0 -195
- package/dist/agents/runtime/registry.js.map +0 -1
- package/dist/agents/runtime/resources.js +0 -146
- package/dist/agents/runtime/resources.js.map +0 -1
- package/dist/agents/runtime/types.js +0 -24
- package/dist/agents/runtime/types.js.map +0 -1
- package/dist/agents/spawn-policy.js +0 -202
- package/dist/agents/spawn-policy.js.map +0 -1
- package/dist/agents/spawn.js +0 -970
- package/dist/agents/spawn.js.map +0 -1
- package/dist/agents/triage.js +0 -81
- package/dist/agents/triage.js.map +0 -1
- package/dist/agents/workflow.js +0 -543
- package/dist/agents/workflow.js.map +0 -1
- package/dist/avatar/client.js +0 -172
- package/dist/avatar/client.js.map +0 -1
- package/dist/avatar/sidecar.js +0 -125
- package/dist/avatar/sidecar.js.map +0 -1
- package/dist/browser/sessions.js +0 -122
- package/dist/browser/sessions.js.map +0 -1
- package/dist/capabilities/definitions/browser.js +0 -242
- package/dist/capabilities/definitions/browser.js.map +0 -1
- package/dist/channels/whatsapp.js +0 -200
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/credentials/store.js +0 -189
- package/dist/credentials/store.js.map +0 -1
- package/dist/files/deep-index.js +0 -337
- package/dist/files/deep-index.js.map +0 -1
- package/dist/files/extract.js +0 -33
- package/dist/files/extract.js.map +0 -1
- package/dist/files/gdrive.js +0 -246
- package/dist/files/gdrive.js.map +0 -1
- package/dist/github/client.js +0 -408
- package/dist/github/client.js.map +0 -1
- package/dist/github/commit-analysis.js +0 -276
- package/dist/github/commit-analysis.js.map +0 -1
- package/dist/github/contributor-stats.js +0 -119
- package/dist/github/contributor-stats.js.map +0 -1
- package/dist/github/issue-sla.js +0 -220
- package/dist/github/issue-sla.js.map +0 -1
- package/dist/github/issue-triage.js +0 -286
- package/dist/github/issue-triage.js.map +0 -1
- package/dist/github/pr-readiness.js +0 -197
- package/dist/github/pr-readiness.js.map +0 -1
- package/dist/github/pr-review.js +0 -410
- package/dist/github/pr-review.js.map +0 -1
- package/dist/github/release-notes.js +0 -227
- package/dist/github/release-notes.js.map +0 -1
- package/dist/github/repo-health.js +0 -303
- package/dist/github/repo-health.js.map +0 -1
- package/dist/github/retry.js +0 -117
- package/dist/github/retry.js.map +0 -1
- package/dist/github/types.js +0 -8
- package/dist/github/types.js.map +0 -1
- package/dist/github/webhooks.js +0 -153
- package/dist/github/webhooks.js.map +0 -1
- package/dist/google/auth.js +0 -325
- package/dist/google/auth.js.map +0 -1
- package/dist/google/calendar-timer.js +0 -91
- package/dist/google/calendar-timer.js.map +0 -1
- package/dist/google/calendar.js +0 -270
- package/dist/google/calendar.js.map +0 -1
- package/dist/google/docs.js +0 -309
- package/dist/google/docs.js.map +0 -1
- package/dist/google/gmail-send.js +0 -219
- package/dist/google/gmail-send.js.map +0 -1
- package/dist/google/gmail-timer.js +0 -223
- package/dist/google/gmail-timer.js.map +0 -1
- package/dist/google/gmail.js +0 -470
- package/dist/google/gmail.js.map +0 -1
- package/dist/google/plugin.js +0 -169
- package/dist/google/plugin.js.map +0 -1
- package/dist/google/tasks-timer.js +0 -107
- package/dist/google/tasks-timer.js.map +0 -1
- package/dist/google/tasks.js +0 -331
- package/dist/google/tasks.js.map +0 -1
- package/dist/google/temporal.js +0 -176
- package/dist/google/temporal.js.map +0 -1
- package/dist/integrations/gate.js +0 -100
- package/dist/integrations/gate.js.map +0 -1
- package/dist/integrations/github.js +0 -331
- package/dist/integrations/github.js.map +0 -1
- package/dist/integrations/google-tasks.js +0 -432
- package/dist/integrations/google-tasks.js.map +0 -1
- package/dist/mdns.js +0 -110
- package/dist/mdns.js.map +0 -1
- package/dist/notifications/channel.js +0 -83
- package/dist/notifications/channel.js.map +0 -1
- package/dist/notifications/channels/adapter.js +0 -55
- package/dist/notifications/channels/adapter.js.map +0 -1
- package/dist/notifications/channels/index.js +0 -6
- package/dist/notifications/channels/index.js.map +0 -1
- package/dist/notifications/channels/log.js +0 -29
- package/dist/notifications/channels/log.js.map +0 -1
- package/dist/notifications/email.js +0 -72
- package/dist/notifications/email.js.map +0 -1
- package/dist/notifications/engine.js +0 -198
- package/dist/notifications/engine.js.map +0 -1
- package/dist/notifications/index.js +0 -24
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/phone.js +0 -48
- package/dist/notifications/phone.js.map +0 -1
- package/dist/notifications/sms.js +0 -65
- package/dist/notifications/sms.js.map +0 -1
- package/dist/notifications/types.js +0 -14
- package/dist/notifications/types.js.map +0 -1
- package/dist/notifications/webhook.js +0 -65
- package/dist/notifications/webhook.js.map +0 -1
- package/dist/resend/inbox.js +0 -199
- package/dist/resend/inbox.js.map +0 -1
- package/dist/resend/webhooks.js +0 -244
- package/dist/resend/webhooks.js.map +0 -1
- package/dist/search/browse.js +0 -225
- package/dist/search/browse.js.map +0 -1
- package/dist/search/perplexity.js +0 -41
- package/dist/search/perplexity.js.map +0 -1
- package/dist/slack/channels.js +0 -277
- package/dist/slack/channels.js.map +0 -1
- package/dist/slack/client.js +0 -468
- package/dist/slack/client.js.map +0 -1
- package/dist/slack/retry.js +0 -100
- package/dist/slack/retry.js.map +0 -1
- package/dist/slack/types.js +0 -52
- package/dist/slack/types.js.map +0 -1
- package/dist/slack/webhooks.js +0 -285
- package/dist/slack/webhooks.js.map +0 -1
- package/dist/stt/client.js +0 -66
- package/dist/stt/client.js.map +0 -1
- package/dist/stt/sidecar.js +0 -115
- package/dist/stt/sidecar.js.map +0 -1
- package/dist/tracing/bridge.js +0 -70
- package/dist/tracing/bridge.js.map +0 -1
- package/dist/tracing/correlation.js +0 -49
- package/dist/tracing/correlation.js.map +0 -1
- package/dist/tracing/index.js +0 -18
- package/dist/tracing/index.js.map +0 -1
- package/dist/tracing/init.js +0 -81
- package/dist/tracing/init.js.map +0 -1
- package/dist/tracing/instrument.js +0 -145
- package/dist/tracing/instrument.js.map +0 -1
- package/dist/tracing/middleware.js +0 -69
- package/dist/tracing/middleware.js.map +0 -1
- package/dist/tracing/tracer.js +0 -327
- package/dist/tracing/tracer.js.map +0 -1
- package/dist/tts/client.js +0 -48
- package/dist/tts/client.js.map +0 -1
- package/dist/tts/sidecar.js +0 -148
- package/dist/tts/sidecar.js.map +0 -1
- package/dist/twilio/call.js +0 -79
- package/dist/twilio/call.js.map +0 -1
- package/dist/vault/matcher.js +0 -197
- package/dist/vault/matcher.js.map +0 -1
- package/dist/vault/personal.js +0 -163
- package/dist/vault/personal.js.map +0 -1
- package/dist/vault/policy.js +0 -159
- package/dist/vault/policy.js.map +0 -1
- package/dist/vault/store.js +0 -122
- package/dist/vault/store.js.map +0 -1
- package/dist/vault/transfer.js +0 -188
- package/dist/vault/transfer.js.map +0 -1
- package/dist/volumes/index.js +0 -2
- package/dist/volumes/index.js.map +0 -1
- package/dist/volumes/manager.js +0 -462
- package/dist/volumes/manager.js.map +0 -1
- package/dist/volumes/types.js +0 -8
- package/dist/volumes/types.js.map +0 -1
- package/dist/webhooks/config.js +0 -214
- package/dist/webhooks/config.js.map +0 -1
- package/dist/webhooks/event-log.js +0 -132
- package/dist/webhooks/event-log.js.map +0 -1
- package/dist/webhooks/handler.js +0 -103
- package/dist/webhooks/handler.js.map +0 -1
- package/dist/webhooks/handlers.js +0 -231
- package/dist/webhooks/handlers.js.map +0 -1
- package/dist/webhooks/index.js +0 -33
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/mount.js +0 -400
- package/dist/webhooks/mount.js.map +0 -1
- package/dist/webhooks/registry.js +0 -143
- package/dist/webhooks/registry.js.map +0 -1
- package/dist/webhooks/relay.js +0 -53
- package/dist/webhooks/relay.js.map +0 -1
- package/dist/webhooks/retry.js +0 -270
- package/dist/webhooks/retry.js.map +0 -1
- package/dist/webhooks/router.js +0 -290
- package/dist/webhooks/router.js.map +0 -1
- package/dist/webhooks/twilio.js +0 -129
- package/dist/webhooks/twilio.js.map +0 -1
- package/dist/webhooks/types.js +0 -8
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/verify.js +0 -154
- package/dist/webhooks/verify.js.map +0 -1
package/dist/agents/feed.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Runtime Feed — per-agent live activity stream.
|
|
3
|
-
*
|
|
4
|
-
* Bridges lifecycle events, activity log entries, and agent runtime output
|
|
5
|
-
* into a per-agent SSE stream. Each feed entry matches the spec types:
|
|
6
|
-
* llm, tool, memory, decision, error, state.
|
|
7
|
-
*
|
|
8
|
-
* Observation without disturbance — subscribing to a feed has zero effect
|
|
9
|
-
* on the running agent.
|
|
10
|
-
*
|
|
11
|
-
* Portability: StreamEmitter is injectable. The server injects the concrete
|
|
12
|
-
* implementation at runtime if live stream bridging is desired.
|
|
13
|
-
*/
|
|
14
|
-
import { EventEmitter } from "node:events";
|
|
15
|
-
import { createLogger } from "../utils/logger.js";
|
|
16
|
-
const log = createLogger("agent-feed");
|
|
17
|
-
/** Map feed entry types to stream action types. */
|
|
18
|
-
const FEED_TO_STREAM_TYPE = {
|
|
19
|
-
llm: "work",
|
|
20
|
-
tool: "work",
|
|
21
|
-
memory: "memory",
|
|
22
|
-
decision: "decision",
|
|
23
|
-
error: "error",
|
|
24
|
-
state: "state",
|
|
25
|
-
};
|
|
26
|
-
const MAX_RECENT = 200;
|
|
27
|
-
class AgentFeedManager {
|
|
28
|
-
feeds = new Map();
|
|
29
|
-
emitter = new EventEmitter();
|
|
30
|
-
streamBridge = null;
|
|
31
|
-
constructor() {
|
|
32
|
-
this.emitter.setMaxListeners(500);
|
|
33
|
-
}
|
|
34
|
-
/** Register a stream bridge for SSE forwarding. */
|
|
35
|
-
setStreamBridge(bridge) {
|
|
36
|
-
this.streamBridge = bridge;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Push a feed entry for a specific agent.
|
|
40
|
-
* Called by instrumentation hooks throughout the agent lifecycle.
|
|
41
|
-
*/
|
|
42
|
-
push(entry, skipStreamBridge = false) {
|
|
43
|
-
const feed = this.getOrCreateFeed(entry.agentId);
|
|
44
|
-
// Store in ring buffer
|
|
45
|
-
feed.recent.push(entry);
|
|
46
|
-
if (feed.recent.length > MAX_RECENT) {
|
|
47
|
-
feed.recent.shift();
|
|
48
|
-
}
|
|
49
|
-
// Broadcast to per-agent listeners
|
|
50
|
-
for (const listener of feed.listeners) {
|
|
51
|
-
try {
|
|
52
|
-
listener(entry);
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
feed.listeners.delete(listener);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// Broadcast to global listeners
|
|
59
|
-
this.emitter.emit("*", entry);
|
|
60
|
-
// Bridge to live stream so feed events appear in the SSE stream pane.
|
|
61
|
-
// Skip when caller already emitted via logActivity (avoids duplicates).
|
|
62
|
-
if (!skipStreamBridge && this.streamBridge) {
|
|
63
|
-
try {
|
|
64
|
-
this.streamBridge.emit({
|
|
65
|
-
agentId: entry.agentId,
|
|
66
|
-
type: FEED_TO_STREAM_TYPE[entry.type] ?? "work",
|
|
67
|
-
summary: entry.summary,
|
|
68
|
-
detail: entry.detail,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
// Stream bridge not ready — skip silently
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Subscribe to a specific agent's feed. Returns unsubscribe function.
|
|
78
|
-
* On subscribe, replays recent entries for "just missed it" context.
|
|
79
|
-
*/
|
|
80
|
-
subscribe(agentId, listener) {
|
|
81
|
-
const feed = this.getOrCreateFeed(agentId);
|
|
82
|
-
feed.listeners.add(listener);
|
|
83
|
-
// Replay recent entries
|
|
84
|
-
for (const entry of feed.recent) {
|
|
85
|
-
try {
|
|
86
|
-
listener(entry);
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
feed.listeners.delete(listener);
|
|
90
|
-
return () => { };
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return () => {
|
|
94
|
-
feed.listeners.delete(listener);
|
|
95
|
-
// Clean up empty feeds
|
|
96
|
-
if (feed.listeners.size === 0 && feed.recent.length === 0) {
|
|
97
|
-
this.feeds.delete(agentId);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Subscribe to ALL agents' feeds (global observer).
|
|
103
|
-
* Useful for the operations view "all activity" stream.
|
|
104
|
-
*/
|
|
105
|
-
subscribeAll(listener) {
|
|
106
|
-
const handler = (entry) => listener(entry);
|
|
107
|
-
this.emitter.on("*", handler);
|
|
108
|
-
// Replay recent from all active feeds
|
|
109
|
-
for (const [, feed] of this.feeds) {
|
|
110
|
-
for (const entry of feed.recent) {
|
|
111
|
-
try {
|
|
112
|
-
listener(entry);
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
this.emitter.off("*", handler);
|
|
116
|
-
return () => { };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return () => {
|
|
121
|
-
this.emitter.off("*", handler);
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
/** Get active listener count for an agent. */
|
|
125
|
-
getListenerCount(agentId) {
|
|
126
|
-
return this.feeds.get(agentId)?.listeners.size ?? 0;
|
|
127
|
-
}
|
|
128
|
-
/** Get recent entries for an agent (snapshot). */
|
|
129
|
-
getRecent(agentId) {
|
|
130
|
-
return [...(this.feeds.get(agentId)?.recent ?? [])];
|
|
131
|
-
}
|
|
132
|
-
/** Get all agent IDs with active feeds. */
|
|
133
|
-
getActiveFeedIds() {
|
|
134
|
-
return [...this.feeds.keys()];
|
|
135
|
-
}
|
|
136
|
-
/** Clean up a finished agent's feed (after all listeners disconnect). */
|
|
137
|
-
cleanup(agentId) {
|
|
138
|
-
const feed = this.feeds.get(agentId);
|
|
139
|
-
if (feed && feed.listeners.size === 0) {
|
|
140
|
-
this.feeds.delete(agentId);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
getOrCreateFeed(agentId) {
|
|
144
|
-
let feed = this.feeds.get(agentId);
|
|
145
|
-
if (!feed) {
|
|
146
|
-
feed = { listeners: new Set(), recent: [] };
|
|
147
|
-
this.feeds.set(agentId, feed);
|
|
148
|
-
}
|
|
149
|
-
return feed;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// ---------------------------------------------------------------------------
|
|
153
|
-
// Singleton
|
|
154
|
-
// ---------------------------------------------------------------------------
|
|
155
|
-
let instance = null;
|
|
156
|
-
export function getAgentFeedManager() {
|
|
157
|
-
if (!instance) {
|
|
158
|
-
instance = new AgentFeedManager();
|
|
159
|
-
}
|
|
160
|
-
return instance;
|
|
161
|
-
}
|
|
162
|
-
// ---------------------------------------------------------------------------
|
|
163
|
-
// Convenience: emit a feed entry
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
export function emitFeedEntry(agentId, type, summary, detail,
|
|
166
|
-
/** Set true when caller already emitted via logActivity (avoids duplicate stream actions). */
|
|
167
|
-
skipStreamBridge = false) {
|
|
168
|
-
getAgentFeedManager().push({
|
|
169
|
-
timestamp: new Date().toISOString(),
|
|
170
|
-
agentId,
|
|
171
|
-
type,
|
|
172
|
-
summary,
|
|
173
|
-
detail,
|
|
174
|
-
}, skipStreamBridge);
|
|
175
|
-
}
|
|
176
|
-
//# sourceMappingURL=feed.js.map
|
package/dist/agents/feed.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"feed.js","sourceRoot":"","sources":["../../src/agents/feed.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Governance Gate — CORE-9
|
|
3
|
-
*
|
|
4
|
-
* Pre-spawn validation that replaces the `--dangerously-skip-permissions`
|
|
5
|
-
* prompt with voucher-based authorization, locked-path enforcement, and
|
|
6
|
-
* principle injection.
|
|
7
|
-
*
|
|
8
|
-
* Every governed spawn:
|
|
9
|
-
* 1. Issues a scoped voucher for the task
|
|
10
|
-
* 2. Reads locked paths and builds a deny-list for the agent's prompt
|
|
11
|
-
* 3. Injects core principles as behavioral constraints
|
|
12
|
-
* 4. Wraps the prompt with governance preamble
|
|
13
|
-
* 5. Logs the governance decision to the audit trail
|
|
14
|
-
*/
|
|
15
|
-
import { readFile } from "node:fs/promises";
|
|
16
|
-
import { join, resolve } from "node:path";
|
|
17
|
-
import { issueVoucher, checkVoucher, revokeVoucher } from "../voucher.js";
|
|
18
|
-
import { loadLockedPaths } from "../lib/locked.js";
|
|
19
|
-
import { checkSpawnPolicy, loadSpawnPolicy } from "./spawn-policy.js";
|
|
20
|
-
import { logActivity } from "../activity/log.js";
|
|
21
|
-
import { createLogger } from "../utils/logger.js";
|
|
22
|
-
const log = createLogger("governance");
|
|
23
|
-
import { BRAIN_DIR } from "../lib/paths.js";
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// Governance preamble components
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
function buildLockedPathsSection(paths) {
|
|
28
|
-
if (paths.length === 0)
|
|
29
|
-
return "";
|
|
30
|
-
const pathList = paths.map((p) => ` - brain/${p}`).join("\n");
|
|
31
|
-
return `
|
|
32
|
-
## Locked Paths (DO NOT ACCESS)
|
|
33
|
-
The following paths are locked by governance policy. Do NOT read, write, or
|
|
34
|
-
reference these files. Violations will be logged and may terminate your session.
|
|
35
|
-
|
|
36
|
-
${pathList}
|
|
37
|
-
`;
|
|
38
|
-
}
|
|
39
|
-
function buildVoucherSection(token, scope) {
|
|
40
|
-
return `
|
|
41
|
-
## Governance Voucher
|
|
42
|
-
You are operating under voucher \`${token}\` with scope \`${scope}\`.
|
|
43
|
-
This voucher is time-limited. If you receive a governance violation, stop immediately.
|
|
44
|
-
`;
|
|
45
|
-
}
|
|
46
|
-
async function loadPrinciples() {
|
|
47
|
-
try {
|
|
48
|
-
const principlesPath = join(BRAIN_DIR, "identity", "principles.md");
|
|
49
|
-
const content = await readFile(principlesPath, "utf-8");
|
|
50
|
-
// Extract just the key principles, not the full document
|
|
51
|
-
const lines = content.split("\n");
|
|
52
|
-
const keyPrinciples = [];
|
|
53
|
-
for (const line of lines) {
|
|
54
|
-
if (line.startsWith("**") && line.endsWith("**")) {
|
|
55
|
-
keyPrinciples.push(line);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (keyPrinciples.length === 0)
|
|
59
|
-
return "";
|
|
60
|
-
return `
|
|
61
|
-
## Operating Principles
|
|
62
|
-
You must adhere to these principles during execution:
|
|
63
|
-
${keyPrinciples.map((p) => `- ${p}`).join("\n")}
|
|
64
|
-
`;
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
log.warn("Could not load principles — proceeding without them");
|
|
68
|
-
return "";
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
// Scope ceiling validation
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
/**
|
|
75
|
-
* Check that a working directory falls within the scope ceiling.
|
|
76
|
-
* Both paths are resolved to absolute before comparison.
|
|
77
|
-
* Returns null if valid, or a denial reason string if out of scope.
|
|
78
|
-
*/
|
|
79
|
-
function validateScopeCeiling(cwd, ceiling) {
|
|
80
|
-
if (!ceiling)
|
|
81
|
-
return null; // No ceiling = no constraint
|
|
82
|
-
if (!cwd)
|
|
83
|
-
return null; // No cwd = will default to process.cwd(), checked at spawn time
|
|
84
|
-
const resolvedCwd = resolve(cwd).replace(/\\/g, "/").toLowerCase();
|
|
85
|
-
const resolvedCeiling = resolve(ceiling).replace(/\\/g, "/").toLowerCase();
|
|
86
|
-
// cwd must be equal to or a subdirectory of the ceiling
|
|
87
|
-
if (resolvedCwd === resolvedCeiling)
|
|
88
|
-
return null;
|
|
89
|
-
if (resolvedCwd.startsWith(resolvedCeiling + "/"))
|
|
90
|
-
return null;
|
|
91
|
-
return `Scope violation: cwd "${cwd}" escapes ceiling "${ceiling}". Agents cannot widen their parent's scope.`;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Compute the effective scope ceiling for a child agent.
|
|
95
|
-
* Takes the narrower of: parent's ceiling vs requested cwd.
|
|
96
|
-
* If no parent ceiling exists, the cwd itself becomes the ceiling.
|
|
97
|
-
*/
|
|
98
|
-
export function narrowScopeCeiling(parentCeiling, cwd) {
|
|
99
|
-
const effectiveCwd = cwd || process.cwd();
|
|
100
|
-
if (!parentCeiling)
|
|
101
|
-
return resolve(effectiveCwd);
|
|
102
|
-
const resolvedCwd = resolve(effectiveCwd).replace(/\\/g, "/").toLowerCase();
|
|
103
|
-
const resolvedCeiling = resolve(parentCeiling).replace(/\\/g, "/").toLowerCase();
|
|
104
|
-
// Return whichever is deeper (more specific)
|
|
105
|
-
if (resolvedCwd.startsWith(resolvedCeiling + "/") || resolvedCwd === resolvedCeiling) {
|
|
106
|
-
return resolve(effectiveCwd); // cwd is inside ceiling — use cwd (narrower)
|
|
107
|
-
}
|
|
108
|
-
// cwd is outside ceiling — this shouldn't happen if validation runs first,
|
|
109
|
-
// but return ceiling as the safe fallback
|
|
110
|
-
return resolve(parentCeiling);
|
|
111
|
-
}
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
|
-
// Main governance gate
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
|
-
/**
|
|
116
|
-
* Run the governance gate before spawning an agent.
|
|
117
|
-
* Returns a GovernanceDecision with the governed prompt (or denial).
|
|
118
|
-
*/
|
|
119
|
-
export async function governanceGate(opts) {
|
|
120
|
-
const { taskId, label, prompt, origin, ltm, scope: scopeOverride, voucherTtlMinutes = 30, skipVoucher = false, } = opts;
|
|
121
|
-
const scope = scopeOverride ?? `agent:spawn:${taskId}`;
|
|
122
|
-
const timestamp = new Date().toISOString();
|
|
123
|
-
// 0. Scope ceiling check — before anything else
|
|
124
|
-
const scopeViolation = validateScopeCeiling(opts.cwd, opts.scopeCeiling);
|
|
125
|
-
if (scopeViolation) {
|
|
126
|
-
log.warn(scopeViolation, { taskId, cwd: opts.cwd, ceiling: opts.scopeCeiling });
|
|
127
|
-
const auditEntry = {
|
|
128
|
-
timestamp,
|
|
129
|
-
taskId,
|
|
130
|
-
label,
|
|
131
|
-
decision: "deny",
|
|
132
|
-
lockedPathCount: 0,
|
|
133
|
-
reason: scopeViolation,
|
|
134
|
-
};
|
|
135
|
-
logActivity({
|
|
136
|
-
source: "agent",
|
|
137
|
-
summary: `Governance DENIED (scope ceiling): ${label}`,
|
|
138
|
-
detail: scopeViolation,
|
|
139
|
-
actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
140
|
-
reason: "governance-gate",
|
|
141
|
-
});
|
|
142
|
-
return {
|
|
143
|
-
allowed: false,
|
|
144
|
-
deniedReason: scopeViolation,
|
|
145
|
-
governedPrompt: prompt,
|
|
146
|
-
lockedPaths: [],
|
|
147
|
-
auditEntry,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
// 1. Load locked paths
|
|
151
|
-
const lockedPaths = await loadLockedPaths();
|
|
152
|
-
// 1b. Spawn policy check (if agentType provided)
|
|
153
|
-
if (opts.agentType) {
|
|
154
|
-
await loadSpawnPolicy();
|
|
155
|
-
const spawnCheck = checkSpawnPolicy(opts.agentType, opts.currentAgentCount ?? 0, opts.currentTypeCount ?? 0);
|
|
156
|
-
if (!spawnCheck.allowed) {
|
|
157
|
-
const reason = `Spawn policy denied: ${spawnCheck.reason}`;
|
|
158
|
-
log.warn(reason, { taskId, agentType: opts.agentType });
|
|
159
|
-
const auditEntry = {
|
|
160
|
-
timestamp,
|
|
161
|
-
taskId,
|
|
162
|
-
label,
|
|
163
|
-
decision: "deny",
|
|
164
|
-
lockedPathCount: lockedPaths.length,
|
|
165
|
-
reason,
|
|
166
|
-
};
|
|
167
|
-
logActivity({
|
|
168
|
-
source: "agent",
|
|
169
|
-
summary: `Governance DENIED (spawn policy): ${label}`,
|
|
170
|
-
detail: reason,
|
|
171
|
-
actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
172
|
-
reason: "governance-gate",
|
|
173
|
-
});
|
|
174
|
-
return {
|
|
175
|
-
allowed: false,
|
|
176
|
-
deniedReason: reason,
|
|
177
|
-
governedPrompt: prompt,
|
|
178
|
-
lockedPaths,
|
|
179
|
-
auditEntry,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// 2. Issue voucher (unless skipped for system tasks)
|
|
184
|
-
let voucherToken;
|
|
185
|
-
if (!skipVoucher) {
|
|
186
|
-
try {
|
|
187
|
-
voucherToken = await issueVoucher(ltm, scope, voucherTtlMinutes);
|
|
188
|
-
log.info("Voucher issued for agent", { taskId, token: voucherToken, scope });
|
|
189
|
-
}
|
|
190
|
-
catch (err) {
|
|
191
|
-
const reason = `Voucher issuance failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
192
|
-
log.error(reason, { taskId });
|
|
193
|
-
const auditEntry = {
|
|
194
|
-
timestamp,
|
|
195
|
-
taskId,
|
|
196
|
-
label,
|
|
197
|
-
decision: "deny",
|
|
198
|
-
lockedPathCount: lockedPaths.length,
|
|
199
|
-
reason,
|
|
200
|
-
};
|
|
201
|
-
logActivity({
|
|
202
|
-
source: "agent",
|
|
203
|
-
summary: `Governance DENIED: ${label}`,
|
|
204
|
-
detail: reason,
|
|
205
|
-
actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
206
|
-
reason: "governance-gate",
|
|
207
|
-
});
|
|
208
|
-
return {
|
|
209
|
-
allowed: false,
|
|
210
|
-
deniedReason: reason,
|
|
211
|
-
governedPrompt: prompt,
|
|
212
|
-
lockedPaths,
|
|
213
|
-
auditEntry,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// 3. Load principles
|
|
218
|
-
const principlesSection = await loadPrinciples();
|
|
219
|
-
// 4. Build governed prompt
|
|
220
|
-
const scopeSection = opts.scopeCeiling
|
|
221
|
-
? `\n## Scope Ceiling\nYou may only operate within: \`${resolve(opts.scopeCeiling)}\`\nDo NOT read, write, or access files outside this directory. Sub-agents\nyou spawn inherit this ceiling and cannot widen it.\n`
|
|
222
|
-
: "";
|
|
223
|
-
const governancePreamble = [
|
|
224
|
-
"## Governance Context",
|
|
225
|
-
"This agent session is governed by the Core orchestration system.",
|
|
226
|
-
"You are running with `--dangerously-skip-permissions`. In exchange,",
|
|
227
|
-
"governance controls replace the permission prompt. Violating these",
|
|
228
|
-
"controls will terminate your session.",
|
|
229
|
-
"",
|
|
230
|
-
voucherToken ? buildVoucherSection(voucherToken, scope) : "",
|
|
231
|
-
scopeSection,
|
|
232
|
-
buildLockedPathsSection(lockedPaths),
|
|
233
|
-
principlesSection,
|
|
234
|
-
"## Heartbeat Requirement",
|
|
235
|
-
"Your actions are monitored. Extended silence (no file writes, no output)",
|
|
236
|
-
"will trigger a timeout and termination. Stay on task.",
|
|
237
|
-
"",
|
|
238
|
-
"---",
|
|
239
|
-
"",
|
|
240
|
-
]
|
|
241
|
-
.filter(Boolean)
|
|
242
|
-
.join("\n");
|
|
243
|
-
const governedPrompt = governancePreamble + prompt;
|
|
244
|
-
// 5. Log the decision
|
|
245
|
-
const auditEntry = {
|
|
246
|
-
timestamp,
|
|
247
|
-
taskId,
|
|
248
|
-
label,
|
|
249
|
-
decision: "allow",
|
|
250
|
-
voucherToken,
|
|
251
|
-
voucherScope: scope,
|
|
252
|
-
lockedPathCount: lockedPaths.length,
|
|
253
|
-
};
|
|
254
|
-
logActivity({
|
|
255
|
-
source: "agent",
|
|
256
|
-
summary: `Governance ALLOWED: ${label}`,
|
|
257
|
-
detail: `Voucher: ${voucherToken ?? "skipped"}, locked paths: ${lockedPaths.length}`,
|
|
258
|
-
actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
259
|
-
reason: "governance-gate",
|
|
260
|
-
});
|
|
261
|
-
log.info("Governance gate passed", { taskId, label, voucherToken });
|
|
262
|
-
return {
|
|
263
|
-
allowed: true,
|
|
264
|
-
voucherToken,
|
|
265
|
-
governedPrompt,
|
|
266
|
-
lockedPaths,
|
|
267
|
-
auditEntry,
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Revoke a governance voucher (call on agent completion or termination).
|
|
272
|
-
*/
|
|
273
|
-
export async function revokeGovernanceVoucher(ltm, token) {
|
|
274
|
-
try {
|
|
275
|
-
await revokeVoucher(ltm, token);
|
|
276
|
-
log.info("Governance voucher revoked", { token });
|
|
277
|
-
}
|
|
278
|
-
catch (err) {
|
|
279
|
-
log.warn("Failed to revoke voucher", {
|
|
280
|
-
token,
|
|
281
|
-
error: err instanceof Error ? err.message : String(err),
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Validate that a voucher is still active (for mid-session checks).
|
|
287
|
-
*/
|
|
288
|
-
export async function validateGovernanceVoucher(ltm, token) {
|
|
289
|
-
const result = await checkVoucher(ltm, token);
|
|
290
|
-
return result.valid;
|
|
291
|
-
}
|
|
292
|
-
//# sourceMappingURL=governance.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"governance.js","sourceRoot":"","sources":["../../src/agents/governance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAY,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAkB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AA0D5C,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,SAAS,uBAAuB,CAAC,KAAe;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO;;;;;EAKP,QAAQ;CACT,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,KAAa;IACvD,OAAO;;oCAE2B,KAAK,mBAAmB,KAAK;;CAEhE,CAAC;AACF,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACxD,yDAAyD;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,OAAO;;;EAGT,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;CAC9C,CAAC;IACA,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,GAAuB,EAAE,OAA2B;IAChF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC,CAAC,6BAA6B;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC,CAAK,gEAAgE;IAE3F,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACnE,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3E,wDAAwD;IACxD,IAAI,WAAW,KAAK,eAAe;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,WAAW,CAAC,UAAU,CAAC,eAAe,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/D,OAAO,yBAAyB,GAAG,sBAAsB,OAAO,8CAA8C,CAAC;AACjH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,aAAiC,EAAE,GAAuB;IAC3F,MAAM,YAAY,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1C,IAAI,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5E,MAAM,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAEjF,6CAA6C;IAC7C,IAAI,WAAW,CAAC,UAAU,CAAC,eAAe,GAAG,GAAG,CAAC,IAAI,WAAW,KAAK,eAAe,EAAE,CAAC;QACrF,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,6CAA6C;IAC7E,CAAC;IACD,2EAA2E;IAC3E,0CAA0C;IAC1C,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC;AAChC,CAAC;AAED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAuB;IAEvB,MAAM,EACJ,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,EACN,GAAG,EACH,KAAK,EAAE,aAAa,EACpB,iBAAiB,GAAG,EAAE,EACtB,WAAW,GAAG,KAAK,GACpB,GAAG,IAAI,CAAC;IAET,MAAM,KAAK,GAAG,aAAa,IAAI,eAAe,MAAM,EAAE,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE3C,gDAAgD;IAChD,MAAM,cAAc,GAAG,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACzE,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAEhF,MAAM,UAAU,GAAyB;YACvC,SAAS;YACT,MAAM;YACN,KAAK;YACL,QAAQ,EAAE,MAAM;YAChB,eAAe,EAAE,CAAC;YAClB,MAAM,EAAE,cAAc;SACvB,CAAC;QAEF,WAAW,CAAC;YACV,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,sCAAsC,KAAK,EAAE;YACtD,MAAM,EAAE,cAAc;YACtB,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;YACxD,MAAM,EAAE,iBAAiB;SAC1B,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,cAAc;YAC5B,cAAc,EAAE,MAAM;YACtB,WAAW,EAAE,EAAE;YACf,UAAU;SACX,CAAC;IACJ,CAAC;IAED,uBAAuB;IACvB,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAE5C,iDAAiD;IACjD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,eAAe,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,gBAAgB,CACjC,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,iBAAiB,IAAI,CAAC,EAC3B,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,wBAAwB,UAAU,CAAC,MAAM,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAExD,MAAM,UAAU,GAAyB;gBACvC,SAAS;gBACT,MAAM;gBACN,KAAK;gBACL,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,WAAW,CAAC,MAAM;gBACnC,MAAM;aACP,CAAC;YAEF,WAAW,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,qCAAqC,KAAK,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;gBACxD,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,MAAM;gBACtB,WAAW;gBACX,UAAU;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAgC,CAAC;IACrC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;YACjE,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9F,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAE9B,MAAM,UAAU,GAAyB;gBACvC,SAAS;gBACT,MAAM;gBACN,KAAK;gBACL,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,WAAW,CAAC,MAAM;gBACnC,MAAM;aACP,CAAC;YAEF,WAAW,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,sBAAsB,KAAK,EAAE;gBACtC,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;gBACxD,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,MAAM;gBACtB,WAAW;gBACX,UAAU;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,iBAAiB,GAAG,MAAM,cAAc,EAAE,CAAC;IAEjD,2BAA2B;IAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY;QACpC,CAAC,CAAC,sDAAsD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,mIAAmI;QACrN,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,kBAAkB,GAAG;QACzB,uBAAuB;QACvB,kEAAkE;QAClE,qEAAqE;QACrE,oEAAoE;QACpE,uCAAuC;QACvC,EAAE;QACF,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5D,YAAY;QACZ,uBAAuB,CAAC,WAAW,CAAC;QACpC,iBAAiB;QACjB,0BAA0B;QAC1B,0EAA0E;QAC1E,uDAAuD;QACvD,EAAE;QACF,KAAK;QACL,EAAE;KACH;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,cAAc,GAAG,kBAAkB,GAAG,MAAM,CAAC;IAEnD,sBAAsB;IACtB,MAAM,UAAU,GAAyB;QACvC,SAAS;QACT,MAAM;QACN,KAAK;QACL,QAAQ,EAAE,OAAO;QACjB,YAAY;QACZ,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,WAAW,CAAC,MAAM;KACpC,CAAC;IAEF,WAAW,CAAC;QACV,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,uBAAuB,KAAK,EAAE;QACvC,MAAM,EAAE,YAAY,YAAY,IAAI,SAAS,mBAAmB,WAAW,CAAC,MAAM,EAAE;QACpF,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;QACxD,MAAM,EAAE,iBAAiB;KAC1B,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IAEpE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,YAAY;QACZ,cAAc;QACd,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAwB,EACxB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE;YACnC,KAAK;YACL,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,GAAwB,EACxB,KAAa;IAEb,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC"}
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Governed Agent Spawn — CORE-9
|
|
3
|
-
*
|
|
4
|
-
* High-level entry point for spawning Claude Code agents with full
|
|
5
|
-
* governance controls. Composes:
|
|
6
|
-
*
|
|
7
|
-
* 1. Governance gate (voucher + locked paths + principles)
|
|
8
|
-
* 2. Agent spawning (via existing pool or direct spawn)
|
|
9
|
-
* 3. Heartbeat monitoring (silence + drift detection)
|
|
10
|
-
* 4. Lifecycle management (cleanup on completion/termination)
|
|
11
|
-
*
|
|
12
|
-
* This replaces raw `--dangerously-skip-permissions` with a governed
|
|
13
|
-
* equivalent where vouchers, locked paths, and principles replace the
|
|
14
|
-
* interactive permission prompt.
|
|
15
|
-
*/
|
|
16
|
-
import { governanceGate, revokeGovernanceVoucher, narrowScopeCeiling, } from "./governance.js";
|
|
17
|
-
import { createHeartbeatTracker, removeHeartbeatTracker, extractTaskKeywords, } from "./heartbeat.js";
|
|
18
|
-
import { logActivity, generateTraceId } from "../activity/log.js";
|
|
19
|
-
import { createLogger } from "../utils/logger.js";
|
|
20
|
-
const log = createLogger("governed-spawn");
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Governed spawn
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
/**
|
|
25
|
-
* Spawn a Claude Code agent with full governance controls.
|
|
26
|
-
*
|
|
27
|
-
* Flow:
|
|
28
|
-
* 1. Run governance gate (voucher + locked paths + principles)
|
|
29
|
-
* 2. If denied → return failure with reason
|
|
30
|
-
* 3. Spawn agent via pool with governed prompt
|
|
31
|
-
* 4. Attach heartbeat tracker
|
|
32
|
-
* 5. Wire lifecycle cleanup (voucher revocation on exit)
|
|
33
|
-
*/
|
|
34
|
-
export async function governedSpawn(request, deps) {
|
|
35
|
-
const traceId = generateTraceId();
|
|
36
|
-
const { ltm, pool } = deps;
|
|
37
|
-
log.info("Governed spawn requested", {
|
|
38
|
-
taskId: request.taskId,
|
|
39
|
-
label: request.label,
|
|
40
|
-
origin: request.origin,
|
|
41
|
-
traceId,
|
|
42
|
-
});
|
|
43
|
-
// 1. Run governance gate (scope ceiling validated here)
|
|
44
|
-
const govOpts = {
|
|
45
|
-
taskId: request.taskId,
|
|
46
|
-
label: request.label,
|
|
47
|
-
prompt: request.prompt,
|
|
48
|
-
origin: request.origin,
|
|
49
|
-
ltm,
|
|
50
|
-
voucherTtlMinutes: request.voucherTtlMinutes,
|
|
51
|
-
skipVoucher: request.skipVoucher,
|
|
52
|
-
agentType: request.agentType,
|
|
53
|
-
currentAgentCount: request.currentAgentCount,
|
|
54
|
-
currentTypeCount: request.currentTypeCount,
|
|
55
|
-
cwd: request.cwd,
|
|
56
|
-
scopeCeiling: request.scopeCeiling,
|
|
57
|
-
};
|
|
58
|
-
const governance = await governanceGate(govOpts);
|
|
59
|
-
// 2. Check governance decision
|
|
60
|
-
if (!governance.allowed) {
|
|
61
|
-
log.warn("Governed spawn denied", {
|
|
62
|
-
taskId: request.taskId,
|
|
63
|
-
reason: governance.deniedReason,
|
|
64
|
-
traceId,
|
|
65
|
-
});
|
|
66
|
-
return {
|
|
67
|
-
success: false,
|
|
68
|
-
governance,
|
|
69
|
-
traceId,
|
|
70
|
-
deniedReason: governance.deniedReason,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
// 3. Spawn agent via pool
|
|
74
|
-
if (!pool) {
|
|
75
|
-
const reason = "No agent pool available — cannot spawn governed agent";
|
|
76
|
-
log.error(reason, { taskId: request.taskId });
|
|
77
|
-
// Revoke the voucher since we can't use it
|
|
78
|
-
if (governance.voucherToken) {
|
|
79
|
-
await revokeGovernanceVoucher(ltm, governance.voucherToken);
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
success: false,
|
|
83
|
-
governance,
|
|
84
|
-
traceId,
|
|
85
|
-
deniedReason: reason,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
// Compute effective scope ceiling for this agent and its children
|
|
89
|
-
const effectiveCeiling = narrowScopeCeiling(request.scopeCeiling, request.cwd);
|
|
90
|
-
let instance;
|
|
91
|
-
try {
|
|
92
|
-
const spawnRequest = {
|
|
93
|
-
taskId: request.taskId,
|
|
94
|
-
label: request.label,
|
|
95
|
-
prompt: governance.governedPrompt,
|
|
96
|
-
cwd: request.cwd,
|
|
97
|
-
origin: request.origin,
|
|
98
|
-
tags: [
|
|
99
|
-
...(request.tags ?? []),
|
|
100
|
-
"governed",
|
|
101
|
-
governance.voucherToken ? `voucher:${governance.voucherToken}` : "voucher:none",
|
|
102
|
-
`scope-ceiling:${effectiveCeiling}`,
|
|
103
|
-
],
|
|
104
|
-
parentId: request.parentId,
|
|
105
|
-
};
|
|
106
|
-
instance = await pool.spawn(spawnRequest);
|
|
107
|
-
logActivity({
|
|
108
|
-
source: "agent",
|
|
109
|
-
summary: `Governed agent spawned: ${request.label}`,
|
|
110
|
-
detail: `Instance: ${instance.id}, PID: ${instance.pid}, voucher: ${governance.voucherToken ?? "none"}`,
|
|
111
|
-
traceId,
|
|
112
|
-
actionLabel: request.origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
113
|
-
reason: "governed-spawn",
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
const reason = `Spawn failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
118
|
-
log.error(reason, { taskId: request.taskId, traceId });
|
|
119
|
-
// Revoke voucher on spawn failure
|
|
120
|
-
if (governance.voucherToken) {
|
|
121
|
-
await revokeGovernanceVoucher(ltm, governance.voucherToken);
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
success: false,
|
|
125
|
-
governance,
|
|
126
|
-
traceId,
|
|
127
|
-
deniedReason: reason,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
// 4. Attach heartbeat tracker
|
|
131
|
-
const taskKeywords = extractTaskKeywords(request.prompt);
|
|
132
|
-
const heartbeat = createHeartbeatTracker(request.taskId, instance.id, {
|
|
133
|
-
taskDescription: request.prompt,
|
|
134
|
-
taskKeywords,
|
|
135
|
-
...request.heartbeat,
|
|
136
|
-
}, async (instanceId, reason) => {
|
|
137
|
-
// Termination callback from heartbeat
|
|
138
|
-
log.warn("Heartbeat triggered termination", { instanceId, reason, traceId });
|
|
139
|
-
try {
|
|
140
|
-
await pool.terminate(instanceId, reason);
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
log.error("Failed to terminate via heartbeat", {
|
|
144
|
-
instanceId,
|
|
145
|
-
error: err instanceof Error ? err.message : String(err),
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
heartbeat.start();
|
|
150
|
-
// 5. Wire lifecycle cleanup via bus events
|
|
151
|
-
const cleanupHandler = async (event) => {
|
|
152
|
-
if (event.agentId !== instance.id)
|
|
153
|
-
return;
|
|
154
|
-
const terminalStates = new Set(["completed", "failed", "terminated"]);
|
|
155
|
-
if (!terminalStates.has(event.newState))
|
|
156
|
-
return;
|
|
157
|
-
// Remove handler
|
|
158
|
-
pool.runtimeManager.bus.off("agent:lifecycle", cleanupHandler);
|
|
159
|
-
// Stop heartbeat
|
|
160
|
-
removeHeartbeatTracker(instance.id);
|
|
161
|
-
// Revoke voucher
|
|
162
|
-
if (governance.voucherToken) {
|
|
163
|
-
await revokeGovernanceVoucher(ltm, governance.voucherToken);
|
|
164
|
-
}
|
|
165
|
-
logActivity({
|
|
166
|
-
source: "agent",
|
|
167
|
-
summary: `Governed agent ${event.newState}: ${request.label}`,
|
|
168
|
-
detail: `Instance: ${instance.id}, voucher revoked: ${governance.voucherToken ?? "none"}`,
|
|
169
|
-
traceId,
|
|
170
|
-
actionLabel: request.origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
|
|
171
|
-
reason: "governed-lifecycle",
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
pool.runtimeManager.bus.on("agent:lifecycle", cleanupHandler);
|
|
175
|
-
log.info("Governed spawn complete", {
|
|
176
|
-
taskId: request.taskId,
|
|
177
|
-
instanceId: instance.id,
|
|
178
|
-
pid: instance.pid,
|
|
179
|
-
voucherToken: governance.voucherToken,
|
|
180
|
-
heartbeatKeywords: taskKeywords.slice(0, 5),
|
|
181
|
-
traceId,
|
|
182
|
-
});
|
|
183
|
-
return {
|
|
184
|
-
success: true,
|
|
185
|
-
instance,
|
|
186
|
-
governance,
|
|
187
|
-
heartbeat,
|
|
188
|
-
traceId,
|
|
189
|
-
scopeCeiling: effectiveCeiling,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
//# sourceMappingURL=governed-spawn.js.map
|