@scotthuang/agent-knock-knock 0.14.12 → 0.14.13

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/src/claude-native-cli-adapter.js +3 -10
  3. package/dist/src/claude-native-cli-adapter.js.map +1 -1
  4. package/dist/src/claude-native-state-store.js +1 -1
  5. package/dist/src/claude-native-state-store.js.map +1 -1
  6. package/dist/src/cli-core.js +21 -4
  7. package/dist/src/cli-core.js.map +1 -1
  8. package/dist/src/cli-usage.js +2 -1
  9. package/dist/src/cli-usage.js.map +1 -1
  10. package/dist/src/codex-native-cli-adapter.js +3 -11
  11. package/dist/src/codex-native-cli-adapter.js.map +1 -1
  12. package/dist/src/codex-native-record-store.d.ts +2 -0
  13. package/dist/src/codex-native-record-store.js +5 -0
  14. package/dist/src/codex-native-record-store.js.map +1 -1
  15. package/dist/src/codex-native-state-store.js +1 -1
  16. package/dist/src/codex-native-state-store.js.map +1 -1
  17. package/dist/src/conversation-list.d.ts +2 -0
  18. package/dist/src/conversation-list.js +19 -0
  19. package/dist/src/conversation-list.js.map +1 -1
  20. package/dist/src/desktop-list.d.ts +0 -2
  21. package/dist/src/desktop-list.js +3 -11
  22. package/dist/src/desktop-list.js.map +1 -1
  23. package/dist/src/desktop-state-store.js +4 -0
  24. package/dist/src/desktop-state-store.js.map +1 -1
  25. package/dist/src/host-monitor-reconciliation.js +20 -0
  26. package/dist/src/host-monitor-reconciliation.js.map +1 -1
  27. package/dist/src/live-lifecycle-smoke.js +56 -37
  28. package/dist/src/live-lifecycle-smoke.js.map +1 -1
  29. package/dist/src/managed-monitoring-list.d.ts +4 -0
  30. package/dist/src/managed-monitoring-list.js +17 -0
  31. package/dist/src/managed-monitoring-list.js.map +1 -0
  32. package/dist/src/semantic-tool-command-helpers.d.ts +4 -0
  33. package/dist/src/semantic-tool-command-helpers.js +28 -3
  34. package/dist/src/semantic-tool-command-helpers.js.map +1 -1
  35. package/dist/src/semantic-tool-descriptions.d.ts +1 -0
  36. package/dist/src/semantic-tool-descriptions.js +7 -5
  37. package/dist/src/semantic-tool-descriptions.js.map +1 -1
  38. package/dist/src/semantic-tool-list-budget.d.ts +2 -3
  39. package/dist/src/semantic-tool-list-budget.js +20 -93
  40. package/dist/src/semantic-tool-list-budget.js.map +1 -1
  41. package/dist/src/semantic-tool-list-projection.d.ts +1 -1
  42. package/dist/src/semantic-tool-list-projection.js +6 -90
  43. package/dist/src/semantic-tool-list-projection.js.map +1 -1
  44. package/dist/src/semantic-tool-runtime.js +27 -5
  45. package/dist/src/semantic-tool-runtime.js.map +1 -1
  46. package/dist/src/semantic-tool-schemas.d.ts +36 -0
  47. package/dist/src/semantic-tool-schemas.js +11 -1
  48. package/dist/src/semantic-tool-schemas.js.map +1 -1
  49. package/dist/src/store.d.ts +1 -1
  50. package/dist/src/store.js +4 -3
  51. package/dist/src/store.js.map +1 -1
  52. package/dist/src/terminal-action-contracts.js +1 -1
  53. package/dist/src/terminal-list-cli-adapter.d.ts +1 -0
  54. package/dist/src/terminal-list-cli-adapter.js +9 -34
  55. package/dist/src/terminal-list-cli-adapter.js.map +1 -1
  56. package/dist/src/terminal-permission-control-list-projection.d.ts +1 -1
  57. package/dist/src/terminal-watch-store.d.ts +1 -1
  58. package/dist/src/terminal-watch-store.js +6 -2
  59. package/dist/src/terminal-watch-store.js.map +1 -1
  60. package/dist/src/watch-history-maintenance-cli-adapter.d.ts +2 -0
  61. package/dist/src/watch-history-maintenance-cli-adapter.js +13 -0
  62. package/dist/src/watch-history-maintenance-cli-adapter.js.map +1 -0
  63. package/dist/src/watch-history-policy.d.ts +9 -0
  64. package/dist/src/watch-history-policy.js +64 -0
  65. package/dist/src/watch-history-policy.js.map +1 -0
  66. package/dist/src/watch-history-receipt.d.ts +27 -0
  67. package/dist/src/watch-history-receipt.js +71 -0
  68. package/dist/src/watch-history-receipt.js.map +1 -0
  69. package/dist/src/watch-history-retention.d.ts +16 -0
  70. package/dist/src/watch-history-retention.js +143 -0
  71. package/dist/src/watch-history-retention.js.map +1 -0
  72. package/dist/src/watch-list-cli-adapter.d.ts +6 -0
  73. package/dist/src/watch-list-cli-adapter.js +62 -0
  74. package/dist/src/watch-list-cli-adapter.js.map +1 -0
  75. package/dist/src/watch-list-projection.d.ts +18 -0
  76. package/dist/src/watch-list-projection.js +158 -0
  77. package/dist/src/watch-list-projection.js.map +1 -0
  78. package/docs/callback-compatibility.md +4 -2
  79. package/docs/list-output.md +65 -67
  80. package/docs/operator-guide.md +11 -8
  81. package/docs/storage-and-logging.md +8 -5
  82. package/docs/testing.md +2 -2
  83. package/openclaw.plugin.json +4 -0
  84. package/package.json +1 -1
  85. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +11 -7
