@adhdev/daemon-core 0.9.82-rc.32 → 0.9.82-rc.320
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 +8 -0
- package/dist/boot/process-hardening.d.ts +50 -0
- package/dist/build-info.d.ts +37 -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 +46 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +115 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +38 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +14 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
- package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
- package/dist/cli-adapters/terminal-screen.d.ts +4 -11
- package/dist/commands/cli-manager.d.ts +2 -1
- package/dist/commands/handler.d.ts +110 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +229 -1
- package/dist/commands/upgrade-helper.d.ts +12 -0
- package/dist/config/chat-history.d.ts +9 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/mesh-config.d.ts +72 -1
- package/dist/detection/ide-detector.d.ts +13 -0
- package/dist/detection/win32-ide-version.d.ts +37 -0
- package/dist/git/git-commands.d.ts +9 -1
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/git/git-executor.d.ts +11 -0
- package/dist/git/git-status.d.ts +9 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/index.d.ts +51 -12
- package/dist/index.js +36031 -12365
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40382 -16833
- 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/logging/log-redactor.d.ts +24 -0
- package/dist/logging/log-tail-reader.d.ts +46 -0
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +36 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +108 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +169 -0
- package/dist/mesh/mesh-events-pending.d.ts +45 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +47 -0
- package/dist/mesh/mesh-events.d.ts +6 -49
- package/dist/mesh/mesh-fast-forward.d.ts +81 -0
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-init.d.ts +86 -0
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-missions.d.ts +116 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -0
- package/dist/mesh/mesh-refine-status.d.ts +62 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-routing.d.ts +70 -0
- package/dist/mesh/mesh-runtime-store.d.ts +401 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
- package/dist/mesh/mesh-work-queue.d.ts +226 -5
- package/dist/mesh/preview-freshness.d.ts +18 -0
- package/dist/mesh/refine-config.d.ts +215 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
- package/dist/providers/acp-provider-instance.d.ts +2 -0
- package/dist/providers/approval-utils.d.ts +13 -0
- package/dist/providers/cli-provider-instance.d.ts +61 -3
- package/dist/providers/contracts.d.ts +130 -6
- 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 +27 -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-manager.d.ts +13 -0
- package/dist/providers/provider-instance.d.ts +13 -1
- 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 +203 -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 +69 -0
- package/dist/providers/spec/cli-adapter.d.ts +217 -0
- package/dist/providers/spec/evaluator.d.ts +23 -0
- package/dist/providers/spec/fsm-driver.d.ts +278 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +128 -0
- package/dist/providers/spec/native-history-executor.d.ts +41 -0
- package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
- package/dist/providers/spec/route.d.ts +4 -0
- package/dist/providers/spec/types.d.ts +180 -0
- package/dist/providers/transcript-v2.d.ts +176 -0
- package/dist/providers/types/interactive-prompt.d.ts +84 -0
- package/dist/providers/working-dir.d.ts +17 -0
- package/dist/repo-mesh-types.d.ts +365 -13
- package/dist/sessions/registry.d.ts +6 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +42 -1
- package/dist/status/normalize.d.ts +1 -1
- package/dist/status/normalize.js +1 -0
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +1 -0
- package/dist/status/normalize.mjs.map +1 -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 -3
- package/src/agent-stream/poller.ts +2 -3
- package/src/boot/daemon-lifecycle.ts +55 -12
- package/src/boot/process-hardening.ts +89 -0
- package/src/build-info.ts +73 -0
- package/src/chat/source-machine.ts +534 -0
- package/src/chat/source-resolver.ts +0 -0
- package/src/chat/subscription-updates.ts +20 -1
- package/src/cli-adapter-types.d.ts +1 -0
- package/src/cli-adapter-types.ts +47 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1215 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +710 -1140
- 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 +56 -7
- package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/src/cli-adapters/provider-cli-shared.ts +85 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +90 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
- package/src/cli-adapters/terminal-backends/types.ts +10 -3
- package/src/cli-adapters/terminal-screen.ts +16 -81
- package/src/commands/chat-commands.ts +1822 -61
- package/src/commands/cli-manager.ts +286 -14
- package/src/commands/handler.ts +809 -2
- package/src/commands/mesh-coordinator.ts +332 -122
- package/src/commands/router.ts +6370 -704
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +81 -30
- package/src/config/chat-history.ts +483 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +391 -4
- package/src/config/recent-activity.ts +8 -2
- package/src/daemon/dev-auto-implement.ts +3 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/detection/cli-detector.ts +28 -9
- package/src/detection/ide-detector.ts +55 -16
- package/src/detection/win32-ide-version.ts +106 -0
- package/src/git/git-commands.ts +42 -12
- package/src/git/git-diff.ts +53 -0
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +408 -43
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +8 -1
- package/src/index.ts +151 -11
- 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/log-redactor.ts +100 -0
- package/src/logging/log-tail-reader.ts +220 -0
- package/src/logging/logger.ts +2 -1
- package/src/mesh/contracts.ts +329 -0
- package/src/mesh/coordinator-prompt.ts +235 -31
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +469 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-events-coordinator.ts +2102 -0
- package/src/mesh/mesh-events-pending.ts +508 -0
- package/src/mesh/mesh-events-stale.ts +290 -0
- package/src/mesh/mesh-events-utils.ts +254 -0
- package/src/mesh/mesh-events.ts +30 -1035
- package/src/mesh/mesh-fast-forward.ts +839 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-init.ts +260 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
- package/src/mesh/mesh-ledger.ts +589 -102
- package/src/mesh/mesh-missions.ts +248 -0
- package/src/mesh/mesh-reconcile-loop.ts +496 -0
- package/src/mesh/mesh-refine-batch.ts +197 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +1578 -0
- package/src/mesh/mesh-task-stats.ts +154 -0
- package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
- package/src/mesh/mesh-work-queue.ts +780 -139
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +403 -0
- package/src/mesh/worktree-bootstrap-config.ts +326 -0
- package/src/providers/acp-provider-instance.ts +19 -4
- 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 +958 -91
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +141 -6
- package/src/providers/extension-provider-instance.ts +5 -1
- package/src/providers/external-sources.ts +218 -0
- package/src/providers/ide-provider-instance.ts +25 -6
- 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 +479 -0
- package/src/providers/native-history/dispatcher.ts +340 -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-manager.ts +30 -0
- package/src/providers/provider-instance.ts +10 -1
- package/src/providers/provider-loader.ts +662 -50
- package/src/providers/provider-schema.ts +87 -14
- 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 +504 -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 +229 -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 +986 -0
- package/src/providers/spec/evaluator.ts +345 -0
- package/src/providers/spec/fsm-driver.ts +909 -0
- package/src/providers/spec/fsm-evaluator.ts +255 -0
- package/src/providers/spec/fsm-loader.ts +112 -0
- package/src/providers/spec/fsm-types.ts +222 -0
- package/src/providers/spec/native-history-executor.ts +1136 -0
- package/src/providers/spec/pre-launch-trust.ts +104 -0
- package/src/providers/spec/route.ts +51 -0
- package/src/providers/spec/types.ts +226 -0
- package/src/providers/transcript-v2.ts +567 -0
- package/src/providers/types/interactive-prompt.ts +536 -0
- package/src/providers/version-archive.ts +64 -24
- package/src/providers/working-dir.ts +23 -0
- package/src/repo-mesh-types.ts +494 -13
- package/src/sessions/registry.ts +6 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.ts +45 -1
- package/src/status/builders.ts +26 -6
- package/src/status/normalize.ts +2 -0
- 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
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
- package/dist/mesh/mesh-sync.d.ts +0 -53
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
- package/src/mesh/mesh-sync.ts +0 -111
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
* Migrated from @adhdev/core — this is now the single source of truth.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { exec } from 'child_process';
|
|
11
|
+
import { promisify } from 'util';
|
|
12
|
+
const execAsync = promisify(exec);
|
|
13
|
+
import { existsSync, statSync } from 'fs';
|
|
12
14
|
import { platform, homedir } from 'os';
|
|
13
15
|
import * as path from 'path';
|
|
14
16
|
import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
17
|
+
import { isKnownWin32GuiExe, readWin32IdeVersionFromDisk } from './win32-ide-version.js';
|
|
15
18
|
|
|
16
19
|
// ─── Types ──────────────────────────────────────
|
|
17
20
|
|
|
@@ -73,25 +76,54 @@ function findCliCommand(command: string): string | null {
|
|
|
73
76
|
const resolved = path.isAbsolute(candidate) ? candidate : path.resolve(candidate);
|
|
74
77
|
return existsSync(resolved) ? resolved : null;
|
|
75
78
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const isWin = platform() === 'win32';
|
|
80
|
+
const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
|
|
81
|
+
const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
|
|
82
|
+
for (const p of paths) {
|
|
83
|
+
if (!p) continue;
|
|
84
|
+
for (const ext of exes) {
|
|
85
|
+
const fullPath = path.join(p, trimmed + ext);
|
|
86
|
+
try {
|
|
87
|
+
if (existsSync(fullPath)) {
|
|
88
|
+
const stat = statSync(fullPath);
|
|
89
|
+
if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
|
|
90
|
+
return fullPath;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch { }
|
|
94
|
+
}
|
|
84
95
|
}
|
|
96
|
+
return null;
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Resolve an IDE version on demand (NOT at boot).
|
|
101
|
+
*
|
|
102
|
+
* Order of preference, all spawn-free where possible:
|
|
103
|
+
* 1. win32: read the bundled product.json/package.json next to the exe.
|
|
104
|
+
* 2. Otherwise spawn `<cli> --version` — but ONLY when the binary is not a
|
|
105
|
+
* known GUI executable (the #4 guard), so we never boot an IDE window.
|
|
106
|
+
*
|
|
107
|
+
* `win32ProcessNames` is provider.json `processNames.win32` (type → exe names),
|
|
108
|
+
* used to recognise GUI executables. Callers that have a ProviderLoader can
|
|
109
|
+
* pass `providerLoader.getWinProcessNames()`.
|
|
110
|
+
*/
|
|
111
|
+
export async function getIdeVersion(
|
|
112
|
+
cliCommand: string,
|
|
113
|
+
win32ProcessNames: Record<string, string[]> = {},
|
|
114
|
+
): Promise<string | null> {
|
|
115
|
+
if (platform() === 'win32') {
|
|
116
|
+
const fromDisk = readWin32IdeVersionFromDisk(cliCommand);
|
|
117
|
+
if (fromDisk) return fromDisk;
|
|
118
|
+
// Refuse to spawn a known GUI exe — it would launch the IDE window.
|
|
119
|
+
if (isKnownWin32GuiExe(cliCommand, win32ProcessNames)) return null;
|
|
120
|
+
}
|
|
88
121
|
try {
|
|
89
|
-
const
|
|
122
|
+
const { stdout } = await execAsync(`"${cliCommand}" --version`, {
|
|
90
123
|
encoding: 'utf-8',
|
|
91
124
|
timeout: 10000,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return result.split('\n')[0] || null;
|
|
125
|
+
});
|
|
126
|
+
return stdout.trim().split('\n')[0] || null;
|
|
95
127
|
} catch {
|
|
96
128
|
return null;
|
|
97
129
|
}
|
|
@@ -152,7 +184,14 @@ export async function detectIDEs(providerLoader?: ProviderLoader): Promise<IDEIn
|
|
|
152
184
|
const installed = os === 'darwin'
|
|
153
185
|
? !!(resolvedCli || appPath)
|
|
154
186
|
: !!resolvedCli;
|
|
155
|
-
|
|
187
|
+
// Boot-time IDE detection must NOT spawn `<cli> --version`. On Windows
|
|
188
|
+
// the resolved "CLI" is frequently the GUI Electron exe (case-insensitive
|
|
189
|
+
// FS matches `...\cursor\cursor.exe` against `Cursor.exe`), and running it
|
|
190
|
+
// with `--version` boots the IDE window. `installed` is decided purely by
|
|
191
|
+
// existsSync above, and the dashboard drops `version` anyway — the only
|
|
192
|
+
// real version consumer is provider-loader.resolve() at CDP attach time,
|
|
193
|
+
// which fetches the version lazily. So leave it null here.
|
|
194
|
+
const version: string | null = null;
|
|
156
195
|
|
|
157
196
|
results.push({
|
|
158
197
|
id: def.id,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADHDev — Windows IDE version detection (execution-free)
|
|
3
|
+
*
|
|
4
|
+
* On Windows the resolved "CLI" for a VS Code fork (Cursor, Antigravity, …)
|
|
5
|
+
* frequently resolves to the GUI Electron executable itself, because the
|
|
6
|
+
* case-insensitive filesystem matches `...\cursor\cursor.exe` against the
|
|
7
|
+
* real `Cursor.exe`. Running `<that exe> --version` boots the GUI instead of
|
|
8
|
+
* printing a version (Electron ignores the unknown flag and opens a window).
|
|
9
|
+
*
|
|
10
|
+
* To learn the version WITHOUT spawning anything, we read the bundled
|
|
11
|
+
* `product.json` / `package.json` that ship next to the executable. VS Code
|
|
12
|
+
* forks embed their version there. This is a pure filesystem read.
|
|
13
|
+
*
|
|
14
|
+
* It also exposes a guard so any remaining `--version` exec path can refuse to
|
|
15
|
+
* spawn a binary that is a known GUI executable for an IDE provider.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Candidate locations for the version manifest relative to the GUI exe dir.
|
|
23
|
+
* VS Code forks place `resources/app/{product,package}.json` next to the exe.
|
|
24
|
+
*/
|
|
25
|
+
function manifestCandidates(exeDir: string): string[] {
|
|
26
|
+
return [
|
|
27
|
+
path.join(exeDir, 'resources', 'app', 'product.json'),
|
|
28
|
+
path.join(exeDir, 'resources', 'app', 'package.json'),
|
|
29
|
+
// Some packagings keep product.json one level up.
|
|
30
|
+
path.join(exeDir, 'product.json'),
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parseVersionFromManifest(raw: string): string | null {
|
|
35
|
+
try {
|
|
36
|
+
const json = JSON.parse(raw) as Record<string, unknown>;
|
|
37
|
+
// product.json forks expose the IDE's own version here; package.json
|
|
38
|
+
// exposes the upstream VS Code engine version. Prefer the former.
|
|
39
|
+
const candidate = json.version;
|
|
40
|
+
if (typeof candidate === 'string' && candidate.trim()) {
|
|
41
|
+
return candidate.trim();
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
/* not valid JSON — ignore */
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Read an IDE version from disk (no process spawn).
|
|
51
|
+
*
|
|
52
|
+
* @param exePath Absolute path to the GUI executable (or any path inside the
|
|
53
|
+
* IDE install dir — we read the manifest relative to its directory).
|
|
54
|
+
* @returns The version string, or null if it could not be determined.
|
|
55
|
+
*/
|
|
56
|
+
export function readWin32IdeVersionFromDisk(exePath: string): string | null {
|
|
57
|
+
if (!exePath) return null;
|
|
58
|
+
let exeDir: string;
|
|
59
|
+
try {
|
|
60
|
+
exeDir = fs.statSync(exePath).isDirectory() ? exePath : path.dirname(exePath);
|
|
61
|
+
} catch {
|
|
62
|
+
exeDir = path.dirname(exePath);
|
|
63
|
+
}
|
|
64
|
+
for (const candidate of manifestCandidates(exeDir)) {
|
|
65
|
+
try {
|
|
66
|
+
if (!fs.existsSync(candidate)) continue;
|
|
67
|
+
const version = parseVersionFromManifest(fs.readFileSync(candidate, 'utf-8'));
|
|
68
|
+
if (version) return version;
|
|
69
|
+
} catch {
|
|
70
|
+
/* ignore unreadable manifest */
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* True when `binPath` resolves to a known GUI executable for some IDE.
|
|
78
|
+
*
|
|
79
|
+
* Used as a safety net: any code path about to run `<bin> --version` must skip
|
|
80
|
+
* the spawn when the binary is actually the GUI Electron exe, since that would
|
|
81
|
+
* launch the IDE window. Comparison is case-insensitive on the basename
|
|
82
|
+
* (Windows filesystem semantics) against every provider's `processNames.win32`.
|
|
83
|
+
*
|
|
84
|
+
* @param binPath Resolved binary path that would be exec'd.
|
|
85
|
+
* @param win32ProcessNames Map of provider type → list of GUI exe names
|
|
86
|
+
* (from provider.json `processNames.win32`, e.g. `["Cursor.exe"]`).
|
|
87
|
+
*/
|
|
88
|
+
export function isKnownWin32GuiExe(
|
|
89
|
+
binPath: string | null | undefined,
|
|
90
|
+
win32ProcessNames: Record<string, string[]>,
|
|
91
|
+
): boolean {
|
|
92
|
+
if (!binPath) return false;
|
|
93
|
+
// Use win32 basename semantics regardless of host OS: this matches Windows
|
|
94
|
+
// paths even when the daemon-core test/CI host is POSIX (where `/` is the
|
|
95
|
+
// only separator). On the real win32 target this is identical to basename().
|
|
96
|
+
const base = path.win32.basename(binPath).toLowerCase();
|
|
97
|
+
if (!base.endsWith('.exe')) return false;
|
|
98
|
+
for (const names of Object.values(win32ProcessNames)) {
|
|
99
|
+
for (const name of names) {
|
|
100
|
+
if (typeof name === 'string' && name.toLowerCase() === base) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
package/src/git/git-commands.ts
CHANGED
|
@@ -42,8 +42,12 @@ export interface GitLogResult extends GitRepoIdentity {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export interface GitCheckpointResult extends GitRepoIdentity {
|
|
45
|
-
commit
|
|
45
|
+
commit?: string;
|
|
46
46
|
message: string;
|
|
47
|
+
status?: 'created' | 'skipped';
|
|
48
|
+
skipped?: boolean;
|
|
49
|
+
noop?: boolean;
|
|
50
|
+
reason?: 'nothing_to_commit';
|
|
47
51
|
lastCheckedAt: number;
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -62,9 +66,9 @@ export interface GitPushResult extends GitRepoIdentity {
|
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
export interface GitCommandServices {
|
|
65
|
-
getStatus?: (params: { workspace: string; refreshUpstream?: boolean }) => Promise<GitRepoStatus> | GitRepoStatus;
|
|
66
|
-
getDiffSummary?: (params: { workspace: string; staged?: boolean }) => Promise<GitDiffSummary> | GitDiffSummary;
|
|
67
|
-
getDiffFile?: (params: { workspace: string; path: string; staged?: boolean }) => Promise<GitFileDiff> | GitFileDiff;
|
|
69
|
+
getStatus?: (params: { workspace: string; refreshUpstream?: boolean; includeSubmodules?: boolean; submoduleIgnorePaths?: string[] }) => Promise<GitRepoStatus> | GitRepoStatus;
|
|
70
|
+
getDiffSummary?: (params: { workspace: string; staged?: boolean; base?: string }) => Promise<GitDiffSummary> | GitDiffSummary;
|
|
71
|
+
getDiffFile?: (params: { workspace: string; path: string; staged?: boolean; base?: string }) => Promise<GitFileDiff> | GitFileDiff;
|
|
68
72
|
createSnapshot?: (params: {
|
|
69
73
|
workspace: string;
|
|
70
74
|
reason: GitSnapshotReason;
|
|
@@ -172,8 +176,8 @@ const defaultSnapshotStore = createGitSnapshotStore({
|
|
|
172
176
|
export function createDefaultGitCommandServices(): GitCommandServices {
|
|
173
177
|
return {
|
|
174
178
|
getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
|
|
175
|
-
getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
|
|
176
|
-
getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
|
|
179
|
+
getDiffSummary: ({ workspace, base }) => getGitDiffSummary(workspace, base ? { baseRef: base } : {}),
|
|
180
|
+
getDiffFile: ({ workspace, path: filePath, base }) => getGitFileDiff(workspace, filePath, base ? { baseRef: base } : {}),
|
|
177
181
|
createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
|
|
178
182
|
workspace,
|
|
179
183
|
reason,
|
|
@@ -290,13 +294,22 @@ export async function handleGitCommand(
|
|
|
290
294
|
switch (command) {
|
|
291
295
|
case 'git_status': {
|
|
292
296
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
293
|
-
const
|
|
297
|
+
const submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths)
|
|
298
|
+
? args.submoduleIgnorePaths.filter((value: unknown): value is string => typeof value === 'string' && value.trim().length > 0)
|
|
299
|
+
: undefined;
|
|
300
|
+
const statusParams: { workspace: string; refreshUpstream?: boolean; includeSubmodules?: boolean; submoduleIgnorePaths?: string[] } = { workspace };
|
|
301
|
+
const refreshUpstream = optionalBoolean(args?.refreshUpstream);
|
|
302
|
+
const includeSubmodules = optionalBoolean(args?.includeSubmodules);
|
|
303
|
+
if (refreshUpstream !== undefined) statusParams.refreshUpstream = refreshUpstream;
|
|
304
|
+
if (includeSubmodules !== undefined) statusParams.includeSubmodules = includeSubmodules;
|
|
305
|
+
if (submoduleIgnorePaths && submoduleIgnorePaths.length > 0) statusParams.submoduleIgnorePaths = submoduleIgnorePaths;
|
|
306
|
+
const status = await runService(() => services.getStatus!(statusParams));
|
|
294
307
|
return 'success' in status ? status : { success: true, status };
|
|
295
308
|
}
|
|
296
309
|
|
|
297
310
|
case 'git_diff_summary': {
|
|
298
311
|
if (!services.getDiffSummary) return serviceNotImplemented(command);
|
|
299
|
-
const diffSummary = await runService(() => services.getDiffSummary!({ workspace, staged: optionalBoolean(args?.staged) }));
|
|
312
|
+
const diffSummary = await runService(() => services.getDiffSummary!({ workspace, staged: optionalBoolean(args?.staged), base: optionalString(args?.base) }));
|
|
300
313
|
return 'success' in diffSummary ? diffSummary : { success: true, diffSummary };
|
|
301
314
|
}
|
|
302
315
|
|
|
@@ -442,6 +455,15 @@ async function gitCheckpoint(
|
|
|
442
455
|
if (statusResult.hasConflicts) {
|
|
443
456
|
throw new GitCommandError('conflict', 'Repository has conflicts — resolve before checkpointing');
|
|
444
457
|
}
|
|
458
|
+
const dirtySubmodules = (statusResult.submodules || []).filter(submodule => submodule.dirty);
|
|
459
|
+
if (dirtySubmodules.length > 0) {
|
|
460
|
+
const paths = dirtySubmodules.map(submodule => submodule.path).join(', ');
|
|
461
|
+
throw new GitCommandError(
|
|
462
|
+
'dirty_index_required',
|
|
463
|
+
`Repository has dirty submodules that must be checkpointed first: ${paths}. ` +
|
|
464
|
+
'Checkpoint or commit each dirty submodule, then checkpoint this repository to record gitlink changes.',
|
|
465
|
+
);
|
|
466
|
+
}
|
|
445
467
|
|
|
446
468
|
const addArgs = includeUntracked ? ['-A'] : ['-u'];
|
|
447
469
|
await runGit(repo, ['add', ...addArgs], { cwd: repoRoot });
|
|
@@ -455,10 +477,17 @@ async function gitCheckpoint(
|
|
|
455
477
|
} catch (err: any) {
|
|
456
478
|
const output = (err?.stdout || '') + (err?.stderr || '');
|
|
457
479
|
if (/nothing to commit/i.test(output)) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
480
|
+
return {
|
|
481
|
+
workspace: repo.workspace,
|
|
482
|
+
repoRoot,
|
|
483
|
+
isGitRepo: true,
|
|
484
|
+
message: fullMsg,
|
|
485
|
+
status: 'skipped',
|
|
486
|
+
skipped: true,
|
|
487
|
+
noop: true,
|
|
488
|
+
reason: 'nothing_to_commit',
|
|
489
|
+
lastCheckedAt: Date.now(),
|
|
490
|
+
};
|
|
462
491
|
}
|
|
463
492
|
throw err;
|
|
464
493
|
}
|
|
@@ -469,6 +498,7 @@ async function gitCheckpoint(
|
|
|
469
498
|
isGitRepo: true,
|
|
470
499
|
commit: commitSha,
|
|
471
500
|
message: fullMsg,
|
|
501
|
+
status: 'created',
|
|
472
502
|
lastCheckedAt: Date.now(),
|
|
473
503
|
};
|
|
474
504
|
}
|
package/src/git/git-diff.ts
CHANGED
|
@@ -10,6 +10,20 @@ export interface GitDiffOptions {
|
|
|
10
10
|
timeoutMs?: number;
|
|
11
11
|
maxFiles?: number;
|
|
12
12
|
maxBytes?: number;
|
|
13
|
+
/**
|
|
14
|
+
* When set, diff `<baseRef>...HEAD` (merge-base range — "what this branch
|
|
15
|
+
* adds on top of base") instead of the working tree. Staged/untracked
|
|
16
|
+
* sections do not apply in this mode.
|
|
17
|
+
*/
|
|
18
|
+
baseRef?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function validateBaseRef(ref: string): string {
|
|
22
|
+
const trimmed = ref.trim();
|
|
23
|
+
if (!trimmed || trimmed.startsWith('-') || trimmed.includes('..') || !/^[A-Za-z0-9][A-Za-z0-9._/@-]*$/.test(trimmed)) {
|
|
24
|
+
throw new GitCommandError('invalid_args', `Invalid base ref: ${ref}`);
|
|
25
|
+
}
|
|
26
|
+
return trimmed;
|
|
13
27
|
}
|
|
14
28
|
|
|
15
29
|
export interface GitFileDiffResult {
|
|
@@ -44,6 +58,30 @@ export async function getGitDiffSummary(
|
|
|
44
58
|
try {
|
|
45
59
|
const repo = await resolveGitRepository(workspace, options);
|
|
46
60
|
const repoRoot = repo.repoRoot!;
|
|
61
|
+
|
|
62
|
+
if (options.baseRef) {
|
|
63
|
+
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
64
|
+
const [nameStatus, numstat] = await Promise.all([
|
|
65
|
+
runGit(repo, ['diff', '--no-ext-diff', '--name-status', range, '--'], { ...options, cwd: repoRoot }),
|
|
66
|
+
runGit(repo, ['diff', '--no-ext-diff', '--numstat', range, '--'], { ...options, cwd: repoRoot }),
|
|
67
|
+
]);
|
|
68
|
+
const outputBytes = byteLength(nameStatus.stdout + numstat.stdout);
|
|
69
|
+
const changes = combineDiffEntries(nameStatus.stdout, numstat.stdout, false);
|
|
70
|
+
const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
|
|
71
|
+
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
72
|
+
const files = changes.slice(0, maxFiles);
|
|
73
|
+
return {
|
|
74
|
+
workspace: repo.workspace,
|
|
75
|
+
repoRoot,
|
|
76
|
+
isGitRepo: true,
|
|
77
|
+
files,
|
|
78
|
+
totalInsertions: files.reduce((sum, file) => sum + file.insertions, 0),
|
|
79
|
+
totalDeletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
80
|
+
truncated: changes.length > files.length || outputBytes > maxBytes,
|
|
81
|
+
lastCheckedAt,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
47
85
|
const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
|
|
48
86
|
runGit(repo, ['diff', '--no-ext-diff', '--name-status'], { ...options, cwd: repoRoot }),
|
|
49
87
|
runGit(repo, ['diff', '--no-ext-diff', '--numstat'], { ...options, cwd: repoRoot }),
|
|
@@ -106,6 +144,21 @@ export async function getGitFileDiff(
|
|
|
106
144
|
const selected = await resolveRepoFilePath(repoRoot, filePath);
|
|
107
145
|
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
108
146
|
|
|
147
|
+
if (options.baseRef) {
|
|
148
|
+
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
149
|
+
const result = await runGit(repo, ['diff', '--no-ext-diff', range, '--', selected.relativePath], { ...options, cwd: repoRoot });
|
|
150
|
+
const bounded = truncateText(result.stdout, maxBytes);
|
|
151
|
+
return {
|
|
152
|
+
workspace: repo.workspace,
|
|
153
|
+
repoRoot,
|
|
154
|
+
isGitRepo: true,
|
|
155
|
+
path: selected.relativePath,
|
|
156
|
+
diff: bounded.text,
|
|
157
|
+
truncated: bounded.truncated,
|
|
158
|
+
lastCheckedAt,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
109
162
|
const [unstaged, staged] = await Promise.all([
|
|
110
163
|
runGit(repo, ['diff', '--no-ext-diff', '--', selected.relativePath], { ...options, cwd: repoRoot }),
|
|
111
164
|
runGit(repo, ['diff', '--cached', '--no-ext-diff', '--', selected.relativePath], { ...options, cwd: repoRoot }),
|
package/src/git/git-executor.ts
CHANGED
|
@@ -10,6 +10,18 @@ const execFileAsync = promisify(execFile);
|
|
|
10
10
|
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
11
11
|
const DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Timeout for status-collection git commands (status/log/submodule/stash/fetch).
|
|
15
|
+
* The default 5s is fine for porcelain status, but on Windows the `git` subprocess
|
|
16
|
+
* spawn itself is pathologically slow (measured: `submodule status` ~3.5s, cold
|
|
17
|
+
* `log -1` ~4.2s) and overlaps with refreshUpstream fetches — a single command
|
|
18
|
+
* routinely exceeds 5s, which previously collapsed the whole status to all-null and
|
|
19
|
+
* dropped the node from the mesh graph. Give the collection path a much larger
|
|
20
|
+
* budget so a slow-but-healthy repo never reads as "not a git repo". Windows gets a
|
|
21
|
+
* larger budget than POSIX because the spawn cost is OS-specific, not repo-specific.
|
|
22
|
+
*/
|
|
23
|
+
export const GIT_STATUS_TIMEOUT_MS = process.platform === 'win32' ? 30_000 : 20_000;
|
|
24
|
+
|
|
13
25
|
export interface GitExecutorOptions {
|
|
14
26
|
timeoutMs?: number;
|
|
15
27
|
maxBuffer?: number;
|