@adhdev/daemon-core 0.9.82-rc.7 → 0.9.82-rc.8
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/daemon-lifecycle.d.ts +2 -0
- package/dist/commands/router.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +134 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -10
- package/dist/index.mjs.map +1 -1
- package/dist/repo-mesh-types.d.ts +121 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +3 -0
- package/src/commands/router.ts +147 -12
- package/src/index.ts +8 -0
- package/src/repo-mesh-types.ts +131 -0
|
@@ -213,14 +213,135 @@ export interface RepoMeshStatus {
|
|
|
213
213
|
repoIdentity: string;
|
|
214
214
|
refreshedAt: string;
|
|
215
215
|
nodes: RepoMeshNodeStatus[];
|
|
216
|
+
queue?: RepoMeshQueueStatus;
|
|
217
|
+
ledger?: RepoMeshLedgerStatus;
|
|
218
|
+
}
|
|
219
|
+
export interface RepoMeshSessionStatus {
|
|
220
|
+
sessionId: string;
|
|
221
|
+
providerType?: string;
|
|
222
|
+
state?: string;
|
|
223
|
+
lifecycle?: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'interrupted';
|
|
224
|
+
surfaceKind?: 'live_runtime' | 'recovery_snapshot' | 'inactive_record';
|
|
225
|
+
recoveryState?: string | null;
|
|
226
|
+
workspace?: string | null;
|
|
227
|
+
title?: string | null;
|
|
228
|
+
lastActivityAt?: string | null;
|
|
229
|
+
isCached?: boolean;
|
|
230
|
+
}
|
|
231
|
+
export type RepoMeshPeerConnectionState = 'self' | 'connected' | 'connecting' | 'disconnected' | 'failed' | 'closed' | 'unknown';
|
|
232
|
+
export type RepoMeshPeerConnectionTransport = 'local' | 'direct' | 'relay' | 'unknown';
|
|
233
|
+
export interface RepoMeshPeerConnectionStatus {
|
|
234
|
+
perspective: 'selected_coordinator';
|
|
235
|
+
source: 'mesh_peer_status' | 'not_reported';
|
|
236
|
+
state: RepoMeshPeerConnectionState;
|
|
237
|
+
transport: RepoMeshPeerConnectionTransport;
|
|
238
|
+
reported: boolean;
|
|
239
|
+
reason?: string;
|
|
240
|
+
lastStateChangeAt?: string;
|
|
241
|
+
lastConnectedAt?: string;
|
|
242
|
+
lastCommandAt?: string;
|
|
216
243
|
}
|
|
217
244
|
export interface RepoMeshNodeStatus {
|
|
218
245
|
nodeId: string;
|
|
219
246
|
machineLabel: string;
|
|
220
247
|
workspace: string;
|
|
248
|
+
repoRoot?: string;
|
|
249
|
+
daemonId?: string;
|
|
250
|
+
machineId?: string;
|
|
251
|
+
machineStatus?: string;
|
|
252
|
+
isLocalWorktree?: boolean;
|
|
253
|
+
worktreeBranch?: string;
|
|
221
254
|
health: RepoMeshNodeHealth;
|
|
222
255
|
git?: GitRepoStatus;
|
|
223
256
|
providers: string[];
|
|
224
257
|
activeSessions: string[];
|
|
258
|
+
activeSessionDetails?: RepoMeshSessionStatus[];
|
|
259
|
+
providerPriority?: string[];
|
|
260
|
+
launchReady?: boolean;
|
|
261
|
+
lastSeenAt?: string;
|
|
262
|
+
updatedAt?: string;
|
|
263
|
+
connection?: RepoMeshPeerConnectionStatus;
|
|
225
264
|
error?: string;
|
|
226
265
|
}
|
|
266
|
+
export type RepoMeshQueueTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled';
|
|
267
|
+
export interface RepoMeshQueueTask {
|
|
268
|
+
id: string;
|
|
269
|
+
meshId: string;
|
|
270
|
+
message: string;
|
|
271
|
+
status: RepoMeshQueueTaskStatus;
|
|
272
|
+
targetNodeId?: string;
|
|
273
|
+
targetSessionId?: string;
|
|
274
|
+
assignedNodeId?: string;
|
|
275
|
+
assignedSessionId?: string;
|
|
276
|
+
cancelReason?: string;
|
|
277
|
+
cancelledAt?: string;
|
|
278
|
+
requeueReason?: string;
|
|
279
|
+
requeuedAt?: string;
|
|
280
|
+
requeueCount?: number;
|
|
281
|
+
autoLaunch?: {
|
|
282
|
+
status: 'skipped' | 'started' | 'failed' | 'completed';
|
|
283
|
+
reason?: string;
|
|
284
|
+
nodeId?: string;
|
|
285
|
+
providerType?: string;
|
|
286
|
+
sessionId?: string;
|
|
287
|
+
updatedAt: string;
|
|
288
|
+
};
|
|
289
|
+
dispatchTimestamp?: string;
|
|
290
|
+
createdAt: string;
|
|
291
|
+
updatedAt: string;
|
|
292
|
+
}
|
|
293
|
+
export interface RepoMeshQueueSummary {
|
|
294
|
+
total: number;
|
|
295
|
+
active: number;
|
|
296
|
+
historical: number;
|
|
297
|
+
pending: number;
|
|
298
|
+
assigned: number;
|
|
299
|
+
completed: number;
|
|
300
|
+
failed: number;
|
|
301
|
+
cancelled: number;
|
|
302
|
+
activeCounts: {
|
|
303
|
+
pending: number;
|
|
304
|
+
assigned: number;
|
|
305
|
+
};
|
|
306
|
+
historicalCounts: {
|
|
307
|
+
completed: number;
|
|
308
|
+
failed: number;
|
|
309
|
+
cancelled: number;
|
|
310
|
+
};
|
|
311
|
+
activeAssignments: Array<{
|
|
312
|
+
id: string;
|
|
313
|
+
nodeId?: string;
|
|
314
|
+
sessionId?: string;
|
|
315
|
+
message: string;
|
|
316
|
+
}>;
|
|
317
|
+
}
|
|
318
|
+
export interface RepoMeshQueueStatus {
|
|
319
|
+
tasks: RepoMeshQueueTask[];
|
|
320
|
+
summary: RepoMeshQueueSummary;
|
|
321
|
+
}
|
|
322
|
+
export interface RepoMeshLedgerEntryStatus {
|
|
323
|
+
id: string;
|
|
324
|
+
meshId: string;
|
|
325
|
+
timestamp: string;
|
|
326
|
+
kind: string;
|
|
327
|
+
nodeId?: string;
|
|
328
|
+
sessionId?: string;
|
|
329
|
+
providerType?: string;
|
|
330
|
+
payload: Record<string, unknown>;
|
|
331
|
+
}
|
|
332
|
+
export interface RepoMeshLedgerSummaryStatus {
|
|
333
|
+
meshId: string;
|
|
334
|
+
totalEntries: number;
|
|
335
|
+
taskDispatched: number;
|
|
336
|
+
taskCompleted: number;
|
|
337
|
+
taskFailed: number;
|
|
338
|
+
taskStalled: number;
|
|
339
|
+
sessionLaunched: number;
|
|
340
|
+
checkpointCreated: number;
|
|
341
|
+
lastActivityAt: string | null;
|
|
342
|
+
recentFailures: number;
|
|
343
|
+
}
|
|
344
|
+
export interface RepoMeshLedgerStatus {
|
|
345
|
+
entries: RepoMeshLedgerEntryStatus[];
|
|
346
|
+
summary: RepoMeshLedgerSummaryStatus;
|
|
347
|
+
}
|
package/package.json
CHANGED
|
@@ -86,6 +86,8 @@ export interface DaemonInitConfig {
|
|
|
86
86
|
|
|
87
87
|
/** Relays a command to a remote mesh node daemon */
|
|
88
88
|
dispatchMeshCommand?: (daemonId: string, command: string, args: Record<string, unknown>) => Promise<any>;
|
|
89
|
+
/** Returns selected-coordinator mesh peer telemetry for a target daemon when available. */
|
|
90
|
+
getMeshPeerConnectionStatus?: (daemonId: string) => Record<string, unknown> | null;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
// ─── Result ───
|
|
@@ -306,6 +308,7 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
|
|
|
306
308
|
sessionHostControl: config.sessionHostControl,
|
|
307
309
|
statusInstanceId: config.statusInstanceId,
|
|
308
310
|
statusVersion: config.statusVersion,
|
|
311
|
+
getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
|
|
309
312
|
getCdpLogFn: config.getCdpLogFn || ((ideType: string) => LOG.forComponent(`CDP:${ideType}`).asLogFn()),
|
|
310
313
|
});
|
|
311
314
|
|
package/src/commands/router.ts
CHANGED
|
@@ -259,17 +259,93 @@ function readCachedInlineMeshActiveSessions(node: any): string[] {
|
|
|
259
259
|
return sessionId ? [sessionId] : [];
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
function readCachedInlineMeshActiveSessionDetails(node: any): Array<Record<string, unknown>> {
|
|
263
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
264
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
265
|
+
const fallbackSession = Object.keys(activeSession).length
|
|
266
|
+
? activeSession
|
|
267
|
+
: readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
268
|
+
const sessionId = readStringValue(
|
|
269
|
+
fallbackSession.id,
|
|
270
|
+
fallbackSession.sessionId,
|
|
271
|
+
fallbackSession.session_id,
|
|
272
|
+
node?.activeSessionId,
|
|
273
|
+
node?.active_session_id,
|
|
274
|
+
node?.sessionId,
|
|
275
|
+
node?.session_id,
|
|
276
|
+
);
|
|
277
|
+
if (!sessionId) return [];
|
|
278
|
+
return [{
|
|
279
|
+
sessionId,
|
|
280
|
+
providerType: readStringValue(
|
|
281
|
+
fallbackSession.providerType,
|
|
282
|
+
fallbackSession.provider_type,
|
|
283
|
+
fallbackSession.cliType,
|
|
284
|
+
fallbackSession.cli_type,
|
|
285
|
+
fallbackSession.provider,
|
|
286
|
+
node?.providerType,
|
|
287
|
+
node?.provider_type,
|
|
288
|
+
),
|
|
289
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
290
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
291
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
292
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
293
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
294
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
295
|
+
isCached: true,
|
|
296
|
+
}];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function readLiveMeshSessionState(record: any): string | undefined {
|
|
300
|
+
return readStringValue(
|
|
301
|
+
record?.meta?.sessionStatus,
|
|
302
|
+
record?.meta?.status,
|
|
303
|
+
record?.meta?.providerStatus,
|
|
304
|
+
record?.status,
|
|
305
|
+
record?.state,
|
|
306
|
+
record?.lifecycle,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function toIsoTimestamp(value: unknown): string | null {
|
|
311
|
+
if (typeof value === 'number' && Number.isFinite(value)) return new Date(value).toISOString();
|
|
312
|
+
const stringValue = readStringValue(value);
|
|
313
|
+
return stringValue || null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function summarizeMeshSessionRecord(record: any): Record<string, unknown> {
|
|
317
|
+
return {
|
|
318
|
+
sessionId: readStringValue(record?.sessionId) || 'unknown',
|
|
319
|
+
providerType: readStringValue(record?.providerType),
|
|
320
|
+
state: readLiveMeshSessionState(record),
|
|
321
|
+
lifecycle: readStringValue(record?.lifecycle),
|
|
322
|
+
surfaceKind: getSessionHostSurfaceKind(record as any),
|
|
323
|
+
recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
|
|
324
|
+
workspace: readStringValue(record?.workspace) ?? null,
|
|
325
|
+
title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
|
|
326
|
+
lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
|
|
327
|
+
isCached: false,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
262
331
|
function applyCachedInlineMeshNodeStatus(status: Record<string, unknown>, node: any): boolean {
|
|
263
332
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
264
333
|
const git = buildCachedInlineMeshGitStatus(node);
|
|
265
334
|
const error = readStringValue(cachedStatus.error, node?.error);
|
|
266
335
|
const health = readStringValue(cachedStatus.health, node?.health);
|
|
267
336
|
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
337
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
338
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
268
339
|
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
269
|
-
|
|
340
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
341
|
+
if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
270
342
|
if (git) status.git = git;
|
|
271
343
|
if (error) status.error = error;
|
|
344
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
345
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
346
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
272
347
|
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
348
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
273
349
|
if (health) {
|
|
274
350
|
status.health = health;
|
|
275
351
|
return true;
|
|
@@ -278,7 +354,7 @@ function applyCachedInlineMeshNodeStatus(status: Record<string, unknown>, node:
|
|
|
278
354
|
status.health = deriveMeshNodeHealthFromGit(git);
|
|
279
355
|
return true;
|
|
280
356
|
}
|
|
281
|
-
return activeSessions.length > 0 || !!machineStatus;
|
|
357
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
282
358
|
}
|
|
283
359
|
|
|
284
360
|
async function resolveProviderTypeFromPriority(args: {
|
|
@@ -698,6 +774,8 @@ export interface CommandRouterDeps {
|
|
|
698
774
|
statusVersion?: string;
|
|
699
775
|
/** Session host control plane */
|
|
700
776
|
sessionHostControl?: SessionHostControlPlane | null;
|
|
777
|
+
/** Selected-coordinator mesh peer telemetry surface for target daemons, when supported by the runtime. */
|
|
778
|
+
getMeshPeerConnectionStatus?: (daemonId: string) => Record<string, unknown> | null;
|
|
701
779
|
}
|
|
702
780
|
|
|
703
781
|
export interface CommandRouterResult {
|
|
@@ -2955,31 +3033,86 @@ export class DaemonCommandRouter {
|
|
|
2955
3033
|
: [];
|
|
2956
3034
|
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
2957
3035
|
|
|
3036
|
+
const localMachineId = loadConfig().machineId || '';
|
|
3037
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes)
|
|
3038
|
+
? readStringValue((mesh.nodes[0] as any)?.id, (mesh.nodes[0] as any)?.nodeId)
|
|
3039
|
+
: undefined;
|
|
3040
|
+
const refreshedAt = new Date().toISOString();
|
|
2958
3041
|
const nodeStatuses = [];
|
|
2959
|
-
for (const node of mesh.nodes || []) {
|
|
3042
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
3043
|
+
const nodeId = String(node.id || node.nodeId || '');
|
|
3044
|
+
const daemonId = readStringValue(node.daemonId);
|
|
3045
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
3046
|
+
const isSelfNode = Boolean(
|
|
3047
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId,
|
|
3048
|
+
) || Boolean(
|
|
3049
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId),
|
|
3050
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
2960
3051
|
const status: Record<string, unknown> = {
|
|
2961
|
-
nodeId
|
|
3052
|
+
nodeId,
|
|
2962
3053
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
2963
3054
|
workspace: node.workspace,
|
|
2964
3055
|
repoRoot: node.repoRoot,
|
|
2965
3056
|
isLocalWorktree: node.isLocalWorktree,
|
|
2966
3057
|
worktreeBranch: node.worktreeBranch,
|
|
2967
|
-
daemonId
|
|
3058
|
+
daemonId,
|
|
2968
3059
|
machineId: node.machineId,
|
|
3060
|
+
machineStatus: node.machineStatus,
|
|
2969
3061
|
health: 'unknown',
|
|
2970
3062
|
providers: node.providers || [],
|
|
3063
|
+
providerPriority,
|
|
2971
3064
|
activeSessions: [],
|
|
3065
|
+
activeSessionDetails: [],
|
|
3066
|
+
launchReady: false,
|
|
2972
3067
|
};
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
3068
|
+
if (isSelfNode) {
|
|
3069
|
+
status.connection = {
|
|
3070
|
+
perspective: 'selected_coordinator',
|
|
3071
|
+
source: 'mesh_peer_status',
|
|
3072
|
+
state: 'self',
|
|
3073
|
+
transport: 'local',
|
|
3074
|
+
reported: true,
|
|
3075
|
+
reason: 'Selected coordinator daemon',
|
|
3076
|
+
lastStateChangeAt: refreshedAt,
|
|
3077
|
+
};
|
|
3078
|
+
} else if (daemonId) {
|
|
3079
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
3080
|
+
status.connection = connection ?? {
|
|
3081
|
+
perspective: 'selected_coordinator',
|
|
3082
|
+
source: 'not_reported',
|
|
3083
|
+
state: 'unknown',
|
|
3084
|
+
transport: 'unknown',
|
|
3085
|
+
reported: false,
|
|
3086
|
+
reason: 'No live mesh peer telemetry reported by the selected coordinator yet.',
|
|
3087
|
+
};
|
|
3088
|
+
} else {
|
|
3089
|
+
status.connection = {
|
|
3090
|
+
perspective: 'selected_coordinator',
|
|
3091
|
+
source: 'not_reported',
|
|
3092
|
+
state: 'unknown',
|
|
3093
|
+
transport: 'unknown',
|
|
3094
|
+
reported: false,
|
|
3095
|
+
reason: 'Node has no daemon id, so mesh transport cannot be reported from the selected coordinator.',
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
const matchedLiveSessionRecords = liveMeshSessions
|
|
3099
|
+
.filter((record) => this.sessionMatchesMeshNode(record, node, nodeId));
|
|
3100
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
3101
|
+
const sessionIds = matchedLiveSessionRecords
|
|
3102
|
+
.map((record: any) => typeof record?.sessionId === 'string' ? record.sessionId : '')
|
|
3103
|
+
.filter(Boolean);
|
|
3104
|
+
const providerTypes = matchedLiveSessionRecords
|
|
3105
|
+
.map((record: any) => readStringValue(record?.providerType))
|
|
3106
|
+
.filter(Boolean) as string[];
|
|
3107
|
+
status.activeSessions = sessionIds;
|
|
3108
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
3109
|
+
if (providerTypes.length > 0) {
|
|
3110
|
+
status.providers = Array.from(new Set([...(Array.isArray(status.providers) ? status.providers as string[] : []), ...providerTypes]));
|
|
3111
|
+
}
|
|
2980
3112
|
}
|
|
2981
3113
|
if (node.workspace && typeof node.workspace === 'string') {
|
|
2982
3114
|
if (!fs.existsSync(node.workspace as string) && applyCachedInlineMeshNodeStatus(status, node)) {
|
|
3115
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === 'online' || isSelfNode);
|
|
2983
3116
|
nodeStatuses.push(status);
|
|
2984
3117
|
continue;
|
|
2985
3118
|
}
|
|
@@ -3000,6 +3133,7 @@ export class DaemonCommandRouter {
|
|
|
3000
3133
|
} else {
|
|
3001
3134
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
3002
3135
|
}
|
|
3136
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === 'online' || isSelfNode);
|
|
3003
3137
|
nodeStatuses.push(status);
|
|
3004
3138
|
}
|
|
3005
3139
|
|
|
@@ -3009,6 +3143,7 @@ export class DaemonCommandRouter {
|
|
|
3009
3143
|
meshName: mesh.name,
|
|
3010
3144
|
repoIdentity: mesh.repoIdentity,
|
|
3011
3145
|
defaultBranch: mesh.defaultBranch,
|
|
3146
|
+
refreshedAt: new Date().toISOString(),
|
|
3012
3147
|
nodes: nodeStatuses,
|
|
3013
3148
|
queue: { tasks: queue, summary: queueSummary },
|
|
3014
3149
|
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
package/src/index.ts
CHANGED
|
@@ -103,6 +103,14 @@ export type {
|
|
|
103
103
|
LocalMeshNodeEntry,
|
|
104
104
|
RepoMeshStatus,
|
|
105
105
|
RepoMeshNodeStatus,
|
|
106
|
+
RepoMeshSessionStatus,
|
|
107
|
+
RepoMeshQueueTask,
|
|
108
|
+
RepoMeshQueueTaskStatus,
|
|
109
|
+
RepoMeshQueueSummary,
|
|
110
|
+
RepoMeshQueueStatus,
|
|
111
|
+
RepoMeshLedgerEntryStatus,
|
|
112
|
+
RepoMeshLedgerSummaryStatus,
|
|
113
|
+
RepoMeshLedgerStatus,
|
|
106
114
|
} from './repo-mesh-types.js';
|
|
107
115
|
export { DEFAULT_MESH_POLICY } from './repo-mesh-types.js';
|
|
108
116
|
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -261,15 +261,146 @@ export interface RepoMeshStatus {
|
|
|
261
261
|
repoIdentity: string;
|
|
262
262
|
refreshedAt: string;
|
|
263
263
|
nodes: RepoMeshNodeStatus[];
|
|
264
|
+
queue?: RepoMeshQueueStatus;
|
|
265
|
+
ledger?: RepoMeshLedgerStatus;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface RepoMeshSessionStatus {
|
|
269
|
+
sessionId: string;
|
|
270
|
+
providerType?: string;
|
|
271
|
+
state?: string;
|
|
272
|
+
lifecycle?: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'interrupted';
|
|
273
|
+
surfaceKind?: 'live_runtime' | 'recovery_snapshot' | 'inactive_record';
|
|
274
|
+
recoveryState?: string | null;
|
|
275
|
+
workspace?: string | null;
|
|
276
|
+
title?: string | null;
|
|
277
|
+
lastActivityAt?: string | null;
|
|
278
|
+
isCached?: boolean;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export type RepoMeshPeerConnectionState = 'self' | 'connected' | 'connecting' | 'disconnected' | 'failed' | 'closed' | 'unknown';
|
|
282
|
+
export type RepoMeshPeerConnectionTransport = 'local' | 'direct' | 'relay' | 'unknown';
|
|
283
|
+
|
|
284
|
+
export interface RepoMeshPeerConnectionStatus {
|
|
285
|
+
perspective: 'selected_coordinator';
|
|
286
|
+
source: 'mesh_peer_status' | 'not_reported';
|
|
287
|
+
state: RepoMeshPeerConnectionState;
|
|
288
|
+
transport: RepoMeshPeerConnectionTransport;
|
|
289
|
+
reported: boolean;
|
|
290
|
+
reason?: string;
|
|
291
|
+
lastStateChangeAt?: string;
|
|
292
|
+
lastConnectedAt?: string;
|
|
293
|
+
lastCommandAt?: string;
|
|
264
294
|
}
|
|
265
295
|
|
|
266
296
|
export interface RepoMeshNodeStatus {
|
|
267
297
|
nodeId: string;
|
|
268
298
|
machineLabel: string;
|
|
269
299
|
workspace: string;
|
|
300
|
+
repoRoot?: string;
|
|
301
|
+
daemonId?: string;
|
|
302
|
+
machineId?: string;
|
|
303
|
+
machineStatus?: string;
|
|
304
|
+
isLocalWorktree?: boolean;
|
|
305
|
+
worktreeBranch?: string;
|
|
270
306
|
health: RepoMeshNodeHealth;
|
|
271
307
|
git?: GitRepoStatus;
|
|
272
308
|
providers: string[];
|
|
273
309
|
activeSessions: string[];
|
|
310
|
+
activeSessionDetails?: RepoMeshSessionStatus[];
|
|
311
|
+
providerPriority?: string[];
|
|
312
|
+
launchReady?: boolean;
|
|
313
|
+
lastSeenAt?: string;
|
|
314
|
+
updatedAt?: string;
|
|
315
|
+
connection?: RepoMeshPeerConnectionStatus;
|
|
274
316
|
error?: string;
|
|
275
317
|
}
|
|
318
|
+
|
|
319
|
+
export type RepoMeshQueueTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled';
|
|
320
|
+
|
|
321
|
+
export interface RepoMeshQueueTask {
|
|
322
|
+
id: string;
|
|
323
|
+
meshId: string;
|
|
324
|
+
message: string;
|
|
325
|
+
status: RepoMeshQueueTaskStatus;
|
|
326
|
+
targetNodeId?: string;
|
|
327
|
+
targetSessionId?: string;
|
|
328
|
+
assignedNodeId?: string;
|
|
329
|
+
assignedSessionId?: string;
|
|
330
|
+
cancelReason?: string;
|
|
331
|
+
cancelledAt?: string;
|
|
332
|
+
requeueReason?: string;
|
|
333
|
+
requeuedAt?: string;
|
|
334
|
+
requeueCount?: number;
|
|
335
|
+
autoLaunch?: {
|
|
336
|
+
status: 'skipped' | 'started' | 'failed' | 'completed';
|
|
337
|
+
reason?: string;
|
|
338
|
+
nodeId?: string;
|
|
339
|
+
providerType?: string;
|
|
340
|
+
sessionId?: string;
|
|
341
|
+
updatedAt: string;
|
|
342
|
+
};
|
|
343
|
+
dispatchTimestamp?: string;
|
|
344
|
+
createdAt: string;
|
|
345
|
+
updatedAt: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface RepoMeshQueueSummary {
|
|
349
|
+
total: number;
|
|
350
|
+
active: number;
|
|
351
|
+
historical: number;
|
|
352
|
+
pending: number;
|
|
353
|
+
assigned: number;
|
|
354
|
+
completed: number;
|
|
355
|
+
failed: number;
|
|
356
|
+
cancelled: number;
|
|
357
|
+
activeCounts: {
|
|
358
|
+
pending: number;
|
|
359
|
+
assigned: number;
|
|
360
|
+
};
|
|
361
|
+
historicalCounts: {
|
|
362
|
+
completed: number;
|
|
363
|
+
failed: number;
|
|
364
|
+
cancelled: number;
|
|
365
|
+
};
|
|
366
|
+
activeAssignments: Array<{
|
|
367
|
+
id: string;
|
|
368
|
+
nodeId?: string;
|
|
369
|
+
sessionId?: string;
|
|
370
|
+
message: string;
|
|
371
|
+
}>;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export interface RepoMeshQueueStatus {
|
|
375
|
+
tasks: RepoMeshQueueTask[];
|
|
376
|
+
summary: RepoMeshQueueSummary;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export interface RepoMeshLedgerEntryStatus {
|
|
380
|
+
id: string;
|
|
381
|
+
meshId: string;
|
|
382
|
+
timestamp: string;
|
|
383
|
+
kind: string;
|
|
384
|
+
nodeId?: string;
|
|
385
|
+
sessionId?: string;
|
|
386
|
+
providerType?: string;
|
|
387
|
+
payload: Record<string, unknown>;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export interface RepoMeshLedgerSummaryStatus {
|
|
391
|
+
meshId: string;
|
|
392
|
+
totalEntries: number;
|
|
393
|
+
taskDispatched: number;
|
|
394
|
+
taskCompleted: number;
|
|
395
|
+
taskFailed: number;
|
|
396
|
+
taskStalled: number;
|
|
397
|
+
sessionLaunched: number;
|
|
398
|
+
checkpointCreated: number;
|
|
399
|
+
lastActivityAt: string | null;
|
|
400
|
+
recentFailures: number;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export interface RepoMeshLedgerStatus {
|
|
404
|
+
entries: RepoMeshLedgerEntryStatus[];
|
|
405
|
+
summary: RepoMeshLedgerSummaryStatus;
|
|
406
|
+
}
|