@ouro.bot/cli 0.1.0-alpha.16 → 0.1.0-alpha.160
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 +3 -2
- package/AdoptionSpecialist.ouro/psyche/SOUL.md +3 -3
- package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
- package/README.md +186 -191
- package/changelog.json +1081 -0
- package/dist/heart/active-work.js +633 -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 +105 -0
- package/dist/heart/config.js +40 -30
- package/dist/heart/core.js +608 -123
- package/dist/heart/cross-chat-delivery.js +146 -0
- package/dist/heart/daemon/agent-discovery.js +81 -0
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/auth-flow.js +477 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/daemon-cli.js +2467 -205
- package/dist/heart/daemon/daemon-entry.js +131 -4
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
- package/dist/heart/daemon/daemon-tombstone.js +123 -0
- package/dist/heart/daemon/daemon.js +434 -17
- package/dist/heart/daemon/habit-migration.js +181 -0
- package/dist/heart/daemon/habit-parser.js +119 -0
- package/dist/heart/daemon/habit-scheduler.js +369 -0
- package/dist/heart/daemon/hatch-animation.js +10 -3
- package/dist/heart/daemon/hatch-flow.js +30 -111
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +92 -0
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/launchd.js +159 -0
- package/dist/heart/daemon/log-tailer.js +4 -3
- package/dist/heart/daemon/mcp-server.js +591 -0
- 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-global-installer.js +128 -0
- package/dist/heart/daemon/ouro-path-installer.js +78 -34
- package/dist/heart/daemon/ouro-version-manager.js +171 -0
- package/dist/heart/daemon/outlook-http.js +307 -0
- package/dist/heart/daemon/outlook-read.js +1281 -0
- package/dist/heart/daemon/outlook-render.js +1032 -0
- package/dist/heart/daemon/outlook-types.js +7 -0
- package/dist/heart/daemon/outlook-view.js +194 -0
- package/dist/heart/daemon/process-manager.js +75 -0
- package/dist/heart/daemon/run-hooks.js +39 -0
- package/dist/heart/daemon/runtime-logging.js +58 -15
- package/dist/heart/daemon/runtime-metadata.js +219 -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 +50 -2
- 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/specialist-orchestrator.js +2 -2
- package/dist/heart/daemon/specialist-prompt.js +13 -8
- package/dist/heart/daemon/specialist-tools.js +53 -4
- package/dist/heart/daemon/staged-restart.js +114 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/daemon/update-checker.js +111 -0
- package/dist/heart/daemon/update-hooks.js +138 -0
- package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/identity.js +136 -55
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/obligations.js +197 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +172 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +196 -36
- 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/streaming.js +117 -33
- package/dist/heart/target-resolution.js +127 -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-coordinator.js +28 -0
- package/dist/mind/associative-recall.js +122 -32
- package/dist/mind/bundle-manifest.js +14 -0
- package/dist/mind/context.js +125 -14
- package/dist/mind/{memory.js → diary.js} +70 -56
- 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 +19 -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/obligations.js +134 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +651 -91
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +15 -2
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +63 -3
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/repertoire/ado-semantic.js +6 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +254 -0
- package/dist/repertoire/coding/feedback.js +301 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +210 -4
- package/dist/repertoire/coding/spawner.js +58 -12
- package/dist/repertoire/coding/tools.js +176 -4
- package/dist/repertoire/guardrails.js +291 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +198 -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 +992 -273
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-github.js +1 -6
- package/dist/repertoire/tools-teams.js +12 -59
- package/dist/repertoire/tools.js +281 -101
- 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 +258 -5
- package/dist/senses/bluebubbles-entry.js +2 -0
- package/dist/senses/bluebubbles-inbound-log.js +109 -0
- package/dist/senses/bluebubbles-media.js +339 -0
- package/dist/senses/bluebubbles-model.js +12 -4
- package/dist/senses/bluebubbles-mutation-log.js +45 -5
- package/dist/senses/bluebubbles-runtime-state.js +109 -0
- package/dist/senses/bluebubbles-session-cleanup.js +72 -0
- package/dist/senses/bluebubbles.js +1040 -45
- package/dist/senses/cli-entry.js +1 -1
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +419 -152
- package/dist/senses/commands.js +38 -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 +592 -84
- package/dist/senses/pipeline.js +502 -0
- package/dist/senses/shared-turn.js +196 -0
- package/dist/senses/surface-tool.js +95 -0
- package/dist/senses/teams.js +667 -120
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +12 -4
- package/skills/configure-dev-tools.md +81 -0
- package/subagents/README.md +4 -70
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.__internal = void 0;
|
|
4
3
|
exports.estimateTokensForMessage = estimateTokensForMessage;
|
|
5
4
|
exports.estimateTokensForMessages = estimateTokensForMessages;
|
|
6
5
|
const runtime_1 = require("../nerves/runtime");
|
|
@@ -53,7 +52,7 @@ function countCharsInContent(content) {
|
|
|
53
52
|
return c.text.length;
|
|
54
53
|
if (typeof c.content === "string")
|
|
55
54
|
return c.content.length;
|
|
56
|
-
return safeStringify(
|
|
55
|
+
return safeStringify(c).length;
|
|
57
56
|
}
|
|
58
57
|
return 0;
|
|
59
58
|
}
|
|
@@ -70,12 +69,13 @@ function countCharsInToolCalls(toolCalls) {
|
|
|
70
69
|
if (typeof t.type === "string")
|
|
71
70
|
total += t.type.length;
|
|
72
71
|
if (t.function && typeof t.function === "object") {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
const fn = t.function;
|
|
73
|
+
if (typeof fn.name === "string")
|
|
74
|
+
total += fn.name.length;
|
|
75
|
+
if (typeof fn.arguments === "string")
|
|
76
|
+
total += fn.arguments.length;
|
|
77
|
+
else if (fn.arguments != null)
|
|
78
|
+
total += safeStringify(fn.arguments).length;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
return total;
|
|
@@ -113,7 +113,3 @@ function estimateTokensForMessages(msgs) {
|
|
|
113
113
|
total += estimateTokensForMessage(msg);
|
|
114
114
|
return total;
|
|
115
115
|
}
|
|
116
|
-
exports.__internal = {
|
|
117
|
-
CHARS_PER_TOKEN,
|
|
118
|
-
PER_MESSAGE_OVERHEAD_TOKENS,
|
|
119
|
-
};
|
|
@@ -5,20 +5,33 @@ const config_1 = require("../heart/config");
|
|
|
5
5
|
const nerves_1 = require("../nerves");
|
|
6
6
|
const runtime_1 = require("./runtime");
|
|
7
7
|
const runtime_2 = require("./runtime");
|
|
8
|
+
const LEVEL_PRIORITY = { debug: 10, info: 20, warn: 30, error: 40 };
|
|
9
|
+
/** Wrap a sink so it only receives events at or above the given level. */
|
|
10
|
+
/* v8 ignore start -- internal filter plumbing, exercised via integration @preserve */
|
|
11
|
+
function filterSink(sink, minLevel) {
|
|
12
|
+
const minPriority = LEVEL_PRIORITY[minLevel] ?? 0;
|
|
13
|
+
return (entry) => {
|
|
14
|
+
if ((LEVEL_PRIORITY[entry.level] ?? 0) >= minPriority)
|
|
15
|
+
sink(entry);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
8
18
|
function resolveCliSinks(sinks) {
|
|
9
19
|
const requested = sinks && sinks.length > 0 ? sinks : ["terminal", "ndjson"];
|
|
10
20
|
return [...new Set(requested)];
|
|
11
21
|
}
|
|
12
22
|
function configureCliRuntimeLogger(_friendId, options = {}) {
|
|
13
23
|
const sinkKinds = resolveCliSinks(options.sinks);
|
|
24
|
+
const level = options.level ?? "info";
|
|
14
25
|
const sinks = sinkKinds.map((sinkKind) => {
|
|
15
26
|
if (sinkKind === "terminal") {
|
|
16
|
-
|
|
27
|
+
// Terminal only shows warnings and errors — INFO is too noisy
|
|
28
|
+
// for an interactive session. Full detail goes to the ndjson file.
|
|
29
|
+
return filterSink((0, nerves_1.createTerminalSink)(), "warn");
|
|
17
30
|
}
|
|
18
31
|
return (0, nerves_1.createNdjsonFileSink)((0, config_1.logPath)("cli", "runtime"));
|
|
19
32
|
});
|
|
20
33
|
const logger = (0, nerves_1.createLogger)({
|
|
21
|
-
level
|
|
34
|
+
level,
|
|
22
35
|
sinks,
|
|
23
36
|
});
|
|
24
37
|
(0, runtime_2.setRuntimeLogger)(logger);
|
|
@@ -14,7 +14,7 @@ const path_1 = require("path");
|
|
|
14
14
|
const os_1 = require("os");
|
|
15
15
|
exports.REPO_SLUG = "ouroboros-agent-harness";
|
|
16
16
|
function getTestRunsRoot(repoSlug = exports.REPO_SLUG) {
|
|
17
|
-
return (0, path_1.join)((0, os_1.
|
|
17
|
+
return (0, path_1.join)((0, os_1.tmpdir)(), "ouroboros-test-runs", repoSlug);
|
|
18
18
|
}
|
|
19
19
|
function createRunId(now = new Date()) {
|
|
20
20
|
return now.toISOString().replace(/[:.]/g, "-");
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBufferedSink = createBufferedSink;
|
|
4
|
+
const runtime_1 = require("./runtime");
|
|
5
|
+
const DEFAULT_MAX_SIZE = 1000;
|
|
6
|
+
const DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
7
|
+
function createBufferedSink(inner, options = {}) {
|
|
8
|
+
const maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
|
|
9
|
+
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
10
|
+
const nowMs = options.nowMs ?? (() => Date.now());
|
|
11
|
+
const buffer = [];
|
|
12
|
+
let dropped = 0;
|
|
13
|
+
let sinkHealthy = true;
|
|
14
|
+
let unhealthySince = null;
|
|
15
|
+
function tryInner(event) {
|
|
16
|
+
try {
|
|
17
|
+
inner(event);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function markUnhealthy() {
|
|
25
|
+
sinkHealthy = false;
|
|
26
|
+
unhealthySince = unhealthySince ?? nowMs();
|
|
27
|
+
}
|
|
28
|
+
function markHealthy() {
|
|
29
|
+
sinkHealthy = true;
|
|
30
|
+
unhealthySince = null;
|
|
31
|
+
}
|
|
32
|
+
function discardBuffer() {
|
|
33
|
+
const count = buffer.length;
|
|
34
|
+
dropped += count;
|
|
35
|
+
buffer.length = 0;
|
|
36
|
+
(0, runtime_1.emitNervesEvent)({
|
|
37
|
+
component: "nerves",
|
|
38
|
+
event: "nerves.buffer_ttl_discard",
|
|
39
|
+
message: `discarded ${count} buffered events after TTL`,
|
|
40
|
+
meta: { discarded: count, ttlMs },
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function checkTtl() {
|
|
44
|
+
if (unhealthySince !== null && nowMs() - unhealthySince > ttlMs) {
|
|
45
|
+
discardBuffer();
|
|
46
|
+
// Reset unhealthySince to now so TTL starts fresh for newly buffered events
|
|
47
|
+
unhealthySince = nowMs();
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
function addToBuffer(event) {
|
|
53
|
+
if (buffer.length >= maxSize) {
|
|
54
|
+
buffer.shift();
|
|
55
|
+
dropped++;
|
|
56
|
+
}
|
|
57
|
+
buffer.push(event);
|
|
58
|
+
}
|
|
59
|
+
function flushBuffer() {
|
|
60
|
+
while (buffer.length > 0) {
|
|
61
|
+
const event = buffer[0];
|
|
62
|
+
if (tryInner(event)) {
|
|
63
|
+
buffer.shift();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
markUnhealthy();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function sink(event) {
|
|
72
|
+
if (!sinkHealthy) {
|
|
73
|
+
checkTtl();
|
|
74
|
+
// Try sending the new event to see if inner has recovered
|
|
75
|
+
if (tryInner(event)) {
|
|
76
|
+
markHealthy();
|
|
77
|
+
flushBuffer();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
addToBuffer(event);
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (tryInner(event)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Inner failed
|
|
88
|
+
markUnhealthy();
|
|
89
|
+
addToBuffer(event);
|
|
90
|
+
}
|
|
91
|
+
function flush() {
|
|
92
|
+
if (buffer.length === 0)
|
|
93
|
+
return;
|
|
94
|
+
// Test if inner is recovered by trying the first buffered event
|
|
95
|
+
const first = buffer[0];
|
|
96
|
+
if (tryInner(first)) {
|
|
97
|
+
buffer.shift();
|
|
98
|
+
markHealthy();
|
|
99
|
+
flushBuffer();
|
|
100
|
+
}
|
|
101
|
+
// If still broken, leave buffer intact
|
|
102
|
+
}
|
|
103
|
+
function state() {
|
|
104
|
+
return {
|
|
105
|
+
buffered: buffer.length,
|
|
106
|
+
dropped,
|
|
107
|
+
sinkHealthy,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return { sink, flush, state };
|
|
111
|
+
}
|
package/dist/nerves/index.js
CHANGED
|
@@ -4,8 +4,10 @@ exports.createTraceId = createTraceId;
|
|
|
4
4
|
exports.ensureTraceId = ensureTraceId;
|
|
5
5
|
exports.createFanoutSink = createFanoutSink;
|
|
6
6
|
exports.formatTerminalEntry = formatTerminalEntry;
|
|
7
|
+
exports.registerSpinnerHooks = registerSpinnerHooks;
|
|
7
8
|
exports.createTerminalSink = createTerminalSink;
|
|
8
9
|
exports.createStderrSink = createStderrSink;
|
|
10
|
+
exports.rotateIfNeeded = rotateIfNeeded;
|
|
9
11
|
exports.createNdjsonFileSink = createNdjsonFileSink;
|
|
10
12
|
exports.registerGlobalLogSink = registerGlobalLogSink;
|
|
11
13
|
exports.createLogger = createLogger;
|
|
@@ -73,36 +75,94 @@ function formatTerminalEntry(entry) {
|
|
|
73
75
|
const level = entry.level.toUpperCase();
|
|
74
76
|
return `${formatTerminalTime(entry.ts)} ${level} [${entry.component}] ${entry.message}${formatTerminalMeta(entry.meta)}`;
|
|
75
77
|
}
|
|
76
|
-
|
|
78
|
+
// Spinner coordination: the CLI sense registers these so log output
|
|
79
|
+
// doesn't interleave with the active spinner animation.
|
|
80
|
+
let _pauseSpinner = null;
|
|
81
|
+
let _resumeSpinner = null;
|
|
82
|
+
function registerSpinnerHooks(pause, resume) {
|
|
83
|
+
_pauseSpinner = pause;
|
|
84
|
+
_resumeSpinner = resume;
|
|
85
|
+
}
|
|
86
|
+
function createTerminalSink(write = (chunk) => { try {
|
|
87
|
+
process.stderr.write(chunk);
|
|
88
|
+
}
|
|
89
|
+
catch { /* EPIPE: daemon detached, no terminal */ } }, colorize = true) {
|
|
77
90
|
return (entry) => {
|
|
91
|
+
_pauseSpinner?.();
|
|
78
92
|
const line = formatTerminalEntry(entry);
|
|
79
93
|
if (!colorize) {
|
|
80
94
|
write(`${line}\n`);
|
|
95
|
+
_resumeSpinner?.();
|
|
81
96
|
return;
|
|
82
97
|
}
|
|
83
98
|
const prefix = LEVEL_COLORS[entry.level];
|
|
84
99
|
write(`${prefix}${line}\x1b[0m\n`);
|
|
100
|
+
_resumeSpinner?.();
|
|
85
101
|
};
|
|
86
102
|
}
|
|
87
103
|
function createStderrSink(write = (chunk) => process.stderr.write(chunk)) {
|
|
88
104
|
return createTerminalSink(write);
|
|
89
105
|
}
|
|
90
|
-
|
|
106
|
+
const DEFAULT_MAX_LOG_SIZE_BYTES = 50 * 1024 * 1024; // 50MB
|
|
107
|
+
const ROTATION_CHECK_INTERVAL_BYTES = 1024 * 1024; // ~1MB between stat checks
|
|
108
|
+
/**
|
|
109
|
+
* Rotate a log file: shift .1 -> .2, delete old .2, rename current -> .1.
|
|
110
|
+
* Uses the ndjson extension pattern: file.ndjson -> file.1.ndjson -> file.2.ndjson
|
|
111
|
+
*/
|
|
112
|
+
function rotateIfNeeded(filePath, maxSizeBytes) {
|
|
113
|
+
let size;
|
|
114
|
+
try {
|
|
115
|
+
size = (0, fs_1.statSync)(filePath).size;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (size < maxSizeBytes)
|
|
121
|
+
return false;
|
|
122
|
+
const ext = filePath.endsWith(".ndjson") ? ".ndjson" : "";
|
|
123
|
+
const base = ext ? filePath.slice(0, -ext.length) : filePath;
|
|
124
|
+
const file1 = `${base}.1${ext}`;
|
|
125
|
+
const file2 = `${base}.2${ext}`;
|
|
126
|
+
try {
|
|
127
|
+
(0, fs_1.unlinkSync)(file2);
|
|
128
|
+
}
|
|
129
|
+
catch { /* may not exist */ }
|
|
130
|
+
try {
|
|
131
|
+
(0, fs_1.renameSync)(file1, file2);
|
|
132
|
+
}
|
|
133
|
+
catch { /* may not exist */ }
|
|
134
|
+
try {
|
|
135
|
+
(0, fs_1.renameSync)(filePath, file1);
|
|
136
|
+
}
|
|
137
|
+
catch { /* best effort */ }
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
function createNdjsonFileSink(filePath, maxSizeBytes) {
|
|
91
141
|
(0, fs_1.mkdirSync)((0, path_1.dirname)(filePath), { recursive: true });
|
|
92
142
|
const queue = [];
|
|
93
143
|
let flushing = false;
|
|
144
|
+
let bytesSinceCheck = 0;
|
|
145
|
+
const maxSize = maxSizeBytes ?? DEFAULT_MAX_LOG_SIZE_BYTES;
|
|
94
146
|
function flush() {
|
|
95
147
|
if (flushing || queue.length === 0)
|
|
96
148
|
return;
|
|
97
149
|
flushing = true;
|
|
98
150
|
const line = queue.shift();
|
|
151
|
+
/* v8 ignore start — rotation triggers only after ~1MB of writes @preserve */
|
|
152
|
+
if (bytesSinceCheck >= ROTATION_CHECK_INTERVAL_BYTES) {
|
|
153
|
+
bytesSinceCheck = 0;
|
|
154
|
+
rotateIfNeeded(filePath, maxSize);
|
|
155
|
+
}
|
|
156
|
+
/* v8 ignore stop */
|
|
99
157
|
(0, fs_1.appendFile)(filePath, line, "utf8", () => {
|
|
100
158
|
flushing = false;
|
|
101
159
|
flush();
|
|
102
160
|
});
|
|
103
161
|
}
|
|
104
162
|
return (entry) => {
|
|
105
|
-
|
|
163
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
164
|
+
bytesSinceCheck += line.length;
|
|
165
|
+
queue.push(line);
|
|
106
166
|
flush();
|
|
107
167
|
};
|
|
108
168
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Nerves observation layer — shared typed readers for runtime state.
|
|
4
|
+
*
|
|
5
|
+
* This module re-exports domain types that multiple consumers need
|
|
6
|
+
* (Outlook, CLI, agent tools) so they don't maintain parallel type universes.
|
|
7
|
+
*
|
|
8
|
+
* The Outlook UI consumes these through the HTTP API, but the same
|
|
9
|
+
* observation functions back CLI commands and future native clients.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
/* v8 ignore start — module-level observability event */
|
|
13
|
+
const runtime_1 = require("./runtime");
|
|
14
|
+
(0, runtime_1.emitNervesEvent)({
|
|
15
|
+
component: "nerves",
|
|
16
|
+
event: "nerves.observation_loaded",
|
|
17
|
+
message: "observation layer loaded",
|
|
18
|
+
meta: {},
|
|
19
|
+
});
|
|
20
|
+
/* v8 ignore stop */
|
package/dist/nerves/runtime.js
CHANGED
|
@@ -6,7 +6,11 @@ const index_1 = require("./index");
|
|
|
6
6
|
let runtimeLogger = null;
|
|
7
7
|
function getRuntimeLogger() {
|
|
8
8
|
if (!runtimeLogger) {
|
|
9
|
-
|
|
9
|
+
// Default logger has no sinks — events emitted before the real logger is
|
|
10
|
+
// configured (e.g. identity resolution during startup) are silently dropped.
|
|
11
|
+
// This prevents INFO lines from leaking to stderr and interleaving with
|
|
12
|
+
// the CLI spinner when the ouro subprocess hasn't configured its logger yet.
|
|
13
|
+
runtimeLogger = (0, index_1.createLogger)({ level: "info", sinks: [] });
|
|
10
14
|
}
|
|
11
15
|
return runtimeLogger;
|
|
12
16
|
}
|
|
@@ -279,6 +279,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
279
279
|
return formatForChannel(items, ctx, organization, project);
|
|
280
280
|
},
|
|
281
281
|
integration: "ado",
|
|
282
|
+
summaryKeys: ["organization", "project"],
|
|
282
283
|
},
|
|
283
284
|
// -- ado_create_epic --
|
|
284
285
|
{
|
|
@@ -318,6 +319,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
318
319
|
},
|
|
319
320
|
integration: "ado",
|
|
320
321
|
confirmationRequired: true,
|
|
322
|
+
summaryKeys: ["organization", "project", "title"],
|
|
321
323
|
},
|
|
322
324
|
// -- ado_create_issue --
|
|
323
325
|
{
|
|
@@ -359,6 +361,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
359
361
|
},
|
|
360
362
|
integration: "ado",
|
|
361
363
|
confirmationRequired: true,
|
|
364
|
+
summaryKeys: ["organization", "project", "title"],
|
|
362
365
|
},
|
|
363
366
|
// -- ado_move_items --
|
|
364
367
|
{
|
|
@@ -413,6 +416,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
413
416
|
},
|
|
414
417
|
integration: "ado",
|
|
415
418
|
confirmationRequired: true,
|
|
419
|
+
summaryKeys: ["organization", "project", "workItemIds"],
|
|
416
420
|
},
|
|
417
421
|
// -- ado_restructure_backlog --
|
|
418
422
|
{
|
|
@@ -471,6 +475,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
471
475
|
},
|
|
472
476
|
integration: "ado",
|
|
473
477
|
confirmationRequired: true,
|
|
478
|
+
summaryKeys: ["organization", "project"],
|
|
474
479
|
},
|
|
475
480
|
// -- ado_validate_structure --
|
|
476
481
|
{
|
|
@@ -672,6 +677,7 @@ exports.adoSemanticToolDefinitions = [
|
|
|
672
677
|
},
|
|
673
678
|
integration: "ado",
|
|
674
679
|
confirmationRequired: true,
|
|
680
|
+
summaryKeys: ["organization", "project"],
|
|
675
681
|
},
|
|
676
682
|
// -- ado_detect_orphans --
|
|
677
683
|
{
|
|
@@ -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
|
+
}
|