@ouro.bot/cli 0.1.0-alpha.16 → 0.1.0-alpha.161
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 +187 -191
- package/changelog.json +1088 -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 +445 -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 +369 -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/outlook-ui/assets/index-CXQG0mVx.js +61 -0
- package/dist/outlook-ui/assets/index-Gq7EdfkO.css +1 -0
- package/dist/outlook-ui/index.html +15 -0
- 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 +13 -5
- 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
|
}
|