@@ -0,0 +1,143 @@
1
+ import { createHash } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { assertCodexNativeTaskRecord } from "./codex-native-state-store.js";
5
+ import { assertClaudeNativeTaskRecord } from "./claude-native-state-store.js";
6
+ import { assertDesktopTaskRecord } from "./desktop-state-store.js";
7
+ import { assertTerminalWatch } from "./terminal-watch-codec.js";
8
+ import { TERMINAL_WATCHES_DIRECTORY, TERMINAL_WATCH_VERSION } from "./terminal-watch-record.js";
9
+ import { atomicSaveJsonFile, isNodeError, readJsonFileNoFollow } from "./durable-json-file.js";
10
+ import { assertStoreReadable, ensureDir, withStoreWriterLease } from "./store.js";
11
+ import { createFileLockCliAdapter } from "./file-lock-cli-adapter.js";
12
+ import { recordValue } from "./value-guards.js";
13
+ import { WATCH_HISTORY_MAINTENANCE_BATCH, WATCH_HISTORY_MAINTENANCE_INTERVAL_MS, watchHistoryExpired, watchHistorySettledAt } from "./watch-history-policy.js";
14
+ import { assertPrivateHistoryPath, loadWatchHistoryReceipt, saveWatchHistoryReceipt, WATCH_HISTORY_RECEIPTS_DIRECTORY } from "./watch-history-receipt.js";
15
+ const PROVIDERS = [
16
+ { name: "codex", directory: "codex-native-tasks", assert: assertCodexNativeTaskRecord },
17
+ { name: "claude", directory: "claude-native-tasks", assert: assertClaudeNativeTaskRecord },
18
+ { name: "desktop", directory: "desktop-tasks", assert: assertDesktopTaskRecord },
19
+ { name: "terminal", directory: TERMINAL_WATCHES_DIRECTORY, assert: value => {
20
+ if (recordValue(value)?.version !== TERMINAL_WATCH_VERSION)
21
+ throw new Error("Legacy Watch history is retained");
22
+ assertTerminalWatch(value);
23
+ } }
24
+ ];
25
+ function maintenancePath(storeDir) {
26
+ return path.join(storeDir, WATCH_HISTORY_RECEIPTS_DIRECTORY, "maintenance.json");
27
+ }
28
+ function loadMaintenance(storeDir) {
29
+ const file = maintenancePath(storeDir);
30
+ try {
31
+ assertPrivateHistoryPath(path.dirname(file), true);
32
+ assertPrivateHistoryPath(file, false);
33
+ const value = readJsonFileNoFollow(file, "Watch history maintenance");
34
+ if (value?.schema !== "agent-knock-knock/watch-history-maintenance" || value.version !== 1 ||
35
+ !Number.isFinite(Date.parse(value.last_run_at)) || value.cursor !== undefined &&
36
+ (typeof value.cursor !== "string" || value.cursor.length > 512))
37
+ throw new Error("Invalid Watch history maintenance state");
38
+ return value;
39
+ }
40
+ catch (error) {
41
+ if (isNodeError(error, "ENOENT"))
42
+ return undefined;
43
+ throw error;
44
+ }
45
+ }
46
+ function entries(storeDir) {
47
+ return PROVIDERS.flatMap(provider => {
48
+ const directory = path.join(storeDir, provider.directory);
49
+ try {
50
+ assertPrivateHistoryPath(directory, true);
51
+ }
52
+ catch (error) {
53
+ if (isNodeError(error, "ENOENT"))
54
+ return [];
55
+ throw error;
56
+ }
57
+ return fs.readdirSync(directory).filter(name => !name.startsWith(".") && name.endsWith(".json"))
58
+ .map(name => ({ provider, name, key: `${provider.name}:${name}`, file: path.join(directory, name) }));
59
+ }).sort((a, b) => a.key.localeCompare(b.key));
60
+ }
61
+ /** Bounded maintenance of AKK-owned healthy history. Never reads or mutates a native agent. */
62
+ export function collectExpiredWatchHistory(options) {
63
+ const result = { checked: 0, deleted: 0, skipped: 0, errors: 0, throttled: false };
64
+ const now = options.now ?? new Date(), limit = options.limit ?? WATCH_HISTORY_MAINTENANCE_BATCH;
65
+ if (!Number.isFinite(now.getTime()) || !Number.isSafeInteger(limit) || limit < 1 || limit > 1000)
66
+ throw new Error("Invalid Watch maintenance bound");
67
+ if (!fs.existsSync(options.storeDir))
68
+ return result;
69
+ assertStoreReadable(options.storeDir);
70
+ const previous = loadMaintenance(options.storeDir);
71
+ if (previous && now.getTime() - Date.parse(previous.last_run_at) < WATCH_HISTORY_MAINTENANCE_INTERVAL_MS) {
72
+ result.throttled = true;
73
+ return result;
74
+ }
75
+ const adapter = createFileLockCliAdapter({ now: () => new Date(), nowMs: Date.now, pid: () => process.pid,
76
+ sleepSync: () => { throw new Error("Watch maintenance never waits for an occupied record lock"); } });
77
+ const locks = options.locks ?? { acquire: (file) => adapter.acquire(file, { timeoutMs: 0 }) };
78
+ return withStoreWriterLease(options.storeDir, () => {
79
+ // Persisted throttling and cursor also coordinate old/new plugin generations and independent processes.
80
+ const state = loadMaintenance(options.storeDir);
81
+ if (state && now.getTime() - Date.parse(state.last_run_at) < WATCH_HISTORY_MAINTENANCE_INTERVAL_MS) {
82
+ result.throttled = true;
83
+ return result;
84
+ }
85
+ const inventory = entries(options.storeDir);
86
+ let remaining = state?.cursor ? inventory.filter(entry => entry.key.localeCompare(state.cursor) > 0) : inventory;
87
+ if (!remaining.length)
88
+ remaining = inventory;
89
+ const selected = remaining.slice(0, limit);
90
+ for (const entry of selected) {
91
+ result.checked++;
92
+ let release;
93
+ try {
94
+ assertPrivateHistoryPath(entry.file, false);
95
+ release = locks.acquire(`${entry.file}.lock`);
96
+ // Re-read only after the same record lock used by observers and callback settlement.
97
+ assertPrivateHistoryPath(entry.file, false);
98
+ const record = readJsonFileNoFollow(entry.file, "Watch history");
99
+ entry.provider.assert(record);
100
+ const raw = recordValue(record);
101
+ const id = String(raw.watch_id);
102
+ if (entry.name !== `${id}.json`)
103
+ throw new Error("Watch history filename identity mismatch");
104
+ const fingerprint = createHash("sha256").update(JSON.stringify(record)).digest("hex");
105
+ const existing = loadWatchHistoryReceipt(options.storeDir, entry.provider.name, id);
106
+ if (existing && existing.record_sha256 !== fingerprint)
107
+ throw new Error("Expired Watch body changed");
108
+ if (!watchHistoryExpired(record, now)) {
109
+ result.skipped++;
110
+ continue;
111
+ }
112
+ saveWatchHistoryReceipt(options.storeDir, { schema: "agent-knock-knock/watch-history-receipt", version: 1,
113
+ provider: entry.provider.name, watch_id: id, status: "completed", settled_at: watchHistorySettledAt(record),
114
+ deleted_at: now.toISOString(), record_sha256: fingerprint });
115
+ fs.unlinkSync(entry.file);
116
+ const directoryFd = fs.openSync(path.dirname(entry.file), fs.constants.O_RDONLY);
117
+ try {
118
+ fs.fsyncSync(directoryFd);
119
+ }
120
+ finally {
121
+ fs.closeSync(directoryFd);
122
+ }
123
+ result.deleted++;
124
+ }
125
+ catch (error) {
126
+ if (isNodeError(error, "ENOENT") || isNodeError(error, "LOCK_TIMEOUT"))
127
+ result.skipped++;
128
+ else
129
+ result.errors++;
130
+ }
131
+ finally {
132
+ release?.();
133
+ }
134
+ }
135
+ const cursor = selected.length && selected.length < remaining.length ? selected.at(-1).key : undefined;
136
+ atomicSaveJsonFile(maintenancePath(options.storeDir), {
137
+ schema: "agent-knock-knock/watch-history-maintenance", version: 1, last_run_at: now.toISOString(), ...(cursor ? { cursor } : {})
138
+ }, { rootLabel: "AKK Store", directoryLabel: "Watch history receipts", fileLabel: "Watch history maintenance",
139
+ ensureDirectory: ensureDir, fsyncNewDirectoryParent: true });
140
+ return result;
141
+ });
142
+ }
143
+ //# sourceMappingURL=watch-history-retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-history-retention.js","sourceRoot":"","sources":["../../src/watch-history-retention.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type WatchListInventory } from "./watch-list-projection.js";
2
+ type Row = Record<string, unknown>;
3
+ /** Pure retained-record inventory: no native clients, monitors, reconciliation or callback attempts. */
4
+ export declare function readWatchListInventory(storeDir: string, readManagedTurns: () => Row[]): WatchListInventory;
5
+ export declare function runWatchList(options: Row, readManagedTurns: () => Row[]): void;
6
+ export {};
@@ -0,0 +1,62 @@
1
+ import { createCodexNativeStateStore } from "./codex-native-state-store.js";
2
+ import { createClaudeNativeStateStore } from "./claude-native-state-store.js";
3
+ import { createDesktopStateStore } from "./desktop-state-store.js";
4
+ import { createTerminalWatchStore } from "./terminal-watch-store.js";
5
+ import { codexNativeTaskProjection } from "./codex-native-public-projection.js";
6
+ import { claudeNativeTaskProjection } from "./claude-native-public-projection.js";
7
+ import { desktopTaskProjection } from "./desktop-public-projection.js";
8
+ import { publicTerminalWatch } from "./terminal-watch-presentation.js";
9
+ import { defaultStoreDir } from "./store.js";
10
+ import { expandHome } from "./cli-command-runtime.js";
11
+ import { cliCwd, cliNowMs, writeCliStdout } from "./cli-runtime-context.js";
12
+ import { parseWatchListOptions, projectWatchList } from "./watch-list-projection.js";
13
+ const readOnlyLocks = { acquire() { throw new Error("Watches listing must not mutate Store"); } };
14
+ /** Pure retained-record inventory: no native clients, monitors, reconciliation or callback attempts. */
15
+ export function readWatchListInventory(storeDir, readManagedTurns) {
16
+ const inventory = { watches: [], managed_turns: [], diagnostics: [] };
17
+ const providers = [
18
+ ["codex_cli", () => {
19
+ const scan = createCodexNativeStateStore(storeDir, readOnlyLocks).scanForReconciliation();
20
+ return { rows: scan.tasks.map(task => ({ ...codexNativeTaskProjection(task), agent: "codex" })), errors: scan.errors.length };
21
+ }],
22
+ ["claude_cli", () => {
23
+ const scan = createClaudeNativeStateStore(storeDir, readOnlyLocks).scanForReconciliation();
24
+ return { rows: scan.tasks.map(task => ({ ...claudeNativeTaskProjection(task), agent: "claude" })), errors: scan.errors.length };
25
+ }],
26
+ ["codex_desktop", () => {
27
+ const scan = createDesktopStateStore(storeDir, readOnlyLocks).scanForReconciliation();
28
+ return { rows: scan.tasks.map(task => ({ ...desktopTaskProjection(task, false), agent: "codex" })), errors: scan.errors.length };
29
+ }],
30
+ ["terminal", () => {
31
+ const scan = createTerminalWatchStore(storeDir, readOnlyLocks).scanForReconciliation();
32
+ return { rows: scan.watches.map(watch => publicTerminalWatch(watch)), errors: scan.errors.length };
33
+ }]
34
+ ];
35
+ for (const [provider, scan] of providers) {
36
+ try {
37
+ const result = scan();
38
+ inventory.watches.push(...result.rows);
39
+ inventory.diagnostics.push({ provider, status: result.errors ? "partial" : "ok", invalid_records: result.errors });
40
+ }
41
+ catch {
42
+ inventory.diagnostics.push({ provider, status: "unavailable" });
43
+ }
44
+ }
45
+ try {
46
+ inventory.managed_turns = readManagedTurns();
47
+ inventory.diagnostics.push({ provider: "managed_turns", status: "ok" });
48
+ }
49
+ catch {
50
+ inventory.diagnostics.push({ provider: "managed_turns", status: "unavailable" });
51
+ }
52
+ return inventory;
53
+ }
54
+ export function runWatchList(options, readManagedTurns) {
55
+ const params = { hours: options.hours, limit: options.limit, cursor: options.cursor, agent: options.agent,
56
+ status: options.status, conversation_id: options.conversation ?? options.conversationId };
57
+ parseWatchListOptions(params, cliNowMs());
58
+ const supplied = options.storeDir ?? options.logDir;
59
+ const storeDir = expandHome(typeof supplied === "string" ? supplied : defaultStoreDir(cliCwd()));
60
+ writeCliStdout(JSON.stringify(projectWatchList(readWatchListInventory(storeDir, readManagedTurns), params, cliNowMs())) + "\n");
61
+ }
62
+ //# sourceMappingURL=watch-list-cli-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-list-cli-adapter.js","sourceRoot":"","sources":["../../src/watch-list-cli-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ type Row = Record<string, unknown>;
2
+ export interface WatchListInventory {
3
+ watches: Row[];
4
+ managed_turns: Row[];
5
+ diagnostics?: Row[];
6
+ }
7
+ export declare function parseWatchListOptions(params?: Row, nowMs?: number): {
8
+ hours: number;
9
+ limit: number;
10
+ filters: Row;
11
+ scope: string;
12
+ asOf: number;
13
+ after: string;
14
+ since: number;
15
+ };
16
+ /** Only public summaries cross this boundary; request text, output and authority never do. */
17
+ export declare function projectWatchList(inventory: WatchListInventory, params?: Row, nowMs?: number): Row;
18
+ export {};
@@ -0,0 +1,158 @@
1
+ import { createHash } from "node:crypto";
2
+ import { DEFAULT_WATCH_HISTORY_HOURS, WATCH_HISTORY_RETENTION_HOURS } from "./watch-history-policy.js";
3
+ import { HOST_LIST_MAX_BYTES, HOST_LIST_MAX_WEIGHTED_CHARS, hostListWatchNeedsAttention, hostListWeightedChars } from "./semantic-tool-list-budget.js";
4
+ import { recordValue } from "./value-guards.js";
5
+ const scalarFields = ["watch_id", "turn_id", "id", "short_ref", "conversation_id", "terminal_id", "session_id", "native_thread_id", "native_turn_id", "native_input_id", "native_receipt_turn_id",
6
+ "source", "agent", "workspace", "status", "observation_status", "observation_state", "renewal_count", "renewed_at", "recovered_at", "observation_mode", "watch_mode", "confidence", "anchor_state", "task_kind", "management_state",
7
+ "created_at", "updated_at", "observed_at", "last_activity_at", "deadline_at", "hard_timeout_at", "closed_at", "unwatched_at",
8
+ "callback_configured", "callback_expected", "callback_in_flight", "callback_state", "callback_delivery_scope", "channel_delivery_state",
9
+ "pending_manual_count", "pending_async_count", "pending_interaction_count", "observation_error", "observation_active", "send_state", "submission_state"];
10
+ export function parseWatchListOptions(params = {}, nowMs = Date.now()) {
11
+ const hours = integer(params.hours, DEFAULT_WATCH_HISTORY_HOURS, 1, WATCH_HISTORY_RETENTION_HOURS, "hours");
12
+ const limit = integer(params.limit, 40, 1, 100, "limit");
13
+ const filters = { hours };
14
+ for (const key of ["agent", "status", "conversation_id"]) {
15
+ if (params[key] === undefined)
16
+ continue;
17
+ if (typeof params[key] !== "string" || !params[key].trim() || params[key].length > 2048)
18
+ throw new Error(`Invalid Watches ${key}`);
19
+ filters[key] = params[key];
20
+ }
21
+ if (filters.agent !== undefined && !["codex", "claude"].includes(String(filters.agent)))
22
+ throw new Error("Watches agent must be codex or claude");
23
+ const scope = digest(JSON.stringify(filters));
24
+ const { asOf, after } = parseWatchListCursor(params.cursor, scope, nowMs);
25
+ return { hours, limit, filters, scope, asOf, after, since: asOf - hours * 3_600_000 };
26
+ }
27
+ /** Bind pagination to the original time window and exact normalized filters. */
28
+ function parseWatchListCursor(value, scope, nowMs) {
29
+ if (value === undefined)
30
+ return { asOf: nowMs, after: "" };
31
+ try {
32
+ if (typeof value !== "string" || value.length > 512 || !/^[A-Za-z0-9_-]+$/u.test(value))
33
+ throw new Error();
34
+ const parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
35
+ if (parsed.version !== 1 || parsed.scope !== scope || !Number.isSafeInteger(parsed.as_of) || parsed.as_of < 0 || parsed.as_of > nowMs ||
36
+ typeof parsed.after !== "string" || !/^[a-f0-9]{64}$/u.test(parsed.after))
37
+ throw new Error();
38
+ return { asOf: parsed.as_of, after: parsed.after };
39
+ }
40
+ catch {
41
+ throw new Error("Invalid Watches cursor or changed filters; restart watches without cursor");
42
+ }
43
+ }
44
+ /** Only public summaries cross this boundary; request text, output and authority never do. */
45
+ export function projectWatchList(inventory, params = {}, nowMs = Date.now()) {
46
+ const options = parseWatchListOptions(params, nowMs);
47
+ const entries = ([...inventory.watches.map(row => ({ row, kind: "watch" })),
48
+ ...inventory.managed_turns.map(row => ({ row, kind: "managed_turn" }))]).flatMap(({ row, kind }) => {
49
+ if (options.filters.agent && row.agent !== options.filters.agent || options.filters.status && row.status !== options.filters.status ||
50
+ options.filters.conversation_id && ![row.conversation_id, row.terminal_id, row.session_id].includes(options.filters.conversation_id))
51
+ return [];
52
+ const attention = hostListWatchNeedsAttention(row);
53
+ const time = latestTime(row);
54
+ const within = time !== undefined && time >= options.since && time <= options.asOf;
55
+ if (!within && !attention)
56
+ return [];
57
+ const id = row.watch_id ?? row.turn_id;
58
+ if (typeof id !== "string" || !id)
59
+ return [];
60
+ return [{ row, kind, attention, within, time, key: digest(`${kind}:${id}`) }];
61
+ }).sort((a, b) => Number(b.attention) - Number(a.attention) || (b.time ?? 0) - (a.time ?? 0) || a.key.localeCompare(b.key));
62
+ const index = options.after ? entries.findIndex(entry => entry.key === options.after) : -1;
63
+ if (options.after && index < 0)
64
+ throw new Error("Watches changed since this cursor; restart watches without cursor");
65
+ const remaining = entries.slice(index + 1);
66
+ const output = {
67
+ projection: { schema: "agent-knock-knock/watch-list", version: 1 },
68
+ watches: [], managed_turns: [],
69
+ window: { hours: options.hours, since: new Date(options.since).toISOString(), as_of: new Date(options.asOf).toISOString(),
70
+ includes_older_attention: true, note: "Active or unresolved records remain visible outside the history window. Managed Turns are not Watches." },
71
+ read_at: new Date(nowMs).toISOString(),
72
+ diagnostics: (inventory.diagnostics ?? []).map(row => ({ provider: row.provider, status: row.status, invalid_records: row.invalid_records })),
73
+ pagination: { limit: options.limit, total_available: entries.length, attention: entries.filter(entry => entry.attention).length,
74
+ max_output_bytes: HOST_LIST_MAX_BYTES, max_output_weighted_chars: HOST_LIST_MAX_WEIGHTED_CHARS,
75
+ live_snapshot: true, note: "Window boundaries stay fixed across pages; record states may change. Exact Status returns current details and recovery actions." }
76
+ };
77
+ let returned = 0;
78
+ update();
79
+ for (const entry of remaining) {
80
+ if (returned >= options.limit)
81
+ break;
82
+ const target = output[entry.kind === "watch" ? "watches" : "managed_turns"];
83
+ target.push(compactWatch(entry.row, entry.kind, entry.attention, entry.within));
84
+ returned++;
85
+ update();
86
+ if (overBudget(output)) {
87
+ target.pop();
88
+ returned--;
89
+ update();
90
+ break;
91
+ }
92
+ }
93
+ if (!returned && remaining.length)
94
+ throw new Error("Watch identity exceeds the response budget; use exact Status");
95
+ if (overBudget(output))
96
+ throw new Error("Watches metadata exceeds the response budget");
97
+ return output;
98
+ function update() {
99
+ const more = returned < remaining.length;
100
+ const last = remaining[returned - 1]?.key;
101
+ const cursor = more && last ? Buffer.from(JSON.stringify({ version: 1, scope: options.scope, as_of: options.asOf, after: last })).toString("base64url") : null;
102
+ Object.assign(output.pagination, { returned, has_more: more, remaining: remaining.length - returned, next_cursor: cursor,
103
+ next_args: cursor ? { ...options.filters, limit: options.limit, cursor } : null });
104
+ }
105
+ }
106
+ function compactWatch(row, kind, attention, within) {
107
+ const output = { kind, attention_required: attention, outside_window: !within };
108
+ for (const key of scalarFields)
109
+ if (["string", "number", "boolean"].includes(typeof row[key]) || row[key] === null)
110
+ output[key] = row[key];
111
+ const delivery = recordValue(row.callback_delivery);
112
+ if (delivery)
113
+ output.callback_delivery = pick(delivery, ["status", "attempts", "attempt_state", "next_attempt_at"]);
114
+ const callback = recordValue(row.callback);
115
+ if (callback)
116
+ output.callback = pick(callback, ["pending", "delivered", "failed", "superseded", "last_error_code"]);
117
+ const notifications = Array.isArray(row.callback_notifications) ? row.callback_notifications : [];
118
+ if (notifications.length) {
119
+ const statuses = {};
120
+ for (const note of notifications) {
121
+ const status = recordValue(note)?.status;
122
+ if (typeof status === "string" && ["accepted", "uncertain", "failed", "ready", "leased", "retry_wait"].includes(status))
123
+ statuses[status] = (statuses[status] ?? 0) + 1;
124
+ }
125
+ output.callback_notifications = { total: notifications.length, statuses };
126
+ }
127
+ const input = kind === "watch" ? { watch_id: row.watch_id } : { turn_id: row.turn_id };
128
+ const actions = recordValue(row.available_actions) ?? {};
129
+ output.available_actions = kind === "managed_turn"
130
+ ? Object.fromEntries(["status", "retry_callback", "close"].filter(name => recordValue(actions[name])).map(name => [name, actions[name]]))
131
+ : { status: true };
132
+ if (kind !== "managed_turn" || !Object.keys(output.available_actions).length) {
133
+ output.available_actions = { status: true };
134
+ output.action_inputs = { status: { arguments: input } };
135
+ }
136
+ output.detail_tool = "agent_knock_knock_status";
137
+ return output;
138
+ }
139
+ function pick(row, keys) { return Object.fromEntries(keys.filter(key => row[key] !== undefined).map(key => [key, row[key]])); }
140
+ function latestTime(row) {
141
+ const times = ["updated_at", "observed_at", "last_activity_at", "closed_at", "unwatched_at", "created_at"].map(key => typeof row[key] === "string" ? Date.parse(row[key]) : NaN).filter(Number.isFinite);
142
+ const settlement = recordValue(row.settlement);
143
+ if (typeof settlement?.observed_at === "string" && Number.isFinite(Date.parse(settlement.observed_at)))
144
+ times.push(Date.parse(settlement.observed_at));
145
+ return times.length ? Math.max(...times) : undefined;
146
+ }
147
+ function integer(value, fallback, min, max, name) {
148
+ const number = value === undefined ? fallback : typeof value === "string" && /^\d+$/u.test(value) ? Number(value) : value;
149
+ if (!Number.isSafeInteger(number) || Number(number) < min || Number(number) > max)
150
+ throw new Error(`Watches ${name} must be between ${min} and ${max}`);
151
+ return Number(number);
152
+ }
153
+ function digest(value) { return createHash("sha256").update(value).digest("hex"); }
154
+ function overBudget(value) {
155
+ const json = JSON.stringify(value);
156
+ return Buffer.byteLength(json, "utf8") > HOST_LIST_MAX_BYTES || hostListWeightedChars(json) > HOST_LIST_MAX_WEIGHTED_CHARS;
157
+ }
158
+ //# sourceMappingURL=watch-list-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-list-projection.js","sourceRoot":"","sources":["../../src/watch-list-projection.ts"],"names":[],"mappings":"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"}
@@ -42,11 +42,13 @@ they are not converted into a permissive activity fallback.
42
42
  Ordinary List/Status remains observation-only and does not create either Watch.
