@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,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
5
|
+
const runtime_logging_1 = require("./runtime-logging");
|
|
6
|
+
const ouro_bot_wrapper_1 = require("./ouro-bot-wrapper");
|
|
7
|
+
(0, runtime_logging_1.configureDaemonRuntimeLogger)("ouro-bot");
|
|
8
|
+
(0, runtime_1.emitNervesEvent)({
|
|
9
|
+
component: "daemon",
|
|
10
|
+
event: "daemon.ouro_bot_entry_start",
|
|
11
|
+
message: "starting ouro.bot wrapper entrypoint",
|
|
12
|
+
meta: { args: process.argv.slice(2) },
|
|
13
|
+
});
|
|
14
|
+
void (0, ouro_bot_wrapper_1.runOuroBotWrapper)(process.argv.slice(2)).catch((error) => {
|
|
15
|
+
(0, runtime_1.emitNervesEvent)({
|
|
16
|
+
level: "error",
|
|
17
|
+
component: "daemon",
|
|
18
|
+
event: "daemon.ouro_bot_entry_error",
|
|
19
|
+
message: "ouro.bot wrapper entrypoint failed",
|
|
20
|
+
meta: { error: error instanceof Error ? error.message : String(error) },
|
|
21
|
+
});
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
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.runOuroBotWrapper = runOuroBotWrapper;
|
|
37
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
38
|
+
const daemon_cli_1 = require("./daemon-cli");
|
|
39
|
+
async function defaultLoadCanonicalRunner() {
|
|
40
|
+
const packageName = "@ouro.bot/cli";
|
|
41
|
+
const specifier = packageName;
|
|
42
|
+
const loaded = await Promise.resolve(`${specifier}`).then(s => __importStar(require(s)));
|
|
43
|
+
const candidate = Object.prototype.hasOwnProperty.call(loaded, "runOuroCli")
|
|
44
|
+
? loaded["runOuroCli"]
|
|
45
|
+
: undefined;
|
|
46
|
+
if (typeof candidate === "function") {
|
|
47
|
+
return candidate;
|
|
48
|
+
}
|
|
49
|
+
throw new Error("@ouro.bot/cli does not export runOuroCli");
|
|
50
|
+
}
|
|
51
|
+
function defaultWriteStdout(_text) {
|
|
52
|
+
// Wrapper is intentionally silent by default to avoid duplicate terminal output.
|
|
53
|
+
}
|
|
54
|
+
async function runOuroBotWrapper(args, deps = {}) {
|
|
55
|
+
(0, runtime_1.emitNervesEvent)({
|
|
56
|
+
component: "daemon",
|
|
57
|
+
event: "daemon.ouro_bot_wrapper_start",
|
|
58
|
+
message: "starting ouro.bot wrapper delegation",
|
|
59
|
+
meta: { args },
|
|
60
|
+
});
|
|
61
|
+
const loadCanonicalRunner = deps.loadCanonicalRunner ?? defaultLoadCanonicalRunner;
|
|
62
|
+
const fallbackRunCli = deps.fallbackRunCli ?? daemon_cli_1.runOuroCli;
|
|
63
|
+
const writeStdout = deps.writeStdout ?? defaultWriteStdout;
|
|
64
|
+
let delegatedTo = "@ouro.bot/cli";
|
|
65
|
+
let runner = fallbackRunCli;
|
|
66
|
+
try {
|
|
67
|
+
runner = await loadCanonicalRunner();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
delegatedTo = "local-fallback";
|
|
71
|
+
(0, runtime_1.emitNervesEvent)({
|
|
72
|
+
level: "warn",
|
|
73
|
+
component: "daemon",
|
|
74
|
+
event: "daemon.ouro_bot_wrapper_fallback",
|
|
75
|
+
message: "canonical ouro.bot package unavailable; falling back to local CLI",
|
|
76
|
+
meta: { error: error instanceof Error ? error.message : String(error) },
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const result = await runner(args);
|
|
80
|
+
if (result.trim().length > 0) {
|
|
81
|
+
writeStdout(result);
|
|
82
|
+
}
|
|
83
|
+
(0, runtime_1.emitNervesEvent)({
|
|
84
|
+
component: "daemon",
|
|
85
|
+
event: "daemon.ouro_bot_wrapper_end",
|
|
86
|
+
message: "completed ouro.bot wrapper delegation",
|
|
87
|
+
meta: { delegatedTo },
|
|
88
|
+
});
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
5
|
+
const daemon_cli_1 = require("./daemon-cli");
|
|
6
|
+
const runtime_logging_1 = require("./runtime-logging");
|
|
7
|
+
(0, runtime_logging_1.configureDaemonRuntimeLogger)("ouro");
|
|
8
|
+
(0, runtime_1.emitNervesEvent)({
|
|
9
|
+
component: "daemon",
|
|
10
|
+
event: "daemon.cli_entry_start",
|
|
11
|
+
message: "starting ouro CLI entrypoint",
|
|
12
|
+
meta: { args: process.argv.slice(2) },
|
|
13
|
+
});
|
|
14
|
+
void (0, daemon_cli_1.runOuroCli)(process.argv.slice(2)).catch((error) => {
|
|
15
|
+
(0, runtime_1.emitNervesEvent)({
|
|
16
|
+
level: "error",
|
|
17
|
+
component: "daemon",
|
|
18
|
+
event: "daemon.cli_entry_error",
|
|
19
|
+
message: "ouro CLI entrypoint failed",
|
|
20
|
+
meta: { error: error instanceof Error ? error.message : String(error) },
|
|
21
|
+
});
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
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.registerOuroBundleUti = registerOuroBundleUti;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const identity_1 = require("../identity");
|
|
42
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
43
|
+
const LSREGISTER_PATH = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
|
|
44
|
+
const ICON_SIZES = [16, 32, 128, 256, 512];
|
|
45
|
+
function resolveIconSourcePath(repoRoot) {
|
|
46
|
+
return path.resolve(repoRoot, "..", "ouroboros-website", "public", "images", "ouroboros.png");
|
|
47
|
+
}
|
|
48
|
+
function buildIconAsset(iconSourcePath, icnsPath, iconsetDir, deps) {
|
|
49
|
+
try {
|
|
50
|
+
deps.mkdirSync(iconsetDir, { recursive: true });
|
|
51
|
+
for (const size of ICON_SIZES) {
|
|
52
|
+
const basePng = path.join(iconsetDir, `icon_${size}x${size}.png`);
|
|
53
|
+
const retinaPng = path.join(iconsetDir, `icon_${size}x${size}@2x.png`);
|
|
54
|
+
deps.execFileSync("sips", ["-z", String(size), String(size), iconSourcePath, "--out", basePng]);
|
|
55
|
+
deps.execFileSync("sips", ["-z", String(size * 2), String(size * 2), iconSourcePath, "--out", retinaPng]);
|
|
56
|
+
}
|
|
57
|
+
deps.execFileSync("iconutil", ["-c", "icns", iconsetDir, "-o", icnsPath]);
|
|
58
|
+
deps.rmSync(iconsetDir, { recursive: true, force: true });
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
deps.rmSync(iconsetDir, { recursive: true, force: true });
|
|
63
|
+
(0, runtime_1.emitNervesEvent)({
|
|
64
|
+
level: "warn",
|
|
65
|
+
component: "daemon",
|
|
66
|
+
event: "daemon.ouro_uti_icon_error",
|
|
67
|
+
message: "failed building .ouro icon; continuing without custom icon",
|
|
68
|
+
meta: { error: error instanceof Error ? error.message : String(error) },
|
|
69
|
+
});
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function buildInfoPlist(iconInstalled) {
|
|
74
|
+
const iconTag = iconInstalled ? "\n <key>CFBundleTypeIconFile</key>\n <string>ouro</string>" : "";
|
|
75
|
+
return [
|
|
76
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
77
|
+
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
78
|
+
'<plist version="1.0">',
|
|
79
|
+
"<dict>",
|
|
80
|
+
" <key>CFBundleIdentifier</key>",
|
|
81
|
+
" <string>bot.ouro.bundle-registry</string>",
|
|
82
|
+
" <key>CFBundleName</key>",
|
|
83
|
+
" <string>Ouro Bundle Registry</string>",
|
|
84
|
+
" <key>CFBundlePackageType</key>",
|
|
85
|
+
" <string>APPL</string>",
|
|
86
|
+
" <key>UTExportedTypeDeclarations</key>",
|
|
87
|
+
" <array>",
|
|
88
|
+
" <dict>",
|
|
89
|
+
" <key>UTTypeIdentifier</key>",
|
|
90
|
+
" <string>bot.ouro.bundle</string>",
|
|
91
|
+
" <key>UTTypeConformsTo</key>",
|
|
92
|
+
" <array>",
|
|
93
|
+
" <string>public.folder</string>",
|
|
94
|
+
" </array>",
|
|
95
|
+
" <key>UTTypeTagSpecification</key>",
|
|
96
|
+
" <dict>",
|
|
97
|
+
" <key>public.filename-extension</key>",
|
|
98
|
+
" <array>",
|
|
99
|
+
" <string>ouro</string>",
|
|
100
|
+
" </array>",
|
|
101
|
+
" </dict>",
|
|
102
|
+
" </dict>",
|
|
103
|
+
" </array>",
|
|
104
|
+
" <key>CFBundleDocumentTypes</key>",
|
|
105
|
+
" <array>",
|
|
106
|
+
" <dict>",
|
|
107
|
+
" <key>CFBundleTypeName</key>",
|
|
108
|
+
" <string>Ouro Agent Bundle</string>",
|
|
109
|
+
" <key>LSItemContentTypes</key>",
|
|
110
|
+
" <array>",
|
|
111
|
+
" <string>bot.ouro.bundle</string>",
|
|
112
|
+
" </array>",
|
|
113
|
+
" <key>CFBundleTypeRole</key>",
|
|
114
|
+
" <string>Editor</string>",
|
|
115
|
+
` ${iconTag.trim()}`,
|
|
116
|
+
" </dict>",
|
|
117
|
+
" </array>",
|
|
118
|
+
"</dict>",
|
|
119
|
+
"</plist>",
|
|
120
|
+
"",
|
|
121
|
+
]
|
|
122
|
+
.filter((line) => line.length > 0)
|
|
123
|
+
.join("\n");
|
|
124
|
+
}
|
|
125
|
+
function registerOuroBundleUti(deps = {}) {
|
|
126
|
+
const platform = deps.platform ?? process.platform;
|
|
127
|
+
if (platform !== "darwin") {
|
|
128
|
+
(0, runtime_1.emitNervesEvent)({
|
|
129
|
+
component: "daemon",
|
|
130
|
+
event: "daemon.ouro_uti_register_skip",
|
|
131
|
+
message: "skipped .ouro UTI registration on non-macOS platform",
|
|
132
|
+
meta: { platform },
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
attempted: false,
|
|
136
|
+
registered: false,
|
|
137
|
+
iconInstalled: false,
|
|
138
|
+
skippedReason: "non-macos",
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const homeDir = deps.homeDir ?? os.homedir();
|
|
142
|
+
const repoRoot = deps.repoRoot ?? (0, identity_1.getRepoRoot)();
|
|
143
|
+
const existsSync = deps.existsSync ?? fs.existsSync;
|
|
144
|
+
const mkdirSync = deps.mkdirSync ?? fs.mkdirSync;
|
|
145
|
+
const writeFileSync = deps.writeFileSync ?? fs.writeFileSync;
|
|
146
|
+
const rmSync = deps.rmSync ?? fs.rmSync;
|
|
147
|
+
const exec = deps.execFileSync ?? ((file, args) => (0, child_process_1.execFileSync)(file, args));
|
|
148
|
+
const supportRoot = path.join(homeDir, "Library", "Application Support", "ouro", "uti");
|
|
149
|
+
const appBundlePath = path.join(supportRoot, "OuroBundleRegistry.app");
|
|
150
|
+
const contentsDir = path.join(appBundlePath, "Contents");
|
|
151
|
+
const resourcesDir = path.join(contentsDir, "Resources");
|
|
152
|
+
const plistPath = path.join(contentsDir, "Info.plist");
|
|
153
|
+
const icnsPath = path.join(resourcesDir, "ouro.icns");
|
|
154
|
+
const iconsetDir = path.join(supportRoot, "ouro.iconset");
|
|
155
|
+
const iconSourcePath = resolveIconSourcePath(repoRoot);
|
|
156
|
+
(0, runtime_1.emitNervesEvent)({
|
|
157
|
+
component: "daemon",
|
|
158
|
+
event: "daemon.ouro_uti_register_start",
|
|
159
|
+
message: "registering .ouro UTI on macOS",
|
|
160
|
+
meta: { appBundlePath },
|
|
161
|
+
});
|
|
162
|
+
let iconInstalled = false;
|
|
163
|
+
try {
|
|
164
|
+
mkdirSync(resourcesDir, { recursive: true });
|
|
165
|
+
if (existsSync(iconSourcePath)) {
|
|
166
|
+
iconInstalled = buildIconAsset(iconSourcePath, icnsPath, iconsetDir, {
|
|
167
|
+
mkdirSync,
|
|
168
|
+
rmSync,
|
|
169
|
+
execFileSync: exec,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
(0, runtime_1.emitNervesEvent)({
|
|
174
|
+
component: "daemon",
|
|
175
|
+
event: "daemon.ouro_uti_icon_skip",
|
|
176
|
+
message: "icon source image missing; continuing without custom icon",
|
|
177
|
+
meta: { iconSourcePath },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
writeFileSync(plistPath, buildInfoPlist(iconInstalled), "utf-8");
|
|
181
|
+
exec(LSREGISTER_PATH, ["-f", appBundlePath]);
|
|
182
|
+
(0, runtime_1.emitNervesEvent)({
|
|
183
|
+
component: "daemon",
|
|
184
|
+
event: "daemon.ouro_uti_register_end",
|
|
185
|
+
message: "registered .ouro UTI on macOS",
|
|
186
|
+
meta: { iconInstalled },
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
attempted: true,
|
|
190
|
+
registered: true,
|
|
191
|
+
iconInstalled,
|
|
192
|
+
registrationBundlePath: appBundlePath,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
197
|
+
(0, runtime_1.emitNervesEvent)({
|
|
198
|
+
level: "warn",
|
|
199
|
+
component: "daemon",
|
|
200
|
+
event: "daemon.ouro_uti_register_error",
|
|
201
|
+
message: "failed .ouro UTI registration; continuing non-blocking",
|
|
202
|
+
meta: { reason },
|
|
203
|
+
});
|
|
204
|
+
return {
|
|
205
|
+
attempted: true,
|
|
206
|
+
registered: false,
|
|
207
|
+
iconInstalled,
|
|
208
|
+
skippedReason: reason,
|
|
209
|
+
registrationBundlePath: appBundlePath,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
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.DaemonProcessManager = void 0;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const identity_1 = require("../identity");
|
|
40
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
41
|
+
function startOfHour(ms) {
|
|
42
|
+
return ms - 60 * 60 * 1000;
|
|
43
|
+
}
|
|
44
|
+
class DaemonProcessManager {
|
|
45
|
+
agents = new Map();
|
|
46
|
+
maxRestartsPerHour;
|
|
47
|
+
stabilityThresholdMs;
|
|
48
|
+
initialBackoffMs;
|
|
49
|
+
maxBackoffMs;
|
|
50
|
+
spawnFn;
|
|
51
|
+
now;
|
|
52
|
+
setTimeoutFn;
|
|
53
|
+
clearTimeoutFn;
|
|
54
|
+
constructor(options) {
|
|
55
|
+
this.maxRestartsPerHour = options.maxRestartsPerHour ?? 10;
|
|
56
|
+
this.stabilityThresholdMs = options.stabilityThresholdMs ?? 60_000;
|
|
57
|
+
this.initialBackoffMs = options.initialBackoffMs ?? 1_000;
|
|
58
|
+
this.maxBackoffMs = options.maxBackoffMs ?? 60_000;
|
|
59
|
+
this.spawnFn = options.spawn ?? ((command, args, spawnOptions) => (0, child_process_1.spawn)(command, args, spawnOptions));
|
|
60
|
+
this.now = options.now ?? (() => Date.now());
|
|
61
|
+
this.setTimeoutFn = options.setTimeoutFn ?? ((cb, delay) => setTimeout(cb, delay));
|
|
62
|
+
this.clearTimeoutFn = options.clearTimeoutFn ?? ((timer) => clearTimeout(timer));
|
|
63
|
+
for (const agent of options.agents) {
|
|
64
|
+
this.agents.set(agent.name, {
|
|
65
|
+
config: agent,
|
|
66
|
+
process: null,
|
|
67
|
+
restartTimer: null,
|
|
68
|
+
crashTimestamps: [],
|
|
69
|
+
stopRequested: false,
|
|
70
|
+
snapshot: {
|
|
71
|
+
name: agent.name,
|
|
72
|
+
channel: agent.channel,
|
|
73
|
+
status: "stopped",
|
|
74
|
+
pid: null,
|
|
75
|
+
restartCount: 0,
|
|
76
|
+
startedAt: null,
|
|
77
|
+
lastCrashAt: null,
|
|
78
|
+
backoffMs: this.initialBackoffMs,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async startAutoStartAgents() {
|
|
84
|
+
for (const state of this.agents.values()) {
|
|
85
|
+
if (state.config.autoStart) {
|
|
86
|
+
await this.startAgent(state.config.name);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async startAgent(agent) {
|
|
91
|
+
const state = this.requireAgent(agent);
|
|
92
|
+
if (state.process)
|
|
93
|
+
return;
|
|
94
|
+
this.clearRestartTimer(state);
|
|
95
|
+
state.stopRequested = false;
|
|
96
|
+
state.snapshot.status = "starting";
|
|
97
|
+
const runCwd = (0, identity_1.getRepoRoot)();
|
|
98
|
+
const entryScript = path.join((0, identity_1.getRepoRoot)(), "dist", state.config.entry);
|
|
99
|
+
const args = [entryScript, "--agent", agent, ...(state.config.args ?? [])];
|
|
100
|
+
const child = this.spawnFn("node", args, {
|
|
101
|
+
cwd: runCwd,
|
|
102
|
+
env: state.config.env ? { ...process.env, ...state.config.env } : process.env,
|
|
103
|
+
stdio: ["ignore", "ignore", "ignore", "ipc"],
|
|
104
|
+
});
|
|
105
|
+
state.process = child;
|
|
106
|
+
state.snapshot.status = "running";
|
|
107
|
+
state.snapshot.pid = child.pid ?? null;
|
|
108
|
+
state.snapshot.startedAt = new Date(this.now()).toISOString();
|
|
109
|
+
(0, runtime_1.emitNervesEvent)({
|
|
110
|
+
component: "daemon",
|
|
111
|
+
event: "daemon.agent_started",
|
|
112
|
+
message: "daemon started managed agent process",
|
|
113
|
+
meta: { agent, pid: child.pid ?? null, cwd: runCwd },
|
|
114
|
+
});
|
|
115
|
+
child.once("exit", (code, signal) => {
|
|
116
|
+
this.onExit(state, code, signal);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
async stopAgent(agent) {
|
|
120
|
+
const state = this.requireAgent(agent);
|
|
121
|
+
this.clearRestartTimer(state);
|
|
122
|
+
state.stopRequested = true;
|
|
123
|
+
if (!state.process) {
|
|
124
|
+
state.snapshot.status = "stopped";
|
|
125
|
+
state.snapshot.pid = null;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const child = state.process;
|
|
129
|
+
state.process = null;
|
|
130
|
+
state.snapshot.status = "stopped";
|
|
131
|
+
state.snapshot.pid = null;
|
|
132
|
+
try {
|
|
133
|
+
child.kill("SIGTERM");
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
(0, runtime_1.emitNervesEvent)({
|
|
137
|
+
level: "warn",
|
|
138
|
+
component: "daemon",
|
|
139
|
+
event: "daemon.agent_stop_error",
|
|
140
|
+
message: "failed to send SIGTERM to managed agent",
|
|
141
|
+
meta: { agent },
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async restartAgent(agent) {
|
|
146
|
+
await this.stopAgent(agent);
|
|
147
|
+
await this.startAgent(agent);
|
|
148
|
+
}
|
|
149
|
+
async stopAll() {
|
|
150
|
+
for (const state of this.agents.values()) {
|
|
151
|
+
await this.stopAgent(state.config.name);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
sendToAgent(agent, message) {
|
|
155
|
+
const state = this.requireAgent(agent);
|
|
156
|
+
if (!state.process)
|
|
157
|
+
return;
|
|
158
|
+
try {
|
|
159
|
+
state.process.send(message);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
(0, runtime_1.emitNervesEvent)({
|
|
163
|
+
level: "warn",
|
|
164
|
+
component: "daemon",
|
|
165
|
+
event: "daemon.agent_ipc_send_error",
|
|
166
|
+
message: "failed to send IPC message to managed agent",
|
|
167
|
+
meta: { agent },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
getAgentSnapshot(agent) {
|
|
172
|
+
return this.agents.get(agent)?.snapshot;
|
|
173
|
+
}
|
|
174
|
+
listAgentSnapshots() {
|
|
175
|
+
return [...this.agents.values()].map((state) => state.snapshot);
|
|
176
|
+
}
|
|
177
|
+
onExit(state, code, signal) {
|
|
178
|
+
if (!state.process)
|
|
179
|
+
return;
|
|
180
|
+
state.process = null;
|
|
181
|
+
state.snapshot.pid = null;
|
|
182
|
+
const crashed = !state.stopRequested && code !== 0;
|
|
183
|
+
const now = this.now();
|
|
184
|
+
const startedAt = state.snapshot.startedAt ? Date.parse(state.snapshot.startedAt) : now;
|
|
185
|
+
const runDuration = Math.max(0, now - startedAt);
|
|
186
|
+
(0, runtime_1.emitNervesEvent)({
|
|
187
|
+
level: crashed ? "warn" : "info",
|
|
188
|
+
component: "daemon",
|
|
189
|
+
event: "daemon.agent_exit",
|
|
190
|
+
message: "managed agent process exited",
|
|
191
|
+
meta: { agent: state.config.name, code, signal, crashed, runDurationMs: runDuration },
|
|
192
|
+
});
|
|
193
|
+
if (!crashed) {
|
|
194
|
+
state.snapshot.status = "stopped";
|
|
195
|
+
if (runDuration >= this.stabilityThresholdMs) {
|
|
196
|
+
state.snapshot.backoffMs = this.initialBackoffMs;
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
state.snapshot.lastCrashAt = new Date(now).toISOString();
|
|
201
|
+
state.crashTimestamps = state.crashTimestamps.filter((crashTs) => crashTs >= startOfHour(now));
|
|
202
|
+
state.crashTimestamps.push(now);
|
|
203
|
+
if (state.crashTimestamps.length > this.maxRestartsPerHour) {
|
|
204
|
+
state.snapshot.status = "crashed";
|
|
205
|
+
(0, runtime_1.emitNervesEvent)({
|
|
206
|
+
level: "error",
|
|
207
|
+
component: "daemon",
|
|
208
|
+
event: "daemon.agent_restart_exhausted",
|
|
209
|
+
message: "managed agent exceeded restart limit and is marked crashed",
|
|
210
|
+
meta: { agent: state.config.name, maxRestartsPerHour: this.maxRestartsPerHour },
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
state.snapshot.status = "starting";
|
|
215
|
+
state.snapshot.restartCount += 1;
|
|
216
|
+
const waitMs = state.snapshot.backoffMs;
|
|
217
|
+
state.snapshot.backoffMs = Math.min(state.snapshot.backoffMs * 2, this.maxBackoffMs);
|
|
218
|
+
this.clearRestartTimer(state);
|
|
219
|
+
state.restartTimer = this.setTimeoutFn(() => {
|
|
220
|
+
void this.startAgent(state.config.name);
|
|
221
|
+
}, waitMs);
|
|
222
|
+
}
|
|
223
|
+
clearRestartTimer(state) {
|
|
224
|
+
if (state.restartTimer === null)
|
|
225
|
+
return;
|
|
226
|
+
this.clearTimeoutFn(state.restartTimer);
|
|
227
|
+
state.restartTimer = null;
|
|
228
|
+
}
|
|
229
|
+
requireAgent(agent) {
|
|
230
|
+
const state = this.agents.get(agent);
|
|
231
|
+
if (!state) {
|
|
232
|
+
throw new Error(`Unknown managed agent '${agent}'.`);
|
|
233
|
+
}
|
|
234
|
+
return state;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
exports.DaemonProcessManager = DaemonProcessManager;
|
|
@@ -0,0 +1,98 @@
|
|
|
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.configureDaemonRuntimeLogger = configureDaemonRuntimeLogger;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const nerves_1 = require("../../nerves");
|
|
41
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
42
|
+
const DEFAULT_RUNTIME_LOGGING = {
|
|
43
|
+
level: "info",
|
|
44
|
+
sinks: ["terminal", "ndjson"],
|
|
45
|
+
};
|
|
46
|
+
function isLogLevel(value) {
|
|
47
|
+
return value === "debug" || value === "info" || value === "warn" || value === "error";
|
|
48
|
+
}
|
|
49
|
+
function resolveRuntimeLoggingConfig(configPath) {
|
|
50
|
+
let parsed = null;
|
|
51
|
+
try {
|
|
52
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
53
|
+
parsed = JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return { ...DEFAULT_RUNTIME_LOGGING };
|
|
57
|
+
}
|
|
58
|
+
if (!parsed || typeof parsed !== "object") {
|
|
59
|
+
return { ...DEFAULT_RUNTIME_LOGGING };
|
|
60
|
+
}
|
|
61
|
+
const candidate = parsed;
|
|
62
|
+
const level = isLogLevel(candidate.level) ? candidate.level : DEFAULT_RUNTIME_LOGGING.level;
|
|
63
|
+
const sinks = Array.isArray(candidate.sinks)
|
|
64
|
+
? candidate.sinks.filter((entry) => entry === "terminal" || entry === "ndjson")
|
|
65
|
+
: DEFAULT_RUNTIME_LOGGING.sinks;
|
|
66
|
+
return {
|
|
67
|
+
level,
|
|
68
|
+
sinks: sinks.length > 0 ? [...new Set(sinks)] : [...DEFAULT_RUNTIME_LOGGING.sinks],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function configureDaemonRuntimeLogger(processName, options = {}) {
|
|
72
|
+
const homeDir = options.homeDir ?? os.homedir();
|
|
73
|
+
const configPath = options.configPath ?? path.join(homeDir, ".agentstate", "daemon", "logging.json");
|
|
74
|
+
const config = resolveRuntimeLoggingConfig(configPath);
|
|
75
|
+
const sinks = config.sinks.map((sinkName) => {
|
|
76
|
+
if (sinkName === "terminal") {
|
|
77
|
+
return (0, nerves_1.createTerminalSink)();
|
|
78
|
+
}
|
|
79
|
+
const ndjsonPath = path.join(homeDir, ".agentstate", "daemon", "logs", `${processName}.ndjson`);
|
|
80
|
+
return (0, nerves_1.createNdjsonFileSink)(ndjsonPath);
|
|
81
|
+
});
|
|
82
|
+
const logger = (0, nerves_1.createLogger)({
|
|
83
|
+
level: config.level,
|
|
84
|
+
sinks,
|
|
85
|
+
});
|
|
86
|
+
(0, runtime_1.setRuntimeLogger)(logger);
|
|
87
|
+
(0, runtime_1.emitNervesEvent)({
|
|
88
|
+
component: "daemon",
|
|
89
|
+
event: "daemon.runtime_logger_configured",
|
|
90
|
+
message: "configured daemon runtime logger",
|
|
91
|
+
meta: {
|
|
92
|
+
processName,
|
|
93
|
+
level: config.level,
|
|
94
|
+
sinks: config.sinks,
|
|
95
|
+
configPath,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|