@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
|
@@ -29,9 +29,10 @@ import { buildBaseOptions } from "./simple-options.js";
|
|
|
29
29
|
// ============================================================================
|
|
30
30
|
const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
31
31
|
const JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
32
|
-
const
|
|
32
|
+
const DEFAULT_MAX_RETRIES = 0;
|
|
33
33
|
const BASE_DELAY_MS = 1000;
|
|
34
|
-
const
|
|
34
|
+
const DEFAULT_MAX_RETRY_DELAY_MS = 60_000;
|
|
35
|
+
const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
|
|
35
36
|
const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009;
|
|
36
37
|
const CODEX_RESPONSE_STATUSES = new Set([
|
|
37
38
|
"completed",
|
|
@@ -44,12 +45,44 @@ const CODEX_RESPONSE_STATUSES = new Set([
|
|
|
44
45
|
// ============================================================================
|
|
45
46
|
// Retry Helpers
|
|
46
47
|
// ============================================================================
|
|
48
|
+
function isTerminalRateLimitError(errorText) {
|
|
49
|
+
return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorText);
|
|
50
|
+
}
|
|
47
51
|
function isRetryableError(status, errorText) {
|
|
52
|
+
if (status === 429 && isTerminalRateLimitError(errorText)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
48
55
|
if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
|
|
49
56
|
return true;
|
|
50
57
|
}
|
|
51
58
|
return /rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(errorText);
|
|
52
59
|
}
|
|
60
|
+
function getRetryAfterDelayMs(headers) {
|
|
61
|
+
const retryAfterMs = headers.get("retry-after-ms");
|
|
62
|
+
if (retryAfterMs !== null) {
|
|
63
|
+
const millis = Number(retryAfterMs);
|
|
64
|
+
if (Number.isFinite(millis)) {
|
|
65
|
+
return Math.max(0, millis);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const retryAfter = headers.get("retry-after");
|
|
69
|
+
if (!retryAfter) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
const seconds = Number(retryAfter);
|
|
73
|
+
if (Number.isFinite(seconds)) {
|
|
74
|
+
return Math.max(0, seconds * 1000);
|
|
75
|
+
}
|
|
76
|
+
const date = Date.parse(retryAfter);
|
|
77
|
+
if (!Number.isNaN(date)) {
|
|
78
|
+
return Math.max(0, date - Date.now());
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
function capRetryDelayMs(delayMs, options) {
|
|
83
|
+
const maxRetryDelayMs = options?.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
84
|
+
return maxRetryDelayMs > 0 ? Math.min(delayMs, maxRetryDelayMs) : delayMs;
|
|
85
|
+
}
|
|
53
86
|
function sleep(ms, signal) {
|
|
54
87
|
return new Promise((resolve, reject) => {
|
|
55
88
|
if (signal?.aborted) {
|
|
@@ -91,7 +124,7 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
91
124
|
if (!apiKey) {
|
|
92
125
|
throw new Error(`No API key for provider: ${model.provider}`);
|
|
93
126
|
}
|
|
94
|
-
const accountId = extractAccountId(apiKey)
|
|
127
|
+
const accountId = extractAccountId(apiKey);
|
|
95
128
|
let body = buildRequestBody(model, context, options);
|
|
96
129
|
const nextBody = await options?.onPayload?.(body, model);
|
|
97
130
|
if (nextBody !== undefined) {
|
|
@@ -145,7 +178,8 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
145
178
|
// Fetch with retry logic for rate limits and transient errors
|
|
146
179
|
let response;
|
|
147
180
|
let lastError;
|
|
148
|
-
|
|
181
|
+
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
182
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
149
183
|
if (options?.signal?.aborted) {
|
|
150
184
|
throw new Error("Request was aborted");
|
|
151
185
|
}
|
|
@@ -161,30 +195,13 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
161
195
|
break;
|
|
162
196
|
}
|
|
163
197
|
const errorText = await response.text();
|
|
164
|
-
if (attempt <
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
const retryAfter = response.headers.get("retry-after");
|
|
175
|
-
if (retryAfter) {
|
|
176
|
-
const seconds = Number(retryAfter);
|
|
177
|
-
if (Number.isFinite(seconds)) {
|
|
178
|
-
delayMs = Math.max(0, seconds * 1000);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
const date = Date.parse(retryAfter);
|
|
182
|
-
if (!Number.isNaN(date)) {
|
|
183
|
-
delayMs = Math.max(0, date - Date.now());
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
198
|
+
if (attempt < maxRetries && isRetryableError(response.status, errorText)) {
|
|
199
|
+
const retryAfterDelayMs = getRetryAfterDelayMs(response.headers);
|
|
200
|
+
const delayMs = retryAfterDelayMs === undefined
|
|
201
|
+
? BASE_DELAY_MS * 2 ** attempt
|
|
202
|
+
: response.status === 429
|
|
203
|
+
? capRetryDelayMs(retryAfterDelayMs, options)
|
|
204
|
+
: retryAfterDelayMs;
|
|
188
205
|
await sleep(delayMs, options?.signal);
|
|
189
206
|
continue;
|
|
190
207
|
}
|
|
@@ -204,7 +221,7 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
204
221
|
}
|
|
205
222
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
206
223
|
// Network errors are retryable
|
|
207
|
-
if (attempt <
|
|
224
|
+
if (attempt < maxRetries && !lastError.message.includes("usage limit")) {
|
|
208
225
|
const delayMs = BASE_DELAY_MS * 2 ** attempt;
|
|
209
226
|
await sleep(delayMs, options?.signal);
|
|
210
227
|
continue;
|
|
@@ -265,7 +282,7 @@ function buildRequestBody(model, context, options) {
|
|
|
265
282
|
stream: true,
|
|
266
283
|
instructions: context.systemPrompt || "You are a helpful assistant.",
|
|
267
284
|
input: messages,
|
|
268
|
-
text: { verbosity: options?.textVerbosity || "
|
|
285
|
+
text: { verbosity: options?.textVerbosity || "low" },
|
|
269
286
|
include: ["reasoning.encrypted_content"],
|
|
270
287
|
prompt_cache_key: clampOpenAIPromptCacheKey(options?.sessionId),
|
|
271
288
|
tool_choice: "auto",
|
|
@@ -322,7 +339,11 @@ function resolveCodexServiceTier(responseServiceTier, requestServiceTier) {
|
|
|
322
339
|
function resolveCodexUrl(baseUrl) {
|
|
323
340
|
const raw = baseUrl && baseUrl.trim().length > 0 ? baseUrl : DEFAULT_CODEX_BASE_URL;
|
|
324
341
|
const normalized = raw.replace(/\/+$/, "");
|
|
325
|
-
|
|
342
|
+
if (normalized.endsWith("/codex/responses"))
|
|
343
|
+
return normalized;
|
|
344
|
+
if (normalized.endsWith("/codex"))
|
|
345
|
+
return `${normalized}/responses`;
|
|
346
|
+
return `${normalized}/codex/responses`;
|
|
326
347
|
}
|
|
327
348
|
function resolveCodexWebSocketUrl(baseUrl) {
|
|
328
349
|
const url = new URL(resolveCodexUrl(baseUrl));
|
|
@@ -1031,13 +1052,15 @@ function extractAccountId(token) {
|
|
|
1031
1052
|
try {
|
|
1032
1053
|
const parts = token.split(".");
|
|
1033
1054
|
if (parts.length !== 3)
|
|
1034
|
-
|
|
1055
|
+
throw new Error("Invalid token");
|
|
1035
1056
|
const payload = JSON.parse(atob(parts[1]));
|
|
1036
1057
|
const accountId = payload?.[JWT_CLAIM_PATH]?.chatgpt_account_id;
|
|
1037
|
-
|
|
1058
|
+
if (!accountId)
|
|
1059
|
+
throw new Error("No account ID in token");
|
|
1060
|
+
return accountId;
|
|
1038
1061
|
}
|
|
1039
1062
|
catch {
|
|
1040
|
-
|
|
1063
|
+
throw new Error("Failed to extract accountId from token");
|
|
1041
1064
|
}
|
|
1042
1065
|
}
|
|
1043
1066
|
function createCodexRequestId() {
|
|
@@ -1052,10 +1075,7 @@ function buildBaseCodexHeaders(initHeaders, additionalHeaders, accountId, token)
|
|
|
1052
1075
|
headers.set(key, value);
|
|
1053
1076
|
}
|
|
1054
1077
|
headers.set("Authorization", `Bearer ${token}`);
|
|
1055
|
-
|
|
1056
|
-
if (accountId) {
|
|
1057
|
-
headers.set("chatgpt-account-id", accountId);
|
|
1058
|
-
}
|
|
1078
|
+
headers.set("chatgpt-account-id", accountId);
|
|
1059
1079
|
headers.set("originator", "pi");
|
|
1060
1080
|
const userAgent = _os ? `pi (${_os.platform()} ${_os.release()}; ${_os.arch()})` : "pi (browser)";
|
|
1061
1081
|
headers.set("User-Agent", userAgent);
|
|
@@ -1067,7 +1087,7 @@ function buildSSEHeaders(initHeaders, additionalHeaders, accountId, token, sessi
|
|
|
1067
1087
|
headers.set("accept", "text/event-stream");
|
|
1068
1088
|
headers.set("content-type", "application/json");
|
|
1069
1089
|
if (sessionId) {
|
|
1070
|
-
headers.set("
|
|
1090
|
+
headers.set("session-id", sessionId);
|
|
1071
1091
|
headers.set("x-client-request-id", sessionId);
|
|
1072
1092
|
}
|
|
1073
1093
|
return headers;
|
|
@@ -1080,7 +1100,7 @@ function buildWebSocketHeaders(initHeaders, additionalHeaders, accountId, token,
|
|
|
1080
1100
|
headers.delete("openai-beta");
|
|
1081
1101
|
headers.set("OpenAI-Beta", OPENAI_BETA_RESPONSES_WEBSOCKETS);
|
|
1082
1102
|
headers.set("x-client-request-id", requestId);
|
|
1083
|
-
headers.set("
|
|
1103
|
+
headers.set("session-id", requestId);
|
|
1084
1104
|
return headers;
|
|
1085
1105
|
}
|
|
1086
1106
|
//# sourceMappingURL=openai-codex-responses.js.map
|
|
@@ -83,7 +83,7 @@ export const streamOpenAICompletions = (model, context, options) => {
|
|
|
83
83
|
const requestOptions = {
|
|
84
84
|
...(options?.signal ? { signal: options.signal } : {}),
|
|
85
85
|
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
86
|
-
|
|
86
|
+
maxRetries: options?.maxRetries ?? 0,
|
|
87
87
|
};
|
|
88
88
|
const { data: openaiStream, response } = await client.chat.completions
|
|
89
89
|
.create(params, requestOptions)
|
|
@@ -85,7 +85,7 @@ export const streamOpenAIResponses = (model, context, options) => {
|
|
|
85
85
|
const requestOptions = {
|
|
86
86
|
...(options?.signal ? { signal: options.signal } : {}),
|
|
87
87
|
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
88
|
-
|
|
88
|
+
maxRetries: options?.maxRetries ?? 0,
|
|
89
89
|
};
|
|
90
90
|
const { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();
|
|
91
91
|
await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const CANCEL_MESSAGE = "Login cancelled";
|
|
2
|
+
const TIMEOUT_MESSAGE = "Device flow timed out";
|
|
3
|
+
const SLOW_DOWN_TIMEOUT_MESSAGE = "Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.";
|
|
4
|
+
const MINIMUM_INTERVAL_MS = 1000;
|
|
5
|
+
// RFC 8628 section 3.2: if the authorization server omits `interval`, the client must use 5 seconds.
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_SECONDS = 5;
|
|
7
|
+
// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.
|
|
8
|
+
const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;
|
|
9
|
+
function abortableSleep(ms, signal, cancelMessage) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
if (signal?.aborted) {
|
|
12
|
+
reject(new Error(cancelMessage));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const onAbort = () => {
|
|
16
|
+
clearTimeout(timeout);
|
|
17
|
+
reject(new Error(cancelMessage));
|
|
18
|
+
};
|
|
19
|
+
const timeout = setTimeout(() => {
|
|
20
|
+
signal?.removeEventListener("abort", onAbort);
|
|
21
|
+
resolve();
|
|
22
|
+
}, ms);
|
|
23
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export async function pollOAuthDeviceCodeFlow(options) {
|
|
27
|
+
const deadline = typeof options.expiresInSeconds === "number"
|
|
28
|
+
? Date.now() + options.expiresInSeconds * 1000
|
|
29
|
+
: Number.POSITIVE_INFINITY;
|
|
30
|
+
let intervalMs = Math.max(MINIMUM_INTERVAL_MS, Math.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS) * 1000));
|
|
31
|
+
let slowDownResponses = 0;
|
|
32
|
+
while (Date.now() < deadline) {
|
|
33
|
+
if (options.signal?.aborted) {
|
|
34
|
+
throw new Error(CANCEL_MESSAGE);
|
|
35
|
+
}
|
|
36
|
+
const remainingMs = deadline - Date.now();
|
|
37
|
+
await abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);
|
|
38
|
+
const result = await options.poll();
|
|
39
|
+
if (result.status === "complete") {
|
|
40
|
+
return result.accessToken;
|
|
41
|
+
}
|
|
42
|
+
if (result.status === "pending") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (result.status === "slow_down") {
|
|
46
|
+
slowDownResponses += 1;
|
|
47
|
+
// RFC 8628 section 3.5: apply this increase to this and all subsequent requests.
|
|
48
|
+
intervalMs = Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
throw new Error(result.message);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=device-code.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* GitHub Copilot OAuth flow
|
|
3
3
|
*/
|
|
4
4
|
import { getModels } from "../../models.js";
|
|
5
|
+
import { pollOAuthDeviceCodeFlow } from "./device-code.js";
|
|
5
6
|
const decode = (s) => atob(s);
|
|
6
7
|
const CLIENT_ID = decode("SXYxLmI1MDdhMDhjODdlY2ZlOTg=");
|
|
7
8
|
const COPILOT_HEADERS = {
|
|
@@ -10,8 +11,6 @@ const COPILOT_HEADERS = {
|
|
|
10
11
|
"Editor-Plugin-Version": "copilot-chat/0.35.0",
|
|
11
12
|
"Copilot-Integration-Id": "vscode-chat",
|
|
12
13
|
};
|
|
13
|
-
const INITIAL_POLL_INTERVAL_MULTIPLIER = 1.2;
|
|
14
|
-
const SLOW_DOWN_POLL_INTERVAL_MULTIPLIER = 1.4;
|
|
15
14
|
export function normalizeDomain(input) {
|
|
16
15
|
const trimmed = input.trim();
|
|
17
16
|
if (!trimmed)
|
|
@@ -90,7 +89,7 @@ async function startDeviceFlow(domain) {
|
|
|
90
89
|
if (typeof deviceCode !== "string" ||
|
|
91
90
|
typeof userCode !== "string" ||
|
|
92
91
|
typeof verificationUri !== "string" ||
|
|
93
|
-
typeof interval !== "number" ||
|
|
92
|
+
(interval !== undefined && typeof interval !== "number") ||
|
|
94
93
|
typeof expiresIn !== "number") {
|
|
95
94
|
throw new Error("Invalid device code response fields");
|
|
96
95
|
}
|
|
@@ -102,71 +101,43 @@ async function startDeviceFlow(domain) {
|
|
|
102
101
|
expires_in: expiresIn,
|
|
103
102
|
};
|
|
104
103
|
}
|
|
105
|
-
|
|
106
|
-
* Sleep that can be interrupted by an AbortSignal
|
|
107
|
-
*/
|
|
108
|
-
function abortableSleep(ms, signal) {
|
|
109
|
-
return new Promise((resolve, reject) => {
|
|
110
|
-
if (signal?.aborted) {
|
|
111
|
-
reject(new Error("Login cancelled"));
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const timeout = setTimeout(resolve, ms);
|
|
115
|
-
signal?.addEventListener("abort", () => {
|
|
116
|
-
clearTimeout(timeout);
|
|
117
|
-
reject(new Error("Login cancelled"));
|
|
118
|
-
}, { once: true });
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
async function pollForGitHubAccessToken(domain, deviceCode, intervalSeconds, expiresIn, signal) {
|
|
104
|
+
async function pollForGitHubAccessToken(domain, device, signal) {
|
|
122
105
|
const urls = getUrls(domain);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
device_code: deviceCode,
|
|
144
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
145
|
-
}),
|
|
146
|
-
});
|
|
147
|
-
if (raw && typeof raw === "object" && typeof raw.access_token === "string") {
|
|
148
|
-
return raw.access_token;
|
|
149
|
-
}
|
|
150
|
-
if (raw && typeof raw === "object" && typeof raw.error === "string") {
|
|
151
|
-
const { error, error_description: description, interval } = raw;
|
|
152
|
-
if (error === "authorization_pending") {
|
|
153
|
-
continue;
|
|
106
|
+
return pollOAuthDeviceCodeFlow({
|
|
107
|
+
intervalSeconds: device.interval,
|
|
108
|
+
expiresInSeconds: device.expires_in,
|
|
109
|
+
signal,
|
|
110
|
+
poll: async () => {
|
|
111
|
+
const raw = await fetchJson(urls.accessTokenUrl, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: {
|
|
114
|
+
Accept: "application/json",
|
|
115
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
116
|
+
"User-Agent": "GitHubCopilotChat/0.35.0",
|
|
117
|
+
},
|
|
118
|
+
body: new URLSearchParams({
|
|
119
|
+
client_id: CLIENT_ID,
|
|
120
|
+
device_code: device.device_code,
|
|
121
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
if (raw && typeof raw === "object" && typeof raw.access_token === "string") {
|
|
125
|
+
return { status: "complete", accessToken: raw.access_token };
|
|
154
126
|
}
|
|
155
|
-
if (error === "
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
127
|
+
if (raw && typeof raw === "object" && typeof raw.error === "string") {
|
|
128
|
+
const { error, error_description: description } = raw;
|
|
129
|
+
if (error === "authorization_pending") {
|
|
130
|
+
return { status: "pending" };
|
|
131
|
+
}
|
|
132
|
+
if (error === "slow_down") {
|
|
133
|
+
return { status: "slow_down" };
|
|
134
|
+
}
|
|
135
|
+
const descriptionSuffix = description ? `: ${description}` : "";
|
|
136
|
+
return { status: "failed", message: `Device flow failed: ${error}${descriptionSuffix}` };
|
|
161
137
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
if (slowDownResponses > 0) {
|
|
167
|
-
throw new Error("Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.");
|
|
168
|
-
}
|
|
169
|
-
throw new Error("Device flow timed out");
|
|
138
|
+
return { status: "failed", message: "Invalid device token response" };
|
|
139
|
+
},
|
|
140
|
+
});
|
|
170
141
|
}
|
|
171
142
|
/**
|
|
172
143
|
* Refresh GitHub Copilot token
|
|
@@ -235,7 +206,7 @@ async function enableAllGitHubCopilotModels(token, enterpriseDomain, onProgress)
|
|
|
235
206
|
/**
|
|
236
207
|
* Login with GitHub Copilot OAuth (device code flow)
|
|
237
208
|
*
|
|
238
|
-
* @param options.
|
|
209
|
+
* @param options.onDeviceCode - Callback with URL and user code
|
|
239
210
|
* @param options.onPrompt - Callback to prompt user for input
|
|
240
211
|
* @param options.onProgress - Optional progress callback
|
|
241
212
|
* @param options.signal - Optional AbortSignal for cancellation
|
|
@@ -256,8 +227,13 @@ export async function loginGitHubCopilot(options) {
|
|
|
256
227
|
}
|
|
257
228
|
const domain = enterpriseDomain || "github.com";
|
|
258
229
|
const device = await startDeviceFlow(domain);
|
|
259
|
-
options.
|
|
260
|
-
|
|
230
|
+
options.onDeviceCode({
|
|
231
|
+
userCode: device.user_code,
|
|
232
|
+
verificationUri: device.verification_uri,
|
|
233
|
+
intervalSeconds: device.interval,
|
|
234
|
+
expiresInSeconds: device.expires_in,
|
|
235
|
+
});
|
|
236
|
+
const githubAccessToken = await pollForGitHubAccessToken(domain, device, options.signal);
|
|
261
237
|
const credentials = await refreshGitHubCopilotToken(githubAccessToken, enterpriseDomain ?? undefined);
|
|
262
238
|
// Enable all models after successful login
|
|
263
239
|
options.onProgress?.("Enabling models...");
|
|
@@ -269,7 +245,7 @@ export const githubCopilotOAuthProvider = {
|
|
|
269
245
|
name: "GitHub Copilot",
|
|
270
246
|
async login(callbacks) {
|
|
271
247
|
return loginGitHubCopilot({
|
|
272
|
-
|
|
248
|
+
onDeviceCode: callbacks.onDeviceCode,
|
|
273
249
|
onPrompt: callbacks.onPrompt,
|
|
274
250
|
onProgress: callbacks.onProgress,
|
|
275
251
|
signal: callbacks.signal,
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
// Anthropic
|
|
10
10
|
export { anthropicOAuthProvider, loginAnthropic, refreshAnthropicToken } from "./anthropic.js";
|
|
11
|
+
export * from "./device-code.js";
|
|
11
12
|
// GitHub Copilot
|
|
12
13
|
export { getGitHubCopilotBaseUrl, githubCopilotOAuthProvider, loginGitHubCopilot, normalizeDomain, refreshGitHubCopilotToken, } from "./github-copilot.js";
|
|
13
14
|
// OpenAI Codex (ChatGPT OAuth)
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - xAI: "This model's maximum prompt length is 131072 but the request contains 537812 tokens"
|
|
15
15
|
* - Groq: "Please reduce the length of the messages or completion"
|
|
16
16
|
* - OpenRouter: "This endpoint's maximum context length is X tokens. However, you requested about Y tokens"
|
|
17
|
+
* - OpenRouter/Poolside: "Input length X exceeds the maximum allowed input length of Y tokens."
|
|
17
18
|
* - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
|
|
18
19
|
* - llama.cpp: "the request exceeds the available context size, try increasing it"
|
|
19
20
|
* - LM Studio: "tokens to keep from the initial prompt is greater than the context length"
|
|
@@ -37,7 +38,8 @@ const OVERFLOW_PATTERNS = [
|
|
|
37
38
|
/input token count.*exceeds the maximum/i, // Google (Gemini)
|
|
38
39
|
/maximum prompt length is \d+/i, // xAI (Grok)
|
|
39
40
|
/reduce the length of the messages/i, // Groq
|
|
40
|
-
/maximum context length is \d+ tokens/i, // OpenRouter (
|
|
41
|
+
/maximum context length is \d+ tokens/i, // OpenRouter (most backends)
|
|
42
|
+
/exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i, // OpenRouter/Poolside
|
|
41
43
|
/input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i, // Together AI
|
|
42
44
|
/exceeds the limit of \d+/i, // GitHub Copilot
|
|
43
45
|
/exceeds the available context size/i, // llama.cpp server
|
|
@@ -85,7 +87,8 @@ const NON_OVERFLOW_PATTERNS = [
|
|
|
85
87
|
* - Groq: "reduce the length of the messages"
|
|
86
88
|
* - Cerebras: 400/413 status code (no body)
|
|
87
89
|
* - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
|
|
88
|
-
* - OpenRouter (
|
|
90
|
+
* - OpenRouter (most backends): "maximum context length is X tokens"
|
|
91
|
+
* - OpenRouter/Poolside: "Input length X exceeds the maximum allowed input length of Y tokens."
|
|
89
92
|
* - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
|
|
90
93
|
* - llama.cpp: "exceeds the available context size"
|
|
91
94
|
* - LM Studio: "greater than the context length"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-ai",
|
|
3
|
-
"version": "0.75.
|
|
3
|
+
"version": "0.75.5",
|
|
4
4
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
],
|
|
61
61
|
"scripts": {
|
|
62
62
|
"clean": "shx rm -rf dist",
|
|
63
|
-
"generate-models": "
|
|
64
|
-
"generate-image-models": "
|
|
63
|
+
"generate-models": "node scripts/generate-models.ts",
|
|
64
|
+
"generate-image-models": "node scripts/generate-image-models.ts",
|
|
65
65
|
"build": "npm run generate-models && npm run generate-image-models && tsgo -p tsconfig.build.json",
|
|
66
66
|
"test": "vitest --run",
|
|
67
67
|
"prepublishOnly": "npm run clean && npm run build"
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@anthropic-ai/sdk": "0.91.1",
|
|
71
71
|
"@aws-sdk/client-bedrock-runtime": "3.1048.0",
|
|
72
|
+
"@smithy/node-http-handler": "4.7.3",
|
|
72
73
|
"@google/genai": "1.52.0",
|
|
73
74
|
"@mistralai/mistralai": "2.2.1",
|
|
74
75
|
"http-proxy-agent": "7.0.2",
|
|
@@ -33,11 +33,10 @@ export async function processFileArguments(fileArgs, options) {
|
|
|
33
33
|
if (mimeType) {
|
|
34
34
|
// Handle image file
|
|
35
35
|
const content = await readFile(absolutePath);
|
|
36
|
-
const base64Content = content.toString("base64");
|
|
37
36
|
let attachment;
|
|
38
37
|
let dimensionNote;
|
|
39
38
|
if (autoResizeImages) {
|
|
40
|
-
const resized = await resizeImage(
|
|
39
|
+
const resized = await resizeImage(content, mimeType);
|
|
41
40
|
if (!resized) {
|
|
42
41
|
text += `<file name="${absolutePath}">[Image omitted: could not be resized below the inline image size limit.]</file>\n`;
|
|
43
42
|
continue;
|
|
@@ -53,7 +52,7 @@ export async function processFileArguments(fileArgs, options) {
|
|
|
53
52
|
attachment = {
|
|
54
53
|
type: "image",
|
|
55
54
|
mimeType,
|
|
56
|
-
data:
|
|
55
|
+
data: content.toString("base64"),
|
|
57
56
|
};
|
|
58
57
|
}
|
|
59
58
|
images.push(attachment);
|
|
@@ -3,6 +3,7 @@ import { homedir } from "os";
|
|
|
3
3
|
import { basename, dirname, join, resolve, sep, win32 } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { spawnProcessSync } from "./utils/child-process.js";
|
|
6
|
+
import { normalizePath } from "./utils/paths.js";
|
|
6
7
|
// =============================================================================
|
|
7
8
|
// Package Detection
|
|
8
9
|
// =============================================================================
|
|
@@ -76,7 +77,13 @@ function getSelfUpdateCommandForMethod(method, installedPackageName, updatePacka
|
|
|
76
77
|
case "bun-binary":
|
|
77
78
|
return undefined;
|
|
78
79
|
case "pnpm":
|
|
79
|
-
return makeSelfUpdateCommand(makeSelfUpdateCommandStep("pnpm", [
|
|
80
|
+
return makeSelfUpdateCommand(makeSelfUpdateCommandStep("pnpm", [
|
|
81
|
+
"install",
|
|
82
|
+
"-g",
|
|
83
|
+
"--ignore-scripts",
|
|
84
|
+
"--config.minimumReleaseAge=0",
|
|
85
|
+
updatePackageName,
|
|
86
|
+
]), updatePackageName === installedPackageName
|
|
80
87
|
? undefined
|
|
81
88
|
: makeSelfUpdateCommandStep("pnpm", ["remove", "-g", installedPackageName]));
|
|
82
89
|
case "yarn":
|
|
@@ -84,7 +91,13 @@ function getSelfUpdateCommandForMethod(method, installedPackageName, updatePacka
|
|
|
84
91
|
? undefined
|
|
85
92
|
: makeSelfUpdateCommandStep("yarn", ["global", "remove", installedPackageName]));
|
|
86
93
|
case "bun":
|
|
87
|
-
return makeSelfUpdateCommand(makeSelfUpdateCommandStep("bun", [
|
|
94
|
+
return makeSelfUpdateCommand(makeSelfUpdateCommandStep("bun", [
|
|
95
|
+
"install",
|
|
96
|
+
"-g",
|
|
97
|
+
"--ignore-scripts",
|
|
98
|
+
"--minimum-release-age=0",
|
|
99
|
+
updatePackageName,
|
|
100
|
+
]), updatePackageName === installedPackageName
|
|
88
101
|
? undefined
|
|
89
102
|
: makeSelfUpdateCommandStep("bun", ["uninstall", "-g", installedPackageName]));
|
|
90
103
|
case "npm": {
|
|
@@ -96,6 +109,7 @@ function getSelfUpdateCommandForMethod(method, installedPackageName, updatePacka
|
|
|
96
109
|
"install",
|
|
97
110
|
"-g",
|
|
98
111
|
"--ignore-scripts",
|
|
112
|
+
"--min-release-age=0",
|
|
99
113
|
updatePackageName,
|
|
100
114
|
]);
|
|
101
115
|
const uninstallStep = updatePackageName === installedPackageName
|
|
@@ -261,11 +275,7 @@ export function getPackageDir() {
|
|
|
261
275
|
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
|
|
262
276
|
const envDir = process.env.PI_PACKAGE_DIR;
|
|
263
277
|
if (envDir) {
|
|
264
|
-
|
|
265
|
-
return homedir();
|
|
266
|
-
if (envDir.startsWith("~/"))
|
|
267
|
-
return homedir() + envDir.slice(1);
|
|
268
|
-
return envDir;
|
|
278
|
+
return normalizePath(envDir);
|
|
269
279
|
}
|
|
270
280
|
if (isBunBinary) {
|
|
271
281
|
// Bun binary: process.execPath points to the compiled executable
|
|
@@ -360,11 +370,7 @@ export const VERSION = pkg.version || "0.0.0";
|
|
|
360
370
|
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
|
361
371
|
export const ENV_SESSION_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;
|
|
362
372
|
export function expandTildePath(path) {
|
|
363
|
-
|
|
364
|
-
return homedir();
|
|
365
|
-
if (path.startsWith("~/"))
|
|
366
|
-
return homedir() + path.slice(1);
|
|
367
|
-
return path;
|
|
373
|
+
return normalizePath(path);
|
|
368
374
|
}
|
|
369
375
|
const DEFAULT_SHARE_VIEWER_URL = "https://pi.dev/session/";
|
|
370
376
|
/** Get the share viewer URL for a gist ID */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
|
+
import { resolvePath } from "../utils/paths.js";
|
|
3
4
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
4
5
|
import { assertSessionCwdExists } from "./session-cwd.js";
|
|
5
6
|
import { SessionManager } from "./session-manager.js";
|
|
@@ -246,7 +247,7 @@ export class AgentSessionRuntime {
|
|
|
246
247
|
* @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.
|
|
247
248
|
*/
|
|
248
249
|
async importFromJsonl(inputPath, cwdOverride) {
|
|
249
|
-
const resolvedPath =
|
|
250
|
+
const resolvedPath = resolvePath(inputPath);
|
|
250
251
|
if (!existsSync(resolvedPath)) {
|
|
251
252
|
throw new SessionImportFileNotFoundError(resolvedPath);
|
|
252
253
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { getAgentDir } from "../config.js";
|
|
3
|
+
import { resolvePath } from "../utils/paths.js";
|
|
3
4
|
import { AuthStorage } from "./auth-storage.js";
|
|
4
5
|
import { ModelRegistry } from "./model-registry.js";
|
|
5
6
|
import { DefaultResourceLoader } from "./resource-loader.js";
|
|
@@ -51,8 +52,8 @@ function applyExtensionFlagValues(resourceLoader, extensionFlagValues) {
|
|
|
51
52
|
* Returns services plus diagnostics. It does not create an AgentSession.
|
|
52
53
|
*/
|
|
53
54
|
export async function createAgentSessionServices(options) {
|
|
54
|
-
const cwd = options.cwd;
|
|
55
|
-
const agentDir = options.agentDir
|
|
55
|
+
const cwd = resolvePath(options.cwd);
|
|
56
|
+
const agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();
|
|
56
57
|
const authStorage = options.authStorage ?? AuthStorage.create(join(agentDir, "auth.json"));
|
|
57
58
|
const settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);
|
|
58
59
|
const modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, join(agentDir, "models.json"));
|