43
43
  Existing managed tasks and user terminals are not restarted by this policy.
44
44
 
45
- The store writer protocol is 9. Outer Terminal Watch schema remains 3; new
45
+ The store writer protocol is 10. Outer Terminal Watch schema remains 3; new
46
46
  paginated anchors and request-correlated activity anchors use version 2. Earlier
47
47
  anchors remain readable. The store upgrade changes the writer fence without
48
48
  rewriting existing private Watch records, and older writers cannot mutate the
49
- upgraded store.
49
+ upgraded store. Protocol 10 also fences Watch deletion receipts: a pruned
50
+ completed request cannot be recreated by an older writer. Uncertain or pending
51
+ notifications are never eligible for history cleanup.
50
52
 
51
53
  Read errors expose only the operation stage and parsed actual/expected backend
52
54
  versions. Full server responses, task text and raw RPC errors are not copied into
@@ -1,79 +1,77 @@
1
- # List output and history
1
+ # Conversations and Watch inventory
2
2
 
3
- AKK 0.14.9 bounds the entire controller-facing List result before serializing
4
- JSON. Current conversations come first; healthy ended Watches no longer crowd
5
- them out. Failed or uncertain callbacks, pending interactions and active
6
- observations remain in the current view. This changes presentation, not Watch
7
- deadlines, callback delivery or persisted history.
3
+ Since 0.14.13, discovery is separate from monitoring. `agent_knock_knock_list`,
4
+ `/akk list` and CLI `list` return currently discoverable conversations. They do
5
+ not include Watch inventories or retained managed Turn history. Current managed
6
+ ownership, pending approvals and blocking conditions remain on the conversation.
7
+ Desktop sidebar entries whose live owner is unconfirmed remain visible with
8
+ their actual connection status; visibility does not authorize Send.
8
9
 
