@draht/coding-agent 2026.3.14 → 2026.3.25
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/README.md +45 -30
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +7 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +4 -0
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +2 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session.d.ts +38 -5
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +201 -73
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +6 -7
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +8 -107
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +2 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +7 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +43 -13
- package/dist/core/export-html/template.html +1 -0
- package/dist/core/export-html/template.js +107 -0
- package/dist/core/export-html/tool-renderer.d.ts +2 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +41 -16
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +4 -3
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +16 -6
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -9
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +89 -71
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +49 -13
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +6 -86
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +13 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +155 -37
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +270 -50
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +222 -134
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +49 -23
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +41 -17
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +6 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +59 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +22 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +373 -53
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +2 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +39 -39
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +43 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +6 -7
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +141 -118
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +9 -10
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +5 -3
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +54 -9
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -3
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +17 -60
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +24 -6
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +210 -110
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -0
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +14 -2
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +95 -23
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +11 -4
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +82 -30
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +15 -4
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +83 -29
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +58 -19
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +51 -26
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +9 -3
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +67 -13
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +10 -3
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +110 -51
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +21 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +49 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +30 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/write.d.ts +9 -3
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +168 -30
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +105 -226
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +22 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +2 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +2 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +8 -8
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +6 -6
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +9 -9
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +5 -5
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +8 -8
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +3 -36
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +5 -44
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +6 -6
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +13 -9
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +6 -6
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +4 -4
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +32 -35
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +5 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +5 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +2 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +5 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +16 -34
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +128 -636
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +27 -16
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +6 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +2 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -11
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +353 -214
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +3 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +63 -37
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +5 -11
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +27 -17
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +3 -4
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +27 -16
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts +5 -5
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +51 -95
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +5 -4
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +6 -2
- package/docs/extensions.md +108 -21
- package/docs/keybindings.md +103 -112
- package/docs/models.md +39 -1
- package/docs/packages.md +9 -0
- package/docs/providers.md +7 -0
- package/docs/rpc.md +15 -6
- package/docs/sdk.md +2 -2
- package/docs/settings.md +9 -0
- package/docs/terminal-setup.md +11 -0
- package/docs/tui.md +2 -2
- package/examples/extensions/README.md +2 -2
- package/examples/extensions/antigravity-image-gen.ts +5 -3
- package/examples/extensions/built-in-tool-renderer.ts +8 -8
- package/examples/extensions/commands.ts +3 -3
- package/examples/extensions/minimal-mode.ts +14 -14
- package/examples/extensions/question.ts +2 -2
- package/examples/extensions/questionnaire.ts +2 -2
- package/examples/extensions/subagent/index.ts +30 -8
- package/examples/extensions/titlebar-spinner.ts +2 -2
- package/examples/extensions/todo.ts +2 -2
- package/examples/extensions/tool-override.ts +9 -7
- package/examples/extensions/truncated-tool.ts +8 -5
- package/examples/sdk/04-skills.ts +8 -2
- package/examples/sdk/08-prompt-templates.ts +8 -2
- package/examples/sdk/12-full-control.ts +0 -1
- package/examples/sdk/README.md +1 -1
- package/package.json +4 -4
|
@@ -7,7 +7,9 @@ import ignore from "ignore";
|
|
|
7
7
|
import { minimatch } from "minimatch";
|
|
8
8
|
import { getProjectConfigDir } from "../config.js";
|
|
9
9
|
import { parseGitUrl } from "../utils/git.js";
|
|
10
|
+
import { isStdoutTakenOver } from "./output-guard.js";
|
|
10
11
|
const NETWORK_TIMEOUT_MS = 10000;
|
|
12
|
+
const UPDATE_CHECK_CONCURRENCY = 4;
|
|
11
13
|
function isOfflineModeEnabled() {
|
|
12
14
|
const value = process.env.DRAHT_OFFLINE ?? process.env.PI_OFFLINE;
|
|
13
15
|
if (!value)
|
|
@@ -25,6 +27,9 @@ const IGNORE_FILE_NAMES = [".gitignore", ".ignore", ".fdignore"];
|
|
|
25
27
|
function toPosixPath(p) {
|
|
26
28
|
return p.split(sep).join("/");
|
|
27
29
|
}
|
|
30
|
+
function getHomeDir() {
|
|
31
|
+
return process.env.HOME || homedir();
|
|
32
|
+
}
|
|
28
33
|
function prefixIgnorePattern(line, prefix) {
|
|
29
34
|
const trimmed = line.trim();
|
|
30
35
|
if (!trimmed)
|
|
@@ -383,43 +388,50 @@ function collectResourceFiles(dir, resourceType) {
|
|
|
383
388
|
return collectFiles(dir, FILE_PATTERNS[resourceType]);
|
|
384
389
|
}
|
|
385
390
|
function matchesAnyPattern(filePath, patterns, baseDir) {
|
|
386
|
-
const rel = relative(baseDir, filePath);
|
|
391
|
+
const rel = toPosixPath(relative(baseDir, filePath));
|
|
387
392
|
const name = basename(filePath);
|
|
393
|
+
const filePathPosix = toPosixPath(filePath);
|
|
388
394
|
const isSkillFile = name === "SKILL.md";
|
|
389
395
|
const parentDir = isSkillFile ? dirname(filePath) : undefined;
|
|
390
|
-
const parentRel = isSkillFile ? relative(baseDir, parentDir) : undefined;
|
|
396
|
+
const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
|
|
391
397
|
const parentName = isSkillFile ? basename(parentDir) : undefined;
|
|
398
|
+
const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
|
|
392
399
|
return patterns.some((pattern) => {
|
|
393
|
-
|
|
400
|
+
const normalizedPattern = toPosixPath(pattern);
|
|
401
|
+
if (minimatch(rel, normalizedPattern) ||
|
|
402
|
+
minimatch(name, normalizedPattern) ||
|
|
403
|
+
minimatch(filePathPosix, normalizedPattern)) {
|
|
394
404
|
return true;
|
|
395
405
|
}
|
|
396
406
|
if (!isSkillFile)
|
|
397
407
|
return false;
|
|
398
|
-
return minimatch(parentRel,
|
|
408
|
+
return (minimatch(parentRel, normalizedPattern) ||
|
|
409
|
+
minimatch(parentName, normalizedPattern) ||
|
|
410
|
+
minimatch(parentDirPosix, normalizedPattern));
|
|
399
411
|
});
|
|
400
412
|
}
|
|
401
413
|
function normalizeExactPattern(pattern) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
return pattern;
|
|
414
|
+
const normalized = pattern.startsWith("./") || pattern.startsWith(".\\") ? pattern.slice(2) : pattern;
|
|
415
|
+
return toPosixPath(normalized);
|
|
406
416
|
}
|
|
407
417
|
function matchesAnyExactPattern(filePath, patterns, baseDir) {
|
|
408
418
|
if (patterns.length === 0)
|
|
409
419
|
return false;
|
|
410
|
-
const rel = relative(baseDir, filePath);
|
|
420
|
+
const rel = toPosixPath(relative(baseDir, filePath));
|
|
411
421
|
const name = basename(filePath);
|
|
422
|
+
const filePathPosix = toPosixPath(filePath);
|
|
412
423
|
const isSkillFile = name === "SKILL.md";
|
|
413
424
|
const parentDir = isSkillFile ? dirname(filePath) : undefined;
|
|
414
|
-
const parentRel = isSkillFile ? relative(baseDir, parentDir) : undefined;
|
|
425
|
+
const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
|
|
426
|
+
const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
|
|
415
427
|
return patterns.some((pattern) => {
|
|
416
428
|
const normalized = normalizeExactPattern(pattern);
|
|
417
|
-
if (normalized === rel || normalized ===
|
|
429
|
+
if (normalized === rel || normalized === filePathPosix) {
|
|
418
430
|
return true;
|
|
419
431
|
}
|
|
420
432
|
if (!isSkillFile)
|
|
421
433
|
return false;
|
|
422
|
-
return normalized === parentRel || normalized ===
|
|
434
|
+
return normalized === parentRel || normalized === parentDirPosix;
|
|
423
435
|
});
|
|
424
436
|
}
|
|
425
437
|
function getOverridePatterns(entries) {
|
|
@@ -500,6 +512,7 @@ export class DefaultPackageManager {
|
|
|
500
512
|
agentDir;
|
|
501
513
|
settingsManager;
|
|
502
514
|
globalNpmRoot;
|
|
515
|
+
globalNpmRootCommandKey;
|
|
503
516
|
progressCallback;
|
|
504
517
|
constructor(options) {
|
|
505
518
|
this.cwd = options.cwd;
|
|
@@ -662,18 +675,27 @@ export class DefaultPackageManager {
|
|
|
662
675
|
const globalSettings = this.settingsManager.getGlobalSettings();
|
|
663
676
|
const projectSettings = this.settingsManager.getProjectSettings();
|
|
664
677
|
const identity = source ? this.getPackageIdentity(source) : undefined;
|
|
678
|
+
let matched = false;
|
|
665
679
|
for (const pkg of globalSettings.packages ?? []) {
|
|
666
680
|
const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
|
|
667
681
|
if (identity && this.getPackageIdentity(sourceStr, "user") !== identity)
|
|
668
682
|
continue;
|
|
683
|
+
matched = true;
|
|
669
684
|
await this.updateSourceForScope(sourceStr, "user");
|
|
670
685
|
}
|
|
671
686
|
for (const pkg of projectSettings.packages ?? []) {
|
|
672
687
|
const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
|
|
673
688
|
if (identity && this.getPackageIdentity(sourceStr, "project") !== identity)
|
|
674
689
|
continue;
|
|
690
|
+
matched = true;
|
|
675
691
|
await this.updateSourceForScope(sourceStr, "project");
|
|
676
692
|
}
|
|
693
|
+
if (source && !matched) {
|
|
694
|
+
throw new Error(this.buildNoMatchingPackageMessage(source, [
|
|
695
|
+
...(globalSettings.packages ?? []),
|
|
696
|
+
...(projectSettings.packages ?? []),
|
|
697
|
+
]));
|
|
698
|
+
}
|
|
677
699
|
}
|
|
678
700
|
async updateSourceForScope(source, scope) {
|
|
679
701
|
if (isOfflineModeEnabled()) {
|
|
@@ -684,7 +706,10 @@ export class DefaultPackageManager {
|
|
|
684
706
|
if (parsed.pinned)
|
|
685
707
|
return;
|
|
686
708
|
await this.withProgress("update", source, `Updating ${source}...`, async () => {
|
|
687
|
-
await this.installNpm(
|
|
709
|
+
await this.installNpm({
|
|
710
|
+
...parsed,
|
|
711
|
+
spec: `${parsed.name}@latest`,
|
|
712
|
+
}, scope, false);
|
|
688
713
|
});
|
|
689
714
|
return;
|
|
690
715
|
}
|
|
@@ -697,6 +722,62 @@ export class DefaultPackageManager {
|
|
|
697
722
|
return;
|
|
698
723
|
}
|
|
699
724
|
}
|
|
725
|
+
async checkForAvailableUpdates() {
|
|
726
|
+
if (isOfflineModeEnabled()) {
|
|
727
|
+
return [];
|
|
728
|
+
}
|
|
729
|
+
const globalSettings = this.settingsManager.getGlobalSettings();
|
|
730
|
+
const projectSettings = this.settingsManager.getProjectSettings();
|
|
731
|
+
const allPackages = [];
|
|
732
|
+
for (const pkg of projectSettings.packages ?? []) {
|
|
733
|
+
allPackages.push({ pkg, scope: "project" });
|
|
734
|
+
}
|
|
735
|
+
for (const pkg of globalSettings.packages ?? []) {
|
|
736
|
+
allPackages.push({ pkg, scope: "user" });
|
|
737
|
+
}
|
|
738
|
+
const packageSources = this.dedupePackages(allPackages);
|
|
739
|
+
const checks = packageSources
|
|
740
|
+
.filter((entry) => entry.scope !== "temporary")
|
|
741
|
+
.map((entry) => async () => {
|
|
742
|
+
const source = typeof entry.pkg === "string" ? entry.pkg : entry.pkg.source;
|
|
743
|
+
const parsed = this.parseSource(source);
|
|
744
|
+
if (parsed.type === "local" || parsed.pinned) {
|
|
745
|
+
return undefined;
|
|
746
|
+
}
|
|
747
|
+
if (parsed.type === "npm") {
|
|
748
|
+
const installedPath = this.getNpmInstallPath(parsed, entry.scope);
|
|
749
|
+
if (!existsSync(installedPath)) {
|
|
750
|
+
return undefined;
|
|
751
|
+
}
|
|
752
|
+
const hasUpdate = await this.npmHasAvailableUpdate(parsed, installedPath);
|
|
753
|
+
if (!hasUpdate) {
|
|
754
|
+
return undefined;
|
|
755
|
+
}
|
|
756
|
+
return {
|
|
757
|
+
source,
|
|
758
|
+
displayName: parsed.name,
|
|
759
|
+
type: "npm",
|
|
760
|
+
scope: entry.scope,
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
const installedPath = this.getGitInstallPath(parsed, entry.scope);
|
|
764
|
+
if (!existsSync(installedPath)) {
|
|
765
|
+
return undefined;
|
|
766
|
+
}
|
|
767
|
+
const hasUpdate = await this.gitHasAvailableUpdate(installedPath);
|
|
768
|
+
if (!hasUpdate) {
|
|
769
|
+
return undefined;
|
|
770
|
+
}
|
|
771
|
+
return {
|
|
772
|
+
source,
|
|
773
|
+
displayName: `${parsed.host}/${parsed.path}`,
|
|
774
|
+
type: "git",
|
|
775
|
+
scope: entry.scope,
|
|
776
|
+
};
|
|
777
|
+
});
|
|
778
|
+
const results = await this.runWithConcurrency(checks, UPDATE_CHECK_CONCURRENCY);
|
|
779
|
+
return results.filter((result) => result !== undefined);
|
|
780
|
+
}
|
|
700
781
|
async resolvePackageSources(sources, accumulator, onMissing) {
|
|
701
782
|
for (const { pkg, scope } of sources) {
|
|
702
783
|
const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
|
|
@@ -726,7 +807,8 @@ export class DefaultPackageManager {
|
|
|
726
807
|
};
|
|
727
808
|
if (parsed.type === "npm") {
|
|
728
809
|
const installedPath = this.getNpmInstallPath(parsed, scope);
|
|
729
|
-
const needsInstall = !existsSync(installedPath) ||
|
|
810
|
+
const needsInstall = !existsSync(installedPath) ||
|
|
811
|
+
(parsed.pinned && !(await this.installedNpmMatchesPinnedVersion(parsed, installedPath)));
|
|
730
812
|
if (needsInstall) {
|
|
731
813
|
const installed = await installMissing();
|
|
732
814
|
if (!installed)
|
|
@@ -809,6 +891,35 @@ export class DefaultPackageManager {
|
|
|
809
891
|
const baseDir = this.getBaseDirForScope(scope);
|
|
810
892
|
return `local:${this.resolvePathFromBase(parsed.path, baseDir)}`;
|
|
811
893
|
}
|
|
894
|
+
buildNoMatchingPackageMessage(source, configuredPackages) {
|
|
895
|
+
const suggestion = this.findSuggestedConfiguredSource(source, configuredPackages);
|
|
896
|
+
if (!suggestion) {
|
|
897
|
+
return `No matching package found for ${source}`;
|
|
898
|
+
}
|
|
899
|
+
return `No matching package found for ${source}. Did you mean ${suggestion}?`;
|
|
900
|
+
}
|
|
901
|
+
findSuggestedConfiguredSource(source, configuredPackages) {
|
|
902
|
+
const trimmedSource = source.trim();
|
|
903
|
+
const suggestions = new Set();
|
|
904
|
+
for (const pkg of configuredPackages) {
|
|
905
|
+
const sourceStr = this.getPackageSourceString(pkg);
|
|
906
|
+
const parsed = this.parseSource(sourceStr);
|
|
907
|
+
if (parsed.type === "npm") {
|
|
908
|
+
if (trimmedSource === parsed.name || trimmedSource === parsed.spec) {
|
|
909
|
+
suggestions.add(sourceStr);
|
|
910
|
+
}
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
if (parsed.type === "git") {
|
|
914
|
+
const shorthand = `${parsed.host}/${parsed.path}`;
|
|
915
|
+
const shorthandWithRef = parsed.ref ? `${shorthand}@${parsed.ref}` : undefined;
|
|
916
|
+
if (trimmedSource === shorthand || (shorthandWithRef && trimmedSource === shorthandWithRef)) {
|
|
917
|
+
suggestions.add(sourceStr);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return suggestions.values().next().value;
|
|
922
|
+
}
|
|
812
923
|
packageSourcesMatch(existing, inputSource, scope) {
|
|
813
924
|
const left = this.getSourceMatchKeyForSettings(this.getPackageSourceString(existing), scope);
|
|
814
925
|
const right = this.getSourceMatchKeyForInput(inputSource);
|
|
@@ -852,30 +963,30 @@ export class DefaultPackageManager {
|
|
|
852
963
|
}
|
|
853
964
|
return { type: "local", path: source };
|
|
854
965
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
966
|
+
async installedNpmMatchesPinnedVersion(source, installedPath) {
|
|
967
|
+
const installedVersion = this.getInstalledNpmVersion(installedPath);
|
|
968
|
+
if (!installedVersion) {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
const { version: pinnedVersion } = this.parseNpmSpec(source.spec);
|
|
972
|
+
if (!pinnedVersion) {
|
|
973
|
+
return true;
|
|
974
|
+
}
|
|
975
|
+
return installedVersion === pinnedVersion;
|
|
976
|
+
}
|
|
977
|
+
async npmHasAvailableUpdate(source, installedPath) {
|
|
861
978
|
if (isOfflineModeEnabled()) {
|
|
862
979
|
return false;
|
|
863
980
|
}
|
|
864
981
|
const installedVersion = this.getInstalledNpmVersion(installedPath);
|
|
865
|
-
if (!installedVersion)
|
|
866
|
-
return
|
|
867
|
-
const { version: pinnedVersion } = this.parseNpmSpec(source.spec);
|
|
868
|
-
if (pinnedVersion) {
|
|
869
|
-
// Pinned: check if installed matches pinned (exact match for now)
|
|
870
|
-
return installedVersion !== pinnedVersion;
|
|
982
|
+
if (!installedVersion) {
|
|
983
|
+
return false;
|
|
871
984
|
}
|
|
872
|
-
// Unpinned: check registry for latest version
|
|
873
985
|
try {
|
|
874
986
|
const latestVersion = await this.getLatestNpmVersion(source.name);
|
|
875
987
|
return latestVersion !== installedVersion;
|
|
876
988
|
}
|
|
877
989
|
catch {
|
|
878
|
-
// If we can't check registry, assume it's fine
|
|
879
990
|
return false;
|
|
880
991
|
}
|
|
881
992
|
}
|
|
@@ -901,6 +1012,145 @@ export class DefaultPackageManager {
|
|
|
901
1012
|
const data = (await response.json());
|
|
902
1013
|
return data.version;
|
|
903
1014
|
}
|
|
1015
|
+
async gitHasAvailableUpdate(installedPath) {
|
|
1016
|
+
if (isOfflineModeEnabled()) {
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
1019
|
+
try {
|
|
1020
|
+
const localHead = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
|
|
1021
|
+
cwd: installedPath,
|
|
1022
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1023
|
+
});
|
|
1024
|
+
const remoteHead = await this.getRemoteGitHead(installedPath);
|
|
1025
|
+
return localHead.trim() !== remoteHead.trim();
|
|
1026
|
+
}
|
|
1027
|
+
catch {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
async getRemoteGitHead(installedPath) {
|
|
1032
|
+
const upstreamRef = await this.getGitUpstreamRef(installedPath);
|
|
1033
|
+
if (upstreamRef) {
|
|
1034
|
+
const remoteHead = await this.runGitRemoteCommand(installedPath, ["ls-remote", "origin", upstreamRef]);
|
|
1035
|
+
const match = remoteHead.match(/^([0-9a-f]{40})\s+/m);
|
|
1036
|
+
if (match?.[1]) {
|
|
1037
|
+
return match[1];
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
const remoteHead = await this.runGitRemoteCommand(installedPath, ["ls-remote", "origin", "HEAD"]);
|
|
1041
|
+
const match = remoteHead.match(/^([0-9a-f]{40})\s+HEAD$/m);
|
|
1042
|
+
if (!match?.[1]) {
|
|
1043
|
+
throw new Error("Failed to determine remote HEAD");
|
|
1044
|
+
}
|
|
1045
|
+
return match[1];
|
|
1046
|
+
}
|
|
1047
|
+
async getLocalGitUpdateTarget(installedPath) {
|
|
1048
|
+
try {
|
|
1049
|
+
const upstream = await this.runCommandCapture("git", ["rev-parse", "--abbrev-ref", "@{upstream}"], {
|
|
1050
|
+
cwd: installedPath,
|
|
1051
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1052
|
+
});
|
|
1053
|
+
const trimmedUpstream = upstream.trim();
|
|
1054
|
+
if (!trimmedUpstream.startsWith("origin/")) {
|
|
1055
|
+
throw new Error(`Unsupported upstream remote: ${trimmedUpstream}`);
|
|
1056
|
+
}
|
|
1057
|
+
const branch = trimmedUpstream.slice("origin/".length);
|
|
1058
|
+
if (!branch) {
|
|
1059
|
+
throw new Error("Missing upstream branch name");
|
|
1060
|
+
}
|
|
1061
|
+
const head = await this.runCommandCapture("git", ["rev-parse", "@{upstream}"], {
|
|
1062
|
+
cwd: installedPath,
|
|
1063
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1064
|
+
});
|
|
1065
|
+
return {
|
|
1066
|
+
ref: "@{upstream}",
|
|
1067
|
+
head,
|
|
1068
|
+
fetchArgs: [
|
|
1069
|
+
"fetch",
|
|
1070
|
+
"--prune",
|
|
1071
|
+
"--no-tags",
|
|
1072
|
+
"origin",
|
|
1073
|
+
`+refs/heads/${branch}:refs/remotes/origin/${branch}`,
|
|
1074
|
+
],
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
catch {
|
|
1078
|
+
await this.runCommand("git", ["remote", "set-head", "origin", "-a"], { cwd: installedPath }).catch(() => { });
|
|
1079
|
+
const head = await this.runCommandCapture("git", ["rev-parse", "origin/HEAD"], {
|
|
1080
|
+
cwd: installedPath,
|
|
1081
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1082
|
+
});
|
|
1083
|
+
const originHeadRef = await this.runCommandCapture("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
|
|
1084
|
+
cwd: installedPath,
|
|
1085
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1086
|
+
}).catch(() => "");
|
|
1087
|
+
const branch = originHeadRef.trim().replace(/^refs\/remotes\/origin\//, "");
|
|
1088
|
+
if (branch) {
|
|
1089
|
+
return {
|
|
1090
|
+
ref: "origin/HEAD",
|
|
1091
|
+
head,
|
|
1092
|
+
fetchArgs: [
|
|
1093
|
+
"fetch",
|
|
1094
|
+
"--prune",
|
|
1095
|
+
"--no-tags",
|
|
1096
|
+
"origin",
|
|
1097
|
+
`+refs/heads/${branch}:refs/remotes/origin/${branch}`,
|
|
1098
|
+
],
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
return {
|
|
1102
|
+
ref: "origin/HEAD",
|
|
1103
|
+
head,
|
|
1104
|
+
fetchArgs: ["fetch", "--prune", "--no-tags", "origin", "+HEAD:refs/remotes/origin/HEAD"],
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
async getGitUpstreamRef(installedPath) {
|
|
1109
|
+
try {
|
|
1110
|
+
const upstream = await this.runCommandCapture("git", ["rev-parse", "--abbrev-ref", "@{upstream}"], {
|
|
1111
|
+
cwd: installedPath,
|
|
1112
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1113
|
+
});
|
|
1114
|
+
const trimmed = upstream.trim();
|
|
1115
|
+
if (!trimmed.startsWith("origin/")) {
|
|
1116
|
+
return undefined;
|
|
1117
|
+
}
|
|
1118
|
+
const branch = trimmed.slice("origin/".length);
|
|
1119
|
+
return branch ? `refs/heads/${branch}` : undefined;
|
|
1120
|
+
}
|
|
1121
|
+
catch {
|
|
1122
|
+
return undefined;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
runGitRemoteCommand(installedPath, args) {
|
|
1126
|
+
return this.runCommandCapture("git", args, {
|
|
1127
|
+
cwd: installedPath,
|
|
1128
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1129
|
+
env: {
|
|
1130
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
1131
|
+
},
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
async runWithConcurrency(tasks, limit) {
|
|
1135
|
+
if (tasks.length === 0) {
|
|
1136
|
+
return [];
|
|
1137
|
+
}
|
|
1138
|
+
const results = new Array(tasks.length);
|
|
1139
|
+
let nextIndex = 0;
|
|
1140
|
+
const workerCount = Math.max(1, Math.min(limit, tasks.length));
|
|
1141
|
+
const worker = async () => {
|
|
1142
|
+
while (true) {
|
|
1143
|
+
const index = nextIndex;
|
|
1144
|
+
nextIndex += 1;
|
|
1145
|
+
if (index >= tasks.length) {
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
results[index] = await tasks[index]();
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
1152
|
+
return results;
|
|
1153
|
+
}
|
|
904
1154
|
/**
|
|
905
1155
|
* Get a unique identity for a package, ignoring version/ref.
|
|
906
1156
|
* Used to detect when the same package is in both global and project settings.
|
|
@@ -953,25 +1203,44 @@ export class DefaultPackageManager {
|
|
|
953
1203
|
const version = match[2];
|
|
954
1204
|
return { name, version };
|
|
955
1205
|
}
|
|
1206
|
+
getNpmCommand() {
|
|
1207
|
+
const configuredCommand = this.settingsManager.getNpmCommand();
|
|
1208
|
+
if (!configuredCommand || configuredCommand.length === 0) {
|
|
1209
|
+
return { command: "npm", args: [] };
|
|
1210
|
+
}
|
|
1211
|
+
const [command, ...args] = configuredCommand;
|
|
1212
|
+
if (!command) {
|
|
1213
|
+
throw new Error("Invalid npmCommand: first array entry must be a non-empty command");
|
|
1214
|
+
}
|
|
1215
|
+
return { command, args };
|
|
1216
|
+
}
|
|
1217
|
+
async runNpmCommand(args, options) {
|
|
1218
|
+
const npmCommand = this.getNpmCommand();
|
|
1219
|
+
await this.runCommand(npmCommand.command, [...npmCommand.args, ...args], options);
|
|
1220
|
+
}
|
|
1221
|
+
runNpmCommandSync(args) {
|
|
1222
|
+
const npmCommand = this.getNpmCommand();
|
|
1223
|
+
return this.runCommandSync(npmCommand.command, [...npmCommand.args, ...args]);
|
|
1224
|
+
}
|
|
956
1225
|
async installNpm(source, scope, temporary) {
|
|
957
1226
|
if (scope === "user" && !temporary) {
|
|
958
|
-
await this.
|
|
1227
|
+
await this.runNpmCommand(["install", "-g", source.spec]);
|
|
959
1228
|
return;
|
|
960
1229
|
}
|
|
961
1230
|
const installRoot = this.getNpmInstallRoot(scope, temporary);
|
|
962
1231
|
this.ensureNpmProject(installRoot);
|
|
963
|
-
await this.
|
|
1232
|
+
await this.runNpmCommand(["install", source.spec, "--prefix", installRoot]);
|
|
964
1233
|
}
|
|
965
1234
|
async uninstallNpm(source, scope) {
|
|
966
1235
|
if (scope === "user") {
|
|
967
|
-
await this.
|
|
1236
|
+
await this.runNpmCommand(["uninstall", "-g", source.name]);
|
|
968
1237
|
return;
|
|
969
1238
|
}
|
|
970
1239
|
const installRoot = this.getNpmInstallRoot(scope, false);
|
|
971
1240
|
if (!existsSync(installRoot)) {
|
|
972
1241
|
return;
|
|
973
1242
|
}
|
|
974
|
-
await this.
|
|
1243
|
+
await this.runNpmCommand(["uninstall", source.name, "--prefix", installRoot]);
|
|
975
1244
|
}
|
|
976
1245
|
async installGit(source, scope) {
|
|
977
1246
|
const targetDir = this.getGitInstallPath(source, scope);
|
|
@@ -989,7 +1258,7 @@ export class DefaultPackageManager {
|
|
|
989
1258
|
}
|
|
990
1259
|
const packageJsonPath = join(targetDir, "package.json");
|
|
991
1260
|
if (existsSync(packageJsonPath)) {
|
|
992
|
-
await this.
|
|
1261
|
+
await this.runNpmCommand(["install"], { cwd: targetDir });
|
|
993
1262
|
}
|
|
994
1263
|
}
|
|
995
1264
|
async updateGit(source, scope) {
|
|
@@ -998,21 +1267,26 @@ export class DefaultPackageManager {
|
|
|
998
1267
|
await this.installGit(source, scope);
|
|
999
1268
|
return;
|
|
1000
1269
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1270
|
+
const target = await this.getLocalGitUpdateTarget(targetDir);
|
|
1271
|
+
// Fetch only the ref we will reset to, avoiding unrelated branch/tag noise.
|
|
1272
|
+
await this.runCommand("git", target.fetchArgs, { cwd: targetDir });
|
|
1273
|
+
const localHead = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
|
|
1274
|
+
cwd: targetDir,
|
|
1275
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1276
|
+
});
|
|
1277
|
+
const refreshedTargetHead = await this.runCommandCapture("git", ["rev-parse", target.ref], {
|
|
1278
|
+
cwd: targetDir,
|
|
1279
|
+
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1280
|
+
});
|
|
1281
|
+
if (localHead.trim() === refreshedTargetHead.trim()) {
|
|
1282
|
+
return;
|
|
1010
1283
|
}
|
|
1284
|
+
await this.runCommand("git", ["reset", "--hard", target.ref], { cwd: targetDir });
|
|
1011
1285
|
// Clean untracked files (extensions should be pristine)
|
|
1012
1286
|
await this.runCommand("git", ["clean", "-fdx"], { cwd: targetDir });
|
|
1013
1287
|
const packageJsonPath = join(targetDir, "package.json");
|
|
1014
1288
|
if (existsSync(packageJsonPath)) {
|
|
1015
|
-
await this.
|
|
1289
|
+
await this.runNpmCommand(["install"], { cwd: targetDir });
|
|
1016
1290
|
}
|
|
1017
1291
|
}
|
|
1018
1292
|
async refreshTemporaryGitSource(source, sourceStr) {
|
|
@@ -1088,11 +1362,14 @@ export class DefaultPackageManager {
|
|
|
1088
1362
|
return join(this.getGlobalNpmRoot(), "..");
|
|
1089
1363
|
}
|
|
1090
1364
|
getGlobalNpmRoot() {
|
|
1091
|
-
|
|
1365
|
+
const npmCommand = this.getNpmCommand();
|
|
1366
|
+
const commandKey = [npmCommand.command, ...npmCommand.args].join("\0");
|
|
1367
|
+
if (this.globalNpmRoot && this.globalNpmRootCommandKey === commandKey) {
|
|
1092
1368
|
return this.globalNpmRoot;
|
|
1093
1369
|
}
|
|
1094
|
-
const result = this.
|
|
1370
|
+
const result = this.runNpmCommandSync(["root", "-g"]);
|
|
1095
1371
|
this.globalNpmRoot = result.trim();
|
|
1372
|
+
this.globalNpmRootCommandKey = commandKey;
|
|
1096
1373
|
return this.globalNpmRoot;
|
|
1097
1374
|
}
|
|
1098
1375
|
getNpmInstallPath(source, scope) {
|
|
@@ -1141,21 +1418,21 @@ export class DefaultPackageManager {
|
|
|
1141
1418
|
resolvePath(input) {
|
|
1142
1419
|
const trimmed = input.trim();
|
|
1143
1420
|
if (trimmed === "~")
|
|
1144
|
-
return
|
|
1421
|
+
return getHomeDir();
|
|
1145
1422
|
if (trimmed.startsWith("~/"))
|
|
1146
|
-
return join(
|
|
1423
|
+
return join(getHomeDir(), trimmed.slice(2));
|
|
1147
1424
|
if (trimmed.startsWith("~"))
|
|
1148
|
-
return join(
|
|
1425
|
+
return join(getHomeDir(), trimmed.slice(1));
|
|
1149
1426
|
return resolve(this.cwd, trimmed);
|
|
1150
1427
|
}
|
|
1151
1428
|
resolvePathFromBase(input, baseDir) {
|
|
1152
1429
|
const trimmed = input.trim();
|
|
1153
1430
|
if (trimmed === "~")
|
|
1154
|
-
return
|
|
1431
|
+
return getHomeDir();
|
|
1155
1432
|
if (trimmed.startsWith("~/"))
|
|
1156
|
-
return join(
|
|
1433
|
+
return join(getHomeDir(), trimmed.slice(2));
|
|
1157
1434
|
if (trimmed.startsWith("~"))
|
|
1158
|
-
return join(
|
|
1435
|
+
return join(getHomeDir(), trimmed.slice(1));
|
|
1159
1436
|
return resolve(baseDir, trimmed);
|
|
1160
1437
|
}
|
|
1161
1438
|
collectPackageResources(packageRoot, accumulator, filter, metadata) {
|
|
@@ -1329,7 +1606,7 @@ export class DefaultPackageManager {
|
|
|
1329
1606
|
prompts: join(projectBaseDir, "prompts"),
|
|
1330
1607
|
themes: join(projectBaseDir, "themes"),
|
|
1331
1608
|
};
|
|
1332
|
-
const userAgentsSkillsDir = join(
|
|
1609
|
+
const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
|
|
1333
1610
|
const projectAgentsSkillDirs = collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir));
|
|
1334
1611
|
const addResources = (resourceType, paths, metadata, overrides, baseDir) => {
|
|
1335
1612
|
const target = this.getTargetMap(accumulator, resourceType);
|
|
@@ -1414,11 +1691,54 @@ export class DefaultPackageManager {
|
|
|
1414
1691
|
themes: toResolved(accumulator.themes),
|
|
1415
1692
|
};
|
|
1416
1693
|
}
|
|
1694
|
+
runCommandCapture(command, args, options) {
|
|
1695
|
+
return new Promise((resolvePromise, reject) => {
|
|
1696
|
+
const child = spawn(command, args, {
|
|
1697
|
+
cwd: options?.cwd,
|
|
1698
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1699
|
+
shell: process.platform === "win32",
|
|
1700
|
+
env: options?.env ? { ...process.env, ...options.env } : process.env,
|
|
1701
|
+
});
|
|
1702
|
+
let stdout = "";
|
|
1703
|
+
let stderr = "";
|
|
1704
|
+
let timedOut = false;
|
|
1705
|
+
const timeout = typeof options?.timeoutMs === "number"
|
|
1706
|
+
? setTimeout(() => {
|
|
1707
|
+
timedOut = true;
|
|
1708
|
+
child.kill();
|
|
1709
|
+
}, options.timeoutMs)
|
|
1710
|
+
: undefined;
|
|
1711
|
+
child.stdout?.on("data", (data) => {
|
|
1712
|
+
stdout += data.toString();
|
|
1713
|
+
});
|
|
1714
|
+
child.stderr?.on("data", (data) => {
|
|
1715
|
+
stderr += data.toString();
|
|
1716
|
+
});
|
|
1717
|
+
child.on("error", (error) => {
|
|
1718
|
+
if (timeout)
|
|
1719
|
+
clearTimeout(timeout);
|
|
1720
|
+
reject(error);
|
|
1721
|
+
});
|
|
1722
|
+
child.on("exit", (code) => {
|
|
1723
|
+
if (timeout)
|
|
1724
|
+
clearTimeout(timeout);
|
|
1725
|
+
if (timedOut) {
|
|
1726
|
+
reject(new Error(`${command} ${args.join(" ")} timed out after ${options?.timeoutMs}ms`));
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
if (code === 0) {
|
|
1730
|
+
resolvePromise(stdout.trim());
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
reject(new Error(`${command} ${args.join(" ")} failed with code ${code}: ${stderr || stdout}`));
|
|
1734
|
+
});
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1417
1737
|
runCommand(command, args, options) {
|
|
1418
1738
|
return new Promise((resolvePromise, reject) => {
|
|
1419
1739
|
const child = spawn(command, args, {
|
|
1420
1740
|
cwd: options?.cwd,
|
|
1421
|
-
stdio: "inherit",
|
|
1741
|
+
stdio: isStdoutTakenOver() ? ["ignore", 2, 2] : "inherit",
|
|
1422
1742
|
shell: process.platform === "win32",
|
|
1423
1743
|
});
|
|
1424
1744
|
child.on("error", reject);
|