@adhdev/daemon-standalone 0.9.82-rc.7 → 0.9.82-rc.9

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/index.js CHANGED
@@ -28062,8 +28062,14 @@ ${lastSnapshot}`;
28062
28062
  const includeSubmodules = options.includeSubmodules !== false;
28063
28063
  try {
28064
28064
  const repo = await resolveGitRepository(workspace, options);
28065
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
28066
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
28065
+ let parsed = await readPorcelainStatus(repo, options);
28066
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
28067
+ if (options.refreshUpstream) {
28068
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
28069
+ if (upstreamProbe.upstreamStatus === "fresh") {
28070
+ parsed = await readPorcelainStatus(repo, options);
28071
+ }
28072
+ }
28067
28073
  const head = await readHead(repo, options);
28068
28074
  const stashCount = await readStashCount(repo, options);
28069
28075
  let submodules;
@@ -28078,6 +28084,9 @@ ${lastSnapshot}`;
28078
28084
  headCommit: head.commit,
28079
28085
  headMessage: head.message,
28080
28086
  upstream: parsed.upstream,
28087
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
28088
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
28089
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
28081
28090
  ahead: parsed.ahead,
28082
28091
  behind: parsed.behind,
28083
28092
  staged: parsed.staged,
@@ -28102,6 +28111,60 @@ ${lastSnapshot}`;
28102
28111
  );
28103
28112
  }
28104
28113
  }
28114
+ async function readPorcelainStatus(repo, options) {
28115
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
28116
+ return parsePorcelainV2Status(statusOutput.stdout);
28117
+ }
28118
+ function getInitialUpstreamProbe(parsed) {
28119
+ return {
28120
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
28121
+ };
28122
+ }
28123
+ async function refreshTrackedUpstream(repo, parsed, options) {
28124
+ if (!parsed.upstream || !parsed.branch) {
28125
+ return { upstreamStatus: "no_upstream" };
28126
+ }
28127
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
28128
+ if (!remoteName) {
28129
+ return {
28130
+ upstreamStatus: "stale",
28131
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
28132
+ };
28133
+ }
28134
+ try {
28135
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
28136
+ return {
28137
+ upstreamStatus: "fresh",
28138
+ upstreamFetchedAt: Date.now()
28139
+ };
28140
+ } catch (error48) {
28141
+ return {
28142
+ upstreamStatus: "stale",
28143
+ upstreamFetchError: formatGitError(error48)
28144
+ };
28145
+ }
28146
+ }
28147
+ async function readBranchRemote(repo, branch, options) {
28148
+ try {
28149
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
28150
+ return result.stdout.trim() || null;
28151
+ } catch {
28152
+ return null;
28153
+ }
28154
+ }
28155
+ function inferRemoteName(upstream) {
28156
+ const [remoteName] = upstream.split("/");
28157
+ return remoteName?.trim() || null;
28158
+ }
28159
+ function formatGitError(error48) {
28160
+ if (error48 instanceof GitCommandError) {
28161
+ return error48.stderr || error48.message;
28162
+ }
28163
+ if (error48 instanceof Error) {
28164
+ return error48.message;
28165
+ }
28166
+ return String(error48);
28167
+ }
28105
28168
  function parsePorcelainV2Status(output) {
28106
28169
  const parsed = {
28107
28170
  branch: null,
@@ -28196,6 +28259,7 @@ ${lastSnapshot}`;
28196
28259
  headCommit: null,
28197
28260
  headMessage: null,
28198
28261
  upstream: null,
28262
+ upstreamStatus: "unavailable",
28199
28263
  ahead: 0,
28200
28264
  behind: 0,
28201
28265
  staged: 0,
@@ -28472,6 +28536,9 @@ ${lastSnapshot}`;
28472
28536
  isGitRepo: status.isGitRepo,
28473
28537
  repoRoot: status.repoRoot,
28474
28538
  branch: status.branch,
28539
+ upstreamStatus: status.upstreamStatus,
28540
+ upstreamFetchedAt: status.upstreamFetchedAt,
28541
+ upstreamFetchError: status.upstreamFetchError,
28475
28542
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
28476
28543
  changedFiles,
28477
28544
  ahead: status.ahead,
@@ -28810,7 +28877,7 @@ ${lastSnapshot}`;
28810
28877
  });
