@ouro.bot/cli 0.1.0-alpha.22 → 0.1.0-alpha.220
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +187 -191
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
- package/changelog.json +1354 -2
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +119 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +120 -0
- package/dist/arc/obligations.js +237 -0
- package/dist/arc/presence.js +185 -0
- package/dist/heart/active-work.js +832 -0
- package/dist/heart/agent-entry.js +37 -2
- package/dist/heart/auth/auth-flow.js +444 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +305 -0
- package/dist/heart/config.js +59 -30
- package/dist/heart/core.js +601 -145
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +149 -0
- package/dist/heart/daemon/agent-discovery.js +81 -0
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +557 -0
- package/dist/heart/daemon/cli-exec.js +1847 -0
- package/dist/heart/daemon/cli-parse.js +759 -0
- package/dist/heart/daemon/cli-render.js +316 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1163
- package/dist/heart/daemon/daemon-entry.js +202 -4
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
- package/dist/heart/daemon/daemon-tombstone.js +123 -0
- package/dist/heart/daemon/daemon.js +487 -20
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/launchd.js +39 -8
- package/dist/heart/daemon/log-tailer.js +4 -3
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/os-cron-deps.js +134 -0
- package/dist/heart/daemon/ouro-bot-entry.js +1 -1
- package/dist/heart/daemon/process-manager.js +123 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +58 -15
- package/dist/heart/daemon/runtime-metadata.js +101 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +72 -3
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +202 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/habits/habit-migration.js +181 -0
- package/dist/heart/habits/habit-parser.js +119 -0
- package/dist/heart/habits/habit-scheduler.js +369 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +29 -119
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
- package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
- package/dist/heart/identity.js +144 -55
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/mcp/mcp-server.js +608 -0
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/outlook/outlook-http.js +439 -0
- package/dist/heart/outlook/outlook-read.js +1618 -0
- package/dist/heart/outlook/outlook-render.js +1032 -0
- package/dist/heart/outlook/outlook-types.js +7 -0
- package/dist/heart/outlook/outlook-view.js +194 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +162 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +187 -41
- package/dist/heart/providers/azure.js +116 -10
- package/dist/heart/providers/github-copilot.js +157 -0
- package/dist/heart/providers/minimax.js +33 -3
- package/dist/heart/providers/openai-codex.js +51 -16
- package/dist/heart/session-activity.js +172 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/start-of-turn-packet.js +330 -0
- package/dist/heart/streaming.js +36 -27
- package/dist/heart/sync.js +217 -0
- package/dist/heart/target-resolution.js +127 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/tool-activity-callbacks.js +36 -0
- package/dist/heart/tool-description.js +135 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +358 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
- package/dist/heart/versioning/ouro-version-manager.js +171 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
- package/dist/heart/{daemon → versioning}/update-checker.js +9 -1
- package/dist/heart/{daemon → versioning}/update-hooks.js +20 -2
- package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
- package/dist/mind/associative-recall.js +126 -66
- package/dist/mind/bundle-manifest.js +8 -1
- package/dist/mind/context.js +125 -14
- package/dist/mind/{memory.js → diary.js} +73 -96
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +56 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/store-file.js +36 -0
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +779 -109
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +47 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +64 -4
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
- package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
- package/dist/outlook-ui/index.html +15 -0
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +11 -5
- package/dist/repertoire/api-client.js +100 -0
- package/dist/repertoire/bitwarden-client.js +290 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +330 -0
- package/dist/repertoire/coding/feedback.js +197 -30
- package/dist/repertoire/coding/manager.js +149 -2
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +170 -7
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +342 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +251 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +14 -23
- package/dist/repertoire/tasks/board.js +43 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +28 -10
- package/dist/repertoire/tasks/lifecycle.js +2 -2
- package/dist/repertoire/tasks/parser.js +3 -2
- package/dist/repertoire/tasks/scanner.js +194 -37
- package/dist/repertoire/tasks/transitions.js +11 -28
- package/dist/repertoire/tools-base.js +35 -771
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-bridge.js +141 -0
- package/dist/repertoire/tools-config.js +266 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flow.js +62 -0
- package/dist/repertoire/tools-github.js +1 -6
- package/dist/repertoire/tools-memory.js +347 -0
- package/dist/repertoire/tools-session.js +721 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-surface.js +242 -0
- package/dist/repertoire/tools-teams.js +12 -59
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-vault.js +185 -0
- package/dist/repertoire/tools.js +132 -124
- package/dist/repertoire/travel-api-client.js +224 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/attention-queue.js +97 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +109 -10
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +109 -0
- package/dist/senses/bluebubbles/index.js +1327 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +119 -24
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +13 -5
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
- package/dist/senses/bluebubbles/runtime-state.js +109 -0
- package/dist/senses/bluebubbles/session-cleanup.js +72 -0
- package/dist/senses/cli/adapter.js +274 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +358 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +83 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +198 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +1 -1
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +503 -244
- package/dist/senses/commands.js +65 -1
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +112 -19
- package/dist/senses/inner-dialog.js +591 -84
- package/dist/senses/pipeline.js +559 -0
- package/dist/senses/shared-turn.js +196 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +667 -120
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +12 -6
- package/skills/browser-navigation.md +110 -0
- package/skills/configure-dev-tools.md +81 -0
- package/skills/travel-planning.md +143 -0
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/senses/bluebubbles-entry.js +0 -11
- package/dist/senses/bluebubbles.js +0 -421
- package/dist/senses/debug-activity.js +0 -107
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -235
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -382
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bitwarden vault client for credential management.
|
|
4
|
+
*
|
|
5
|
+
* SDK-first approach: attempts dynamic import of @bitwarden/sdk-napi,
|
|
6
|
+
* falls back to `bw` CLI with --session flag.
|
|
7
|
+
*
|
|
8
|
+
* Raw secrets are NEVER returned to callers except via getRawSecret(),
|
|
9
|
+
* which is reserved for internal use by the credential gateway (apiRequest vaultKey).
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.BitwardenClient = void 0;
|
|
46
|
+
exports.getBitwardenClient = getBitwardenClient;
|
|
47
|
+
exports.resetBitwardenClient = resetBitwardenClient;
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
49
|
+
const runtime_1 = require("../nerves/runtime");
|
|
50
|
+
class BitwardenClient {
|
|
51
|
+
sessionKey = null;
|
|
52
|
+
connected = false;
|
|
53
|
+
clientMode = null;
|
|
54
|
+
async connect(config) {
|
|
55
|
+
(0, runtime_1.emitNervesEvent)({
|
|
56
|
+
event: "client.vault_connect_start",
|
|
57
|
+
component: "clients",
|
|
58
|
+
message: "connecting to Bitwarden vault",
|
|
59
|
+
meta: { mode: config.mode ?? "auto" },
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
if (config.mode === "cli") {
|
|
63
|
+
await this.connectCli(config);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Try SDK first, fall back to CLI
|
|
67
|
+
try {
|
|
68
|
+
await this.connectSdk(config);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
(0, runtime_1.emitNervesEvent)({
|
|
72
|
+
event: "client.vault_sdk_fallback",
|
|
73
|
+
component: "clients",
|
|
74
|
+
message: "SDK not available, falling back to bw CLI",
|
|
75
|
+
meta: {},
|
|
76
|
+
});
|
|
77
|
+
await this.connectCli(config);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
(0, runtime_1.emitNervesEvent)({
|
|
81
|
+
event: "client.vault_connect_end",
|
|
82
|
+
component: "clients",
|
|
83
|
+
message: "connected to Bitwarden vault",
|
|
84
|
+
meta: { mode: this.clientMode },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
(0, runtime_1.emitNervesEvent)({
|
|
89
|
+
level: "error",
|
|
90
|
+
event: "client.vault_connect_error",
|
|
91
|
+
component: "clients",
|
|
92
|
+
message: "failed to connect to Bitwarden vault",
|
|
93
|
+
/* v8 ignore next -- defensive: execCli always wraps in Error @preserve */
|
|
94
|
+
meta: { reason: err instanceof Error ? err.message : String(err) },
|
|
95
|
+
});
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async disconnect() {
|
|
100
|
+
this.sessionKey = null;
|
|
101
|
+
this.connected = false;
|
|
102
|
+
this.clientMode = null;
|
|
103
|
+
(0, runtime_1.emitNervesEvent)({
|
|
104
|
+
event: "client.vault_disconnect",
|
|
105
|
+
component: "clients",
|
|
106
|
+
message: "disconnected from Bitwarden vault",
|
|
107
|
+
meta: {},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
isConnected() {
|
|
111
|
+
return this.connected;
|
|
112
|
+
}
|
|
113
|
+
async getItem(id) {
|
|
114
|
+
this.requireConnected();
|
|
115
|
+
return this.withNervesEvents("getItem", { id }, async () => {
|
|
116
|
+
const raw = await this.fetchRawItem(id);
|
|
117
|
+
return this.stripSecrets(raw);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async createItem(name, fields) {
|
|
121
|
+
this.requireConnected();
|
|
122
|
+
return this.withNervesEvents("createItem", { name }, async () => {
|
|
123
|
+
const itemFields = Object.entries(fields).map(([k, v]) => ({
|
|
124
|
+
name: k,
|
|
125
|
+
value: v,
|
|
126
|
+
type: 0, // text type
|
|
127
|
+
}));
|
|
128
|
+
const itemTemplate = {
|
|
129
|
+
type: 1, // login type
|
|
130
|
+
name,
|
|
131
|
+
fields: itemFields,
|
|
132
|
+
login: {},
|
|
133
|
+
};
|
|
134
|
+
const encoded = Buffer.from(JSON.stringify(itemTemplate)).toString("base64");
|
|
135
|
+
const stdout = await this.execCli(["create", "item", encoded]);
|
|
136
|
+
const parsed = this.parseCliResponse(stdout);
|
|
137
|
+
return { id: parsed.id, name: parsed.name, type: parsed.type };
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
async listItems(search) {
|
|
141
|
+
this.requireConnected();
|
|
142
|
+
return this.withNervesEvents("listItems", { search }, async () => {
|
|
143
|
+
const args = ["list", "items"];
|
|
144
|
+
if (search) {
|
|
145
|
+
args.push("--search", search);
|
|
146
|
+
}
|
|
147
|
+
const stdout = await this.execCli(args);
|
|
148
|
+
const parsed = this.parseCliResponse(stdout);
|
|
149
|
+
const items = Array.isArray(parsed.data) ? parsed.data : (Array.isArray(parsed) ? parsed : []);
|
|
150
|
+
return items.map((item) => ({ id: item.id, name: item.name, type: item.type }));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
async deleteItem(id) {
|
|
154
|
+
this.requireConnected();
|
|
155
|
+
return this.withNervesEvents("deleteItem", { id }, async () => {
|
|
156
|
+
await this.execCli(["delete", "item", id]);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Internal: used by credential gateway (PR 5) to get raw secret for HTTP injection.
|
|
161
|
+
* NOT exposed via tools -- only called by apiRequest() internally.
|
|
162
|
+
*/
|
|
163
|
+
async getRawSecret(itemId, fieldName) {
|
|
164
|
+
this.requireConnected();
|
|
165
|
+
return this.withNervesEvents("getRawSecret", { itemId, fieldName }, async () => {
|
|
166
|
+
const raw = await this.fetchRawItem(itemId);
|
|
167
|
+
// Check custom fields first
|
|
168
|
+
if (raw.fields) {
|
|
169
|
+
const field = raw.fields.find((f) => f.name === fieldName);
|
|
170
|
+
if (field)
|
|
171
|
+
return field.value;
|
|
172
|
+
}
|
|
173
|
+
// Check login.password
|
|
174
|
+
if (fieldName === "password" && raw.login?.password) {
|
|
175
|
+
return raw.login.password;
|
|
176
|
+
}
|
|
177
|
+
throw new Error(`field "${fieldName}" not found on vault item "${itemId}"`);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// --- Private methods ---
|
|
181
|
+
requireConnected() {
|
|
182
|
+
if (!this.connected) {
|
|
183
|
+
throw new Error("vault not connected -- call connect() first");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async withNervesEvents(operation, meta, fn) {
|
|
187
|
+
(0, runtime_1.emitNervesEvent)({
|
|
188
|
+
event: "client.request_start",
|
|
189
|
+
component: "clients",
|
|
190
|
+
message: `vault ${operation} starting`,
|
|
191
|
+
meta: { operation, ...meta },
|
|
192
|
+
});
|
|
193
|
+
try {
|
|
194
|
+
const result = await fn();
|
|
195
|
+
(0, runtime_1.emitNervesEvent)({
|
|
196
|
+
event: "client.request_end",
|
|
197
|
+
component: "clients",
|
|
198
|
+
message: `vault ${operation} complete`,
|
|
199
|
+
meta: { operation, ...meta },
|
|
200
|
+
});
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
(0, runtime_1.emitNervesEvent)({
|
|
205
|
+
level: "error",
|
|
206
|
+
event: "client.error",
|
|
207
|
+
component: "clients",
|
|
208
|
+
message: `vault ${operation} failed`,
|
|
209
|
+
/* v8 ignore next -- defensive: callers always throw Error instances @preserve */
|
|
210
|
+
meta: { operation, reason: err instanceof Error ? err.message : String(err), ...meta },
|
|
211
|
+
});
|
|
212
|
+
throw err;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async connectSdk(_config) {
|
|
216
|
+
// Attempt dynamic import of SDK
|
|
217
|
+
// This will throw if the package is not installed
|
|
218
|
+
const sdk = await Promise.resolve(`${"@bitwarden/sdk-napi"}`).then(s => __importStar(require(s)));
|
|
219
|
+
/* v8 ignore start -- SDK not yet published; path tested when package becomes available @preserve */
|
|
220
|
+
const client = new sdk.BitwardenClient({ apiUrl: _config.serverUrl ?? "https://api.bitwarden.com" }, 0);
|
|
221
|
+
await client.auth().loginAccessToken(_config.accessToken, "");
|
|
222
|
+
this.connected = true;
|
|
223
|
+
this.clientMode = "sdk";
|
|
224
|
+
/* v8 ignore stop */
|
|
225
|
+
}
|
|
226
|
+
async connectCli(config) {
|
|
227
|
+
this.sessionKey = config.accessToken;
|
|
228
|
+
// Verify CLI is available and session key works
|
|
229
|
+
await this.execCli(["status"]);
|
|
230
|
+
this.connected = true;
|
|
231
|
+
this.clientMode = "cli";
|
|
232
|
+
}
|
|
233
|
+
async fetchRawItem(id) {
|
|
234
|
+
const stdout = await this.execCli(["get", "item", id]);
|
|
235
|
+
const parsed = this.parseCliResponse(stdout);
|
|
236
|
+
return parsed;
|
|
237
|
+
}
|
|
238
|
+
stripSecrets(raw) {
|
|
239
|
+
const item = {
|
|
240
|
+
id: raw.id,
|
|
241
|
+
name: raw.name,
|
|
242
|
+
type: raw.type,
|
|
243
|
+
};
|
|
244
|
+
if (raw.notes)
|
|
245
|
+
item.notes = raw.notes;
|
|
246
|
+
if (raw.fields)
|
|
247
|
+
item.fields = raw.fields;
|
|
248
|
+
if (raw.login) {
|
|
249
|
+
item.login = {};
|
|
250
|
+
if (raw.login.username)
|
|
251
|
+
item.login.username = raw.login.username;
|
|
252
|
+
if (raw.login.uris)
|
|
253
|
+
item.login.uris = raw.login.uris;
|
|
254
|
+
// password intentionally NOT copied
|
|
255
|
+
}
|
|
256
|
+
return item;
|
|
257
|
+
}
|
|
258
|
+
parseCliResponse(stdout) {
|
|
259
|
+
const parsed = JSON.parse(stdout);
|
|
260
|
+
// bw CLI with --response wraps in { success, data }
|
|
261
|
+
if (parsed.success !== undefined && parsed.data !== undefined) {
|
|
262
|
+
return parsed.data;
|
|
263
|
+
}
|
|
264
|
+
return parsed;
|
|
265
|
+
}
|
|
266
|
+
execCli(args) {
|
|
267
|
+
return new Promise((resolve, reject) => {
|
|
268
|
+
const fullArgs = [...args, "--session", this.sessionKey, "--response"];
|
|
269
|
+
(0, child_process_1.execFile)("bw", fullArgs, { timeout: 30_000 }, (err, stdout, _stderr) => {
|
|
270
|
+
if (err) {
|
|
271
|
+
reject(new Error(`bw CLI error: ${err.message}`));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
resolve(stdout);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
exports.BitwardenClient = BitwardenClient;
|
|
280
|
+
// Singleton accessor
|
|
281
|
+
let _client = null;
|
|
282
|
+
function getBitwardenClient() {
|
|
283
|
+
if (!_client) {
|
|
284
|
+
_client = new BitwardenClient();
|
|
285
|
+
}
|
|
286
|
+
return _client;
|
|
287
|
+
}
|
|
288
|
+
function resetBitwardenClient() {
|
|
289
|
+
_client = null;
|
|
290
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Codex JSONL event parser.
|
|
4
|
+
* Parses typed events from Codex --json output:
|
|
5
|
+
* thread.started, turn.started, turn.completed, item.completed.
|
|
6
|
+
* Maps events to coding session status transitions.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.parseCodexJsonlEvent = parseCodexJsonlEvent;
|
|
10
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
11
|
+
const KNOWN_TYPES = new Set(["thread.started", "turn.started", "turn.completed", "item.completed"]);
|
|
12
|
+
/**
|
|
13
|
+
* Parse a single JSONL line from Codex --json output.
|
|
14
|
+
* Returns null for invalid JSON, empty strings, or unknown event types.
|
|
15
|
+
*/
|
|
16
|
+
function parseCodexJsonlEvent(line) {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
if (trimmed.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
let parsed;
|
|
21
|
+
try {
|
|
22
|
+
parsed = JSON.parse(trimmed);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
(0, runtime_1.emitNervesEvent)({
|
|
26
|
+
component: "repertoire",
|
|
27
|
+
event: "repertoire.codex_jsonl_parse_error",
|
|
28
|
+
message: "failed to parse codex JSONL line",
|
|
29
|
+
meta: { line: trimmed.slice(0, 100) },
|
|
30
|
+
});
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const type = parsed.type;
|
|
34
|
+
if (!type || !KNOWN_TYPES.has(type))
|
|
35
|
+
return null;
|
|
36
|
+
const event = {
|
|
37
|
+
type: type,
|
|
38
|
+
threadId: typeof parsed.thread_id === "string" ? parsed.thread_id : undefined,
|
|
39
|
+
turnId: typeof parsed.turn_id === "string" ? parsed.turn_id : undefined,
|
|
40
|
+
item: typeof parsed.item === "object" && parsed.item !== null ? parsed.item : undefined,
|
|
41
|
+
raw: parsed,
|
|
42
|
+
statusHint: mapStatusHint(type),
|
|
43
|
+
};
|
|
44
|
+
(0, runtime_1.emitNervesEvent)({
|
|
45
|
+
component: "repertoire",
|
|
46
|
+
event: "repertoire.codex_jsonl_event",
|
|
47
|
+
message: "parsed codex JSONL event",
|
|
48
|
+
meta: { type, threadId: event.threadId ?? null },
|
|
49
|
+
});
|
|
50
|
+
return event;
|
|
51
|
+
}
|
|
52
|
+
function mapStatusHint(type) {
|
|
53
|
+
switch (type) {
|
|
54
|
+
case "thread.started":
|
|
55
|
+
case "turn.started":
|
|
56
|
+
return "running";
|
|
57
|
+
case "turn.completed":
|
|
58
|
+
case "item.completed":
|
|
59
|
+
return null; // No automatic status change for completion events
|
|
60
|
+
/* v8 ignore next -- defensive default for unknown event types */
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.prepareCodingContextPack = prepareCodingContextPack;
|
|
37
|
+
exports.emitCodingEpisode = emitCodingEpisode;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const active_work_1 = require("../../heart/active-work");
|
|
43
|
+
const identity_1 = require("../../heart/identity");
|
|
44
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
45
|
+
const episodes_1 = require("../../arc/episodes");
|
|
46
|
+
const skills_1 = require("../skills");
|
|
47
|
+
const CONTEXT_FILENAMES = ["AGENTS.md", "CLAUDE.md"];
|
|
48
|
+
function defaultRunCommand(command, args, cwd) {
|
|
49
|
+
const result = (0, child_process_1.spawnSync)(command, args, {
|
|
50
|
+
cwd,
|
|
51
|
+
encoding: "utf-8",
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
status: result.status ?? 1,
|
|
55
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
56
|
+
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function stableContextKey(request) {
|
|
60
|
+
const payload = JSON.stringify({
|
|
61
|
+
runner: request.runner,
|
|
62
|
+
workdir: request.workdir,
|
|
63
|
+
taskRef: request.taskRef ?? "",
|
|
64
|
+
parentAgent: request.parentAgent ?? "",
|
|
65
|
+
obligationId: request.obligationId ?? "",
|
|
66
|
+
originSession: request.originSession ?? null,
|
|
67
|
+
});
|
|
68
|
+
return crypto.createHash("sha1").update(payload).digest("hex").slice(0, 12);
|
|
69
|
+
}
|
|
70
|
+
function collectProjectContextFiles(workdir, deps) {
|
|
71
|
+
const files = [];
|
|
72
|
+
const seen = new Set();
|
|
73
|
+
let current = path.resolve(workdir);
|
|
74
|
+
const root = path.parse(current).root;
|
|
75
|
+
while (true) {
|
|
76
|
+
for (const filename of CONTEXT_FILENAMES) {
|
|
77
|
+
const candidate = path.join(current, filename);
|
|
78
|
+
if (!deps.existsSync(candidate) || seen.has(candidate))
|
|
79
|
+
continue;
|
|
80
|
+
try {
|
|
81
|
+
const content = deps.readFileSync(candidate, "utf-8").trim();
|
|
82
|
+
if (content.length > 0) {
|
|
83
|
+
files.unshift({ path: candidate, content });
|
|
84
|
+
seen.add(candidate);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Best-effort loading only.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (current === root)
|
|
92
|
+
break;
|
|
93
|
+
current = path.dirname(current);
|
|
94
|
+
}
|
|
95
|
+
return files;
|
|
96
|
+
}
|
|
97
|
+
function captureRepoSnapshot(workdir, runCommand) {
|
|
98
|
+
const repoRoot = runCommand("git", ["rev-parse", "--show-toplevel"], workdir);
|
|
99
|
+
if (repoRoot.status !== 0) {
|
|
100
|
+
return {
|
|
101
|
+
available: false,
|
|
102
|
+
repoRoot: null,
|
|
103
|
+
branch: null,
|
|
104
|
+
head: null,
|
|
105
|
+
statusLines: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const branch = runCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"], workdir);
|
|
109
|
+
const head = runCommand("git", ["rev-parse", "--short", "HEAD"], workdir);
|
|
110
|
+
const status = runCommand("git", ["status", "--short"], workdir);
|
|
111
|
+
return {
|
|
112
|
+
available: true,
|
|
113
|
+
repoRoot: repoRoot.stdout.trim() || null,
|
|
114
|
+
branch: branch.status === 0 ? branch.stdout.trim() || null : null,
|
|
115
|
+
head: head.status === 0 ? head.stdout.trim() || null : null,
|
|
116
|
+
statusLines: status.status === 0
|
|
117
|
+
? status.stdout.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean)
|
|
118
|
+
: [],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function buildIdentityPacket(snapshot, request) {
|
|
122
|
+
if (!snapshot.available) {
|
|
123
|
+
return {
|
|
124
|
+
repoPath: null,
|
|
125
|
+
worktreePath: null,
|
|
126
|
+
branch: null,
|
|
127
|
+
commit: null,
|
|
128
|
+
dirty: false,
|
|
129
|
+
dirtyFiles: [],
|
|
130
|
+
taskRef: request.taskRef ?? null,
|
|
131
|
+
verificationCommands: request.verificationCommands ?? [],
|
|
132
|
+
verificationStatus: "not-verified",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const dirtyFiles = snapshot.statusLines.filter((line) => line.length > 0);
|
|
136
|
+
return {
|
|
137
|
+
repoPath: snapshot.repoRoot,
|
|
138
|
+
worktreePath: snapshot.repoRoot,
|
|
139
|
+
branch: snapshot.branch,
|
|
140
|
+
commit: snapshot.head,
|
|
141
|
+
dirty: dirtyFiles.length > 0,
|
|
142
|
+
dirtyFiles,
|
|
143
|
+
taskRef: request.taskRef ?? null,
|
|
144
|
+
verificationCommands: request.verificationCommands ?? [],
|
|
145
|
+
verificationStatus: "not-verified",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function formatIdentitySection(packet) {
|
|
149
|
+
const lines = [
|
|
150
|
+
"## Coding Identity",
|
|
151
|
+
`repoPath: ${packet.repoPath ?? "unknown"}`,
|
|
152
|
+
`worktreePath: ${packet.worktreePath ?? "unknown"}`,
|
|
153
|
+
`branch: ${packet.branch ?? "unknown"}`,
|
|
154
|
+
`commit: ${packet.commit ?? "unknown"}`,
|
|
155
|
+
`dirty: ${packet.dirty}`,
|
|
156
|
+
];
|
|
157
|
+
if (packet.dirtyFiles.length > 0) {
|
|
158
|
+
lines.push("dirtyFiles:");
|
|
159
|
+
for (const file of packet.dirtyFiles) {
|
|
160
|
+
lines.push(file);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
lines.push(`taskRef: ${packet.taskRef ?? "none"}`);
|
|
164
|
+
if (packet.verificationCommands.length > 0) {
|
|
165
|
+
lines.push(`verificationCommands: ${packet.verificationCommands.join(", ")}`);
|
|
166
|
+
}
|
|
167
|
+
lines.push(`verificationStatus: ${packet.verificationStatus}`);
|
|
168
|
+
return lines.join("\n");
|
|
169
|
+
}
|
|
170
|
+
function formatContextFiles(files) {
|
|
171
|
+
if (files.length === 0)
|
|
172
|
+
return "(none found)";
|
|
173
|
+
return files.map((file) => `### ${file.path}\n${file.content}`).join("\n\n");
|
|
174
|
+
}
|
|
175
|
+
function formatSkills(skills) {
|
|
176
|
+
return skills.length > 0 ? skills.join(", ") : "(none found)";
|
|
177
|
+
}
|
|
178
|
+
function formatExistingSessions(sessions) {
|
|
179
|
+
if (sessions.length === 0)
|
|
180
|
+
return "activeSessions: none";
|
|
181
|
+
return sessions
|
|
182
|
+
.map((session) => {
|
|
183
|
+
return [
|
|
184
|
+
`- ${session.id}`,
|
|
185
|
+
`status=${session.status}`,
|
|
186
|
+
`lastActivityAt=${session.lastActivityAt}`,
|
|
187
|
+
session.taskRef ? `taskRef=${session.taskRef}` : null,
|
|
188
|
+
session.checkpoint ? `checkpoint=${session.checkpoint}` : null,
|
|
189
|
+
session.artifactPath ? `artifact=${session.artifactPath}` : null,
|
|
190
|
+
].filter(Boolean).join(" ");
|
|
191
|
+
})
|
|
192
|
+
.join("\n");
|
|
193
|
+
}
|
|
194
|
+
function formatOrigin(request) {
|
|
195
|
+
if (!request.originSession)
|
|
196
|
+
return "originSession: none";
|
|
197
|
+
return `originSession: ${request.originSession.channel}/${request.originSession.key} (${request.originSession.friendId})`;
|
|
198
|
+
}
|
|
199
|
+
function buildScopeContent(request, contextFiles, skills, agentName) {
|
|
200
|
+
return [
|
|
201
|
+
"# Coding Session Scope",
|
|
202
|
+
"",
|
|
203
|
+
"## Request",
|
|
204
|
+
`runner: ${request.runner}`,
|
|
205
|
+
`taskRef: ${request.taskRef ?? "unassigned"}`,
|
|
206
|
+
`parentAgent: ${request.parentAgent ?? agentName}`,
|
|
207
|
+
`workdir: ${request.workdir}`,
|
|
208
|
+
formatOrigin(request),
|
|
209
|
+
`obligationId: ${request.obligationId ?? "none"}`,
|
|
210
|
+
"",
|
|
211
|
+
"## Prompt",
|
|
212
|
+
request.prompt,
|
|
213
|
+
"",
|
|
214
|
+
"## Session Contract",
|
|
215
|
+
"- This is a focused coding lane opened by the parent Ouro agent.",
|
|
216
|
+
"- Execute the concrete prompt in the supplied workdir directly.",
|
|
217
|
+
"- Do not switch into planning/doing workflows or approval gates unless the prompt explicitly asks for them.",
|
|
218
|
+
"- Treat the current prompt, scope file, and live world-state checkpoint in the state file as the authoritative briefing for this lane.",
|
|
219
|
+
"",
|
|
220
|
+
"## Project Context Files",
|
|
221
|
+
formatContextFiles(contextFiles),
|
|
222
|
+
"",
|
|
223
|
+
"## Available Bundle Skills",
|
|
224
|
+
formatSkills(skills),
|
|
225
|
+
].join("\n");
|
|
226
|
+
}
|
|
227
|
+
function buildStateContent(request, contextKey, generatedAt, snapshot, existingSessions, agentName, identityPacket, activeWorkFrame, startOfTurnPacket) {
|
|
228
|
+
const gitSection = snapshot.available
|
|
229
|
+
? [
|
|
230
|
+
`repoRoot: ${snapshot.repoRoot ?? "unknown"}`,
|
|
231
|
+
`branch: ${snapshot.branch ?? "unknown"}`,
|
|
232
|
+
`head: ${snapshot.head ?? "unknown"}`,
|
|
233
|
+
"status:",
|
|
234
|
+
snapshot.statusLines.length > 0 ? snapshot.statusLines.join("\n") : "(clean)",
|
|
235
|
+
].join("\n")
|
|
236
|
+
: "git: unavailable";
|
|
237
|
+
return [
|
|
238
|
+
"# Coding Session State",
|
|
239
|
+
`generatedAt: ${generatedAt}`,
|
|
240
|
+
`contextKey: ${contextKey}`,
|
|
241
|
+
`agent: ${request.parentAgent ?? agentName}`,
|
|
242
|
+
formatOrigin(request),
|
|
243
|
+
`obligationId: ${request.obligationId ?? "none"}`,
|
|
244
|
+
...(startOfTurnPacket ? ["", "## Continuity", startOfTurnPacket] : []),
|
|
245
|
+
"",
|
|
246
|
+
formatIdentitySection(identityPacket),
|
|
247
|
+
"",
|
|
248
|
+
"## Workspace Snapshot",
|
|
249
|
+
gitSection,
|
|
250
|
+
...(activeWorkFrame ? ["", (0, active_work_1.formatLiveWorldStateCheckpoint)(activeWorkFrame)] : []),
|
|
251
|
+
"",
|
|
252
|
+
"## Related Coding Sessions",
|
|
253
|
+
formatExistingSessions(existingSessions),
|
|
254
|
+
].join("\n");
|
|
255
|
+
}
|
|
256
|
+
function relatedSessions(request, existingSessions) {
|
|
257
|
+
return existingSessions.filter((session) => {
|
|
258
|
+
return session.runner === request.runner
|
|
259
|
+
&& session.workdir === request.workdir
|
|
260
|
+
&& session.taskRef === request.taskRef;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
function prepareCodingContextPack(input, deps = {}) {
|
|
264
|
+
const agentRoot = deps.agentRoot ?? (0, identity_1.getAgentRoot)();
|
|
265
|
+
const agentName = deps.agentName ?? (0, identity_1.getAgentName)();
|
|
266
|
+
const nowIso = deps.nowIso ?? (() => new Date().toISOString());
|
|
267
|
+
const existsSync = deps.existsSync ?? fs.existsSync;
|
|
268
|
+
const readFileSync = deps.readFileSync ?? fs.readFileSync;
|
|
269
|
+
const writeFileSync = deps.writeFileSync ?? fs.writeFileSync;
|
|
270
|
+
const mkdirSync = deps.mkdirSync ?? fs.mkdirSync;
|
|
271
|
+
const listAvailableSkills = deps.listSkills ?? skills_1.listSkills;
|
|
272
|
+
const runCommand = deps.runCommand ?? defaultRunCommand;
|
|
273
|
+
const contextKey = stableContextKey(input.request);
|
|
274
|
+
const contextDir = path.join(agentRoot, "state", "coding", "context");
|
|
275
|
+
const scopeFile = path.join(contextDir, `${contextKey}-scope.md`);
|
|
276
|
+
const stateFile = path.join(contextDir, `${contextKey}-state.md`);
|
|
277
|
+
const contextFiles = collectProjectContextFiles(input.request.workdir, { existsSync, readFileSync });
|
|
278
|
+
const skills = listAvailableSkills();
|
|
279
|
+
const existingSessions = relatedSessions(input.request, input.existingSessions ?? []);
|
|
280
|
+
const snapshot = captureRepoSnapshot(input.request.workdir, runCommand);
|
|
281
|
+
const generatedAt = nowIso();
|
|
282
|
+
const identityPacket = buildIdentityPacket(snapshot, input.request);
|
|
283
|
+
const scopeContent = buildScopeContent(input.request, contextFiles, skills, agentName);
|
|
284
|
+
const stateContent = buildStateContent(input.request, contextKey, generatedAt, snapshot, existingSessions, agentName, identityPacket, input.activeWorkFrame, input.startOfTurnPacket || undefined);
|
|
285
|
+
mkdirSync(contextDir, { recursive: true });
|
|
286
|
+
writeFileSync(scopeFile, `${scopeContent}\n`, "utf-8");
|
|
287
|
+
writeFileSync(stateFile, `${stateContent}\n`, "utf-8");
|
|
288
|
+
(0, runtime_1.emitNervesEvent)({
|
|
289
|
+
component: "repertoire",
|
|
290
|
+
event: "repertoire.coding_context_pack_written",
|
|
291
|
+
message: "prepared coding session context pack",
|
|
292
|
+
meta: {
|
|
293
|
+
contextKey,
|
|
294
|
+
workdir: input.request.workdir,
|
|
295
|
+
taskRef: input.request.taskRef ?? null,
|
|
296
|
+
contextFiles: contextFiles.length,
|
|
297
|
+
skills: skills.length,
|
|
298
|
+
relatedSessions: existingSessions.length,
|
|
299
|
+
gitAvailable: snapshot.available,
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
return {
|
|
303
|
+
contextKey,
|
|
304
|
+
scopeFile,
|
|
305
|
+
stateFile,
|
|
306
|
+
scopeContent,
|
|
307
|
+
stateContent,
|
|
308
|
+
identityPacket,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Emit a coding milestone episode when a session completes or blocks.
|
|
313
|
+
* This is the outbound leg of the coding round-trip: compact start-of-turn packet goes IN,
|
|
314
|
+
* episodes come BACK OUT.
|
|
315
|
+
*/
|
|
316
|
+
function emitCodingEpisode(agentRoot, session, outcome) {
|
|
317
|
+
(0, episodes_1.emitEpisode)(agentRoot, {
|
|
318
|
+
kind: "coding_milestone",
|
|
319
|
+
summary: `coding session ${session.id} (${session.runner}): ${outcome}`,
|
|
320
|
+
whyItMattered: `coding lane ${session.status}`,
|
|
321
|
+
relatedEntities: [`coding:${session.id}`],
|
|
322
|
+
salience: session.status === "failed" ? "high" : "medium",
|
|
323
|
+
});
|
|
324
|
+
(0, runtime_1.emitNervesEvent)({
|
|
325
|
+
component: "repertoire",
|
|
326
|
+
event: "repertoire.coding_episode_emitted",
|
|
327
|
+
message: `coding episode emitted for ${session.id}`,
|
|
328
|
+
meta: { sessionId: session.id, outcome, status: session.status },
|
|
329
|
+
});
|
|
330
|
+
}
|