@ouro.bot/cli 0.1.0-alpha.595 → 0.1.0-alpha.596

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/changelog.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.596",
6
+ "changes": [
7
+ "New await_condition primitive. Agents can file a natural-language condition (`await_condition({ name, condition, cadence, alert?, mode?, max_age?, body? })`); the daemon polls on cadence and queues an inner-dialog tick titled `await tick: <name> — <condition>` with the file body + history block (checked count, last-checked age, last observation). The agent calls `resolve_await({ name, verdict, observation })`: verdict=yes archives the file to `awaiting/.done/` and fires an alert via cross-chat-delivery (intent=generic_outreach) targeting `filed_for_friend_id` on the `alert` channel — proactive sends slot into the user's existing thread, no self-loopback. verdict=no records the observation and increments the tick count. `cancel_await({ name, reason? })` silently archives without alert. max_age triggers auto-expiry with a 'timed out' alert. Surfaces `## what i'm waiting on` in the commitments section. Validated end-to-end with Slugger: file → tick → resolve(no, x2) → resolve(yes) → archive + cross_chat_delivery queued_for_later. AwaitScheduler mkdirs its awaits dir at start so the fs.watch watcher attaches on first boot (no need to wait for a periodic reconcile)."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.595",
6
12
  "changes": [
@@ -0,0 +1,146 @@
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.resolveAlertKey = resolveAlertKey;
37
+ exports.buildAlertContent = buildAlertContent;
38
+ exports.deliverAwaitAlert = deliverAwaitAlert;
39
+ exports.buildAwaitDeliveryDeps = buildAwaitDeliveryDeps;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const runtime_1 = require("../../nerves/runtime");
43
+ const cross_chat_delivery_1 = require("../cross-chat-delivery");
44
+ function readNonEmpty(value) {
45
+ if (value === null)
46
+ return null;
47
+ const trimmed = value.trim();
48
+ return trimmed.length > 0 ? trimmed : null;
49
+ }
50
+ /**
51
+ * Find a session key for (friendId, channel) by scanning the bundle's
52
+ * sessions directory. Prefers BlueBubbles DM keys (containing ";-;");
53
+ * for other channels, returns the first available session file stem.
54
+ *
55
+ * Returns null when nothing is available — caller decides whether to skip
56
+ * delivery or fall back to a default like "session".
57
+ */
58
+ function resolveAlertKey(agentRoot, friendId, channel) {
59
+ const dir = path.join(agentRoot, "state", "sessions", friendId, channel);
60
+ let entries;
61
+ try {
62
+ entries = fs.readdirSync(dir);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ const jsonFiles = entries.filter((f) => f.endsWith(".json"));
68
+ if (jsonFiles.length === 0)
69
+ return null;
70
+ const dm = jsonFiles.find((f) => f.includes(";-;"));
71
+ const chosen = dm ?? jsonFiles[0];
72
+ return chosen.replace(/\.json$/, "");
73
+ }
74
+ function buildAlertContent(awaitFile, reason, observation) {
75
+ const condition = awaitFile.condition ?? awaitFile.name;
76
+ const obs = readNonEmpty(observation);
77
+ if (reason === "resolved") {
78
+ return obs ? `${condition} — ready. ${obs}` : `${condition} — ready.`;
79
+ }
80
+ return obs ? `${condition} — timed out. last seen: ${obs}` : `${condition} — timed out. last seen: never observed`;
81
+ }
82
+ async function deliverAwaitAlert(options) {
83
+ const { awaitFile, reason, observation, agentRoot, deliveryDeps } = options;
84
+ (0, runtime_1.emitNervesEvent)({
85
+ component: "daemon",
86
+ event: "daemon.await_alert_start",
87
+ message: "preparing await alert",
88
+ meta: { awaitName: awaitFile.name, reason },
89
+ });
90
+ const channel = readNonEmpty(awaitFile.alert);
91
+ const friendId = readNonEmpty(awaitFile.filed_for_friend_id);
92
+ if (!channel) {
93
+ (0, runtime_1.emitNervesEvent)({
94
+ level: "warn",
95
+ component: "daemon",
96
+ event: "daemon.await_alert_end",
97
+ message: "skipping alert — no alert channel configured",
98
+ meta: { awaitName: awaitFile.name, reason },
99
+ });
100
+ return { attempted: false, skipped: "no alert channel" };
101
+ }
102
+ if (!friendId) {
103
+ (0, runtime_1.emitNervesEvent)({
104
+ level: "warn",
105
+ component: "daemon",
106
+ event: "daemon.await_alert_end",
107
+ message: "skipping alert — no filed_for_friend_id",
108
+ meta: { awaitName: awaitFile.name, reason },
109
+ });
110
+ return { attempted: false, skipped: "no friend id" };
111
+ }
112
+ const key = resolveAlertKey(agentRoot, friendId, channel);
113
+ if (!key) {
114
+ (0, runtime_1.emitNervesEvent)({
115
+ level: "warn",
116
+ component: "daemon",
117
+ event: "daemon.await_alert_end",
118
+ message: "skipping alert — no resolvable session key",
119
+ meta: { awaitName: awaitFile.name, reason, friendId, channel },
120
+ });
121
+ return { attempted: false, skipped: "no session key" };
122
+ }
123
+ const content = buildAlertContent(awaitFile, reason, observation);
124
+ const delivery = await (0, cross_chat_delivery_1.deliverCrossChatMessage)({
125
+ friendId,
126
+ channel,
127
+ key,
128
+ content,
129
+ intent: "generic_outreach",
130
+ }, deliveryDeps);
131
+ (0, runtime_1.emitNervesEvent)({
132
+ component: "daemon",
133
+ event: "daemon.await_alert_end",
134
+ message: "await alert delivered",
135
+ meta: { awaitName: awaitFile.name, reason, status: delivery.status },
136
+ });
137
+ return { attempted: true, delivery };
138
+ }
139
+ function buildAwaitDeliveryDeps(options) {
140
+ return {
141
+ agentName: options.agentName,
142
+ queuePending: options.queuePending,
143
+ deliverers: options.deliverers,
144
+ now: options.now,
145
+ };
146
+ }
@@ -0,0 +1,108 @@
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.archiveAndAlertExpiredAwait = archiveAndAlertExpiredAwait;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const runtime_1 = require("../../nerves/runtime");
40
+ const await_parser_1 = require("./await-parser");
41
+ const await_runtime_state_1 = require("./await-runtime-state");
42
+ const await_alert_1 = require("./await-alert");
43
+ /**
44
+ * Daemon-side max_age expiry helper. Reads the pending await, moves it to
45
+ * `awaiting/.done/` with `status: expired`, writes `expired_at` and
46
+ * `last_observation_at_expiry`, then fires the alert via deliverAwaitAlert.
47
+ *
48
+ * Idempotent w.r.t. the alert path: if the file is gone (already archived
49
+ * by a concurrent path) it returns `archived: false` without alerting.
50
+ */
51
+ async function archiveAndAlertExpiredAwait(options) {
52
+ const now = options.now ?? (() => new Date());
53
+ const source = path.join(options.agentRoot, "awaiting", `${options.awaitName}.md`);
54
+ const doneDir = path.join(options.agentRoot, "awaiting", ".done");
55
+ const target = path.join(doneDir, `${options.awaitName}.md`);
56
+ let content;
57
+ try {
58
+ content = fs.readFileSync(source, "utf-8");
59
+ }
60
+ catch {
61
+ (0, runtime_1.emitNervesEvent)({
62
+ level: "warn",
63
+ component: "daemon",
64
+ event: "daemon.await_expiry_skip",
65
+ message: "expired await file no longer present at archive time",
66
+ meta: { agent: options.agentName, awaitName: options.awaitName },
67
+ });
68
+ return { archived: false, alerted: false, reason: "file missing" };
69
+ }
70
+ const parsed = (0, await_parser_1.parseAwaitFile)(content, source);
71
+ const runtime = (0, await_runtime_state_1.readAwaitRuntimeState)(options.agentRoot, options.awaitName);
72
+ const lastObservation = runtime?.last_observation ?? null;
73
+ const expiredAt = now().toISOString();
74
+ const merged = {
75
+ condition: parsed.condition,
76
+ cadence: parsed.cadence,
77
+ alert: parsed.alert,
78
+ mode: parsed.mode,
79
+ max_age: parsed.max_age,
80
+ status: "expired",
81
+ created_at: parsed.created_at,
82
+ filed_from: parsed.filed_from,
83
+ filed_for_friend_id: parsed.filed_for_friend_id,
84
+ expired_at: expiredAt,
85
+ last_observation_at_expiry: lastObservation,
86
+ };
87
+ fs.mkdirSync(doneDir, { recursive: true });
88
+ fs.writeFileSync(target, (0, await_parser_1.renderAwaitFile)(merged, parsed.body), "utf-8");
89
+ fs.unlinkSync(source);
90
+ (0, runtime_1.emitNervesEvent)({
91
+ component: "daemon",
92
+ event: "daemon.await_expired_archived",
93
+ message: "expired await archived",
94
+ meta: { agent: options.agentName, awaitName: options.awaitName, expiredAt },
95
+ });
96
+ // Re-parse archived file to feed the alert with merged fields
97
+ const archivedContent = fs.readFileSync(target, "utf-8");
98
+ const archived = (0, await_parser_1.parseAwaitFile)(archivedContent, target);
99
+ const alertResult = await (0, await_alert_1.deliverAwaitAlert)({
100
+ awaitFile: archived,
101
+ reason: "expired",
102
+ observation: lastObservation,
103
+ agentRoot: options.agentRoot,
104
+ agentName: options.agentName,
105
+ deliveryDeps: options.deliveryDeps,
106
+ });
107
+ return { archived: true, alerted: alertResult.attempted };
108
+ }
@@ -0,0 +1,91 @@
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.loadPendingAwaitsForCommitments = loadPendingAwaitsForCommitments;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const runtime_1 = require("../../nerves/runtime");
40
+ const await_parser_1 = require("./await-parser");
41
+ const await_runtime_state_1 = require("./await-runtime-state");
42
+ /**
43
+ * Load the bundle's pending awaits, merged with runtime state, projected into
44
+ * the AwaitingCommitment shape consumed by the commitments / prompt pipeline.
45
+ *
46
+ * Reads only `<bundle>/awaiting/` (never `.done/`). Skips malformed files
47
+ * silently — those are surfaced via the scheduler's parseErrors path.
48
+ */
49
+ function loadPendingAwaitsForCommitments(agentRoot) {
50
+ const dir = path.join(agentRoot, "awaiting");
51
+ let entries;
52
+ try {
53
+ const raw = fs.readdirSync(dir);
54
+ /* v8 ignore next -- defensive: real readdirSync returns string[]; this only fires when callers stub it to a non-array @preserve */
55
+ entries = Array.isArray(raw) ? raw : [];
56
+ }
57
+ catch {
58
+ return [];
59
+ }
60
+ const out = [];
61
+ for (const entry of entries) {
62
+ if (!entry.endsWith(".md"))
63
+ continue;
64
+ const filePath = path.join(dir, entry);
65
+ try {
66
+ const content = fs.readFileSync(filePath, "utf-8");
67
+ const merged = (0, await_runtime_state_1.applyAwaitRuntimeState)(agentRoot, (0, await_parser_1.parseAwaitFile)(content, filePath));
68
+ if (merged.status !== "pending")
69
+ continue;
70
+ if (!merged.condition)
71
+ continue;
72
+ out.push({
73
+ name: merged.name,
74
+ condition: merged.condition,
75
+ checkedCount: typeof merged.checked_count === "number" ? merged.checked_count : 0,
76
+ lastCheckedAt: merged.last_checked ?? null,
77
+ lastObservation: merged.last_observation ?? null,
78
+ });
79
+ }
80
+ catch {
81
+ // Skip unreadable/unparseable files — surfaced elsewhere
82
+ }
83
+ }
84
+ (0, runtime_1.emitNervesEvent)({
85
+ component: "engine",
86
+ event: "engine.awaits_loaded_for_commitments",
87
+ message: "loaded pending awaits for commitments",
88
+ meta: { agentRoot, count: out.length },
89
+ });
90
+ return out;
91
+ }
@@ -0,0 +1,141 @@
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.parseAwaitFile = parseAwaitFile;
37
+ exports.renderAwaitFile = renderAwaitFile;
38
+ const path = __importStar(require("path"));
39
+ const parser_1 = require("../../repertoire/tasks/parser");
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ function isAwaitStatus(value) {
42
+ return value === "pending" || value === "resolved" || value === "expired" || value === "canceled";
43
+ }
44
+ function isAwaitMode(value) {
45
+ return value === "full" || value === "quick";
46
+ }
47
+ function nonEmptyString(value) {
48
+ return typeof value === "string" && value.length > 0 ? value : null;
49
+ }
50
+ function extractFrontmatterAndBody(content) {
51
+ const lines = content.split(/\r?\n/);
52
+ if (lines[0]?.trim() !== "---")
53
+ return null;
54
+ const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
55
+ if (closing === -1)
56
+ return null;
57
+ const rawFrontmatter = lines.slice(1, closing).join("\n");
58
+ const body = lines.slice(closing + 1).join("\n").trim();
59
+ return { frontmatter: (0, parser_1.parseFrontmatter)(rawFrontmatter), body };
60
+ }
61
+ function emptyAwait(stem, body) {
62
+ return {
63
+ name: stem,
64
+ condition: null,
65
+ cadence: null,
66
+ alert: null,
67
+ mode: "full",
68
+ max_age: null,
69
+ status: "pending",
70
+ created_at: null,
71
+ filed_from: null,
72
+ filed_for_friend_id: null,
73
+ body,
74
+ resolved_at: null,
75
+ resolution_observation: null,
76
+ expired_at: null,
77
+ last_observation_at_expiry: null,
78
+ canceled_at: null,
79
+ cancel_reason: null,
80
+ };
81
+ }
82
+ function parseAwaitFile(content, filePath) {
83
+ (0, runtime_1.emitNervesEvent)({
84
+ event: "daemon.await_parse",
85
+ component: "daemon",
86
+ message: "parsing await file",
87
+ meta: { filePath },
88
+ });
89
+ const stem = path.basename(filePath, ".md");
90
+ const parsed = extractFrontmatterAndBody(content);
91
+ if (!parsed)
92
+ return { ...emptyAwait(stem, content.trim()) };
93
+ const { frontmatter, body } = parsed;
94
+ const rawStatus = frontmatter.status;
95
+ const status = typeof rawStatus === "string" && isAwaitStatus(rawStatus) ? rawStatus : "pending";
96
+ const rawMode = frontmatter.mode;
97
+ const mode = typeof rawMode === "string" && isAwaitMode(rawMode) ? rawMode : "full";
98
+ return {
99
+ name: stem,
100
+ condition: nonEmptyString(frontmatter.condition),
101
+ cadence: nonEmptyString(frontmatter.cadence),
102
+ alert: nonEmptyString(frontmatter.alert),
103
+ mode,
104
+ max_age: nonEmptyString(frontmatter.max_age),
105
+ status,
106
+ created_at: nonEmptyString(frontmatter.created_at),
107
+ filed_from: nonEmptyString(frontmatter.filed_from),
108
+ filed_for_friend_id: nonEmptyString(frontmatter.filed_for_friend_id),
109
+ body,
110
+ resolved_at: nonEmptyString(frontmatter.resolved_at),
111
+ resolution_observation: nonEmptyString(frontmatter.resolution_observation),
112
+ expired_at: nonEmptyString(frontmatter.expired_at),
113
+ last_observation_at_expiry: nonEmptyString(frontmatter.last_observation_at_expiry),
114
+ canceled_at: nonEmptyString(frontmatter.canceled_at),
115
+ cancel_reason: nonEmptyString(frontmatter.cancel_reason),
116
+ };
117
+ }
118
+ function formatFrontmatterValue(value) {
119
+ if (value === null || value === undefined)
120
+ return "null";
121
+ if (Array.isArray(value))
122
+ return `[${value.join(", ")}]`;
123
+ return String(value);
124
+ }
125
+ function renderAwaitFile(frontmatter, body) {
126
+ (0, runtime_1.emitNervesEvent)({
127
+ event: "daemon.await_render",
128
+ component: "daemon",
129
+ message: "rendering await file",
130
+ meta: {},
131
+ });
132
+ const lines = ["---"];
133
+ for (const key of Object.keys(frontmatter)) {
134
+ lines.push(`${key}: ${formatFrontmatterValue(frontmatter[key])}`);
135
+ }
136
+ lines.push("---");
137
+ lines.push("");
138
+ lines.push(body.trim());
139
+ lines.push("");
140
+ return lines.join("\n");
141
+ }
@@ -0,0 +1,97 @@
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.readAwaitRuntimeState = readAwaitRuntimeState;
37
+ exports.applyAwaitRuntimeState = applyAwaitRuntimeState;
38
+ exports.writeAwaitRuntimeState = writeAwaitRuntimeState;
39
+ exports.recordAwaitCheck = recordAwaitCheck;
40
+ const path = __importStar(require("path"));
41
+ const json_store_1 = require("../../arc/json-store");
42
+ const runtime_1 = require("../../nerves/runtime");
43
+ function awaitRuntimeStateDir(agentRoot) {
44
+ return path.join(agentRoot, "state", "awaits");
45
+ }
46
+ function readAwaitRuntimeState(agentRoot, name) {
47
+ const record = (0, json_store_1.readJsonFile)(awaitRuntimeStateDir(agentRoot), name);
48
+ if (!record)
49
+ return null;
50
+ return {
51
+ last_checked: typeof record.last_checked === "string" ? record.last_checked : null,
52
+ last_observation: typeof record.last_observation === "string" ? record.last_observation : null,
53
+ checked_count: typeof record.checked_count === "number" ? record.checked_count : 0,
54
+ };
55
+ }
56
+ function applyAwaitRuntimeState(agentRoot, awaitFile) {
57
+ const state = readAwaitRuntimeState(agentRoot, awaitFile.name);
58
+ if (state === null)
59
+ return awaitFile;
60
+ return {
61
+ ...awaitFile,
62
+ // Cast: runtime fields are merged onto the file for prompt/commitments consumers
63
+ ...state,
64
+ };
65
+ }
66
+ function writeAwaitRuntimeState(agentRoot, name, partial) {
67
+ const existing = readAwaitRuntimeState(agentRoot, name);
68
+ const merged = {
69
+ last_checked: partial.last_checked ?? existing?.last_checked ?? null,
70
+ last_observation: partial.last_observation ?? existing?.last_observation ?? null,
71
+ checked_count: partial.checked_count ?? existing?.checked_count ?? 0,
72
+ };
73
+ const record = {
74
+ schemaVersion: 1,
75
+ name,
76
+ last_checked: merged.last_checked,
77
+ last_observation: merged.last_observation,
78
+ checked_count: merged.checked_count,
79
+ updatedAt: new Date().toISOString(),
80
+ };
81
+ (0, json_store_1.writeJsonFile)(awaitRuntimeStateDir(agentRoot), name, record);
82
+ (0, runtime_1.emitNervesEvent)({
83
+ component: "daemon",
84
+ event: "daemon.await_runtime_state_write",
85
+ message: "wrote await runtime state",
86
+ meta: { agentRoot, name, last_checked: merged.last_checked, checked_count: merged.checked_count },
87
+ });
88
+ }
89
+ function recordAwaitCheck(agentRoot, name, observation, now) {
90
+ const existing = readAwaitRuntimeState(agentRoot, name);
91
+ const nextCount = (existing?.checked_count ?? 0) + 1;
92
+ writeAwaitRuntimeState(agentRoot, name, {
93
+ last_checked: now,
94
+ last_observation: observation,
95
+ checked_count: nextCount,
96
+ });
97
+ }