28811
28878
  function createDefaultGitCommandServices() {
28812
28879
  return {
28813
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
28880
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
28814
28881
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
28815
28882
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
28816
28883
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -28896,7 +28963,7 @@ ${lastSnapshot}`;
28896
28963
  switch (command) {
28897
28964
  case "git_status": {
28898
28965
  if (!services.getStatus) return serviceNotImplemented(command);
28899
- const status = await runService(() => services.getStatus({ workspace }));
28966
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
28900
28967
  return "success" in status ? status : { success: true, status };
28901
28968
  }
28902
28969
  case "git_diff_summary": {
@@ -45934,17 +46001,87 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45934
46001
  const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
45935
46002
  return sessionId ? [sessionId] : [];
45936
46003
  }
46004
+ function readCachedInlineMeshActiveSessionDetails(node) {
46005
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
46006
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
46007
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
46008
+ const sessionId = readStringValue(
46009
+ fallbackSession.id,
46010
+ fallbackSession.sessionId,
46011
+ fallbackSession.session_id,
46012
+ node?.activeSessionId,
46013
+ node?.active_session_id,
46014
+ node?.sessionId,
46015
+ node?.session_id
46016
+ );
46017
+ if (!sessionId) return [];
46018
+ return [{
46019
+ sessionId,
46020
+ providerType: readStringValue(
46021
+ fallbackSession.providerType,
46022
+ fallbackSession.provider_type,
46023
+ fallbackSession.cliType,
46024
+ fallbackSession.cli_type,
46025
+ fallbackSession.provider,
46026
+ node?.providerType,
46027
+ node?.provider_type
46028
+ ),
46029
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
46030
+ lifecycle: readStringValue(fallbackSession.lifecycle),
46031
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
46032
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
46033
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
46034
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
46035
+ isCached: true
46036
+ }];
46037
+ }
46038
+ function readLiveMeshSessionState(record2) {
46039
+ return readStringValue(
46040
+ record2?.meta?.sessionStatus,
46041
+ record2?.meta?.status,
46042
+ record2?.meta?.providerStatus,
46043
+ record2?.status,
46044
+ record2?.state,
46045
+ record2?.lifecycle
46046
+ );
46047
+ }
46048
+ function toIsoTimestamp(value) {
46049
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
46050
+ const stringValue = readStringValue(value);
46051
+ return stringValue || null;
46052
+ }
46053
+ function summarizeMeshSessionRecord(record2) {
46054
+ return {
46055
+ sessionId: readStringValue(record2?.sessionId) || "unknown",
46056
+ providerType: readStringValue(record2?.providerType),
46057
+ state: readLiveMeshSessionState(record2),
46058
+ lifecycle: readStringValue(record2?.lifecycle),
46059
+ surfaceKind: getSessionHostSurfaceKind(record2),
46060
+ recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
46061
+ workspace: readStringValue(record2?.workspace) ?? null,
46062
+ title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
46063
+ lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
46064
+ isCached: false
46065
+ };
46066
+ }
45937
46067
  function applyCachedInlineMeshNodeStatus(status, node) {
45938
46068
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45939
46069
  const git = buildCachedInlineMeshGitStatus(node);
45940
46070
  const error48 = readStringValue(cachedStatus.error, node?.error);
45941
46071
  const health = readStringValue(cachedStatus.health, node?.health);
45942
46072
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
46073
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
46074
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
45943
46075
  const activeSessions = readCachedInlineMeshActiveSessions(node);
45944
- if (!git && !error48 && !health && !machineStatus && activeSessions.length === 0) return false;
46076
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
46077
+ if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
45945
46078
  if (git) status.git = git;
45946
46079
  if (error48) status.error = error48;
46080
+ if (machineStatus) status.machineStatus = machineStatus;
46081
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
46082
+ if (updatedAt) status.updatedAt = updatedAt;
45947
46083
  if (activeSessions.length > 0) status.activeSessions = activeSessions;
46084
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
45948
46085
  if (health) {
45949
46086
  status.health = health;
45950
46087
  return true;
@@ -45953,7 +46090,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45953
46090
  status.health = deriveMeshNodeHealthFromGit(git);
45954
46091
  return true;
45955
46092
  }
45956
- return activeSessions.length > 0 || !!machineStatus;
46093
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
45957
46094
  }
45958
46095
  async function resolveProviderTypeFromPriority(args) {
45959
46096
  if (!args.providerPriority.length) {
@@ -48195,33 +48332,84 @@ ${block}`);
48195
48332
  const ledgerSummary = getLedgerSummary2(meshId);
48196
48333
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
48197
48334
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
48335
+ const localMachineId = loadConfig2().machineId || "";
48336
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? readStringValue(mesh.nodes[0]?.id, mesh.nodes[0]?.nodeId) : void 0;
48337
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
48198
48338
  const nodeStatuses = [];
48199
- for (const node of mesh.nodes || []) {
48339
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
48340
+ const nodeId = String(node.id || node.nodeId || "");
48341
+ const daemonId = readStringValue(node.daemonId);
48342
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
48343
+ const isSelfNode = Boolean(
48344
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
48345
+ ) || Boolean(
48346
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
48347
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
48200
48348
  const status = {
48201
- nodeId: node.id || node.nodeId,
48349
+ nodeId,
48202
48350
  machineLabel: node.machineLabel || node.id || node.nodeId,
48203
48351
  workspace: node.workspace,
48204
48352
  repoRoot: node.repoRoot,
48205
48353
  isLocalWorktree: node.isLocalWorktree,
48206
48354
  worktreeBranch: node.worktreeBranch,
48207
- daemonId: node.daemonId,
48355
+ daemonId,
48208
48356
  machineId: node.machineId,
48357
+ machineStatus: node.machineStatus,
48209
48358
  health: "unknown",
48210
48359
  providers: node.providers || [],
48211
- activeSessions: []
48360
+ providerPriority,
48361
+ activeSessions: [],
48362
+ activeSessionDetails: [],
48363
+ launchReady: false
48212
48364
  };
48213
- const nodeId = String(node.id || node.nodeId || "");
48214
- const matchedLiveSessions = liveMeshSessions.filter((record2) => this.sessionMatchesMeshNode(record2, node, nodeId)).map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
48215
- if (matchedLiveSessions.length > 0) {
48216
- status.activeSessions = matchedLiveSessions;
48365
+ if (isSelfNode) {
48366
+ status.connection = {
48367
+ perspective: "selected_coordinator",
48368
+ source: "mesh_peer_status",
48369
+ state: "self",
48370
+ transport: "local",
48371
+ reported: true,
48372
+ reason: "Selected coordinator daemon",
48373
+ lastStateChangeAt: refreshedAt
48374
+ };
48375
+ } else if (daemonId) {
48376
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
48377
+ status.connection = connection ?? {
48378
+ perspective: "selected_coordinator",
48379
+ source: "not_reported",
48380
+ state: "unknown",
48381
+ transport: "unknown",
48382
+ reported: false,
48383
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
48384
+ };
48385
+ } else {
48386
+ status.connection = {
48387
+ perspective: "selected_coordinator",
48388
+ source: "not_reported",
48389
+ state: "unknown",
48390
+ transport: "unknown",
48391
+ reported: false,
48392
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
48393
+ };
48394
+ }
48395
+ const matchedLiveSessionRecords = liveMeshSessions.filter((record2) => this.sessionMatchesMeshNode(record2, node, nodeId));
48396
+ if (matchedLiveSessionRecords.length > 0) {
48397
+ const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
48398
+ const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
48399
+ status.activeSessions = sessionIds;
48400
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
48401
+ if (providerTypes.length > 0) {
48402
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
48403
+ }
48217
48404
  }
48218
48405
  if (node.workspace && typeof node.workspace === "string") {
48219
48406
  if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
48407
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
48220
48408
  nodeStatuses.push(status);
48221
48409
  continue;
48222
48410
  }
48223
48411
  try {
48224
- const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4 });
48412
+ const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4, refreshUpstream: true });
48225
48413
  status.git = gitStatus;
48226
48414
  if (gitStatus.isGitRepo) {
48227
48415
  status.health = deriveMeshNodeHealthFromGit(gitStatus);
@@ -48237,6 +48425,7 @@ ${block}`);
48237
48425
  } else {
48238
48426
  applyCachedInlineMeshNodeStatus(status, node);
48239
48427
  }
48428
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
48240
48429
  nodeStatuses.push(status);
48241
48430
  }
48242
48431
  return {
@@ -48245,6 +48434,7 @@ ${block}`);
48245
48434
  meshName: mesh.name,
48246
48435
  repoIdentity: mesh.repoIdentity,
48247
48436
  defaultBranch: mesh.defaultBranch,
48437
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
48248
48438
  nodes: nodeStatuses,
48249
48439
  queue: { tasks: queue, summary: queueSummary },
48250
48440
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -56120,6 +56310,7 @@ data: ${JSON.stringify(msg.data)}
56120
56310
  sessionHostControl: config2.sessionHostControl,
56121
56311
  statusInstanceId: config2.statusInstanceId,
56122
56312
  statusVersion: config2.statusVersion,
56313
+ getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
56123
56314
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG2.forComponent(`CDP:${ideType}`).asLogFn())
56124
56315
  });
56125
56316
  poller = new AgentStreamPoller({