9
- Starting in 0.14.12, the default view prefers a verified backend as the project's
10
- CLI entry when discovery finds one same-agent terminal and one loaded backend
11
- with no known identity conflict. Its original conversation ID, title, status
12
- and advertised actions are retained. The terminal candidate is available in
13
- `terminalDebug` / `list --terminal-debug`; callers do not choose a transport.
14
- Proven exact aliases still combine their verified capabilities. Display
15
- preference alone neither proves an alias nor copies terminal permissions or
16
- management into the backend. A matching cwd or startup `resume` argument never
17
- redirects an existing terminal selector.
10
+ Use `agent_knock_knock_watches`, `/akk watches` or CLI `watches` to inspect
11
+ monitoring. This is a read-only Store query: it does not create or renew a Watch,
12
+ reconcile callbacks, reconnect a native session or send notifications.
18
13
 
19
- Multiple candidates, identity conflicts and terminal records needing attention
20
- or management recovery remain visible. Direct-only and terminal-only CLI
21
- sessions remain available. Rows and connections are not a count of independent
22
- tasks. AKK still verifies the exact target before terminal fallback; backend
23
- busy/blocked states and uncertain sends never authorize a second route.
14
+ ## Conversation selection
24
15
 
25
- | Request | Included records |
26
- | --- | --- |
27
- | `{}` or `{"listView":"current"}` | Conversations and current/attention-needed observations |
28
- | `{"listView":"history"}` | Healthy ended Watches and retained managed Turns |
29
- | `{"listView":"all"}` or `{"all":true}` | Both, still paged |
16
+ Since 0.14.12 the default view prefers a verified backend as the project's CLI
17
+ entry when discovery finds one same-agent terminal and one loaded backend with
18
+ no known identity conflict. Its original conversation ID, title, status and
19
+ actions are retained. Terminal candidates remain in `terminalDebug` /
20
+ `list --terminal-debug`. Proven exact aliases combine verified capabilities;
21
+ display grouping alone does not copy terminal permissions or redirect selectors.
22
+ Multiple candidates, conflicts and terminals needing management recovery remain
23
+ visible. Rows and connections are not a count of independent tasks.
30
24
 
