@psnext/slingcli 2.4.20260525-4 → 2.4.20260527-2
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/bin/sling.js +4 -1
- package/node_modules/@aws-sdk/core/package.json +2 -2
- package/node_modules/@aws-sdk/credential-provider-env/package.json +2 -2
- package/node_modules/@aws-sdk/credential-provider-http/dist-cjs/fromHttp/fromHttp.js +12 -6
- package/node_modules/@aws-sdk/credential-provider-http/dist-es/fromHttp/fromHttp.js +12 -6
- package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -2
- package/node_modules/@aws-sdk/credential-provider-ini/package.json +9 -9
- package/node_modules/@aws-sdk/credential-provider-login/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-node/package.json +7 -7
- package/node_modules/@aws-sdk/credential-provider-process/package.json +2 -2
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-sso/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +3 -3
- package/node_modules/@aws-sdk/middleware-websocket/package.json +2 -2
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/package.json +3 -3
- package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +1 -2
- package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +18 -24
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/cli.js +14 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +78 -63
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +8 -22
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +60 -40
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +55 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +45 -69
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +5 -2
- package/node_modules/@earendil-works/pi-ai/package.json +4 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js +2 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +18 -12
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-runtime.js +2 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +3 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +8 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js +2 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +18 -24
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/export-html/index.js +8 -6
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/export-html/template.js +6 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js +12 -29
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js +52 -22
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +63 -36
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js +6 -20
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js +38 -31
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +9 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +32 -24
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +6 -13
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js +8 -22
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +54 -53
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit-diff.js +8 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +44 -81
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js +27 -12
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +2 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -5
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js +9 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js +39 -21
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +9 -8
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/truncate.js +12 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +20 -35
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +5 -6
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +29 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +37 -28
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +64 -7
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +15 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js +14 -8
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js +124 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js +31 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js +75 -115
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/paths.js +33 -7
- package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +13 -26
- package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +40 -55
- package/node_modules/@earendil-works/pi-tui/dist/components/input.js +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +12 -2
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +53 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +4 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +38 -16
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +19 -12
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/node_modules/@earendil-works/pi-tui/package.json +3 -5
- package/node_modules/@smithy/node-http-handler/package.json +2 -2
- package/node_modules/undici/lib/api/api-request.js +1 -1
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +3 -3
- package/node_modules/undici/lib/core/connect.js +16 -0
- package/node_modules/undici/lib/core/request.js +17 -2
- package/node_modules/undici/lib/core/socks5-client.js +10 -5
- package/node_modules/undici/lib/core/socks5-utils.js +17 -22
- package/node_modules/undici/lib/dispatcher/client-h1.js +64 -20
- package/node_modules/undici/lib/dispatcher/client.js +6 -2
- package/node_modules/undici/lib/dispatcher/h2c-client.js +1 -1
- package/node_modules/undici/lib/mock/mock-call-history.js +15 -15
- package/node_modules/undici/lib/util/cache.js +8 -7
- package/node_modules/undici/lib/web/fetch/formdata-parser.js +17 -6
- package/node_modules/undici/lib/web/fetch/index.js +5 -2
- package/node_modules/undici/lib/web/webidl/index.js +5 -5
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +1 -7
- package/node_modules/undici/package.json +1 -1
- package/package.json +6 -6
- package/slingshot/index.js +269 -266
- package/node_modules/koffi/CHANGELOG.md +0 -1093
- package/node_modules/koffi/LICENSE.txt +0 -22
- package/node_modules/koffi/README.md +0 -43
- package/node_modules/koffi/build/koffi/darwin_arm64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/darwin_x64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/freebsd_x64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_arm64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_armhf/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_ia32/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_loong64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/linux_x64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/musl_arm64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/musl_x64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/openbsd_x64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/win32_arm64/koffi.exp +0 -0
- package/node_modules/koffi/build/koffi/win32_arm64/koffi.lib +0 -0
- package/node_modules/koffi/build/koffi/win32_arm64/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/win32_ia32/koffi.exp +0 -0
- package/node_modules/koffi/build/koffi/win32_ia32/koffi.lib +0 -0
- package/node_modules/koffi/build/koffi/win32_ia32/koffi.node +0 -0
- package/node_modules/koffi/build/koffi/win32_x64/koffi.exp +0 -0
- package/node_modules/koffi/build/koffi/win32_x64/koffi.lib +0 -0
- package/node_modules/koffi/build/koffi/win32_x64/koffi.node +0 -0
- package/node_modules/koffi/doc/benchmarks.md +0 -126
- package/node_modules/koffi/doc/callbacks.md +0 -210
- package/node_modules/koffi/doc/contribute.md +0 -148
- package/node_modules/koffi/doc/functions.md +0 -250
- package/node_modules/koffi/doc/index.md +0 -61
- package/node_modules/koffi/doc/input.md +0 -471
- package/node_modules/koffi/doc/migration.md +0 -159
- package/node_modules/koffi/doc/misc.md +0 -180
- package/node_modules/koffi/doc/output.md +0 -305
- package/node_modules/koffi/doc/packaging.md +0 -88
- package/node_modules/koffi/doc/platforms.md +0 -36
- package/node_modules/koffi/doc/pointers.md +0 -328
- package/node_modules/koffi/doc/start.md +0 -118
- package/node_modules/koffi/doc/unions.md +0 -186
- package/node_modules/koffi/doc/variables.md +0 -102
- package/node_modules/koffi/index.d.ts +0 -288
- package/node_modules/koffi/index.js +0 -634
- package/node_modules/koffi/indirect.js +0 -533
- package/node_modules/koffi/lib/native/base/base.cc +0 -11015
- package/node_modules/koffi/lib/native/base/base.hh +0 -6003
- package/node_modules/koffi/lib/native/base/crc.inc +0 -2214
- package/node_modules/koffi/lib/native/base/crc_gen.py +0 -72
- package/node_modules/koffi/lib/native/base/mimetypes.inc +0 -1248
- package/node_modules/koffi/lib/native/base/mimetypes_gen.py +0 -58
- package/node_modules/koffi/lib/native/base/tower.cc +0 -821
- package/node_modules/koffi/lib/native/base/tower.hh +0 -81
- package/node_modules/koffi/lib/native/base/unicode.inc +0 -408
- package/node_modules/koffi/lib/native/base/unicode_gen.py +0 -152
- package/node_modules/koffi/package.json +0 -38
- package/node_modules/koffi/src/cnoke/LICENSE.txt +0 -22
- package/node_modules/koffi/src/cnoke/README.md +0 -99
- package/node_modules/koffi/src/cnoke/assets/FindCNoke.cmake +0 -127
- package/node_modules/koffi/src/cnoke/assets/toolchains.json +0 -126
- package/node_modules/koffi/src/cnoke/assets/win_delay_hook.c +0 -36
- package/node_modules/koffi/src/cnoke/cnoke.js +0 -170
- package/node_modules/koffi/src/cnoke/package.json +0 -24
- package/node_modules/koffi/src/cnoke/src/builder.js +0 -511
- package/node_modules/koffi/src/cnoke/src/index.js +0 -10
- package/node_modules/koffi/src/cnoke/src/tools.js +0 -407
- package/node_modules/koffi/src/koffi/CMakeLists.txt +0 -182
- package/node_modules/koffi/src/koffi/src/abi_arm32.cc +0 -1018
- package/node_modules/koffi/src/koffi/src/abi_arm32_asm.S +0 -169
- package/node_modules/koffi/src/koffi/src/abi_arm64.cc +0 -1295
- package/node_modules/koffi/src/koffi/src/abi_arm64_asm.S +0 -195
- package/node_modules/koffi/src/koffi/src/abi_arm64_asm.asm +0 -174
- package/node_modules/koffi/src/koffi/src/abi_loong64.cc +0 -5
- package/node_modules/koffi/src/koffi/src/abi_loong64_asm.S +0 -204
- package/node_modules/koffi/src/koffi/src/abi_riscv64.cc +0 -915
- package/node_modules/koffi/src/koffi/src/abi_riscv64_asm.S +0 -203
- package/node_modules/koffi/src/koffi/src/abi_x64_sysv.cc +0 -939
- package/node_modules/koffi/src/koffi/src/abi_x64_sysv_asm.S +0 -231
- package/node_modules/koffi/src/koffi/src/abi_x64_win.cc +0 -715
- package/node_modules/koffi/src/koffi/src/abi_x64_win_asm.S +0 -166
- package/node_modules/koffi/src/koffi/src/abi_x64_win_asm.asm +0 -192
- package/node_modules/koffi/src/koffi/src/abi_x86.cc +0 -860
- package/node_modules/koffi/src/koffi/src/abi_x86_asm.S +0 -193
- package/node_modules/koffi/src/koffi/src/abi_x86_asm.asm +0 -177
- package/node_modules/koffi/src/koffi/src/call.cc +0 -1326
- package/node_modules/koffi/src/koffi/src/call.hh +0 -179
- package/node_modules/koffi/src/koffi/src/errno.inc +0 -462
- package/node_modules/koffi/src/koffi/src/ffi.cc +0 -2702
- package/node_modules/koffi/src/koffi/src/ffi.hh +0 -354
- package/node_modules/koffi/src/koffi/src/init.js +0 -105
- package/node_modules/koffi/src/koffi/src/parser.cc +0 -220
- package/node_modules/koffi/src/koffi/src/parser.hh +0 -54
- package/node_modules/koffi/src/koffi/src/util.cc +0 -1807
- package/node_modules/koffi/src/koffi/src/util.hh +0 -221
- package/node_modules/koffi/src/koffi/src/uv.cc +0 -193
- package/node_modules/koffi/src/koffi/src/uv.def +0 -10
- package/node_modules/koffi/src/koffi/src/uv.hh +0 -40
- package/node_modules/koffi/src/koffi/src/win32.cc +0 -198
- package/node_modules/koffi/src/koffi/src/win32.hh +0 -119
- package/node_modules/koffi/src/koffi/tools/write_trampolines.js +0 -77
- package/node_modules/koffi/vendor/node-addon-api/LICENSE.md +0 -9
- package/node_modules/koffi/vendor/node-addon-api/README.md +0 -95
- package/node_modules/koffi/vendor/node-addon-api/napi-inl.deprecated.h +0 -186
- package/node_modules/koffi/vendor/node-addon-api/napi-inl.h +0 -7033
- package/node_modules/koffi/vendor/node-addon-api/napi.h +0 -3309
- package/node_modules/koffi/vendor/node-api-headers/LICENSE +0 -21
- package/node_modules/koffi/vendor/node-api-headers/README.md +0 -95
- package/node_modules/koffi/vendor/node-api-headers/def/js_native_api.def +0 -125
- package/node_modules/koffi/vendor/node-api-headers/def/node_api.def +0 -157
- package/node_modules/koffi/vendor/node-api-headers/include/js_native_api.h +0 -591
- package/node_modules/koffi/vendor/node-api-headers/include/js_native_api_types.h +0 -210
- package/node_modules/koffi/vendor/node-api-headers/include/node_api.h +0 -265
- package/node_modules/koffi/vendor/node-api-headers/include/node_api_types.h +0 -58
- package/node_modules/koffi/vendor/node-api-headers/include/uv/aix.h +0 -32
- package/node_modules/koffi/vendor/node-api-headers/include/uv/bsd.h +0 -34
- package/node_modules/koffi/vendor/node-api-headers/include/uv/darwin.h +0 -61
- package/node_modules/koffi/vendor/node-api-headers/include/uv/errno.h +0 -483
- package/node_modules/koffi/vendor/node-api-headers/include/uv/linux.h +0 -34
- package/node_modules/koffi/vendor/node-api-headers/include/uv/os390.h +0 -33
- package/node_modules/koffi/vendor/node-api-headers/include/uv/posix.h +0 -31
- package/node_modules/koffi/vendor/node-api-headers/include/uv/sunos.h +0 -44
- package/node_modules/koffi/vendor/node-api-headers/include/uv/threadpool.h +0 -37
- package/node_modules/koffi/vendor/node-api-headers/include/uv/tree.h +0 -521
- package/node_modules/koffi/vendor/node-api-headers/include/uv/unix.h +0 -512
- package/node_modules/koffi/vendor/node-api-headers/include/uv/version.h +0 -43
- package/node_modules/koffi/vendor/node-api-headers/include/uv/win.h +0 -698
- package/node_modules/koffi/vendor/node-api-headers/include/uv.h +0 -1990
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
|
-
import { basename, dirname
|
|
16
|
+
import { basename, dirname } from "node:path";
|
|
17
17
|
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai";
|
|
18
18
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
19
19
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
20
|
+
import { resolvePath } from "../utils/paths.js";
|
|
20
21
|
import { sleep } from "../utils/sleep.js";
|
|
21
22
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
22
23
|
import { executeBashWithOperations } from "./bash-executor.js";
|
|
@@ -1925,6 +1926,9 @@ export class AgentSession {
|
|
|
1925
1926
|
// =========================================================================
|
|
1926
1927
|
// Auto-Retry
|
|
1927
1928
|
// =========================================================================
|
|
1929
|
+
_isNonRetryableProviderLimitError(errorMessage) {
|
|
1930
|
+
return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorMessage);
|
|
1931
|
+
}
|
|
1928
1932
|
/**
|
|
1929
1933
|
* Check if an error is retryable (overloaded, rate limit, server errors).
|
|
1930
1934
|
* Context overflow errors are NOT retryable (handled by compaction instead).
|
|
@@ -1937,6 +1941,8 @@ export class AgentSession {
|
|
|
1937
1941
|
if (isContextOverflow(message, contextWindow))
|
|
1938
1942
|
return false;
|
|
1939
1943
|
const err = message.errorMessage;
|
|
1944
|
+
if (this._isNonRetryableProviderLimitError(err))
|
|
1945
|
+
return false;
|
|
1940
1946
|
// Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, premature stream endings, HTTP/2 closed before response, terminated, retry delay exceeded
|
|
1941
1947
|
return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
|
|
1942
1948
|
}
|
|
@@ -2417,7 +2423,7 @@ export class AgentSession {
|
|
|
2417
2423
|
* @returns The resolved output file path.
|
|
2418
2424
|
*/
|
|
2419
2425
|
exportToJsonl(outputPath) {
|
|
2420
|
-
const filePath =
|
|
2426
|
+
const filePath = resolvePath(outputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd());
|
|
2421
2427
|
const dir = dirname(filePath);
|
|
2422
2428
|
if (!existsSync(dir)) {
|
|
2423
2429
|
mkdirSync(dir, { recursive: true });
|
|
@@ -11,11 +11,12 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "f
|
|
|
11
11
|
import { dirname, join } from "path";
|
|
12
12
|
import lockfile from "proper-lockfile";
|
|
13
13
|
import { getAgentDir } from "../config.js";
|
|
14
|
+
import { normalizePath } from "../utils/paths.js";
|
|
14
15
|
import { resolveConfigValue } from "./resolve-config-value.js";
|
|
15
16
|
export class FileAuthStorageBackend {
|
|
16
17
|
authPath;
|
|
17
18
|
constructor(authPath = join(getAgentDir(), "auth.json")) {
|
|
18
|
-
this.authPath = authPath;
|
|
19
|
+
this.authPath = normalizePath(authPath);
|
|
19
20
|
}
|
|
20
21
|
ensureParentDir() {
|
|
21
22
|
const dir = dirname(this.authPath);
|
|
@@ -154,6 +154,22 @@ export function shouldCompact(contextTokens, contextWindow, settings) {
|
|
|
154
154
|
// ============================================================================
|
|
155
155
|
// Cut point detection
|
|
156
156
|
// ============================================================================
|
|
157
|
+
const ESTIMATED_IMAGE_CHARS = 4800;
|
|
158
|
+
function estimateTextAndImageContentChars(content) {
|
|
159
|
+
if (typeof content === "string") {
|
|
160
|
+
return content.length;
|
|
161
|
+
}
|
|
162
|
+
let chars = 0;
|
|
163
|
+
for (const block of content) {
|
|
164
|
+
if (block.type === "text" && block.text) {
|
|
165
|
+
chars += block.text.length;
|
|
166
|
+
}
|
|
167
|
+
else if (block.type === "image") {
|
|
168
|
+
chars += ESTIMATED_IMAGE_CHARS;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return chars;
|
|
172
|
+
}
|
|
157
173
|
/**
|
|
158
174
|
* Estimate token count for a message using chars/4 heuristic.
|
|
159
175
|
* This is conservative (overestimates tokens).
|
|
@@ -162,17 +178,7 @@ export function estimateTokens(message) {
|
|
|
162
178
|
let chars = 0;
|
|
163
179
|
switch (message.role) {
|
|
164
180
|
case "user": {
|
|
165
|
-
|
|
166
|
-
if (typeof content === "string") {
|
|
167
|
-
chars = content.length;
|
|
168
|
-
}
|
|
169
|
-
else if (Array.isArray(content)) {
|
|
170
|
-
for (const block of content) {
|
|
171
|
-
if (block.type === "text" && block.text) {
|
|
172
|
-
chars += block.text.length;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
181
|
+
chars = estimateTextAndImageContentChars(message.content);
|
|
176
182
|
return Math.ceil(chars / 4);
|
|
177
183
|
}
|
|
178
184
|
case "assistant": {
|
|
@@ -192,19 +198,7 @@ export function estimateTokens(message) {
|
|
|
192
198
|
}
|
|
193
199
|
case "custom":
|
|
194
200
|
case "toolResult": {
|
|
195
|
-
|
|
196
|
-
chars = message.content.length;
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
for (const block of message.content) {
|
|
200
|
-
if (block.type === "text" && block.text) {
|
|
201
|
-
chars += block.text.length;
|
|
202
|
-
}
|
|
203
|
-
if (block.type === "image") {
|
|
204
|
-
chars += 4800; // Estimate images as 4000 chars, or 1200 tokens
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
201
|
+
chars = estimateTextAndImageContentChars(message.content);
|
|
208
202
|
return Math.ceil(chars / 4);
|
|
209
203
|
}
|
|
210
204
|
case "bashExecution": {
|
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
|
2
2
|
import { basename, join } from "path";
|
|
3
3
|
import { APP_NAME, getExportTemplateDir } from "../../config.js";
|
|
4
4
|
import { getResolvedThemeColors, getThemeExportColors } from "../../modes/interactive/theme/theme.js";
|
|
5
|
+
import { normalizePath, resolvePath } from "../../utils/paths.js";
|
|
5
6
|
import { SessionManager } from "../session-manager.js";
|
|
6
7
|
/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */
|
|
7
8
|
function parseColor(color) {
|
|
@@ -187,7 +188,7 @@ export async function exportSessionToHtml(sm, state, options) {
|
|
|
187
188
|
renderedTools,
|
|
188
189
|
};
|
|
189
190
|
const html = generateHtml(sessionData, opts.themeName);
|
|
190
|
-
let outputPath = opts.outputPath;
|
|
191
|
+
let outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;
|
|
191
192
|
if (!outputPath) {
|
|
192
193
|
const sessionBasename = basename(sessionFile, ".jsonl");
|
|
193
194
|
outputPath = `${APP_NAME}-session-${sessionBasename}.html`;
|
|
@@ -201,10 +202,11 @@ export async function exportSessionToHtml(sm, state, options) {
|
|
|
201
202
|
*/
|
|
202
203
|
export async function exportFromFile(inputPath, options) {
|
|
203
204
|
const opts = typeof options === "string" ? { outputPath: options } : options || {};
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
const resolvedInputPath = resolvePath(inputPath);
|
|
206
|
+
if (!existsSync(resolvedInputPath)) {
|
|
207
|
+
throw new Error(`File not found: ${resolvedInputPath}`);
|
|
206
208
|
}
|
|
207
|
-
const sm = SessionManager.open(
|
|
209
|
+
const sm = SessionManager.open(resolvedInputPath);
|
|
208
210
|
const sessionData = {
|
|
209
211
|
header: sm.getHeader(),
|
|
210
212
|
entries: sm.getEntries(),
|
|
@@ -213,9 +215,9 @@ export async function exportFromFile(inputPath, options) {
|
|
|
213
215
|
tools: undefined,
|
|
214
216
|
};
|
|
215
217
|
const html = generateHtml(sessionData, opts.themeName);
|
|
216
|
-
let outputPath = opts.outputPath;
|
|
218
|
+
let outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;
|
|
217
219
|
if (!outputPath) {
|
|
218
|
-
const inputBasename = basename(
|
|
220
|
+
const inputBasename = basename(resolvedInputPath, ".jsonl");
|
|
219
221
|
outputPath = `${APP_NAME}-session-${inputBasename}.html`;
|
|
220
222
|
}
|
|
221
223
|
writeFileSync(outputPath, html, "utf8");
|
|
@@ -605,9 +605,12 @@
|
|
|
605
605
|
}
|
|
606
606
|
|
|
607
607
|
function escapeHtml(text) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
608
|
+
return String(text)
|
|
609
|
+
.replace(/&/g, '&')
|
|
610
|
+
.replace(/</g, '<')
|
|
611
|
+
.replace(/>/g, '>')
|
|
612
|
+
.replace(/"/g, '"')
|
|
613
|
+
.replace(/'/g, ''');
|
|
611
614
|
}
|
|
612
615
|
|
|
613
616
|
/**
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
|
-
import * as os from "node:os";
|
|
8
7
|
import * as path from "node:path";
|
|
9
8
|
import { fileURLToPath } from "node:url";
|
|
10
9
|
import * as _bundledPiAgentCore from "@earendil-works/pi-agent-core";
|
|
@@ -22,6 +21,7 @@ import { CONFIG_DIR_NAME, getAgentDir, isBunBinary } from "../../config.js";
|
|
|
22
21
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
23
22
|
// avoiding a circular dependency. Extensions can import from @earendil-works/pi-coding-agent.
|
|
24
23
|
import * as _bundledPiCodingAgent from "../../index.js";
|
|
24
|
+
import { resolvePath } from "../../utils/paths.js";
|
|
25
25
|
import { createEventBus } from "../event-bus.js";
|
|
26
26
|
import { execCommand } from "../exec.js";
|
|
27
27
|
import { createSyntheticSourceInfo } from "../source-info.js";
|
|
@@ -91,27 +91,6 @@ function getAliases() {
|
|
|
91
91
|
};
|
|
92
92
|
return _aliases;
|
|
93
93
|
}
|
|
94
|
-
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
95
|
-
function normalizeUnicodeSpaces(str) {
|
|
96
|
-
return str.replace(UNICODE_SPACES, " ");
|
|
97
|
-
}
|
|
98
|
-
function expandPath(p) {
|
|
99
|
-
const normalized = normalizeUnicodeSpaces(p);
|
|
100
|
-
if (normalized.startsWith("~/")) {
|
|
101
|
-
return path.join(os.homedir(), normalized.slice(2));
|
|
102
|
-
}
|
|
103
|
-
if (normalized.startsWith("~")) {
|
|
104
|
-
return path.join(os.homedir(), normalized.slice(1));
|
|
105
|
-
}
|
|
106
|
-
return normalized;
|
|
107
|
-
}
|
|
108
|
-
function resolvePath(extPath, cwd) {
|
|
109
|
-
const expanded = expandPath(extPath);
|
|
110
|
-
if (path.isAbsolute(expanded)) {
|
|
111
|
-
return expanded;
|
|
112
|
-
}
|
|
113
|
-
return path.resolve(cwd, expanded);
|
|
114
|
-
}
|
|
115
94
|
/**
|
|
116
95
|
* Create a runtime with throwing stubs for action methods.
|
|
117
96
|
* Runner.bindCore() replaces these with real implementations.
|
|
@@ -315,7 +294,7 @@ function createExtension(extensionPath, resolvedPath) {
|
|
|
315
294
|
};
|
|
316
295
|
}
|
|
317
296
|
async function loadExtension(extensionPath, cwd, eventBus, runtime) {
|
|
318
|
-
const resolvedPath = resolvePath(extensionPath, cwd);
|
|
297
|
+
const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });
|
|
319
298
|
try {
|
|
320
299
|
const factory = await loadExtensionModule(resolvedPath);
|
|
321
300
|
if (!factory) {
|
|
@@ -336,7 +315,8 @@ async function loadExtension(extensionPath, cwd, eventBus, runtime) {
|
|
|
336
315
|
*/
|
|
337
316
|
export async function loadExtensionFromFactory(factory, cwd, eventBus, runtime, extensionPath = "<inline>") {
|
|
338
317
|
const extension = createExtension(extensionPath, extensionPath);
|
|
339
|
-
const
|
|
318
|
+
const resolvedCwd = resolvePath(cwd);
|
|
319
|
+
const api = createExtensionAPI(extension, runtime, resolvedCwd, eventBus);
|
|
340
320
|
await factory(api);
|
|
341
321
|
return extension;
|
|
342
322
|
}
|
|
@@ -346,10 +326,11 @@ export async function loadExtensionFromFactory(factory, cwd, eventBus, runtime,
|
|
|
346
326
|
export async function loadExtensions(paths, cwd, eventBus) {
|
|
347
327
|
const extensions = [];
|
|
348
328
|
const errors = [];
|
|
329
|
+
const resolvedCwd = resolvePath(cwd);
|
|
349
330
|
const resolvedEventBus = eventBus ?? createEventBus();
|
|
350
331
|
const runtime = createExtensionRuntime();
|
|
351
332
|
for (const extPath of paths) {
|
|
352
|
-
const { extension, error } = await loadExtension(extPath,
|
|
333
|
+
const { extension, error } = await loadExtension(extPath, resolvedCwd, resolvedEventBus, runtime);
|
|
353
334
|
if (error) {
|
|
354
335
|
errors.push({ path: extPath, error });
|
|
355
336
|
continue;
|
|
@@ -460,6 +441,8 @@ function discoverExtensionsInDir(dir) {
|
|
|
460
441
|
* Discover and load extensions from standard locations.
|
|
461
442
|
*/
|
|
462
443
|
export async function discoverAndLoadExtensions(configuredPaths, cwd, agentDir = getAgentDir(), eventBus) {
|
|
444
|
+
const resolvedCwd = resolvePath(cwd);
|
|
445
|
+
const resolvedAgentDir = resolvePath(agentDir);
|
|
463
446
|
const allPaths = [];
|
|
464
447
|
const seen = new Set();
|
|
465
448
|
const addPaths = (paths) => {
|
|
@@ -472,14 +455,14 @@ export async function discoverAndLoadExtensions(configuredPaths, cwd, agentDir =
|
|
|
472
455
|
}
|
|
473
456
|
};
|
|
474
457
|
// 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/
|
|
475
|
-
const localExtDir = path.join(
|
|
458
|
+
const localExtDir = path.join(resolvedCwd, CONFIG_DIR_NAME, "extensions");
|
|
476
459
|
addPaths(discoverExtensionsInDir(localExtDir));
|
|
477
460
|
// 2. Global extensions: agentDir/extensions/
|
|
478
|
-
const globalExtDir = path.join(
|
|
461
|
+
const globalExtDir = path.join(resolvedAgentDir, "extensions");
|
|
479
462
|
addPaths(discoverExtensionsInDir(globalExtDir));
|
|
480
463
|
// 3. Explicitly configured paths
|
|
481
464
|
for (const p of configuredPaths) {
|
|
482
|
-
const resolved = resolvePath(p,
|
|
465
|
+
const resolved = resolvePath(p, resolvedCwd, { normalizeUnicodeSpaces: true });
|
|
483
466
|
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
|
484
467
|
// Check for package.json with pi manifest or index.ts
|
|
485
468
|
const entries = resolveExtensionEntries(resolved);
|
|
@@ -493,6 +476,6 @@ export async function discoverAndLoadExtensions(configuredPaths, cwd, agentDir =
|
|
|
493
476
|
}
|
|
494
477
|
addPaths([resolved]);
|
|
495
478
|
}
|
|
496
|
-
return loadExtensions(allPaths,
|
|
479
|
+
return loadExtensions(allPaths, resolvedCwd, eventBus);
|
|
497
480
|
}
|
|
498
481
|
//# sourceMappingURL=loader.js.map
|
|
@@ -8,6 +8,7 @@ import { join } from "path";
|
|
|
8
8
|
import { Type } from "typebox";
|
|
9
9
|
import { Compile } from "typebox/compile";
|
|
10
10
|
import { getAgentDir } from "../config.js";
|
|
11
|
+
import { normalizePath } from "../utils/paths.js";
|
|
11
12
|
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "./provider-display-names.js";
|
|
12
13
|
import { clearConfigValueCache, resolveConfigValueOrThrow, resolveConfigValueUncached, resolveHeadersOrThrow, } from "./resolve-config-value.js";
|
|
13
14
|
// Schema for OpenRouter routing preferences
|
|
@@ -91,6 +92,9 @@ const OpenAIResponsesCompatSchema = Type.Object({
|
|
|
91
92
|
const AnthropicMessagesCompatSchema = Type.Object({
|
|
92
93
|
supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
|
|
93
94
|
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
95
|
+
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
96
|
+
supportsCacheControlOnTools: Type.Optional(Type.Boolean()),
|
|
97
|
+
forceAdaptiveThinking: Type.Optional(Type.Boolean()),
|
|
94
98
|
});
|
|
95
99
|
const ProviderCompatSchema = Type.Union([
|
|
96
100
|
OpenAICompletionsCompatSchema,
|
|
@@ -242,7 +246,7 @@ export class ModelRegistry {
|
|
|
242
246
|
modelsJsonPath;
|
|
243
247
|
constructor(authStorage, modelsJsonPath) {
|
|
244
248
|
this.authStorage = authStorage;
|
|
245
|
-
this.modelsJsonPath = modelsJsonPath;
|
|
249
|
+
this.modelsJsonPath = modelsJsonPath ? normalizePath(modelsJsonPath) : undefined;
|
|
246
250
|
this.loadModels();
|
|
247
251
|
}
|
|
248
252
|
static create(authStorage, modelsJsonPath = join(getAgentDir(), "models.json")) {
|
|
@@ -1,4 +1,40 @@
|
|
|
1
1
|
let stdoutTakeoverState;
|
|
2
|
+
const RAW_STDOUT_RETRY_DELAY_MS = 10;
|
|
3
|
+
let rawStdoutWriteTail = Promise.resolve();
|
|
4
|
+
function getRawStdoutWrite() {
|
|
5
|
+
if (stdoutTakeoverState) {
|
|
6
|
+
return stdoutTakeoverState.rawStdoutWrite;
|
|
7
|
+
}
|
|
8
|
+
return process.stdout.write.bind(process.stdout);
|
|
9
|
+
}
|
|
10
|
+
async function writeRawStdoutChunk(text) {
|
|
11
|
+
while (true) {
|
|
12
|
+
try {
|
|
13
|
+
await new Promise((resolve, reject) => {
|
|
14
|
+
try {
|
|
15
|
+
getRawStdoutWrite()(text, (error) => {
|
|
16
|
+
if (error)
|
|
17
|
+
reject(error);
|
|
18
|
+
else
|
|
19
|
+
resolve();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const writeError = error instanceof Error ? error : new Error(String(error));
|
|
30
|
+
const code = writeError.code;
|
|
31
|
+
if (code !== "ENOBUFS" && code !== "EAGAIN" && code !== "EWOULDBLOCK") {
|
|
32
|
+
throw writeError;
|
|
33
|
+
}
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, RAW_STDOUT_RETRY_DELAY_MS));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
2
38
|
export function takeOverStdout() {
|
|
3
39
|
if (stdoutTakeoverState) {
|
|
4
40
|
return;
|
|
@@ -29,31 +65,25 @@ export function isStdoutTakenOver() {
|
|
|
29
65
|
return stdoutTakeoverState !== undefined;
|
|
30
66
|
}
|
|
31
67
|
export function writeRawStdout(text) {
|
|
32
|
-
if (
|
|
33
|
-
stdoutTakeoverState.rawStdoutWrite(text);
|
|
68
|
+
if (text.length === 0) {
|
|
34
69
|
return;
|
|
35
70
|
}
|
|
36
|
-
|
|
71
|
+
rawStdoutWriteTail = rawStdoutWriteTail.then(() => writeRawStdoutChunk(text));
|
|
72
|
+
void rawStdoutWriteTail.catch(() => {
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
37
75
|
}
|
|
38
|
-
export async function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
resolve();
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
return;
|
|
76
|
+
export async function waitForRawStdoutBackpressure() {
|
|
77
|
+
while (true) {
|
|
78
|
+
const tail = rawStdoutWriteTail;
|
|
79
|
+
await tail;
|
|
80
|
+
if (tail === rawStdoutWriteTail) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
49
83
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else
|
|
55
|
-
resolve();
|
|
56
|
-
});
|
|
57
|
-
});
|
|
84
|
+
}
|
|
85
|
+
export async function flushRawStdout() {
|
|
86
|
+
await waitForRawStdoutBackpressure();
|
|
87
|
+
await writeRawStdoutChunk("");
|
|
58
88
|
}
|
|
59
89
|
//# sourceMappingURL=output-guard.js.map
|
|
@@ -27,7 +27,7 @@ import { minimatch } from "minimatch";
|
|
|
27
27
|
import { CONFIG_DIR_NAME } from "../config.js";
|
|
28
28
|
import { spawnProcess, spawnProcessSync } from "../utils/child-process.js";
|
|
29
29
|
import { parseGitUrl } from "../utils/git.js";
|
|
30
|
-
import { canonicalizePath, isLocalPath, markPathIgnoredByCloudSync } from "../utils/paths.js";
|
|
30
|
+
import { canonicalizePath, isLocalPath, markPathIgnoredByCloudSync, resolvePath } from "../utils/paths.js";
|
|
31
31
|
import { isStdoutTakenOver } from "./output-guard.js";
|
|
32
32
|
const NETWORK_TIMEOUT_MS = 10000;
|
|
33
33
|
const UPDATE_CHECK_CONCURRENCY = 4;
|
|
@@ -577,8 +577,8 @@ export class DefaultPackageManager {
|
|
|
577
577
|
globalNpmRootCommandKey;
|
|
578
578
|
progressCallback;
|
|
579
579
|
constructor(options) {
|
|
580
|
-
this.cwd = options.cwd;
|
|
581
|
-
this.agentDir = options.agentDir;
|
|
580
|
+
this.cwd = resolvePath(options.cwd);
|
|
581
|
+
this.agentDir = resolvePath(options.agentDir);
|
|
582
582
|
this.settingsManager = options.settingsManager;
|
|
583
583
|
}
|
|
584
584
|
setProgressCallback(callback) {
|
|
@@ -589,9 +589,22 @@ export class DefaultPackageManager {
|
|
|
589
589
|
const currentSettings = scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
|
|
590
590
|
const currentPackages = currentSettings.packages ?? [];
|
|
591
591
|
const normalizedSource = this.normalizePackageSourceForSettings(source, scope);
|
|
592
|
-
const
|
|
593
|
-
if (
|
|
594
|
-
|
|
592
|
+
const matchIndex = currentPackages.findIndex((existing) => this.packageSourcesMatch(existing, source, scope));
|
|
593
|
+
if (matchIndex !== -1) {
|
|
594
|
+
const existing = currentPackages[matchIndex];
|
|
595
|
+
if (this.getPackageSourceString(existing) === normalizedSource) {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
const nextPackages = [...currentPackages];
|
|
599
|
+
nextPackages[matchIndex] =
|
|
600
|
+
typeof existing === "string" ? normalizedSource : { ...existing, source: normalizedSource };
|
|
601
|
+
if (scope === "project") {
|
|
602
|
+
this.settingsManager.setProjectPackages(nextPackages);
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
this.settingsManager.setPackages(nextPackages);
|
|
606
|
+
}
|
|
607
|
+
return true;
|
|
595
608
|
}
|
|
596
609
|
const nextPackages = [...currentPackages, normalizedSource];
|
|
597
610
|
if (scope === "project") {
|
|
@@ -801,14 +814,16 @@ export class DefaultPackageManager {
|
|
|
801
814
|
const gitCandidates = [];
|
|
802
815
|
for (const entry of sources) {
|
|
803
816
|
const parsed = this.parseSource(entry.source);
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
817
|
+
// Pinned npm versions are fixed. Pinned git refs are configured checkout targets,
|
|
818
|
+
// so include them to reconcile an existing clone when the configured ref changes.
|
|
807
819
|
if (parsed.type === "npm") {
|
|
808
|
-
|
|
809
|
-
|
|
820
|
+
if (!parsed.pinned) {
|
|
821
|
+
npmCandidates.push({ ...entry, parsed });
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
else if (parsed.type === "git") {
|
|
825
|
+
gitCandidates.push({ ...entry, parsed });
|
|
810
826
|
}
|
|
811
|
-
gitCandidates.push({ ...entry, parsed });
|
|
812
827
|
}
|
|
813
828
|
const npmCheckTasks = npmCandidates.map((entry) => async () => ({
|
|
814
829
|
entry,
|
|
@@ -1383,13 +1398,25 @@ export class DefaultPackageManager {
|
|
|
1383
1398
|
}
|
|
1384
1399
|
getNpmInstallArgs(specs, installRoot) {
|
|
1385
1400
|
const packageManagerName = this.getPackageManagerName();
|
|
1401
|
+
// Extension packages run inside pi and resolve pi APIs through loader aliases/virtual modules.
|
|
1402
|
+
// Disable peer dependency resolution for managed installs (npm's --legacy-peer-deps, and
|
|
1403
|
+
// equivalent bun/pnpm settings) so package managers do not install or solve host-provided
|
|
1404
|
+
// @earendil-works/pi-* peers. Stale auto-installed pi peers can otherwise block updates.
|
|
1386
1405
|
if (packageManagerName === "bun") {
|
|
1387
|
-
return ["install", ...specs, "--cwd", installRoot];
|
|
1406
|
+
return ["install", ...specs, "--cwd", installRoot, "--omit=peer"];
|
|
1388
1407
|
}
|
|
1389
1408
|
if (packageManagerName === "pnpm") {
|
|
1390
|
-
return [
|
|
1391
|
-
|
|
1392
|
-
|
|
1409
|
+
return [
|
|
1410
|
+
"install",
|
|
1411
|
+
...specs,
|
|
1412
|
+
"--prefix",
|
|
1413
|
+
installRoot,
|
|
1414
|
+
"--config.auto-install-peers=false",
|
|
1415
|
+
"--config.strict-peer-dependencies=false",
|
|
1416
|
+
"--config.strict-dep-builds=false",
|
|
1417
|
+
];
|
|
1418
|
+
}
|
|
1419
|
+
return ["install", ...specs, "--prefix", installRoot, "--legacy-peer-deps"];
|
|
1393
1420
|
}
|
|
1394
1421
|
async installNpm(source, scope, temporary) {
|
|
1395
1422
|
const installRoot = this.getNpmInstallRoot(scope, temporary);
|
|
@@ -1410,6 +1437,12 @@ export class DefaultPackageManager {
|
|
|
1410
1437
|
async installGit(source, scope) {
|
|
1411
1438
|
const targetDir = this.getGitInstallPath(source, scope);
|
|
1412
1439
|
if (existsSync(targetDir)) {
|
|
1440
|
+
if (source.ref) {
|
|
1441
|
+
await this.ensureGitRef(targetDir, ["fetch", "origin", source.ref], "FETCH_HEAD");
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
const target = await this.getLocalGitUpdateTarget(targetDir);
|
|
1445
|
+
await this.ensureGitRef(targetDir, target.fetchArgs, target.ref);
|
|
1413
1446
|
return;
|
|
1414
1447
|
}
|
|
1415
1448
|
const gitRoot = this.getGitInstallRoot(scope);
|
|
@@ -1432,21 +1465,29 @@ export class DefaultPackageManager {
|
|
|
1432
1465
|
await this.installGit(source, scope);
|
|
1433
1466
|
return;
|
|
1434
1467
|
}
|
|
1468
|
+
if (source.ref) {
|
|
1469
|
+
await this.ensureGitRef(targetDir, ["fetch", "origin", source.ref], "FETCH_HEAD");
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1435
1472
|
const target = await this.getLocalGitUpdateTarget(targetDir);
|
|
1473
|
+
await this.ensureGitRef(targetDir, target.fetchArgs, target.ref);
|
|
1474
|
+
}
|
|
1475
|
+
async ensureGitRef(targetDir, fetchArgs, ref) {
|
|
1436
1476
|
// Fetch only the ref we will reset to, avoiding unrelated branch/tag noise.
|
|
1437
|
-
await this.runCommand("git",
|
|
1477
|
+
await this.runCommand("git", fetchArgs, { cwd: targetDir });
|
|
1438
1478
|
const localHead = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
|
|
1439
1479
|
cwd: targetDir,
|
|
1440
1480
|
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1441
1481
|
});
|
|
1442
|
-
const
|
|
1482
|
+
const commitRef = `${ref}^{commit}`;
|
|
1483
|
+
const targetHead = await this.runCommandCapture("git", ["rev-parse", commitRef], {
|
|
1443
1484
|
cwd: targetDir,
|
|
1444
1485
|
timeoutMs: NETWORK_TIMEOUT_MS,
|
|
1445
1486
|
});
|
|
1446
|
-
if (localHead.trim() ===
|
|
1487
|
+
if (localHead.trim() === targetHead.trim()) {
|
|
1447
1488
|
return;
|
|
1448
1489
|
}
|
|
1449
|
-
await this.runCommand("git", ["reset", "--hard",
|
|
1490
|
+
await this.runCommand("git", ["reset", "--hard", commitRef], { cwd: targetDir });
|
|
1450
1491
|
// Clean untracked files (extensions should be pristine)
|
|
1451
1492
|
await this.runCommand("git", ["clean", "-fdx"], { cwd: targetDir });
|
|
1452
1493
|
const packageJsonPath = join(targetDir, "package.json");
|
|
@@ -1616,24 +1657,10 @@ export class DefaultPackageManager {
|
|
|
1616
1657
|
return this.cwd;
|
|
1617
1658
|
}
|
|
1618
1659
|
resolvePath(input) {
|
|
1619
|
-
|
|
1620
|
-
if (trimmed === "~")
|
|
1621
|
-
return getHomeDir();
|
|
1622
|
-
if (trimmed.startsWith("~/"))
|
|
1623
|
-
return join(getHomeDir(), trimmed.slice(2));
|
|
1624
|
-
if (trimmed.startsWith("~"))
|
|
1625
|
-
return join(getHomeDir(), trimmed.slice(1));
|
|
1626
|
-
return resolve(this.cwd, trimmed);
|
|
1660
|
+
return resolvePath(input, this.cwd, { homeDir: getHomeDir(), trim: true });
|
|
1627
1661
|
}
|
|
1628
1662
|
resolvePathFromBase(input, baseDir) {
|
|
1629
|
-
|
|
1630
|
-
if (trimmed === "~")
|
|
1631
|
-
return getHomeDir();
|
|
1632
|
-
if (trimmed.startsWith("~/"))
|
|
1633
|
-
return join(getHomeDir(), trimmed.slice(2));
|
|
1634
|
-
if (trimmed.startsWith("~"))
|
|
1635
|
-
return join(getHomeDir(), trimmed.slice(1));
|
|
1636
|
-
return resolve(baseDir, trimmed);
|
|
1663
|
+
return resolvePath(input, baseDir, { homeDir: getHomeDir(), trim: true });
|
|
1637
1664
|
}
|
|
1638
1665
|
collectPackageResources(packageRoot, accumulator, filter, metadata) {
|
|
1639
1666
|
if (filter) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
2
|
-
import {
|
|
3
|
-
import { basename, dirname, isAbsolute, join, resolve, sep } from "path";
|
|
2
|
+
import { basename, dirname, join, resolve, sep } from "path";
|
|
4
3
|
import { CONFIG_DIR_NAME } from "../config.js";
|
|
5
4
|
import { parseFrontmatter } from "../utils/frontmatter.js";
|
|
5
|
+
import { resolvePath } from "../utils/paths.js";
|
|
6
6
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
7
7
|
/**
|
|
8
8
|
* Parse command arguments respecting quoted strings (bash-style)
|
|
@@ -146,20 +146,6 @@ function loadTemplatesFromDir(dir, getSourceInfo) {
|
|
|
146
146
|
}
|
|
147
147
|
return templates;
|
|
148
148
|
}
|
|
149
|
-
function normalizePath(input) {
|
|
150
|
-
const trimmed = input.trim();
|
|
151
|
-
if (trimmed === "~")
|
|
152
|
-
return homedir();
|
|
153
|
-
if (trimmed.startsWith("~/"))
|
|
154
|
-
return join(homedir(), trimmed.slice(2));
|
|
155
|
-
if (trimmed.startsWith("~"))
|
|
156
|
-
return join(homedir(), trimmed.slice(1));
|
|
157
|
-
return trimmed;
|
|
158
|
-
}
|
|
159
|
-
function resolvePromptPath(p, cwd) {
|
|
160
|
-
const normalized = normalizePath(p);
|
|
161
|
-
return isAbsolute(normalized) ? normalized : resolve(cwd, normalized);
|
|
162
|
-
}
|
|
163
149
|
/**
|
|
164
150
|
* Load all prompt templates from:
|
|
165
151
|
* 1. Global: agentDir/prompts/
|
|
@@ -167,12 +153,12 @@ function resolvePromptPath(p, cwd) {
|
|
|
167
153
|
* 3. Explicit prompt paths
|
|
168
154
|
*/
|
|
169
155
|
export function loadPromptTemplates(options) {
|
|
170
|
-
const resolvedCwd = options.cwd;
|
|
171
|
-
const resolvedAgentDir = options.agentDir;
|
|
156
|
+
const resolvedCwd = resolvePath(options.cwd);
|
|
157
|
+
const resolvedAgentDir = resolvePath(options.agentDir);
|
|
172
158
|
const promptPaths = options.promptPaths;
|
|
173
159
|
const includeDefaults = options.includeDefaults;
|
|
174
160
|
const templates = [];
|
|
175
|
-
const globalPromptsDir =
|
|
161
|
+
const globalPromptsDir = join(resolvedAgentDir, "prompts");
|
|
176
162
|
const projectPromptsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, "prompts");
|
|
177
163
|
const isUnderPath = (target, root) => {
|
|
178
164
|
const normalizedRoot = resolve(root);
|
|
@@ -208,7 +194,7 @@ export function loadPromptTemplates(options) {
|
|
|
208
194
|
}
|
|
209
195
|
// 3. Load explicit prompt paths
|
|
210
196
|
for (const rawPath of promptPaths) {
|
|
211
|
-
const resolvedPath =
|
|
197
|
+
const resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });
|
|
212
198
|
if (!existsSync(resolvedPath)) {
|
|
213
199
|
continue;
|
|
214
200
|
}
|