@ouro.bot/cli 0.0.1-alpha.0 → 0.1.0-alpha.2
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/AdoptionSpecialist.ouro/agent.json +20 -0
- package/AdoptionSpecialist.ouro/psyche/SOUL.md +22 -0
- package/AdoptionSpecialist.ouro/psyche/identities/basilisk.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/jafar.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/jormungandr.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/kaa.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/medusa.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/monty.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/nagini.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/ouroboros.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/python.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/quetzalcoatl.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/sir-hiss.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/the-serpent.md +31 -0
- package/AdoptionSpecialist.ouro/psyche/identities/the-snake.md +31 -0
- package/README.md +224 -6
- package/dist/heart/agent-entry.js +17 -0
- package/dist/heart/api-error.js +34 -0
- package/dist/heart/config.js +296 -0
- package/dist/heart/core.js +515 -0
- package/dist/heart/daemon/daemon-cli.js +675 -0
- package/dist/heart/daemon/daemon-entry.js +74 -0
- package/dist/heart/daemon/daemon.js +313 -0
- package/dist/heart/daemon/hatch-flow.js +285 -0
- package/dist/heart/daemon/hatch-specialist.js +107 -0
- package/dist/heart/daemon/health-monitor.js +79 -0
- package/dist/heart/daemon/log-tailer.js +146 -0
- package/dist/heart/daemon/message-router.js +98 -0
- package/dist/heart/daemon/os-cron.js +260 -0
- package/dist/heart/daemon/ouro-bot-entry.js +23 -0
- package/dist/heart/daemon/ouro-bot-wrapper.js +90 -0
- package/dist/heart/daemon/ouro-entry.js +23 -0
- package/dist/heart/daemon/ouro-uti.js +212 -0
- package/dist/heart/daemon/process-manager.js +237 -0
- package/dist/heart/daemon/runtime-logging.js +98 -0
- package/dist/heart/daemon/subagent-installer.js +125 -0
- package/dist/heart/daemon/task-scheduler.js +240 -0
- package/dist/heart/harness.js +26 -0
- package/dist/heart/identity.js +281 -0
- package/dist/heart/kicks.js +144 -0
- package/dist/heart/primitives.js +4 -0
- package/dist/heart/providers/anthropic.js +329 -0
- package/dist/heart/providers/azure.js +66 -0
- package/dist/heart/providers/minimax.js +53 -0
- package/dist/heart/providers/openai-codex.js +162 -0
- package/dist/heart/streaming.js +412 -0
- package/dist/heart/turn-coordinator.js +62 -0
- package/dist/inner-worker-entry.js +4 -0
- package/dist/mind/associative-recall.js +197 -0
- package/dist/mind/bundle-manifest.js +118 -0
- package/dist/mind/context.js +302 -0
- package/dist/mind/first-impressions.js +43 -0
- package/dist/mind/format.js +56 -0
- package/dist/mind/friends/channel.js +41 -0
- package/dist/mind/friends/resolver.js +84 -0
- package/dist/mind/friends/store-file.js +171 -0
- package/dist/mind/friends/store.js +4 -0
- package/dist/mind/friends/tokens.js +26 -0
- package/dist/mind/friends/types.js +21 -0
- package/dist/mind/memory.js +388 -0
- package/dist/mind/pending.js +93 -0
- package/dist/mind/phrases.js +43 -0
- package/dist/mind/prompt-refresh.js +20 -0
- package/dist/mind/prompt.js +352 -0
- package/dist/mind/token-estimate.js +119 -0
- package/dist/nerves/cli-logging.js +31 -0
- package/dist/nerves/coverage/audit-rules.js +81 -0
- package/dist/nerves/coverage/audit.js +200 -0
- package/dist/nerves/coverage/cli-main.js +5 -0
- package/dist/nerves/coverage/cli.js +51 -0
- package/dist/nerves/coverage/contract.js +23 -0
- package/dist/nerves/coverage/file-completeness.js +56 -0
- package/dist/nerves/coverage/run-artifacts.js +77 -0
- package/dist/nerves/coverage/source-scanner.js +34 -0
- package/dist/nerves/index.js +152 -0
- package/dist/nerves/runtime.js +38 -0
- package/dist/repertoire/ado-client.js +211 -0
- package/dist/repertoire/ado-context.js +73 -0
- package/dist/repertoire/ado-semantic.js +841 -0
- package/dist/repertoire/ado-templates.js +146 -0
- package/dist/repertoire/coding/index.js +36 -0
- package/dist/repertoire/coding/manager.js +489 -0
- package/dist/repertoire/coding/monitor.js +60 -0
- package/dist/repertoire/coding/reporter.js +45 -0
- package/dist/repertoire/coding/spawner.js +102 -0
- package/dist/repertoire/coding/tools.js +167 -0
- package/dist/repertoire/coding/types.js +2 -0
- package/dist/repertoire/data/ado-endpoints.json +122 -0
- package/dist/repertoire/data/graph-endpoints.json +212 -0
- package/dist/repertoire/github-client.js +64 -0
- package/dist/repertoire/graph-client.js +118 -0
- package/dist/repertoire/skills.js +156 -0
- package/dist/repertoire/tasks/board.js +122 -0
- package/dist/repertoire/tasks/index.js +210 -0
- package/dist/repertoire/tasks/lifecycle.js +80 -0
- package/dist/repertoire/tasks/middleware.js +65 -0
- package/dist/repertoire/tasks/parser.js +173 -0
- package/dist/repertoire/tasks/scanner.js +132 -0
- package/dist/repertoire/tasks/transitions.js +145 -0
- package/dist/repertoire/tasks/types.js +2 -0
- package/dist/repertoire/tools-base.js +714 -0
- package/dist/repertoire/tools-github.js +53 -0
- package/dist/repertoire/tools-teams.js +308 -0
- package/dist/repertoire/tools.js +199 -0
- package/dist/senses/cli-entry.js +15 -0
- package/dist/senses/cli.js +604 -0
- package/dist/senses/commands.js +98 -0
- package/dist/senses/inner-dialog-worker.js +61 -0
- package/dist/senses/inner-dialog.js +231 -0
- package/dist/senses/session-lock.js +119 -0
- package/dist/senses/teams-entry.js +15 -0
- package/dist/senses/teams.js +696 -0
- package/dist/senses/trust-gate.js +150 -0
- package/package.json +34 -11
- package/subagents/README.md +73 -0
- package/subagents/work-doer.md +233 -0
- package/subagents/work-merger.md +624 -0
- package/subagents/work-planner.md +373 -0
- package/bin/ouro.js +0 -6
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createInnerDialogWorker = createInnerDialogWorker;
|
|
4
|
+
exports.startInnerDialogWorker = startInnerDialogWorker;
|
|
5
|
+
const inner_dialog_1 = require("./inner-dialog");
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
function createInnerDialogWorker(runTurn = (options) => (0, inner_dialog_1.runInnerDialogTurn)(options)) {
|
|
8
|
+
let running = false;
|
|
9
|
+
async function run(reason) {
|
|
10
|
+
if (running)
|
|
11
|
+
return;
|
|
12
|
+
running = true;
|
|
13
|
+
try {
|
|
14
|
+
await runTurn({ reason });
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
(0, runtime_1.emitNervesEvent)({
|
|
18
|
+
level: "error",
|
|
19
|
+
component: "senses",
|
|
20
|
+
event: "senses.inner_dialog_worker_error",
|
|
21
|
+
message: "inner dialog worker turn failed",
|
|
22
|
+
meta: {
|
|
23
|
+
reason,
|
|
24
|
+
error: error instanceof Error ? error.message : String(error),
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
running = false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function handleMessage(message) {
|
|
33
|
+
if (!message || typeof message !== "object")
|
|
34
|
+
return;
|
|
35
|
+
const maybeMessage = message;
|
|
36
|
+
if (maybeMessage.type === "heartbeat") {
|
|
37
|
+
await run("heartbeat");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (maybeMessage.type === "poke" ||
|
|
41
|
+
maybeMessage.type === "chat" ||
|
|
42
|
+
maybeMessage.type === "message") {
|
|
43
|
+
await run("instinct");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (maybeMessage.type === "shutdown") {
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { run, handleMessage };
|
|
51
|
+
}
|
|
52
|
+
async function startInnerDialogWorker() {
|
|
53
|
+
const worker = createInnerDialogWorker();
|
|
54
|
+
process.on("message", (message) => {
|
|
55
|
+
void worker.handleMessage(message);
|
|
56
|
+
});
|
|
57
|
+
process.on("disconnect", () => {
|
|
58
|
+
process.exit(0);
|
|
59
|
+
});
|
|
60
|
+
await worker.run("boot");
|
|
61
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
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.loadInnerDialogInstincts = loadInnerDialogInstincts;
|
|
37
|
+
exports.buildInnerDialogBootstrapMessage = buildInnerDialogBootstrapMessage;
|
|
38
|
+
exports.buildNonCanonicalCleanupNudge = buildNonCanonicalCleanupNudge;
|
|
39
|
+
exports.buildInstinctUserMessage = buildInstinctUserMessage;
|
|
40
|
+
exports.deriveResumeCheckpoint = deriveResumeCheckpoint;
|
|
41
|
+
exports.innerDialogSessionPath = innerDialogSessionPath;
|
|
42
|
+
exports.runInnerDialogTurn = runInnerDialogTurn;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const config_1 = require("../heart/config");
|
|
46
|
+
const core_1 = require("../heart/core");
|
|
47
|
+
const identity_1 = require("../heart/identity");
|
|
48
|
+
const context_1 = require("../mind/context");
|
|
49
|
+
const prompt_1 = require("../mind/prompt");
|
|
50
|
+
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
51
|
+
const nerves_1 = require("../nerves");
|
|
52
|
+
const runtime_1 = require("../nerves/runtime");
|
|
53
|
+
const DEFAULT_INNER_DIALOG_INSTINCTS = [
|
|
54
|
+
{
|
|
55
|
+
id: "heartbeat_checkin",
|
|
56
|
+
prompt: "Heartbeat instinct: check what changed, review priorities, and decide whether to keep resting or act.",
|
|
57
|
+
enabled: true,
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
function readAspirations(agentRoot) {
|
|
61
|
+
try {
|
|
62
|
+
return fs.readFileSync(path.join(agentRoot, "psyche", "ASPIRATIONS.md"), "utf8").trim();
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function loadInnerDialogInstincts() {
|
|
69
|
+
return [...DEFAULT_INNER_DIALOG_INSTINCTS];
|
|
70
|
+
}
|
|
71
|
+
function buildInnerDialogBootstrapMessage(aspirations, stateSummary) {
|
|
72
|
+
const aspirationText = aspirations || "No explicit aspirations file found. Reflect and define what matters next.";
|
|
73
|
+
return [
|
|
74
|
+
"Inner dialog boot.",
|
|
75
|
+
"",
|
|
76
|
+
"## aspirations",
|
|
77
|
+
aspirationText,
|
|
78
|
+
"",
|
|
79
|
+
"## current state",
|
|
80
|
+
stateSummary,
|
|
81
|
+
"",
|
|
82
|
+
"Orient yourself, decide what to do next, and make meaningful progress.",
|
|
83
|
+
].join("\n");
|
|
84
|
+
}
|
|
85
|
+
function buildNonCanonicalCleanupNudge(nonCanonicalPaths) {
|
|
86
|
+
if (nonCanonicalPaths.length === 0)
|
|
87
|
+
return "";
|
|
88
|
+
const listed = nonCanonicalPaths.slice(0, 20).map((entry) => `- ${entry}`);
|
|
89
|
+
if (nonCanonicalPaths.length > 20) {
|
|
90
|
+
listed.push(`- ... (${nonCanonicalPaths.length - 20} more)`);
|
|
91
|
+
}
|
|
92
|
+
return [
|
|
93
|
+
"## canonical cleanup nudge",
|
|
94
|
+
"I found non-canonical files in my bundle. I should distill anything valuable into your memory system and remove these files.",
|
|
95
|
+
...listed,
|
|
96
|
+
].join("\n");
|
|
97
|
+
}
|
|
98
|
+
function buildInstinctUserMessage(instincts, reason, state) {
|
|
99
|
+
const active = instincts.find((instinct) => instinct.enabled !== false) ?? DEFAULT_INNER_DIALOG_INSTINCTS[0];
|
|
100
|
+
const checkpoint = state.checkpoint?.trim() || "no prior checkpoint recorded";
|
|
101
|
+
return [
|
|
102
|
+
active.prompt,
|
|
103
|
+
`reason: ${reason}`,
|
|
104
|
+
`cycle: ${state.cycleCount}`,
|
|
105
|
+
`resting: ${state.resting ? "yes" : "no"}`,
|
|
106
|
+
`checkpoint: ${checkpoint}`,
|
|
107
|
+
"resume_instruction: continue from the checkpoint if still valid; otherwise revise and proceed.",
|
|
108
|
+
].join("\n");
|
|
109
|
+
}
|
|
110
|
+
function contentToText(content) {
|
|
111
|
+
if (typeof content === "string")
|
|
112
|
+
return content.trim();
|
|
113
|
+
if (!Array.isArray(content))
|
|
114
|
+
return "";
|
|
115
|
+
const text = content
|
|
116
|
+
.map((part) => {
|
|
117
|
+
if (typeof part === "string")
|
|
118
|
+
return part;
|
|
119
|
+
if (!part || typeof part !== "object")
|
|
120
|
+
return "";
|
|
121
|
+
if ("text" in part && typeof part.text === "string") {
|
|
122
|
+
return part.text;
|
|
123
|
+
}
|
|
124
|
+
return "";
|
|
125
|
+
})
|
|
126
|
+
.join("\n");
|
|
127
|
+
return text.trim();
|
|
128
|
+
}
|
|
129
|
+
function deriveResumeCheckpoint(messages) {
|
|
130
|
+
const lastAssistant = [...messages].reverse().find((message) => message.role === "assistant");
|
|
131
|
+
if (!lastAssistant)
|
|
132
|
+
return "no prior checkpoint recorded";
|
|
133
|
+
const assistantText = contentToText(lastAssistant.content);
|
|
134
|
+
if (!assistantText)
|
|
135
|
+
return "no prior checkpoint recorded";
|
|
136
|
+
const explicitCheckpoint = assistantText
|
|
137
|
+
.split("\n")
|
|
138
|
+
.map((line) => line.trim())
|
|
139
|
+
.find((line) => /^checkpoint\s*:/i.test(line));
|
|
140
|
+
if (explicitCheckpoint) {
|
|
141
|
+
const parsed = explicitCheckpoint.replace(/^checkpoint\s*:\s*/i, "").trim();
|
|
142
|
+
return parsed || "no prior checkpoint recorded";
|
|
143
|
+
}
|
|
144
|
+
const firstLine = assistantText
|
|
145
|
+
.split("\n")
|
|
146
|
+
.map((line) => line.trim())
|
|
147
|
+
.filter((line) => line.length > 0)[0];
|
|
148
|
+
if (firstLine.length <= 220)
|
|
149
|
+
return firstLine;
|
|
150
|
+
return `${firstLine.slice(0, 217)}...`;
|
|
151
|
+
}
|
|
152
|
+
function createInnerDialogCallbacks() {
|
|
153
|
+
return {
|
|
154
|
+
onModelStart: () => { },
|
|
155
|
+
onModelStreamStart: () => { },
|
|
156
|
+
onTextChunk: () => { },
|
|
157
|
+
onReasoningChunk: () => { },
|
|
158
|
+
onToolStart: () => { },
|
|
159
|
+
onToolEnd: () => { },
|
|
160
|
+
onError: () => { },
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function innerDialogSessionPath() {
|
|
164
|
+
return (0, config_1.sessionPath)("self", "inner", "dialog");
|
|
165
|
+
}
|
|
166
|
+
async function runInnerDialogTurn(options) {
|
|
167
|
+
const now = options?.now ?? (() => new Date());
|
|
168
|
+
const reason = options?.reason ?? "heartbeat";
|
|
169
|
+
const sessionFilePath = innerDialogSessionPath();
|
|
170
|
+
const loaded = (0, context_1.loadSession)(sessionFilePath);
|
|
171
|
+
const messages = loaded?.messages ? [...loaded.messages] : [];
|
|
172
|
+
const instincts = options?.instincts ?? loadInnerDialogInstincts();
|
|
173
|
+
const state = {
|
|
174
|
+
cycleCount: 1,
|
|
175
|
+
resting: false,
|
|
176
|
+
lastHeartbeatAt: now().toISOString(),
|
|
177
|
+
};
|
|
178
|
+
if (messages.length === 0) {
|
|
179
|
+
const systemPrompt = await (0, prompt_1.buildSystem)("cli", { toolChoiceRequired: true });
|
|
180
|
+
messages.push({ role: "system", content: systemPrompt });
|
|
181
|
+
const aspirations = readAspirations((0, identity_1.getAgentRoot)());
|
|
182
|
+
const nonCanonical = (0, bundle_manifest_1.findNonCanonicalBundlePaths)((0, identity_1.getAgentRoot)());
|
|
183
|
+
const cleanupNudge = buildNonCanonicalCleanupNudge(nonCanonical);
|
|
184
|
+
const bootstrapMessage = [
|
|
185
|
+
buildInnerDialogBootstrapMessage(aspirations, "No prior inner dialog session found."),
|
|
186
|
+
cleanupNudge,
|
|
187
|
+
].filter(Boolean).join("\n\n");
|
|
188
|
+
messages.push({ role: "user", content: bootstrapMessage });
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const assistantTurns = messages.filter((message) => message.role === "assistant").length;
|
|
192
|
+
state.cycleCount = assistantTurns + 1;
|
|
193
|
+
state.checkpoint = deriveResumeCheckpoint(messages);
|
|
194
|
+
const instinctPrompt = buildInstinctUserMessage(instincts, reason, state);
|
|
195
|
+
messages.push({ role: "user", content: instinctPrompt });
|
|
196
|
+
}
|
|
197
|
+
const inboxMessages = options?.drainInbox?.() ?? [];
|
|
198
|
+
if (inboxMessages.length > 0) {
|
|
199
|
+
const lastUserIdx = messages.length - 1;
|
|
200
|
+
const lastUser = messages[lastUserIdx];
|
|
201
|
+
/* v8 ignore next -- defensive: all code paths push a user message before here @preserve */
|
|
202
|
+
if (lastUser?.role === "user" && typeof lastUser.content === "string") {
|
|
203
|
+
const section = inboxMessages
|
|
204
|
+
.map((msg) => `- **${msg.from}**: ${msg.content}`)
|
|
205
|
+
.join("\n");
|
|
206
|
+
messages[lastUserIdx] = {
|
|
207
|
+
...lastUser,
|
|
208
|
+
content: `${lastUser.content}\n\n## incoming messages\n${section}`,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const callbacks = createInnerDialogCallbacks();
|
|
213
|
+
const traceId = (0, nerves_1.createTraceId)();
|
|
214
|
+
const result = await (0, core_1.runAgent)(messages, callbacks, "cli", options?.signal, {
|
|
215
|
+
traceId,
|
|
216
|
+
toolChoiceRequired: true,
|
|
217
|
+
skipConfirmation: true,
|
|
218
|
+
});
|
|
219
|
+
(0, context_1.postTurn)(messages, sessionFilePath, result.usage);
|
|
220
|
+
(0, runtime_1.emitNervesEvent)({
|
|
221
|
+
component: "senses",
|
|
222
|
+
event: "senses.inner_dialog_turn",
|
|
223
|
+
message: "inner dialog turn completed",
|
|
224
|
+
meta: { reason, session: sessionFilePath },
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
messages,
|
|
228
|
+
usage: result.usage,
|
|
229
|
+
sessionPath: sessionFilePath,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
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.SessionLockError = void 0;
|
|
37
|
+
exports.acquireSessionLock = acquireSessionLock;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const runtime_1 = require("../nerves/runtime");
|
|
40
|
+
class SessionLockError extends Error {
|
|
41
|
+
agentName;
|
|
42
|
+
constructor(agentName) {
|
|
43
|
+
super(`already chatting with ${agentName} in another terminal`);
|
|
44
|
+
this.name = "SessionLockError";
|
|
45
|
+
this.agentName = agentName;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.SessionLockError = SessionLockError;
|
|
49
|
+
function defaultIsProcessAlive(pid) {
|
|
50
|
+
try {
|
|
51
|
+
process.kill(pid, 0);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const defaultDeps = {
|
|
59
|
+
writeFileSync: (p, d, o) => fs.writeFileSync(p, d, o),
|
|
60
|
+
readFileSync: (p, e) => fs.readFileSync(p, e),
|
|
61
|
+
unlinkSync: (p) => fs.unlinkSync(p),
|
|
62
|
+
pid: process.pid,
|
|
63
|
+
isProcessAlive: defaultIsProcessAlive,
|
|
64
|
+
};
|
|
65
|
+
function acquireSessionLock(lockPath, agentName, deps = defaultDeps) {
|
|
66
|
+
const tryWrite = () => {
|
|
67
|
+
try {
|
|
68
|
+
deps.writeFileSync(lockPath, String(deps.pid), { flag: "wx" });
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
if (!tryWrite()) {
|
|
76
|
+
// Lock file exists — check if stale
|
|
77
|
+
let existingPid;
|
|
78
|
+
try {
|
|
79
|
+
existingPid = parseInt(deps.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Can't read lock file — try removing and retrying
|
|
83
|
+
try {
|
|
84
|
+
deps.unlinkSync(lockPath);
|
|
85
|
+
}
|
|
86
|
+
catch { /* ignore */ }
|
|
87
|
+
if (!tryWrite())
|
|
88
|
+
throw new SessionLockError(agentName);
|
|
89
|
+
return makeRelease(lockPath, deps);
|
|
90
|
+
}
|
|
91
|
+
if (Number.isNaN(existingPid) || !deps.isProcessAlive(existingPid)) {
|
|
92
|
+
// Stale lock — remove and retry
|
|
93
|
+
try {
|
|
94
|
+
deps.unlinkSync(lockPath);
|
|
95
|
+
}
|
|
96
|
+
catch { /* ignore */ }
|
|
97
|
+
if (!tryWrite())
|
|
98
|
+
throw new SessionLockError(agentName);
|
|
99
|
+
(0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.session_lock_stolen", message: "stole stale session lock from dead process", meta: { agentName, existingPid } });
|
|
100
|
+
return makeRelease(lockPath, deps);
|
|
101
|
+
}
|
|
102
|
+
throw new SessionLockError(agentName);
|
|
103
|
+
}
|
|
104
|
+
return makeRelease(lockPath, deps);
|
|
105
|
+
}
|
|
106
|
+
function makeRelease(lockPath, deps) {
|
|
107
|
+
let released = false;
|
|
108
|
+
return {
|
|
109
|
+
release: () => {
|
|
110
|
+
if (released)
|
|
111
|
+
return;
|
|
112
|
+
released = true;
|
|
113
|
+
try {
|
|
114
|
+
deps.unlinkSync(lockPath);
|
|
115
|
+
}
|
|
116
|
+
catch { /* ignore */ }
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Thin entrypoint for `npm run teams` / `node dist/senses/teams-entry.js --agent <name>`.
|
|
3
|
+
// Separated from teams.ts so the Teams adapter is pure library code with clean
|
|
4
|
+
// 100% test coverage -- entrypoints can't be covered by vitest since
|
|
5
|
+
// require.main !== module in the test runner.
|
|
6
|
+
// All config comes from the conventional ~/.agentsecrets/<agent>/secrets.json path.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
// Fail fast if --agent is missing (before any src/ code tries getAgentName())
|
|
9
|
+
if (!process.argv.includes("--agent")) {
|
|
10
|
+
// eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
|
|
11
|
+
console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/teams-entry.js --agent ouroboros");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const teams_1 = require("./teams");
|
|
15
|
+
(0, teams_1.startTeamsApp)();
|