@adhdev/daemon-core 0.9.82-rc.17 → 0.9.82-rc.171
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/dist/boot/process-hardening.d.ts +50 -0
- package/dist/chat/source-machine.d.ts +166 -0
- package/dist/chat/source-resolver.d.ts +104 -0
- package/dist/chat/subscription-updates.d.ts +1 -0
- package/dist/cli-adapter-types.d.ts +22 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +178 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +106 -63
- package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +29 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/commands/handler.d.ts +110 -0
- package/dist/commands/mesh-coordinator.d.ts +72 -1
- package/dist/commands/router.d.ts +22 -0
- package/dist/config/chat-history.d.ts +7 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/mesh-config.d.ts +71 -1
- package/dist/git/git-commands.d.ts +5 -1
- package/dist/index.d.ts +35 -6
- package/dist/index.js +18634 -3760
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18538 -3732
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/ipc/local-ipc-server.d.ts +91 -0
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/mesh/beads-db.d.ts +72 -0
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +30 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +90 -0
- package/dist/mesh/mesh-events.d.ts +96 -5
- package/dist/mesh/mesh-fast-forward.d.ts +39 -0
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-ledger.d.ts +58 -1
- package/dist/mesh/mesh-refine-status.d.ts +26 -0
- package/dist/mesh/mesh-work-queue.d.ts +44 -5
- package/dist/mesh/preview-freshness.d.ts +18 -0
- package/dist/mesh/refine-config.d.ts +193 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +113 -0
- package/dist/providers/approval-utils.d.ts +13 -0
- package/dist/providers/cli-provider-instance.d.ts +9 -3
- package/dist/providers/contracts.d.ts +98 -5
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
- package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
- package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
- package/dist/providers/native-history/dispatcher.d.ts +24 -0
- package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
- package/dist/providers/native-history/index.d.ts +13 -0
- package/dist/providers/provider-instance.d.ts +3 -0
- package/dist/providers/provider-loader.d.ts +26 -4
- package/dist/providers/provider-trust.d.ts +31 -0
- package/dist/providers/read-chat-contract.d.ts +29 -0
- package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
- package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
- package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
- package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
- package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
- package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
- package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
- package/dist/providers/sdk/v1/index.d.ts +30 -0
- package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
- package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
- package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
- package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
- package/dist/providers/sdk/v1/types/common/index.d.ts +169 -0
- package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
- package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
- package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
- package/dist/providers/spec/adapter.d.ts +56 -0
- package/dist/providers/spec/cli-adapter.d.ts +95 -0
- package/dist/providers/spec/driver.d.ts +149 -0
- package/dist/providers/spec/evaluator.d.ts +47 -0
- package/dist/providers/spec/loader.d.ts +14 -0
- package/dist/providers/spec/native-history-executor.d.ts +39 -0
- package/dist/providers/spec/route.d.ts +4 -0
- package/dist/providers/spec/schema.gen.d.ts +511 -0
- package/dist/providers/spec/types.d.ts +212 -0
- package/dist/providers/transcript-v2.d.ts +176 -0
- package/dist/providers/types/interactive-prompt.d.ts +48 -0
- package/dist/repo-mesh-types.d.ts +100 -1
- package/dist/sessions/registry.d.ts +3 -0
- package/dist/shared-types.d.ts +42 -1
- package/dist/status/reporter.d.ts +2 -0
- package/dist/status/snapshot.d.ts +1 -0
- package/dist/types.d.ts +5 -0
- package/package.json +7 -2
- package/src/agent-stream/poller.ts +2 -3
- package/src/boot/daemon-lifecycle.ts +17 -10
- package/src/boot/process-hardening.ts +89 -0
- package/src/chat/source-machine.ts +534 -0
- package/src/chat/source-resolver.ts +0 -0
- package/src/chat/subscription-updates.ts +14 -1
- package/src/cli-adapter-types.d.ts +1 -0
- package/src/cli-adapter-types.ts +21 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1086 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +670 -1137
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +13 -0
- package/src/cli-adapters/provider-cli-runtime.ts +3 -1
- package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/src/cli-adapters/provider-cli-shared.ts +59 -11
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +17 -1
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +8 -1
- package/src/commands/chat-commands.ts +1597 -60
- package/src/commands/cli-manager.ts +214 -3
- package/src/commands/handler.ts +809 -2
- package/src/commands/mesh-coordinator.ts +231 -127
- package/src/commands/router.ts +3574 -502
- package/src/config/chat-history.ts +87 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +264 -2
- package/src/config/recent-activity.ts +8 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/detection/ide-detector.ts +26 -16
- package/src/git/git-commands.ts +17 -5
- package/src/git/git-worktree.ts +8 -1
- package/src/index.ts +113 -5
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/ipc/local-ipc-server.ts +278 -0
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/logger.ts +2 -1
- package/src/mesh/beads-db.ts +479 -0
- package/src/mesh/contracts.ts +329 -0
- package/src/mesh/coordinator-prompt.ts +204 -30
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +437 -0
- package/src/mesh/mesh-events.ts +879 -61
- package/src/mesh/mesh-fast-forward.ts +430 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-ledger.ts +457 -104
- package/src/mesh/mesh-refine-status.ts +144 -0
- package/src/mesh/mesh-work-queue.ts +216 -158
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +366 -0
- package/src/mesh/worktree-bootstrap-config.ts +247 -0
- package/src/providers/approval-utils.d.ts +4 -0
- package/src/providers/approval-utils.ts +47 -5
- package/src/providers/chat-message-normalization.ts +4 -11
- package/src/providers/cli-provider-instance.ts +456 -54
- package/src/providers/contracts.ts +105 -5
- package/src/providers/external-sources.ts +218 -0
- package/src/providers/ide-provider-instance.ts +19 -5
- package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
- package/src/providers/native-history/claude-cli-transcript.ts +396 -0
- package/src/providers/native-history/codex-cli-transcript.ts +419 -0
- package/src/providers/native-history/dispatcher.ts +227 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
- package/src/providers/native-history/index.ts +30 -0
- package/src/providers/provider-instance.ts +3 -0
- package/src/providers/provider-loader.ts +585 -50
- package/src/providers/provider-schema.ts +31 -13
- package/src/providers/provider-trust.ts +114 -0
- package/src/providers/read-chat-contract.ts +76 -16
- package/src/providers/sdk/README.md +49 -0
- package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
- package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
- package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
- package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
- package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
- package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
- package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
- package/src/providers/sdk/v1/index.ts +152 -0
- package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
- package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
- package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +458 -0
- package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
- package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
- package/src/providers/sdk/v1/types/cli/index.ts +365 -0
- package/src/providers/sdk/v1/types/common/index.ts +210 -0
- package/src/providers/sdk/v1/validators/index.ts +19 -0
- package/src/providers/sdk/v1/validators/manifest.ts +110 -0
- package/src/providers/sdk/v1/validators/taint.ts +309 -0
- package/src/providers/spec/adapter.ts +168 -0
- package/src/providers/spec/cli-adapter.ts +430 -0
- package/src/providers/spec/driver.ts +502 -0
- package/src/providers/spec/evaluator.ts +298 -0
- package/src/providers/spec/loader.ts +130 -0
- package/src/providers/spec/native-history-executor.ts +623 -0
- package/src/providers/spec/route.ts +51 -0
- package/src/providers/spec/schema.gen.ts +511 -0
- package/src/providers/spec/schema.json +211 -0
- package/src/providers/spec/types.ts +231 -0
- package/src/providers/transcript-v2.ts +567 -0
- package/src/providers/types/interactive-prompt.ts +297 -0
- package/src/providers/version-archive.ts +38 -20
- package/src/repo-mesh-types.ts +110 -1
- package/src/sessions/registry.ts +3 -0
- package/src/shared-types.ts +45 -1
- package/src/status/builders.ts +24 -6
- package/src/status/reporter.ts +15 -0
- package/src/status/snapshot.ts +84 -25
- package/src/system/host-memory.ts +29 -12
- package/src/types.ts +5 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
export interface InteractivePrompt {
|
|
2
|
+
promptId: string;
|
|
3
|
+
origin: 'cli' | 'mcp' | 'agent';
|
|
4
|
+
providerType: string;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
questions: InteractiveQuestion[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface InteractiveQuestion {
|
|
10
|
+
questionId: string;
|
|
11
|
+
question: string;
|
|
12
|
+
header?: string;
|
|
13
|
+
multiSelect: boolean;
|
|
14
|
+
options: InteractiveOption[];
|
|
15
|
+
allowFreeform?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface InteractiveOption {
|
|
19
|
+
label: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
preview?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InteractivePromptResponse {
|
|
25
|
+
promptId: string;
|
|
26
|
+
answers: Record<string, InteractiveAnswer>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface InteractiveAnswer {
|
|
30
|
+
selectedLabels: string[];
|
|
31
|
+
freeformText?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readString(value: unknown): string | undefined {
|
|
35
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readStringArray(value: unknown): string[] {
|
|
39
|
+
return Array.isArray(value)
|
|
40
|
+
? value.map((item) => readString(item)).filter((item): item is string => !!item)
|
|
41
|
+
: [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function normalizeOption(raw: unknown): InteractiveOption | null {
|
|
45
|
+
if (typeof raw === 'string') {
|
|
46
|
+
const label = raw.trim();
|
|
47
|
+
return label ? { label } : null;
|
|
48
|
+
}
|
|
49
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
50
|
+
const record = raw as Record<string, unknown>;
|
|
51
|
+
const label = readString(record.label);
|
|
52
|
+
if (!label) return null;
|
|
53
|
+
const description = readString(record.description);
|
|
54
|
+
const preview = readString(record.preview);
|
|
55
|
+
return {
|
|
56
|
+
label,
|
|
57
|
+
...(description ? { description } : {}),
|
|
58
|
+
...(preview ? { preview } : {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function normalizeQuestion(raw: unknown, index: number): InteractiveQuestion | null {
|
|
63
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
64
|
+
const record = raw as Record<string, unknown>;
|
|
65
|
+
const question = readString(record.question);
|
|
66
|
+
if (!question) return null;
|
|
67
|
+
const questionId = readString(record.questionId) || readString(record.id) || `q${index + 1}`;
|
|
68
|
+
const options = Array.isArray(record.options)
|
|
69
|
+
? record.options.map(normalizeOption).filter((item): item is InteractiveOption => !!item)
|
|
70
|
+
: [];
|
|
71
|
+
const header = readString(record.header);
|
|
72
|
+
return {
|
|
73
|
+
questionId,
|
|
74
|
+
question,
|
|
75
|
+
...(header ? { header } : {}),
|
|
76
|
+
multiSelect: record.multiSelect === true,
|
|
77
|
+
options,
|
|
78
|
+
...(record.allowFreeform === true ? { allowFreeform: true } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function normalizeInteractivePrompt(raw: unknown): InteractivePrompt | null {
|
|
83
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
84
|
+
const record = raw as Record<string, unknown>;
|
|
85
|
+
const promptId = readString(record.promptId);
|
|
86
|
+
const providerType = readString(record.providerType);
|
|
87
|
+
const origin = record.origin === 'mcp' || record.origin === 'agent' ? record.origin : 'cli';
|
|
88
|
+
const questions = Array.isArray(record.questions)
|
|
89
|
+
? record.questions.map(normalizeQuestion).filter((item): item is InteractiveQuestion => !!item)
|
|
90
|
+
: [];
|
|
91
|
+
if (!promptId || !providerType || questions.length === 0) return null;
|
|
92
|
+
const createdAt = typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
|
|
93
|
+
? record.createdAt
|
|
94
|
+
: Date.now();
|
|
95
|
+
return { promptId, origin, providerType, createdAt, questions };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function normalizeInteractivePromptResponse(raw: unknown): InteractivePromptResponse {
|
|
99
|
+
if (!raw || typeof raw !== 'object') throw new Error('Interactive prompt response must be an object');
|
|
100
|
+
const record = raw as Record<string, unknown>;
|
|
101
|
+
const promptId = readString(record.promptId);
|
|
102
|
+
if (!promptId) throw new Error('promptId must be a non-empty string');
|
|
103
|
+
if (!record.answers || typeof record.answers !== 'object' || Array.isArray(record.answers)) {
|
|
104
|
+
throw new Error('answers must be an object');
|
|
105
|
+
}
|
|
106
|
+
const answers: Record<string, InteractiveAnswer> = {};
|
|
107
|
+
for (const [questionId, answerRaw] of Object.entries(record.answers as Record<string, unknown>)) {
|
|
108
|
+
if (!answerRaw || typeof answerRaw !== 'object' || Array.isArray(answerRaw)) continue;
|
|
109
|
+
const answer = answerRaw as Record<string, unknown>;
|
|
110
|
+
const selectedLabels = readStringArray(answer.selectedLabels);
|
|
111
|
+
const freeformText = readString(answer.freeformText);
|
|
112
|
+
answers[questionId] = {
|
|
113
|
+
selectedLabels,
|
|
114
|
+
...(freeformText ? { freeformText } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return { promptId, answers };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function buildClaudeInteractiveToolResult(response: InteractivePromptResponse): string {
|
|
121
|
+
return JSON.stringify({
|
|
122
|
+
type: 'user',
|
|
123
|
+
message: {
|
|
124
|
+
role: 'user',
|
|
125
|
+
content: [{
|
|
126
|
+
type: 'tool_result',
|
|
127
|
+
tool_use_id: response.promptId,
|
|
128
|
+
content: JSON.stringify({ answers: response.answers }),
|
|
129
|
+
is_error: false,
|
|
130
|
+
}],
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface ClaudeInteractiveTuiPage {
|
|
136
|
+
screenText: string;
|
|
137
|
+
header?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function claudeTuiQuestionHeaders(screenText: string): string[] {
|
|
141
|
+
const navLine = screenText.split(/\r?\n/).find(line => line.includes('✔ Submit') && /[☐☒]/.test(line));
|
|
142
|
+
if (!navLine) return [];
|
|
143
|
+
const headers: string[] = [];
|
|
144
|
+
const pattern = /[☐☒]\s+(.+?)(?=\s+[☐☒]|\s+✔\s+Submit)/g;
|
|
145
|
+
for (const match of navLine.matchAll(pattern)) {
|
|
146
|
+
const header = readString(match[1]);
|
|
147
|
+
if (header) headers.push(header);
|
|
148
|
+
}
|
|
149
|
+
return headers;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function parseClaudeInteractiveTuiQuestion(page: ClaudeInteractiveTuiPage, index: number): InteractiveQuestion | null {
|
|
153
|
+
const lines = page.screenText.split(/\r?\n/);
|
|
154
|
+
let navIndex = -1;
|
|
155
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
156
|
+
if (lines[i].includes('✔ Submit') && /[☐☒]/.test(lines[i])) {
|
|
157
|
+
navIndex = i;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (navIndex < 0 || !page.screenText.includes('Enter to select')) return null;
|
|
162
|
+
|
|
163
|
+
let question = '';
|
|
164
|
+
let questionLineIndex = -1;
|
|
165
|
+
for (let i = navIndex + 1; i < lines.length; i += 1) {
|
|
166
|
+
const candidate = lines[i].trim();
|
|
167
|
+
if (!candidate || /^─+$/.test(candidate)) continue;
|
|
168
|
+
if (candidate === 'Review your answers' || candidate === 'Ready to submit your answers?') return null;
|
|
169
|
+
question = candidate;
|
|
170
|
+
questionLineIndex = i;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
if (!question) return null;
|
|
174
|
+
|
|
175
|
+
const options: InteractiveOption[] = [];
|
|
176
|
+
let allowFreeform = false;
|
|
177
|
+
const optionPattern = /^\s*(?:[❯›>]\s*)?(\d+)\.\s+(.+?)\s*$/;
|
|
178
|
+
for (let i = questionLineIndex + 1; i < lines.length; i += 1) {
|
|
179
|
+
const match = lines[i].match(optionPattern);
|
|
180
|
+
if (!match) continue;
|
|
181
|
+
const label = match[2].trim();
|
|
182
|
+
if (/^Type something\.?$/i.test(label)) {
|
|
183
|
+
allowFreeform = true;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (/^Chat about this$/i.test(label)) continue;
|
|
187
|
+
|
|
188
|
+
let description: string | undefined;
|
|
189
|
+
const nextLine = lines[i + 1]?.trim();
|
|
190
|
+
if (nextLine
|
|
191
|
+
&& !optionPattern.test(lines[i + 1])
|
|
192
|
+
&& !/^─+$/.test(nextLine)
|
|
193
|
+
&& !/^Enter to select\b/.test(nextLine)) {
|
|
194
|
+
description = nextLine;
|
|
195
|
+
}
|
|
196
|
+
options.push({ label, ...(description ? { description } : {}) });
|
|
197
|
+
}
|
|
198
|
+
if (options.length === 0) return null;
|
|
199
|
+
|
|
200
|
+
const header = readString(page.header);
|
|
201
|
+
return {
|
|
202
|
+
questionId: `q${index + 1}`,
|
|
203
|
+
question,
|
|
204
|
+
...(header ? { header } : {}),
|
|
205
|
+
multiSelect: /Space to select|toggle selections/i.test(page.screenText),
|
|
206
|
+
options,
|
|
207
|
+
...(allowFreeform ? { allowFreeform: true } : {}),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function detectClaudeAskUserQuestionPromptFromTuiPages(
|
|
212
|
+
pages: ClaudeInteractiveTuiPage[],
|
|
213
|
+
options: { promptId: string; providerType?: string; createdAt?: number },
|
|
214
|
+
): InteractivePrompt | null {
|
|
215
|
+
if (pages.length === 0) return null;
|
|
216
|
+
const headers = claudeTuiQuestionHeaders(pages[0].screenText);
|
|
217
|
+
const questions = pages.map((page, index) => parseClaudeInteractiveTuiQuestion({
|
|
218
|
+
...page,
|
|
219
|
+
header: page.header || headers[index],
|
|
220
|
+
}, index)).filter((question): question is InteractiveQuestion => !!question);
|
|
221
|
+
if (questions.length !== pages.length) return null;
|
|
222
|
+
return {
|
|
223
|
+
promptId: options.promptId,
|
|
224
|
+
origin: 'cli',
|
|
225
|
+
providerType: options.providerType || 'claude-cli',
|
|
226
|
+
createdAt: options.createdAt || Date.now(),
|
|
227
|
+
questions,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function buildClaudeInteractiveTuiAnswerSteps(
|
|
232
|
+
prompt: InteractivePrompt,
|
|
233
|
+
response: InteractivePromptResponse,
|
|
234
|
+
): string[] {
|
|
235
|
+
if (response.promptId !== prompt.promptId) throw new Error('Interactive prompt response does not match active prompt');
|
|
236
|
+
const steps: string[] = [];
|
|
237
|
+
for (const question of prompt.questions) {
|
|
238
|
+
if (question.multiSelect) throw new Error('Claude TUI multi-select prompts are not supported yet');
|
|
239
|
+
const answer = response.answers[question.questionId];
|
|
240
|
+
if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
|
|
241
|
+
if (answer.freeformText) throw new Error('Claude TUI freeform answers are not supported yet');
|
|
242
|
+
if (answer.selectedLabels.length !== 1) throw new Error(`Expected one selected label for ${question.questionId}`);
|
|
243
|
+
const selectedIndex = question.options.findIndex(option => option.label === answer.selectedLabels[0]);
|
|
244
|
+
if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${answer.selectedLabels[0]}`);
|
|
245
|
+
steps.push(`${'\x1b[B'.repeat(selectedIndex)}\r`);
|
|
246
|
+
}
|
|
247
|
+
steps.push('\r');
|
|
248
|
+
return steps;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function interactivePromptFromClaudeAskUserQuestion(input: unknown, options: {
|
|
252
|
+
promptId: string;
|
|
253
|
+
providerType: string;
|
|
254
|
+
createdAt?: number;
|
|
255
|
+
origin?: InteractivePrompt['origin'];
|
|
256
|
+
}): InteractivePrompt | null {
|
|
257
|
+
if (!input || typeof input !== 'object') return null;
|
|
258
|
+
const record = input as Record<string, unknown>;
|
|
259
|
+
const questions = Array.isArray(record.questions)
|
|
260
|
+
? record.questions.map(normalizeQuestion).filter((item): item is InteractiveQuestion => !!item)
|
|
261
|
+
: [];
|
|
262
|
+
if (questions.length === 0) return null;
|
|
263
|
+
return {
|
|
264
|
+
promptId: options.promptId,
|
|
265
|
+
origin: options.origin || 'cli',
|
|
266
|
+
providerType: options.providerType,
|
|
267
|
+
createdAt: options.createdAt || Date.now(),
|
|
268
|
+
questions,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function detectClaudeAskUserQuestionPromptFromJson(value: unknown, providerType = 'claude-cli'): InteractivePrompt | null {
|
|
273
|
+
if (!value || typeof value !== 'object') return null;
|
|
274
|
+
const record = value as Record<string, unknown>;
|
|
275
|
+
const blocks: unknown[] = [];
|
|
276
|
+
if (Array.isArray(record.content)) blocks.push(...record.content);
|
|
277
|
+
const message = record.message;
|
|
278
|
+
if (message && typeof message === 'object' && Array.isArray((message as Record<string, unknown>).content)) {
|
|
279
|
+
blocks.push(...((message as Record<string, unknown>).content as unknown[]));
|
|
280
|
+
}
|
|
281
|
+
if (record.type === 'tool_use') blocks.push(record);
|
|
282
|
+
|
|
283
|
+
for (const block of blocks) {
|
|
284
|
+
if (!block || typeof block !== 'object') continue;
|
|
285
|
+
const b = block as Record<string, unknown>;
|
|
286
|
+
const name = readString(b.name);
|
|
287
|
+
if (b.type !== 'tool_use' || name !== 'AskUserQuestion') continue;
|
|
288
|
+
const id = readString(b.id) || readString(record.id) || `ask-user-${Date.now()}`;
|
|
289
|
+
const prompt = interactivePromptFromClaudeAskUserQuestion(b.input, {
|
|
290
|
+
promptId: id,
|
|
291
|
+
providerType,
|
|
292
|
+
origin: 'cli',
|
|
293
|
+
});
|
|
294
|
+
if (prompt) return prompt;
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import * as os from 'os';
|
|
15
|
-
|
|
15
|
+
// Removed execSync import
|
|
16
16
|
import { platform } from 'os';
|
|
17
17
|
import type { ProviderLoader } from './provider-loader.js';
|
|
18
18
|
import type { ProviderModule } from './contracts.js';
|
|
@@ -117,22 +117,40 @@ export class VersionArchive {
|
|
|
117
117
|
|
|
118
118
|
// ─── Version Detection ──────────────────────────────
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
import { exec } from 'child_process';
|
|
121
|
+
|
|
122
|
+
async function runCommand(cmd: string, timeout = 10000): Promise<string | null> {
|
|
123
|
+
return new Promise((resolve) => {
|
|
124
|
+
exec(cmd, {
|
|
123
125
|
encoding: 'utf-8',
|
|
124
126
|
timeout,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
127
|
+
}, (error, stdout) => {
|
|
128
|
+
if (error) return resolve(null);
|
|
129
|
+
resolve(stdout.trim());
|
|
130
|
+
});
|
|
131
|
+
});
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
function findBinary(name: string): string | null {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
135
|
+
const isWin = platform() === 'win32';
|
|
136
|
+
const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
|
|
137
|
+
const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
|
|
138
|
+
|
|
139
|
+
for (const p of paths) {
|
|
140
|
+
if (!p) continue;
|
|
141
|
+
for (const ext of exes) {
|
|
142
|
+
const fullPath = path.join(p, name + ext);
|
|
143
|
+
try {
|
|
144
|
+
if (fs.existsSync(fullPath)) {
|
|
145
|
+
const stat = fs.statSync(fullPath);
|
|
146
|
+
if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
|
|
147
|
+
return fullPath;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch { }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
136
154
|
}
|
|
137
155
|
|
|
138
156
|
/** Extract version string from CLI output */
|
|
@@ -162,16 +180,16 @@ function getPlatformVersionCommand(
|
|
|
162
180
|
return undefined;
|
|
163
181
|
}
|
|
164
182
|
|
|
165
|
-
function getVersion(binary: string, versionCommand?: string): string | null {
|
|
183
|
+
async function getVersion(binary: string, versionCommand?: string): Promise<string | null> {
|
|
166
184
|
// Custom version command from provider.json
|
|
167
185
|
if (versionCommand) {
|
|
168
|
-
const raw = runCommand(versionCommand);
|
|
186
|
+
const raw = await runCommand(versionCommand);
|
|
169
187
|
return raw ? parseVersion(raw) : null;
|
|
170
188
|
}
|
|
171
189
|
|
|
172
190
|
// Default: try --version, then -V, then -v
|
|
173
191
|
for (const flag of ['--version', '-V', '-v']) {
|
|
174
|
-
const raw = runCommand(`"${binary}" ${flag}`);
|
|
192
|
+
const raw = await runCommand(`"${binary}" ${flag}`);
|
|
175
193
|
if (raw && raw.length < 500) return parseVersion(raw);
|
|
176
194
|
}
|
|
177
195
|
return null;
|
|
@@ -191,11 +209,11 @@ function checkPathExists(paths: string[]): string | null {
|
|
|
191
209
|
}
|
|
192
210
|
|
|
193
211
|
/** macOS: Get app version from Info.plist */
|
|
194
|
-
function getMacAppVersion(appPath: string): string | null {
|
|
212
|
+
async function getMacAppVersion(appPath: string): Promise<string | null> {
|
|
195
213
|
if (platform() !== 'darwin' || !appPath.endsWith('.app')) return null;
|
|
196
214
|
const plistPath = path.join(appPath, 'Contents', 'Info.plist');
|
|
197
215
|
if (!fs.existsSync(plistPath)) return null;
|
|
198
|
-
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
216
|
+
const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
199
217
|
return raw || null;
|
|
200
218
|
}
|
|
201
219
|
|
|
@@ -242,10 +260,10 @@ export async function detectAllVersions(
|
|
|
242
260
|
|
|
243
261
|
// Version: try CLI first, then plist
|
|
244
262
|
if (resolvedBin) {
|
|
245
|
-
info.version = getVersion(resolvedBin, versionCommand);
|
|
263
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
246
264
|
}
|
|
247
265
|
if (!info.version && appPath) {
|
|
248
|
-
info.version = getMacAppVersion(appPath);
|
|
266
|
+
info.version = await getMacAppVersion(appPath);
|
|
249
267
|
}
|
|
250
268
|
|
|
251
269
|
} else if (provider.category === 'cli' || provider.category === 'acp') {
|
|
@@ -256,7 +274,7 @@ export async function detectAllVersions(
|
|
|
256
274
|
info.binary = binPath || null;
|
|
257
275
|
|
|
258
276
|
if (binPath) {
|
|
259
|
-
info.version = getVersion(binPath, versionCommand);
|
|
277
|
+
info.version = await getVersion(binPath, versionCommand);
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
} else if (provider.category === 'extension') {
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -23,11 +23,42 @@ export interface RepoMesh {
|
|
|
23
23
|
defaultBranch?: string;
|
|
24
24
|
policy: RepoMeshPolicy;
|
|
25
25
|
coordinator: RepoMeshCoordinatorConfig;
|
|
26
|
+
meshHost?: RepoMeshHostMetadata;
|
|
26
27
|
projectContext: ProjectContextSnapshot;
|
|
27
28
|
nodes: RepoMeshNode[];
|
|
28
29
|
status: 'active' | 'archived' | 'deleted';
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
export type RepoMeshDaemonRole = 'host' | 'member';
|
|
33
|
+
|
|
34
|
+
export interface RepoMeshHostPairingMetadata {
|
|
35
|
+
status: 'not_configured' | 'pairing' | 'paired' | 'rejected' | 'revoked';
|
|
36
|
+
tokenId?: string;
|
|
37
|
+
joinedAt?: string;
|
|
38
|
+
lastPairedAt?: string;
|
|
39
|
+
lastRejectedAt?: string;
|
|
40
|
+
expiresAt?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RepoMeshHostMetadata {
|
|
44
|
+
/** Local daemon role for this mesh. Missing metadata defaults to host for standalone compatibility. */
|
|
45
|
+
role: RepoMeshDaemonRole;
|
|
46
|
+
/** Daemon that owns mesh truth/status/git/queue/session/ledger/coordinator ownership. */
|
|
47
|
+
hostDaemonId?: string;
|
|
48
|
+
/** Mesh node that represents the host daemon, when known. */
|
|
49
|
+
hostNodeId?: string;
|
|
50
|
+
/** Future standalone manual pairing endpoint entered by member daemons. */
|
|
51
|
+
hostAddress?: string;
|
|
52
|
+
/** Redacted pairing state only; raw join tokens must not be persisted here. */
|
|
53
|
+
pairing?: RepoMeshHostPairingMetadata;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface RepoMeshHostStatus extends RepoMeshHostMetadata {
|
|
57
|
+
canOwnCoordinator: boolean;
|
|
58
|
+
canOwnQueue: boolean;
|
|
59
|
+
defaulted: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
31
62
|
export interface RepoMeshNode {
|
|
32
63
|
id: string;
|
|
33
64
|
daemonId: string;
|
|
@@ -42,6 +73,7 @@ export interface RepoMeshNode {
|
|
|
42
73
|
effectiveCapabilities: RepoMeshNodeCapabilities;
|
|
43
74
|
policy: RepoMeshNodePolicy;
|
|
44
75
|
health: RepoMeshNodeHealth;
|
|
76
|
+
role?: RepoMeshDaemonRole;
|
|
45
77
|
status: 'enabled' | 'disabled' | 'removed';
|
|
46
78
|
}
|
|
47
79
|
|
|
@@ -62,6 +94,13 @@ export interface RepoMeshPolicy {
|
|
|
62
94
|
requirePreTaskCheckpoint: boolean;
|
|
63
95
|
requirePostTaskCheckpoint: boolean;
|
|
64
96
|
requireApprovalForPush: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Narrow Refinery opt-in: when validation and patch-equivalence have passed,
|
|
99
|
+
* allow Refinery to publish submodule gitlink commits to each submodule's
|
|
100
|
+
* configured remote main branch with a non-force push, then verify reachability.
|
|
101
|
+
* Defaults to false; root branch pushes/merges are not affected.
|
|
102
|
+
*/
|
|
103
|
+
allowAutoPublishSubmoduleMainCommits?: boolean;
|
|
65
104
|
requireApprovalForDestructiveGit: boolean;
|
|
66
105
|
dirtyWorkspaceBehavior: 'block' | 'warn' | 'checkpoint_then_continue';
|
|
67
106
|
maxParallelTasks: number;
|
|
@@ -126,6 +165,7 @@ export const DEFAULT_MESH_POLICY: RepoMeshPolicy = {
|
|
|
126
165
|
requirePreTaskCheckpoint: false,
|
|
127
166
|
requirePostTaskCheckpoint: true,
|
|
128
167
|
requireApprovalForPush: true,
|
|
168
|
+
allowAutoPublishSubmoduleMainCommits: false,
|
|
129
169
|
requireApprovalForDestructiveGit: true,
|
|
130
170
|
dirtyWorkspaceBehavior: 'warn',
|
|
131
171
|
maxParallelTasks: 2,
|
|
@@ -207,7 +247,28 @@ export interface RepoMeshCoordinatorConfig {
|
|
|
207
247
|
providerType?: string;
|
|
208
248
|
/** Preferred node to run coordinator on (null = auto) */
|
|
209
249
|
preferredNodeId?: string;
|
|
210
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Full mesh-level override for the coordinator system prompt. When set,
|
|
252
|
+
* replaces the daemon's rendered default and any user-file override
|
|
253
|
+
* (~/.adhdev/coordinator-prompts/<cli>.md). The per-launch
|
|
254
|
+
* extraSystemPrompt still composes on top — it always lands last as
|
|
255
|
+
* Additional Context. Supports the same {{placeholders}} the daemon's
|
|
256
|
+
* default template uses ({{meshName}}, {{repo}}, {{nodes}}, …).
|
|
257
|
+
*/
|
|
258
|
+
systemPromptOverride?: string;
|
|
259
|
+
/**
|
|
260
|
+
* Mesh-level append. Composes after whichever base prompt won
|
|
261
|
+
* (override → user-file override → daemon default). Use this when you
|
|
262
|
+
* want extra rules for THIS mesh but otherwise the standard prompt is
|
|
263
|
+
* fine. Stacks with the user-file append (`<cli>.append.md`) — both
|
|
264
|
+
* apply if both are set.
|
|
265
|
+
*/
|
|
266
|
+
systemPromptAppend?: string;
|
|
267
|
+
/**
|
|
268
|
+
* @deprecated Use systemPromptAppend. Kept as a fallback alias so
|
|
269
|
+
* existing meshes.json files keep working without a migration step;
|
|
270
|
+
* the daemon prefers systemPromptAppend when both are present.
|
|
271
|
+
*/
|
|
211
272
|
systemPromptSuffix?: string;
|
|
212
273
|
}
|
|
213
274
|
|
|
@@ -229,6 +290,7 @@ export interface LocalMeshEntry {
|
|
|
229
290
|
defaultBranch?: string;
|
|
230
291
|
policy: RepoMeshPolicy;
|
|
231
292
|
coordinator: RepoMeshCoordinatorConfig;
|
|
293
|
+
meshHost?: RepoMeshHostMetadata;
|
|
232
294
|
nodes: LocalMeshNodeEntry[];
|
|
233
295
|
createdAt: string;
|
|
234
296
|
updatedAt: string;
|
|
@@ -243,14 +305,38 @@ export interface LocalMeshNodeEntry {
|
|
|
243
305
|
machineId?: string;
|
|
244
306
|
userOverrides: Partial<RepoMeshNodeCapabilities>;
|
|
245
307
|
policy: RepoMeshNodePolicy;
|
|
308
|
+
/**
|
|
309
|
+
* Per-node instruction surfaced in the coordinator prompt so the LLM
|
|
310
|
+
* knows what each node is for (e.g. "this is the staging mirror — run
|
|
311
|
+
* only smoke tests here", or "use opus on this node, sonnet elsewhere").
|
|
312
|
+
* Empty/missing: omitted silently from the rendered prompt, no rule
|
|
313
|
+
* line about it gets added. The coordinator forwards/honors it when
|
|
314
|
+
* delegating; we don't enforce it at the daemon level.
|
|
315
|
+
*/
|
|
316
|
+
systemPrompt?: string;
|
|
246
317
|
/** For single-machine mesh: same daemon, different worktree */
|
|
247
318
|
isLocalWorktree?: boolean;
|
|
248
319
|
/** Branch this worktree tracks (set when created via clone_mesh_node) */
|
|
249
320
|
worktreeBranch?: string;
|
|
250
321
|
/** Node ID this worktree was cloned from */
|
|
251
322
|
clonedFromNodeId?: string;
|
|
323
|
+
/** Repo-local preparation result for ADHDev-created worktree nodes. */
|
|
324
|
+
worktreeBootstrap?: {
|
|
325
|
+
status: 'ready' | 'running' | 'failed' | 'not_configured' | 'disabled' | 'stale';
|
|
326
|
+
required?: boolean;
|
|
327
|
+
configSource?: string;
|
|
328
|
+
configSourceType?: string;
|
|
329
|
+
startedAt?: string;
|
|
330
|
+
completedAt?: string;
|
|
331
|
+
lastCommand?: string;
|
|
332
|
+
exitCode?: number | null;
|
|
333
|
+
error?: string;
|
|
334
|
+
commandsRun?: Array<Record<string, unknown>>;
|
|
335
|
+
staleInputs?: string[];
|
|
336
|
+
};
|
|
252
337
|
/** Optional associated/external repos configured as node metadata. */
|
|
253
338
|
relatedRepos?: RepoMeshRelatedRepo[];
|
|
339
|
+
role?: RepoMeshDaemonRole;
|
|
254
340
|
}
|
|
255
341
|
|
|
256
342
|
// ─── Mesh Status (runtime, not persisted) ───────
|
|
@@ -261,6 +347,7 @@ export interface RepoMeshStatus {
|
|
|
261
347
|
repoIdentity: string;
|
|
262
348
|
defaultBranch?: string;
|
|
263
349
|
refreshedAt: string;
|
|
350
|
+
meshHost?: RepoMeshHostStatus;
|
|
264
351
|
nodes: RepoMeshNodeStatus[];
|
|
265
352
|
queue?: RepoMeshQueueStatus;
|
|
266
353
|
ledger?: RepoMeshLedgerStatus;
|
|
@@ -301,16 +388,28 @@ export interface RepoMeshNodeStatus {
|
|
|
301
388
|
repoRoot?: string;
|
|
302
389
|
daemonId?: string;
|
|
303
390
|
machineId?: string;
|
|
391
|
+
role?: RepoMeshDaemonRole;
|
|
304
392
|
machineStatus?: string;
|
|
305
393
|
isLocalWorktree?: boolean;
|
|
306
394
|
worktreeBranch?: string;
|
|
395
|
+
/** Mirrored from LocalMeshNodeEntry.systemPrompt for coordinator-prompt rendering. */
|
|
396
|
+
systemPrompt?: string;
|
|
307
397
|
health: RepoMeshNodeHealth;
|
|
308
398
|
git?: GitRepoStatus;
|
|
399
|
+
/**
|
|
400
|
+
* True when the selected coordinator has evidence that a peer git probe is still
|
|
401
|
+
* in flight or just timed out during initial mesh handshake, so callers should
|
|
402
|
+
* treat missing git data as pending instead of authoritative absence.
|
|
403
|
+
*/
|
|
404
|
+
gitProbePending?: boolean;
|
|
309
405
|
providers: string[];
|
|
310
406
|
activeSessions: string[];
|
|
311
407
|
activeSessionDetails?: RepoMeshSessionStatus[];
|
|
312
408
|
providerPriority?: string[];
|
|
313
409
|
launchReady?: boolean;
|
|
410
|
+
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
411
|
+
launchBlockedReason?: string;
|
|
412
|
+
launchBlockedMessage?: string;
|
|
314
413
|
lastSeenAt?: string;
|
|
315
414
|
updatedAt?: string;
|
|
316
415
|
connection?: RepoMeshPeerConnectionStatus;
|
|
@@ -405,3 +504,13 @@ export interface RepoMeshLedgerStatus {
|
|
|
405
504
|
entries: RepoMeshLedgerEntryStatus[];
|
|
406
505
|
summary: RepoMeshLedgerSummaryStatus;
|
|
407
506
|
}
|
|
507
|
+
|
|
508
|
+
// ─── Async Job Lifecycle ─────────────────────────
|
|
509
|
+
// Shared base for all mesh async job types (refine jobs, bootstrap runs, etc.)
|
|
510
|
+
// Each concrete type adds its own status enum and domain-specific fields.
|
|
511
|
+
|
|
512
|
+
export interface MeshAsyncJobLifecycle {
|
|
513
|
+
startedAt?: string;
|
|
514
|
+
completedAt?: string;
|
|
515
|
+
error?: string;
|
|
516
|
+
}
|
package/src/sessions/registry.ts
CHANGED
|
@@ -8,6 +8,9 @@ export interface SessionRuntimeTarget {
|
|
|
8
8
|
cdpManagerKey?: string;
|
|
9
9
|
adapterKey?: string;
|
|
10
10
|
instanceKey?: string;
|
|
11
|
+
/** Wall clock at register time. native-history readers use it as a
|
|
12
|
+
* cutoff so a fresh session can't show records from a prior one. */
|
|
13
|
+
spawnedAtMs?: number;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export class SessionRegistry {
|