31
- An explicit `listView` takes precedence over the view selected by `all`.
32
- `all` continues to control underlying terminal-history discovery; it does not
33
- mean an unlimited Host response. Raw CLI `list --json` and `list --all --json`
34
- retain their operator/debug behavior.
25
+ Host List uses `agent-knock-knock/host-list-compact` v4. Follow
26
+ `pagination.next_args` while `has_more` is true. `listLimit` defaults to 40 and
27
+ accepts 1–100. Pages are fresh discoveries, not a frozen snapshot; restart if
28
+ membership changes invalidate a cursor. Legacy `listView=history/all`, `all=true`
29
+ and CLI `list --all` return a migration error directing callers to `watches`.
35
30
 
36
- Follow `pagination.next_args` unchanged while `pagination.has_more` is true.
37
- Every page is a fresh read, not a frozen snapshot. If the cursor is invalid
38
- after membership changes, restart List. `listLimit` defaults to 40 rows and
39
- accepts 1–100; the output budget may produce a smaller page. Counts describe
40
- all records observed by that discovery, not only the returned page.
31
+ Each Host page is capped at 24 KiB of UTF-8 JSON and 12,000 weighted characters
32
+ (ASCII 1, other code points 16), including metadata. This is not a token budget.
33
+ Oversized rows retain exact IDs and a Status entry point; omitted actions do not
34
+ mean unsupported capabilities. Read exact Status for current questions, approvals
35
+ and bounded public progress. List contains no progress body.
41
36
 
