mixdog 0.9.55 → 0.9.59

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 (120) hide show
  1. package/package.json +3 -1
  2. package/scripts/_smoke_wd.mjs +7 -0
  3. package/scripts/agent-terminal-reap-test.mjs +127 -2
  4. package/scripts/compact-file-reattach-test.mjs +88 -0
  5. package/scripts/compact-pressure-test.mjs +45 -21
  6. package/scripts/compact-recall-digest-test.mjs +57 -0
  7. package/scripts/compact-smoke.mjs +35 -39
  8. package/scripts/desktop-session-bridge-test.mjs +271 -9
  9. package/scripts/generate-oc-icons.mjs +11 -0
  10. package/scripts/live-share-test.mjs +148 -0
  11. package/scripts/live-worker-smoke.mjs +1 -1
  12. package/scripts/max-output-recovery-test.mjs +12 -1
  13. package/scripts/mouse-tracking-restore-smoke.mjs +107 -0
  14. package/scripts/provider-admission-scheduler-test.mjs +100 -0
  15. package/scripts/provider-contract-test.mjs +49 -0
  16. package/scripts/resource-admission-test.mjs +5 -2
  17. package/scripts/session-ingest-compaction-smoke.mjs +38 -0
  18. package/scripts/steering-drain-buckets-test.mjs +15 -0
  19. package/scripts/submit-commandbusy-race-test.mjs +54 -3
  20. package/scripts/tool-smoke.mjs +2 -3
  21. package/scripts/tui-ambiguous-width-test.mjs +113 -0
  22. package/scripts/tui-runtime-load-bench.mjs +5 -0
  23. package/scripts/tui-transcript-perf-test.mjs +167 -0
  24. package/src/app.mjs +23 -0
  25. package/src/cli.mjs +6 -0
  26. package/src/lib/keychain-cjs.cjs +70 -20
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +4 -2
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +18 -17
  29. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +18 -0
  30. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +111 -0
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +6 -6
  32. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +61 -2
  33. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +13 -4
  34. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +43 -2
  35. package/src/runtime/agent/orchestrator/session/compact/file-reattach.mjs +112 -0
  36. package/src/runtime/agent/orchestrator/session/context-utils.mjs +203 -49
  37. package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +6 -2
  38. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +110 -15
  39. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +2 -0
  40. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +7 -1
  41. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +109 -2
  42. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +15 -7
  43. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +39 -39
  44. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +108 -4
  45. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +19 -0
  46. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -11
  47. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +132 -24
  48. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -1
  49. package/src/runtime/agent/orchestrator/session/manager.mjs +16 -1
  50. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +39 -21
  51. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +18 -0
  52. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +91 -1
  53. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +14 -33
  54. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +169 -0
  55. package/src/runtime/agent/orchestrator/session/store.mjs +474 -42
  56. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +17 -2
  57. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +36 -1
  58. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +20 -0
  59. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +5 -1
  60. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +249 -11
  61. package/src/runtime/channels/data/voice-runtime-manifest.json +21 -5
  62. package/src/runtime/channels/lib/scheduler.mjs +8 -6
  63. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +71 -8
  64. package/src/runtime/channels/lib/voice-transcription.mjs +2 -2
  65. package/src/runtime/channels/lib/whisper-language.mjs +4 -0
  66. package/src/runtime/memory/lib/embedding-provider.mjs +7 -0
  67. package/src/runtime/memory/lib/embedding-worker.mjs +20 -0
  68. package/src/runtime/memory/lib/query-handlers.mjs +10 -4
  69. package/src/runtime/memory/lib/recall-format.mjs +43 -2
  70. package/src/runtime/memory/lib/session-ingest-runtime.mjs +90 -64
  71. package/src/runtime/shared/err-text.mjs +4 -1
  72. package/src/runtime/shared/resource-admission.mjs +11 -0
  73. package/src/runtime/shared/schedule-model-ref.mjs +28 -0
  74. package/src/runtime/shared/schedule-session-run.mjs +63 -0
  75. package/src/runtime/shared/schedules-db.mjs +8 -3
  76. package/src/runtime/shared/tool-result-summary.mjs +4 -1
  77. package/src/runtime/shared/tool-surface.mjs +7 -7
  78. package/src/runtime/shared/transcript-writer.mjs +17 -0
  79. package/src/session-runtime/channel-config-api.mjs +11 -0
  80. package/src/session-runtime/config-helpers.mjs +9 -6
  81. package/src/session-runtime/context-status.mjs +80 -3
  82. package/src/session-runtime/lifecycle-api.mjs +154 -40
  83. package/src/session-runtime/provider-auth-api.mjs +21 -2
  84. package/src/session-runtime/provider-usage.mjs +4 -1
  85. package/src/session-runtime/resource-api.mjs +12 -11
  86. package/src/session-runtime/runtime-core.mjs +45 -11
  87. package/src/session-runtime/session-text.mjs +56 -6
  88. package/src/session-runtime/session-turn-api.mjs +70 -2
  89. package/src/session-runtime/tool-catalog.mjs +2 -1
  90. package/src/session-runtime/workflow-agents-api.mjs +2 -2
  91. package/src/standalone/agent-tool/render.mjs +5 -1
  92. package/src/standalone/agent-tool.mjs +63 -3
  93. package/src/standalone/channel-admin.mjs +19 -3
  94. package/src/standalone/channel-daemon.mjs +40 -0
  95. package/src/tui/app/resume-picker.mjs +5 -1
  96. package/src/tui/app/settings-picker.mjs +19 -0
  97. package/src/tui/app/transcript-window.mjs +45 -8
  98. package/src/tui/app/use-mouse-input.mjs +101 -31
  99. package/src/tui/app/use-transcript-window.mjs +53 -9
  100. package/src/tui/components/ToolExecution.jsx +3 -4
  101. package/src/tui/components/TranscriptItem.jsx +3 -0
  102. package/src/tui/dist/index.mjs +17391 -14920
  103. package/src/tui/engine/context-state.mjs +10 -1
  104. package/src/tui/engine/live-share.mjs +390 -0
  105. package/src/tui/engine/queue-helpers.mjs +23 -0
  106. package/src/tui/engine/session-api-ext.mjs +439 -40
  107. package/src/tui/engine/session-api.mjs +7 -1
  108. package/src/tui/engine/session-flow.mjs +21 -7
  109. package/src/tui/engine/tool-card-results.mjs +3 -1
  110. package/src/tui/engine/turn.mjs +57 -4
  111. package/src/tui/engine.mjs +211 -7
  112. package/src/tui/index.jsx +2 -0
  113. package/src/tui/lib/voice-setup.mjs +10 -4
  114. package/src/tui/paste-attachments.mjs +4 -1
  115. package/src/vendor/statusline/src/gateway/session-routes.mjs +24 -1
  116. package/src/workflows/default/WORKFLOW.md +3 -0
  117. package/vendor/ink/build/display-width.js +14 -0
  118. package/vendor/ink/build/output.js +24 -3
  119. package/vendor/ink/build/wrap-text.d.ts +2 -0
  120. package/vendor/ink/build/wrap-text.js +45 -4
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Read-only session summary catalog for cold desktop startup.
3
+ *
4
+ * This module intentionally avoids store.mjs, config/provider loading, workers,
5
+ * and atomic-lock writers. The full runtime remains authoritative after it is
6
+ * loaded; cold startup only needs enough metadata to paint the session list.
7
+ */
8
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
9
+ import { homedir } from 'os';
10
+ import { join } from 'path';
11
+
12
+ const SESSION_SUMMARY_INDEX_VERSION = 2;
13
+
14
+ // Mirror of lifecycle-api.mjs listLeadSessions visibility: the cold catalog
15
+ // must never surface worker/agent dispatches (memory ingest chunks, judges,
16
+ // spawned agents) — the authoritative engine excludes them, so a click on
17
+ // such a row dead-ends in "Session is not available." (user report).
18
+ const LEAD_OWNERS = new Set(['cli', 'user', 'mixdog', 'legacy']);
19
+
20
+ function isLeadVisibleRow(row) {
21
+ const owner = String(row.owner || 'user').trim().toLowerCase();
22
+ if (owner && !LEAD_OWNERS.has(owner)) return false;
23
+ const sourceType = String(row.sourceType || '').trim().toLowerCase();
24
+ const sourceName = String(row.sourceName || '').trim().toLowerCase();
25
+ const agent = String(row.agent || '').trim().toLowerCase();
26
+ return agent === 'lead'
27
+ || sourceType === 'lead'
28
+ || sourceType === 'cli'
29
+ || sourceType === 'schedule'
30
+ || (!sourceType && !sourceName && owner !== 'agent');
31
+ }
32
+
33
+ function dataDir() {
34
+ if (process.env.MIXDOG_DATA_DIR) return process.env.MIXDOG_DATA_DIR;
35
+ const home = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
36
+ return join(home, 'data');
37
+ }
38
+
39
+ function positiveNumber(value, fallback = 0) {
40
+ const number = Number(value);
41
+ return Number.isFinite(number) && number > 0 ? number : fallback;
42
+ }
43
+
44
+ function cleanText(value, maximum = 240) {
45
+ return String(value || '')
46
+ .replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, ' ')
47
+ .replace(/<mcp-instructions>[\s\S]*?<\/mcp-instructions>/gi, ' ')
48
+ .replace(/\s+/g, ' ')
49
+ .trim()
50
+ .slice(0, maximum);
51
+ }
52
+
53
+ function messageText(content) {
54
+ if (typeof content === 'string') return content;
55
+ if (!Array.isArray(content)) return '';
56
+ return content
57
+ .map((part) => typeof part === 'string' ? part : String(part?.text || part?.content || ''))
58
+ .filter(Boolean)
59
+ .join(' ');
60
+ }
61
+
62
+ function desktopSession(value, cwd = '') {
63
+ if (!value || typeof value !== 'object') return null;
64
+ if (value.classification === 'task') return { classification: 'task', projectPath: null };
65
+ if (value.classification !== 'project') return null;
66
+ const projectPath = typeof value.projectPath === 'string' && value.projectPath.trim()
67
+ ? value.projectPath.trim()
68
+ : String(cwd || '').trim();
69
+ return projectPath ? { classification: 'project', projectPath } : null;
70
+ }
71
+
72
+ function normalizedRow(row, heartbeatAt = 0) {
73
+ if (!row || typeof row.id !== 'string' || !/^[A-Za-z0-9_-]+$/.test(row.id)) return null;
74
+ return {
75
+ id: row.id,
76
+ updatedAt: positiveNumber(row.updatedAt, 0),
77
+ createdAt: positiveNumber(row.createdAt, 0),
78
+ lastHeartbeatAt: positiveNumber(row.lastHeartbeatAt, 0),
79
+ heartbeatAt: Math.max(positiveNumber(row.heartbeatAt, 0), positiveNumber(heartbeatAt, 0)),
80
+ closed: row.closed === true,
81
+ status: String(row.status || (row.closed === true ? 'closed' : 'idle')),
82
+ owner: row.owner || 'user',
83
+ agent: row.agent || null,
84
+ sourceType: row.sourceType || null,
85
+ sourceName: row.sourceName || null,
86
+ scopeKey: row.scopeKey || null,
87
+ ownerSessionId: row.ownerSessionId || null,
88
+ clientHostPid: positiveNumber(row.clientHostPid, 0) || null,
89
+ cwd: row.cwd || '',
90
+ desktopSession: desktopSession(row.desktopSession, row.cwd),
91
+ provider: row.provider || null,
92
+ model: row.model || null,
93
+ agentTag: row.agentTag || null,
94
+ task_id: row.task_id || row.taskId || null,
95
+ permission: row.permission || null,
96
+ toolPermission: row.toolPermission || null,
97
+ messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
98
+ preview: cleanText(row.preview),
99
+ generation: typeof row.generation === 'number' ? row.generation : 0,
100
+ implicitBashSessionId: row.implicitBashSessionId || null,
101
+ };
102
+ }
103
+
104
+ function rowFromSession(session, heartbeatAt = 0) {
105
+ const messages = Array.isArray(session?.messages) ? session.messages : [];
106
+ const preview = messages
107
+ .filter((message) => message?.role === 'user')
108
+ .map((message) => cleanText(messageText(message.content)))
109
+ .find(Boolean) || '';
110
+ return normalizedRow({
111
+ ...session,
112
+ messageCount: messages.filter((message) =>
113
+ message?.role === 'user' || message?.role === 'assistant').length,
114
+ preview,
115
+ }, heartbeatAt);
116
+ }
117
+
118
+ function sessionHeartbeatMtimes() {
119
+ const directory = join(dataDir(), 'sessions');
120
+ const result = new Map();
121
+ if (!existsSync(directory)) return result;
122
+ for (const filename of readdirSync(directory)) {
123
+ if (!filename.endsWith('.hb')) continue;
124
+ const id = filename.slice(0, -3);
125
+ if (!/^[A-Za-z0-9_-]+$/.test(id)) continue;
126
+ try {
127
+ const mtime = statSync(join(directory, filename)).mtimeMs || 0;
128
+ if (mtime > 0) result.set(id, mtime);
129
+ } catch { /* sidecar disappeared after readdir */ }
130
+ }
131
+ return result;
132
+ }
133
+
134
+ function scanSessionFiles(heartbeatMtimes = sessionHeartbeatMtimes()) {
135
+ const directory = join(dataDir(), 'sessions');
136
+ if (!existsSync(directory)) return [];
137
+ const rows = [];
138
+ for (const filename of readdirSync(directory)) {
139
+ if (!filename.endsWith('.json')) continue;
140
+ try {
141
+ const session = JSON.parse(readFileSync(join(directory, filename), 'utf8'));
142
+ const row = rowFromSession(session, heartbeatMtimes.get(session?.id) || 0);
143
+ if (row && isLeadVisibleRow(row)) rows.push(row);
144
+ } catch {
145
+ // A corrupt or concurrently replaced session is omitted from the
146
+ // cold catalog; the authoritative runtime can reconcile it later.
147
+ }
148
+ }
149
+ return rows.sort((left, right) => (right.updatedAt || 0) - (left.updatedAt || 0));
150
+ }
151
+
152
+ export function listStoredSessionSummaries(options = {}) {
153
+ const heartbeatMtimes = sessionHeartbeatMtimes();
154
+ if (options.refreshFromStorage === true) return scanSessionFiles(heartbeatMtimes);
155
+ const indexPath = join(dataDir(), 'session-summaries.json');
156
+ try {
157
+ const index = JSON.parse(readFileSync(indexPath, 'utf8'));
158
+ if (Number(index?.version) === SESSION_SUMMARY_INDEX_VERSION) {
159
+ const rows = (Array.isArray(index.rows) ? index.rows : [])
160
+ .map((row) => normalizedRow(row, heartbeatMtimes.get(row?.id) || 0))
161
+ .filter((row) => row && isLeadVisibleRow(row))
162
+ .sort((left, right) => (right.updatedAt || 0) - (left.updatedAt || 0));
163
+ if (rows.length > 0 || options.rebuildIfMissing === false) return rows;
164
+ }
165
+ } catch {
166
+ // Missing/malformed sidecars fall through to the read-only scan.
167
+ }
168
+ return options.rebuildIfMissing === false ? [] : scanSessionFiles(heartbeatMtimes);
169
+ }