42
- The compact contract is `agent-knock-knock/host-list-compact`, version 3,
43
- action contract 31. It retains exact conversation, native task and Watch IDs
44
- and usable action inputs. A very large row becomes a Status reference with
45
- `details_omitted=true`; omitted actions do not mean unsupported capabilities.
46
- Refresh exact Status to obtain pending questions, approvals and current actions.
47
- No progress body is added to List.
37
+ Desktop catalog pagination remains separate: finish Host pages for one catalog
38
+ page, then pass `desktop_scan.next_cursor` as `desktopCursor` with the same filters
39
+ and no previous Host cursor. Explicit Desktop catalog history is a separate
40
+ native discovery view, not AKK Watch history.
48
41
 
49
- `watch_summary` distinguishes current observations from healthy history.
50
- `pagination.attention_counts` reports failed/uncertain/pending delivery and
51
- pending interactions even when their rows appear on a later page. Categories
52
- can overlap. Watches are observations, not extra conversations or independent
53
- tasks. `callback_expected=false` alone does not mean missing or failed delivery;
54
- completed notifications and unresolved delivery have different states.
42
+ ## Monitoring and retention
55
43
 
56
- Each page is limited to 24 KiB of UTF-8 JSON and 12,000 conservative weighted
57
- characters (ASCII costs 1, other Unicode code points cost 16), including its
58
- metadata. These are not token counts or a guarantee for every custom Host's
59
- smaller output allowance. The current OpenClaw Codex harness was checked at
60
- its lowest 16,000-character budget. The limits reduce returned context, not the
61
- cost of reading the underlying local records.
44
+ `watches` defaults to a 24-hour lookback, 40 rows per page (maximum 100) and the
45
+ same whole-response output limits. The lookback may be set from 1 to 48 hours.
46
+ Continuation freezes the query's `as_of` and filters, not the underlying Store;
47
+ refresh before acting. Active or unresolved observations remain visible even
48
+ outside the lookback, marked `outside_window`. Retained terminal managed Turns
49
+ are listed separately from Watches so offline recovery is still discoverable.
50
+ Use each row's exact Status input to inspect it; managed rows retain the existing
51
+ pane-independent Close / callback-retry actions where permitted; these records are
52
+ observations, not additional conversations or a count of independent tasks.
62
53
 
63
- Desktop catalog pagination is separate: finish the Host pages for one catalog
64
- page, then use `desktop_scan.next_cursor` as `desktopCursor` with the same
65
- Desktop filters and no previous Host cursor. Sidebar membership and a saved
66
- history row still do not prove a live Desktop owner.
54
+ Healthy completed Watch bodies become eligible for cleanup 48 hours after
55
+ settlement and callback completion. Cleanup is bounded and performed by Host
56
+ maintenance, at most once per hour and up to 100 records per pass. Active,
57
+ failed, uncertain, pending-interaction or otherwise unresolved records are
58
+ retained. Managed Turns, Sessions and native coding-agent history are not deleted.
67
59
 
68
- See [the operator guide](operator-guide.md), [Desktop discovery](codex-desktop-compatibility.md#find-and-select-a-conversation),
69
- and [task recovery](backend-task-recovery.md) for the related workflows.
60
+ Cleanup writes a minimal durable tombstone before removing the body. It retains
61
+ the provider, exact Watch ID, settlement/prune time and record fingerprint, not
62
+ prompts, results or callback payloads. Old deterministic Send IDs cannot recreate
63
+ a task after cleanup. An exact request for pruned history returns
64
+ `watch_history_expired` with replay forbidden, not a misleading missing-record
65
+ success. Tombstones are retained for deduplication; this is not a promise that
66
+ all AKK metadata disappears after 48 hours. Writer protocol 10 prevents older processes from recreating pruned requests;
67
+ rolling back requires a coherent pre-upgrade Store backup, not lowering the manifest.
68
+ Nothing is cleaned merely by reading
69
+ `list` or `watches`.
70
70
 
71
- Terminal Send routing uses the same authoritative action projection as List,
72
- then revalidates the current process, endpoint, approval and input ownership at
73
- dispatch. A displayed action is not permission to bypass a changed terminal.
74
- New route journals record a preparation rejection with `request_dispatched:false`
75
- only when no executor has started. The v1 `reserved` route remains pinned;
76
- this is neither task acceptance nor uncertain delivery. An explicit retry with
77
- the same message ID can prepare that same route again, never switch transports.
78
- Executor failures retain uncertain semantics. Legacy records without phase
79
- proof are left conservative; upgrades do not replay or rewrite old outcomes.
71
+ `callback_expected=false` alone is not a delivery failure or proof of delivery.
72
+ Native completion, controller callback acceptance and delivery to an external
73
+ chat remain separate states. Missing Watch fields in List are intentional, not
74
+ proof that Send lacked monitoring. Query `watches` or the exact returned Watch ID.
75
+
76
+ See [the operator guide](operator-guide.md), [Desktop discovery](codex-desktop-compatibility.md#find-and-select-a-conversation)
77
+ and [task recovery](backend-task-recovery.md).