@psnext/slingcli 2.5.20260602-4 → 2.5.20260607-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.
Files changed (144) hide show
  1. package/node_modules/@aws-sdk/core/dist-cjs/index.js +12 -6
  2. package/node_modules/@aws-sdk/core/dist-cjs/submodules/httpAuthSchemes/index.js +12 -6
  3. package/node_modules/@aws-sdk/core/dist-es/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.js +1 -0
  4. package/node_modules/@aws-sdk/core/dist-es/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.js +11 -6
  5. package/node_modules/@aws-sdk/core/package.json +7 -7
  6. package/node_modules/@aws-sdk/credential-provider-env/package.json +6 -6
  7. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-cjs/index.js +6 -4
  8. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +7 -6
  9. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +2 -1
  10. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-es/node-http2.js +2 -0
  11. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-es/node-https.js +2 -0
  12. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +2 -2
  13. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +1 -1
  14. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-types/node-http2.d.ts +2 -0
  15. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/dist-types/node-https.d.ts +2 -0
  16. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/package.json +1 -1
  17. package/node_modules/@aws-sdk/credential-provider-http/package.json +8 -8
  18. package/node_modules/@aws-sdk/credential-provider-ini/package.json +14 -14
  19. package/node_modules/@aws-sdk/credential-provider-login/package.json +7 -7
  20. package/node_modules/@aws-sdk/credential-provider-node/package.json +12 -12
  21. package/node_modules/@aws-sdk/credential-provider-process/package.json +6 -6
  22. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +7 -7
  23. package/node_modules/@aws-sdk/credential-provider-sso/package.json +8 -8
  24. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +7 -7
  25. package/node_modules/@aws-sdk/eventstream-handler-node/package.json +5 -5
  26. package/node_modules/@aws-sdk/middleware-eventstream/package.json +5 -5
  27. package/node_modules/@aws-sdk/middleware-websocket/package.json +8 -8
  28. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +99 -106
  29. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +62 -120
  30. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +55 -86
  31. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +73 -104
  32. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +102 -185
  33. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/auth/httpAuthSchemeProvider.js +4 -5
  34. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/endpoint/bdd.js +21 -57
  35. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/runtimeConfig.browser.js +1 -2
  36. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/runtimeConfig.js +2 -4
  37. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/schemas/schemas_0.js +73 -41
  38. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/auth/httpAuthSchemeProvider.js +4 -5
  39. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/endpoint/bdd.js +20 -52
  40. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/runtimeConfig.browser.js +1 -2
  41. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/runtimeConfig.js +2 -4
  42. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/schemas/schemas_0.js +36 -59
  43. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/auth/httpAuthSchemeProvider.js +4 -5
  44. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/endpoint/bdd.js +17 -45
  45. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/runtimeConfig.browser.js +1 -2
  46. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/runtimeConfig.js +2 -4
  47. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/schemas/schemas_0.js +32 -32
  48. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/auth/httpAuthSchemeProvider.js +4 -5
  49. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/endpoint/bdd.js +17 -45
  50. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/runtimeConfig.browser.js +1 -2
  51. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/runtimeConfig.js +2 -4
  52. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/schemas/schemas_0.js +50 -50
  53. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/auth/httpAuthSchemeProvider.js +4 -5
  54. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/defaultRoleAssumers.js +1 -1
  55. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/endpoint/bdd.js +34 -96
  56. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/runtimeConfig.browser.js +1 -2
  57. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/runtimeConfig.js +3 -6
  58. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/schemas/schemas_0.js +63 -80
  59. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-cjs/index.js +6 -4
  60. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +7 -6
  61. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +2 -1
  62. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-es/node-http2.js +2 -0
  63. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-es/node-https.js +2 -0
  64. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +2 -2
  65. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +1 -1
  66. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-types/node-http2.d.ts +2 -0
  67. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/dist-types/node-https.d.ts +2 -0
  68. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/package.json +1 -1
  69. package/node_modules/@aws-sdk/nested-clients/package.json +9 -9
  70. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +5 -5
  71. package/node_modules/@aws-sdk/types/package.json +3 -3
  72. package/node_modules/@aws-sdk/util-locate-window/package.json +2 -2
  73. package/node_modules/@aws-sdk/xml-builder/package.json +3 -3
  74. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  75. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +3 -0
  76. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +45 -0
  77. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +827 -140
  78. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +32 -12
  79. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +13 -1
  80. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +4 -2
  81. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  82. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +15 -2
  83. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +1 -0
  84. package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js +4 -3
  85. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/branch-summarization.js +9 -3
  86. package/node_modules/@earendil-works/pi-coding-agent/dist/core/export-html/template.js +19 -6
  87. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +3 -0
  88. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +47 -13
  89. package/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-attribution.js +72 -0
  90. package/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-display-names.js +3 -0
  91. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js +28 -20
  92. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +2 -30
  93. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +71 -30
  94. package/node_modules/@earendil-works/pi-coding-agent/dist/core/slash-commands.js +1 -0
  95. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +1 -1
  96. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +1 -1
  97. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +1 -1
  98. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +1 -1
  99. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +1 -1
  100. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +1 -1
  101. package/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js +130 -0
  102. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +1 -0
  103. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +54 -2
  104. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +2 -2
  105. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js +1 -1
  106. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js +7 -0
  107. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/index.js +1 -0
  108. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +3 -12
  109. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +22 -0
  110. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/trust-selector.js +86 -0
  111. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
  112. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js +55 -8
  113. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/git.js +54 -22
  114. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/open-browser.js +22 -0
  115. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +12 -12
  116. package/node_modules/@earendil-works/pi-coding-agent/package.json +5 -4
  117. package/node_modules/@earendil-works/pi-tui/dist/utils.js +3 -0
  118. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  119. package/node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/httpRequest.js +2 -2
  120. package/node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/node-http.js +2 -0
  121. package/node_modules/@smithy/credential-provider-imds/dist-types/remoteProvider/httpRequest.d.ts +1 -1
  122. package/node_modules/@smithy/credential-provider-imds/dist-types/remoteProvider/node-http.d.ts +2 -0
  123. package/node_modules/@smithy/credential-provider-imds/package.json +1 -1
  124. package/node_modules/@types/node/README.md +1 -1
  125. package/node_modules/@types/node/http2.d.ts +3 -0
  126. package/node_modules/@types/node/package.json +2 -2
  127. package/node_modules/gaxios/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  128. package/node_modules/gaxios/build/esm/tsconfig.tsbuildinfo +1 -1
  129. package/node_modules/gaxios/package.json +7 -9
  130. package/node_modules/google-auth-library/build/src/auth/gdchclient.d.ts +47 -0
  131. package/node_modules/google-auth-library/build/src/auth/gdchclient.js +307 -0
  132. package/node_modules/google-auth-library/build/src/auth/googleauth.d.ts +5 -4
  133. package/node_modules/google-auth-library/build/src/auth/googleauth.js +18 -1
  134. package/node_modules/google-auth-library/build/src/index.d.ts +1 -0
  135. package/node_modules/google-auth-library/build/src/index.js +4 -1
  136. package/node_modules/google-auth-library/package.json +2 -4
  137. package/node_modules/semver/classes/semver.js +19 -2
  138. package/node_modules/semver/package.json +1 -1
  139. package/node_modules/undici/lib/global.js +1 -1
  140. package/node_modules/undici/lib/handler/unwrap-handler.js +6 -0
  141. package/node_modules/undici/package.json +1 -1
  142. package/node_modules/undici/types/dispatcher.d.ts +2 -0
  143. package/package.json +6 -6
  144. package/slingshot/index.js +275 -273
@@ -461,6 +461,12 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
461
461
  openRouterParams.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
462
462
  }
463
463
  }
464
+ else if (compat.thinkingFormat === "ant-ling" && model.reasoning && options?.reasoningEffort) {
465
+ const effort = model.thinkingLevelMap?.[options.reasoningEffort];
466
+ if (typeof effort === "string") {
467
+ params.reasoning = { effort };
468
+ }
469
+ }
464
470
  else if (compat.thinkingFormat === "together" && model.reasoning) {
465
471
  const togetherParams = params;
466
472
  togetherParams.reasoning = { enabled: !!options?.reasoningEffort };
@@ -488,7 +494,7 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
488
494
  }
489
495
  }
490
496
  // OpenRouter provider routing preferences
491
- if (model.baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) {
497
+ if (model.compat?.openRouterRouting) {
492
498
  params.provider = model.compat.openRouterRouting;
493
499
  }
494
500
  // Vercel AI Gateway provider routing preferences
@@ -873,13 +879,19 @@ function mapStopReason(reason) {
873
879
  function detectCompat(model) {
874
880
  const provider = model.provider;
875
881
  const baseUrl = model.baseUrl;
876
- const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
882
+ const isZai = provider === "zai" ||
883
+ provider === "zai-coding-cn" ||
884
+ baseUrl.includes("api.z.ai") ||
885
+ baseUrl.includes("open.bigmodel.cn");
877
886
  const isTogether = provider === "together" || baseUrl.includes("api.together.ai") || baseUrl.includes("api.together.xyz");
878
887
  const isMoonshot = provider === "moonshotai" || provider === "moonshotai-cn" || baseUrl.includes("api.moonshot.");
879
888
  const isOpenRouter = provider === "openrouter" || baseUrl.includes("openrouter.ai");
880
889
  const isCloudflareWorkersAI = provider === "cloudflare-workers-ai" || baseUrl.includes("api.cloudflare.com");
881
890
  const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || baseUrl.includes("gateway.ai.cloudflare.com");
882
- const isNonStandard = provider === "cerebras" ||
891
+ const isNvidia = provider === "nvidia" || baseUrl.includes("integrate.api.nvidia.com");
892
+ const isAntLing = provider === "ant-ling" || baseUrl.includes("api.ant-ling.com");
893
+ const isNonStandard = isNvidia ||
894
+ provider === "cerebras" ||
883
895
  baseUrl.includes("cerebras.ai") ||
884
896
  provider === "xai" ||
885
897
  baseUrl.includes("api.x.ai") ||
@@ -891,15 +903,17 @@ function detectCompat(model) {
891
903
  provider === "opencode" ||
892
904
  baseUrl.includes("opencode.ai") ||
893
905
  isCloudflareWorkersAI ||
894
- isCloudflareAiGateway;
895
- const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether;
906
+ isCloudflareAiGateway ||
907
+ isAntLing;
908
+ const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether || isNvidia || isAntLing;
896
909
  const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
897
910
  const isDeepSeek = provider === "deepseek" || baseUrl.includes("deepseek.com");
911
+ const isOpenRouterDeveloperRoleModel = isOpenRouter && (model.id.startsWith("anthropic/") || model.id.startsWith("openai/"));
898
912
  const cacheControlFormat = provider === "openrouter" && model.id.startsWith("anthropic/") ? "anthropic" : undefined;
899
913
  return {
900
914
  supportsStore: !isNonStandard,
901
- supportsDeveloperRole: !isNonStandard && !isOpenRouter,
902
- supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isTogether && !isCloudflareAiGateway,
915
+ supportsDeveloperRole: isOpenRouterDeveloperRoleModel || (!isNonStandard && !isOpenRouter),
916
+ supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia && !isAntLing,
903
917
  supportsUsageInStreaming: true,
904
918
  maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
905
919
  requiresToolResultName: false,
@@ -912,16 +926,22 @@ function detectCompat(model) {
912
926
  ? "zai"
913
927
  : isTogether
914
928
  ? "together"
915
- : isOpenRouter
916
- ? "openrouter"
917
- : "openai",
929
+ : isAntLing
930
+ ? "ant-ling"
931
+ : isOpenRouter
932
+ ? "openrouter"
933
+ : "openai",
918
934
  openRouterRouting: {},
919
935
  vercelGatewayRouting: {},
920
936
  zaiToolStream: false,
921
- supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway,
937
+ supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia,
922
938
  cacheControlFormat,
923
939
  sendSessionAffinityHeaders: false,
924
- supportsLongCacheRetention: !(isTogether || isCloudflareWorkersAI || isCloudflareAiGateway),
940
+ supportsLongCacheRetention: !(isTogether ||
941
+ isCloudflareWorkersAI ||
942
+ isCloudflareAiGateway ||
943
+ isNvidia ||
944
+ isAntLing),
925
945
  };
926
946
  }
927
947
  /**
@@ -93,10 +93,22 @@ async function startDeviceFlow(domain) {
93
93
  typeof expiresIn !== "number") {
94
94
  throw new Error("Invalid device code response fields");
95
95
  }
96
+ // The verification URI is opened in the user's browser and to prevent `open` from
97
+ // opening an executable or similar, we force it to be a URL.
98
+ let parsedUri;
99
+ try {
100
+ parsedUri = new URL(verificationUri);
101
+ }
102
+ catch {
103
+ throw new Error("Untrusted verification_uri in device code response");
104
+ }
105
+ if (parsedUri.protocol !== "https:" && parsedUri.protocol !== "http:") {
106
+ throw new Error("Untrusted verification_uri in device code response");
107
+ }
96
108
  return {
97
109
  device_code: deviceCode,
98
110
  user_code: userCode,
99
- verification_uri: verificationUri,
111
+ verification_uri: parsedUri.href,
100
112
  interval,
101
113
  expires_in: expiresIn,
102
114
  };
@@ -18,7 +18,6 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
18
18
  import { pollOAuthDeviceCodeFlow } from "./device-code.js";
19
19
  import { oauthErrorHtml, oauthSuccessHtml } from "./oauth-page.js";
20
20
  import { generatePKCE } from "./pkce.js";
21
- const CALLBACK_HOST = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
22
21
  const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
23
22
  const AUTH_BASE_URL = "https://auth.openai.com";
24
23
  const AUTHORIZE_URL = `${AUTH_BASE_URL}/oauth/authorize`;
@@ -33,6 +32,9 @@ export const OPENAI_CODEX_BROWSER_LOGIN_METHOD = "browser";
33
32
  export const OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD = "device_code";
34
33
  const SCOPE = "openid profile email offline_access";
35
34
  const JWT_CLAIM_PATH = "https://api.openai.com/auth";
35
+ function getCallbackHost() {
36
+ return typeof process !== "undefined" ? process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1" : "127.0.0.1";
37
+ }
36
38
  function createState() {
37
39
  if (!_randomBytes) {
38
40
  throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
@@ -287,7 +289,7 @@ function startLocalOAuthServer(state) {
287
289
  });
288
290
  return new Promise((resolve) => {
289
291
  server
290
- .listen(1455, CALLBACK_HOST, () => {
292
+ .listen(1455, getCallbackHost(), () => {
291
293
  resolve({
292
294
  close: () => server.close(),
293
295
  cancelWait: () => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-ai",
3
- "version": "0.78.0",
3
+ "version": "0.78.1",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -160,6 +160,12 @@ export function parseArgs(args) {
160
160
  else if (arg === "--verbose") {
161
161
  result.verbose = true;
162
162
  }
163
+ else if (arg === "--approve" || arg === "-a") {
164
+ result.projectTrustOverride = true;
165
+ }
166
+ else if (arg === "--no-approve" || arg === "-na") {
167
+ result.projectTrustOverride = false;
168
+ }
163
169
  else if (arg === "--offline") {
164
170
  result.offline = true;
165
171
  }
@@ -212,8 +218,10 @@ ${chalk.bold("Commands:")}
212
218
  ${APP_NAME} remove <source> [-l] Remove extension source from settings
213
219
  ${APP_NAME} uninstall <source> [-l] Alias for remove
214
220
  ${APP_NAME} update [source|self|pi] Update pi and installed extensions
215
- ${APP_NAME} list List installed extensions from settings
216
- ${APP_NAME} config Open TUI to enable/disable package resources
221
+ ${APP_NAME} list [--approve|--no-approve]
222
+ List installed extensions from settings
223
+ ${APP_NAME} config [--no-approve]
224
+ Open TUI to enable/disable package resources
217
225
  ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list
218
226
 
219
227
  ${chalk.bold("Options:")}
@@ -253,6 +261,8 @@ ${chalk.bold("Options:")}
253
261
  --export <file> Export session file to HTML and exit
254
262
  --list-models [search] List available models (with optional fuzzy search)
255
263
  --verbose Force verbose startup (overrides quietStartup setting)
264
+ --approve, -a Trust project-local files for this run
265
+ --no-approve, -na Ignore project-local files for this run
256
266
  --offline Disable startup network operations (same as PI_OFFLINE=1)
257
267
  --help, -h Show this help
258
268
  --version, -v Show version number
@@ -315,6 +325,7 @@ ${chalk.bold("Examples:")}
315
325
  ${chalk.bold("Environment Variables:")}
316
326
  ANTHROPIC_API_KEY - Anthropic Claude API key
317
327
  ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)
328
+ ANT_LING_API_KEY - Ant Ling API key
318
329
  OPENAI_API_KEY - OpenAI GPT API key
319
330
  AZURE_OPENAI_API_KEY - Azure OpenAI API key
320
331
  AZURE_OPENAI_BASE_URL - Azure OpenAI/Cognitive Services base URL (e.g. https://{resource}.openai.azure.com)
@@ -322,6 +333,7 @@ ${chalk.bold("Environment Variables:")}
322
333
  AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)
323
334
  AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)
324
335
  DEEPSEEK_API_KEY - DeepSeek API key
336
+ NVIDIA_API_KEY - NVIDIA NIM API key
325
337
  GEMINI_API_KEY - Google Gemini API key
326
338
  GROQ_API_KEY - Groq API key
327
339
  CEREBRAS_API_KEY - Cerebras API key
@@ -331,6 +343,7 @@ ${chalk.bold("Environment Variables:")}
331
343
  OPENROUTER_API_KEY - OpenRouter API key
332
344
  AI_GATEWAY_API_KEY - Vercel AI Gateway API key
333
345
  ZAI_API_KEY - ZAI API key
346
+ ZAI_CODING_CN_API_KEY - ZAI Coding Plan API key (China)
334
347
  MISTRAL_API_KEY - Mistral API key
335
348
  MINIMAX_API_KEY - MiniMax API key
336
349
  MOONSHOT_API_KEY - Moonshot AI API key
@@ -2225,6 +2225,7 @@ export class AgentSession {
2225
2225
  customInstructions,
2226
2226
  replaceInstructions,
2227
2227
  reserveTokens: branchSummarySettings.reserveTokens,
2228
+ streamFn: this.agent.streamFn,
2228
2229
  });
2229
2230
  if (result.aborted) {
2230
2231
  return { cancelled: true, aborted: true };
@@ -13,6 +13,7 @@ import lockfile from "proper-lockfile";
13
13
  import { getAgentDir } from "../config.js";
14
14
  import { normalizePath } from "../utils/paths.js";
15
15
  import { resolveConfigValue } from "./resolve-config-value.js";
16
+ const AUTH_FILE_WRITE_OPTIONS = { encoding: "utf-8", mode: 0o600 };
16
17
  export class FileAuthStorageBackend {
17
18
  authPath;
18
19
  constructor(authPath = join(getAgentDir(), "auth.json")) {
@@ -26,7 +27,7 @@ export class FileAuthStorageBackend {
26
27
  }
27
28
  ensureFileExists() {
28
29
  if (!existsSync(this.authPath)) {
29
- writeFileSync(this.authPath, "{}", "utf-8");
30
+ writeFileSync(this.authPath, "{}", AUTH_FILE_WRITE_OPTIONS);
30
31
  chmodSync(this.authPath, 0o600);
31
32
  }
32
33
  }
@@ -63,7 +64,7 @@ export class FileAuthStorageBackend {
63
64
  const current = existsSync(this.authPath) ? readFileSync(this.authPath, "utf-8") : undefined;
64
65
  const { result, next } = fn(current);
65
66
  if (next !== undefined) {
66
- writeFileSync(this.authPath, next, "utf-8");
67
+ writeFileSync(this.authPath, next, AUTH_FILE_WRITE_OPTIONS);
67
68
  chmodSync(this.authPath, 0o600);
68
69
  }
69
70
  return result;
@@ -105,7 +106,7 @@ export class FileAuthStorageBackend {
105
106
  const { result, next } = await fn(current);
106
107
  throwIfCompromised();
107
108
  if (next !== undefined) {
108
- writeFileSync(this.authPath, next, "utf-8");
109
+ writeFileSync(this.authPath, next, AUTH_FILE_WRITE_OPTIONS);
109
110
  chmodSync(this.authPath, 0o600);
110
111
  }
111
112
  throwIfCompromised();
@@ -185,7 +185,7 @@ Keep each section concise. Preserve exact file paths, function names, and error
185
185
  * @param options - Generation options
186
186
  */
187
187
  export async function generateBranchSummary(entries, options) {
188
- const { model, apiKey, headers, signal, customInstructions, replaceInstructions, reserveTokens = 16384 } = options;
188
+ const { model, apiKey, headers, signal, customInstructions, replaceInstructions, reserveTokens = 16384, streamFn, } = options;
189
189
  // Token budget = context window minus reserved space for prompt + response
190
190
  const contextWindow = model.contextWindow || 128000;
191
191
  const tokenBudget = contextWindow - reserveTokens;
@@ -216,8 +216,14 @@ export async function generateBranchSummary(entries, options) {
216
216
  timestamp: Date.now(),
217
217
  },
218
218
  ];
219
- // Call LLM for summarization
220
- const response = await completeSimple(model, { systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages }, { apiKey, headers, signal, maxTokens: 2048 });
219
+ // Call LLM for summarization. Prefer the session stream function so SDK
220
+ // request behavior (timeouts, retries, attribution headers) stays consistent
221
+ // without running through agent state/events.
222
+ const context = { systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages };
223
+ const requestOptions = { apiKey, headers, signal, maxTokens: 2048 };
224
+ const response = streamFn
225
+ ? await (await streamFn(model, context, requestOptions)).result()
226
+ : await completeSimple(model, context, requestOptions);
221
227
  // Check if aborted or errored
222
228
  if (response.stopReason === "aborted") {
223
229
  return { aborted: true };
@@ -613,6 +613,18 @@
613
613
  .replace(/'/g, '&#39;');
614
614
  }
615
615
 
616
+ function sanitizeMarkdownUrl(value) {
617
+ const href = String(value || '').trim().replace(/[\x00-\x1f\x7f]/g, '');
618
+ if (!href) return href;
619
+
620
+ const scheme = href.match(/^([A-Za-z][A-Za-z0-9+.-]*):/);
621
+ if (scheme && !/^(https?|mailto|tel|ftp)$/i.test(scheme[1])) {
622
+ return null;
623
+ }
624
+
625
+ return href;
626
+ }
627
+
616
628
  /**
617
629
  * Truncate string to maxLen chars, append "..." if truncated.
618
630
  */
@@ -1569,10 +1581,11 @@
1569
1581
  }
1570
1582
  },
1571
1583
  renderer: {
1572
- // Sanitize link URLs to prevent javascript:/vbscript:/data: XSS
1584
+ // Sanitize link URLs with a scheme allow-list. Browsers strip C0
1585
+ // controls from schemes, so strip them before checking and emitting.
1573
1586
  link(token) {
1574
- const href = (token.href || '').trim();
1575
- if (/^\s*(javascript|vbscript|data):/i.test(href)) {
1587
+ const href = sanitizeMarkdownUrl(token.href);
1588
+ if (href === null) {
1576
1589
  return this.parser.parseInline(token.tokens);
1577
1590
  }
1578
1591
  let out = '<a href="' + escapeHtml(href) + '"';
@@ -1582,10 +1595,10 @@
1582
1595
  out += '>' + this.parser.parseInline(token.tokens) + '</a>';
1583
1596
  return out;
1584
1597
  },
1585
- // Sanitize image src URLs
1598
+ // Sanitize image src URLs with the same scheme allow-list.
1586
1599
  image(token) {
1587
- const href = (token.href || '').trim();
1588
- if (/^\s*(javascript|vbscript|data):/i.test(href)) {
1600
+ const href = sanitizeMarkdownUrl(token.href);
1601
+ if (href === null) {
1589
1602
  return escapeHtml(token.text || '');
1590
1603
  }
1591
1604
  let out = '<img src="' + escapeHtml(href) + '" alt="' + escapeHtml(token.text || '') + '"';
@@ -9,10 +9,12 @@ import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
9
9
  /** Default model IDs for each known provider */
10
10
  export const defaultModelPerProvider = {
11
11
  "amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",
12
+ "ant-ling": "Ring-2.6-1T",
12
13
  anthropic: "claude-opus-4-8",
13
14
  openai: "gpt-5.4",
14
15
  "azure-openai-responses": "gpt-5.4",
15
16
  "openai-codex": "gpt-5.5",
17
+ nvidia: "nvidia/nemotron-3-super-120b-a12b",
16
18
  deepseek: "deepseek-v4-pro",
17
19
  google: "gemini-3.1-pro-preview",
18
20
  "google-vertex": "gemini-3.1-pro-preview",
@@ -23,6 +25,7 @@ export const defaultModelPerProvider = {
23
25
  groq: "openai/gpt-oss-120b",
24
26
  cerebras: "zai-glm-4.7",
25
27
  zai: "glm-5.1",
28
+ "zai-coding-cn": "glm-5.1",
26
29
  mistral: "devstral-medium-latest",
27
30
  minimax: "MiniMax-M2.7",
28
31
  "minimax-cn": "MiniMax-M2.7",
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
- import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
3
- import { homedir, tmpdir } from "node:os";
2
+ import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
4
  function getEnv() {
5
5
  if (process.platform !== "linux" || Object.keys(process.env).length > 0) {
6
6
  return process.env;
@@ -70,6 +70,12 @@ function toPosixPath(p) {
70
70
  function getHomeDir() {
71
71
  return process.env.HOME || homedir();
72
72
  }
73
+ export function getExtensionTempFolder(agentDir) {
74
+ const tempFolder = join(agentDir, "tmp", "extensions");
75
+ mkdirSync(tempFolder, { recursive: true, mode: 0o700 });
76
+ chmodSync(tempFolder, 0o700);
77
+ return tempFolder;
78
+ }
73
79
  function prefixIgnorePattern(line, prefix) {
74
80
  const trimmed = line.trim();
75
81
  if (!trimmed)
@@ -733,6 +739,7 @@ export class DefaultPackageManager {
733
739
  async install(source, options) {
734
740
  const parsed = this.parseSource(source);
735
741
  const scope = options?.local ? "project" : "user";
742
+ this.assertProjectTrustedForScope(scope);
736
743
  await this.withProgress("install", source, `Installing ${source}...`, async () => {
737
744
  if (parsed.type === "npm") {
738
745
  await this.installNpm(parsed, scope, false);
@@ -759,6 +766,7 @@ export class DefaultPackageManager {
759
766
  async remove(source, options) {
760
767
  const parsed = this.parseSource(source);
761
768
  const scope = options?.local ? "project" : "user";
769
+ this.assertProjectTrustedForScope(scope);
762
770
  await this.withProgress("remove", source, `Removing ${source}...`, async () => {
763
771
  if (parsed.type === "npm") {
764
772
  await this.uninstallNpm(parsed, scope);
@@ -1363,6 +1371,11 @@ export class DefaultPackageManager {
1363
1371
  const version = match[2];
1364
1372
  return { name, version };
1365
1373
  }
1374
+ assertProjectTrustedForScope(scope) {
1375
+ if (scope === "project" && !this.settingsManager.isProjectTrusted()) {
1376
+ throw new Error("Project is not trusted; refusing to access project package storage");
1377
+ }
1378
+ }
1366
1379
  getNpmCommand() {
1367
1380
  const configuredCommand = this.settingsManager.getNpmCommand();
1368
1381
  if (!configuredCommand || configuredCommand.length === 0) {
@@ -1564,6 +1577,7 @@ export class DefaultPackageManager {
1564
1577
  return this.getTemporaryDir("npm");
1565
1578
  }
1566
1579
  if (scope === "project") {
1580
+ this.assertProjectTrustedForScope(scope);
1567
1581
  return join(this.cwd, CONFIG_DIR_NAME, "npm");
1568
1582
  }
1569
1583
  return join(this.agentDir, "npm");
@@ -1602,6 +1616,7 @@ export class DefaultPackageManager {
1602
1616
  return join(this.getTemporaryDir("npm"), "node_modules", source.name);
1603
1617
  }
1604
1618
  if (scope === "project") {
1619
+ this.assertProjectTrustedForScope(scope);
1605
1620
  return join(this.cwd, CONFIG_DIR_NAME, "npm", "node_modules", source.name);
1606
1621
  }
1607
1622
  return join(this.agentDir, "npm", "node_modules", source.name);
@@ -1626,29 +1641,41 @@ export class DefaultPackageManager {
1626
1641
  if (scope === "temporary") {
1627
1642
  return this.getTemporaryDir(`git-${source.host}`, source.path);
1628
1643
  }
1629
- if (scope === "project") {
1630
- return join(this.cwd, CONFIG_DIR_NAME, "git", source.host, source.path);
1644
+ const installRoot = this.getGitInstallRoot(scope);
1645
+ if (!installRoot) {
1646
+ throw new Error("Missing git install root");
1631
1647
  }
1632
- return join(this.agentDir, "git", source.host, source.path);
1648
+ return this.resolveManagedPath(installRoot, source.host, source.path);
1633
1649
  }
1634
1650
  getGitInstallRoot(scope) {
1635
1651
  if (scope === "temporary") {
1636
1652
  return undefined;
1637
1653
  }
1638
1654
  if (scope === "project") {
1655
+ this.assertProjectTrustedForScope(scope);
1639
1656
  return join(this.cwd, CONFIG_DIR_NAME, "git");
1640
1657
  }
1641
1658
  return join(this.agentDir, "git");
1642
1659
  }
1643
1660
  getTemporaryDir(prefix, suffix) {
1661
+ const root = this.resolveManagedPath(getExtensionTempFolder(this.agentDir), prefix);
1644
1662
  const hash = createHash("sha256")
1645
1663
  .update(`${prefix}-${suffix ?? ""}`)
1646
1664
  .digest("hex")
1647
1665
  .slice(0, 8);
1648
- return join(tmpdir(), "pi-extensions", prefix, hash, suffix ?? "");
1666
+ return this.resolveManagedPath(root, hash, suffix ?? "");
1667
+ }
1668
+ resolveManagedPath(root, ...parts) {
1669
+ const resolvedRoot = resolve(root);
1670
+ const resolvedPath = resolve(resolvedRoot, ...parts);
1671
+ if (resolvedPath !== resolvedRoot && !resolvedPath.startsWith(`${resolvedRoot}${sep}`)) {
1672
+ throw new Error(`Refusing to use path outside package install root: ${resolvedPath}`);
1673
+ }
1674
+ return resolvedPath;
1649
1675
  }
1650
1676
  getBaseDirForScope(scope) {
1651
1677
  if (scope === "project") {
1678
+ this.assertProjectTrustedForScope(scope);
1652
1679
  return join(this.cwd, CONFIG_DIR_NAME);
1653
1680
  }
1654
1681
  if (scope === "user") {
@@ -1844,7 +1871,10 @@ export class DefaultPackageManager {
1844
1871
  themes: join(projectBaseDir, "themes"),
1845
1872
  };
1846
1873
  const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
1847
- const projectAgentsSkillDirs = collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir));
1874
+ const projectTrusted = this.settingsManager.isProjectTrusted();
1875
+ const projectAgentsSkillDirs = projectTrusted
1876
+ ? collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir))
1877
+ : [];
1848
1878
  const addResources = (resourceType, paths, metadata, overrides, baseDir) => {
1849
1879
  const target = this.getTargetMap(accumulator, resourceType);
1850
1880
  for (const path of paths) {
@@ -1852,10 +1882,12 @@ export class DefaultPackageManager {
1852
1882
  this.addResource(target, path, metadata, enabled);
1853
1883
  }
1854
1884
  };
1855
- // Project extensions from .pi/
1856
- addResources("extensions", collectAutoExtensionEntries(projectDirs.extensions), projectMetadata, projectOverrides.extensions, projectBaseDir);
1857
- // Project skills from .pi/
1858
- addResources("skills", collectAutoSkillEntries(projectDirs.skills, "pi"), projectMetadata, projectOverrides.skills, projectBaseDir);
1885
+ if (projectTrusted) {
1886
+ // Project extensions from .pi/
1887
+ addResources("extensions", collectAutoExtensionEntries(projectDirs.extensions), projectMetadata, projectOverrides.extensions, projectBaseDir);
1888
+ // Project skills from .pi/
1889
+ addResources("skills", collectAutoSkillEntries(projectDirs.skills, "pi"), projectMetadata, projectOverrides.skills, projectBaseDir);
1890
+ }
1859
1891
  // Project skills from .agents/ (each with its own baseDir)
1860
1892
  for (const agentsSkillsDir of projectAgentsSkillDirs) {
1861
1893
  const agentsBaseDir = dirname(agentsSkillsDir); // the .agents directory
@@ -1865,8 +1897,10 @@ export class DefaultPackageManager {
1865
1897
  };
1866
1898
  addResources("skills", collectAutoSkillEntries(agentsSkillsDir, "agents"), agentsMetadata, projectOverrides.skills, agentsBaseDir);
1867
1899
  }
1868
- addResources("prompts", collectAutoPromptEntries(projectDirs.prompts), projectMetadata, projectOverrides.prompts, projectBaseDir);
1869
- addResources("themes", collectAutoThemeEntries(projectDirs.themes), projectMetadata, projectOverrides.themes, projectBaseDir);
1900
+ if (projectTrusted) {
1901
+ addResources("prompts", collectAutoPromptEntries(projectDirs.prompts), projectMetadata, projectOverrides.prompts, projectBaseDir);
1902
+ addResources("themes", collectAutoThemeEntries(projectDirs.themes), projectMetadata, projectOverrides.themes, projectBaseDir);
1903
+ }
1870
1904
  // User extensions from ~/.pi/agent/
1871
1905
  addResources("extensions", collectAutoExtensionEntries(userDirs.extensions), userMetadata, userOverrides.extensions, globalBaseDir);
1872
1906
  // User skills from ~/.pi/agent/
@@ -0,0 +1,72 @@
1
+ import { isInstallTelemetryEnabled } from "./telemetry.js";
2
+ const OPENROUTER_HOST = "openrouter.ai";
3
+ const NVIDIA_NIM_HOST = "integrate.api.nvidia.com";
4
+ const CLOUDFLARE_API_HOST = "api.cloudflare.com";
5
+ const CLOUDFLARE_AI_GATEWAY_HOST = "gateway.ai.cloudflare.com";
6
+ const OPENCODE_HOST = "opencode.ai";
7
+ function matchesHost(baseUrl, expectedHost) {
8
+ try {
9
+ return new URL(baseUrl).hostname === expectedHost;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ function isOpenRouterModel(model) {
16
+ return model.provider === "openrouter" || model.baseUrl.includes(OPENROUTER_HOST);
17
+ }
18
+ function isNvidiaNimModel(model) {
19
+ return model.provider === "nvidia" || matchesHost(model.baseUrl, NVIDIA_NIM_HOST);
20
+ }
21
+ function isCloudflareModel(model) {
22
+ return (model.provider === "cloudflare-workers-ai" ||
23
+ model.provider === "cloudflare-ai-gateway" ||
24
+ matchesHost(model.baseUrl, CLOUDFLARE_API_HOST) ||
25
+ matchesHost(model.baseUrl, CLOUDFLARE_AI_GATEWAY_HOST));
26
+ }
27
+ function getDefaultAttributionHeaders(model, settingsManager) {
28
+ if (!isInstallTelemetryEnabled(settingsManager)) {
29
+ return undefined;
30
+ }
31
+ if (isOpenRouterModel(model)) {
32
+ return {
33
+ "HTTP-Referer": "https://pi.dev",
34
+ "X-OpenRouter-Title": "pi",
35
+ "X-OpenRouter-Categories": "cli-agent",
36
+ };
37
+ }
38
+ if (isNvidiaNimModel(model)) {
39
+ return {
40
+ "X-BILLING-INVOKE-ORIGIN": "Pi",
41
+ };
42
+ }
43
+ if (isCloudflareModel(model)) {
44
+ return {
45
+ "User-Agent": "pi-coding-agent",
46
+ };
47
+ }
48
+ return undefined;
49
+ }
50
+ function getSessionHeaders(model, sessionId) {
51
+ if (!sessionId)
52
+ return undefined;
53
+ if (model.provider !== "opencode" &&
54
+ model.provider !== "opencode-go" &&
55
+ !matchesHost(model.baseUrl, OPENCODE_HOST)) {
56
+ return undefined;
57
+ }
58
+ return { "x-opencode-session": sessionId, "x-opencode-client": "pi" };
59
+ }
60
+ export function mergeProviderAttributionHeaders(model, settingsManager, sessionId, ...headerSources) {
61
+ const merged = {
62
+ ...getSessionHeaders(model, sessionId),
63
+ ...getDefaultAttributionHeaders(model, settingsManager),
64
+ };
65
+ for (const headers of headerSources) {
66
+ if (headers) {
67
+ Object.assign(merged, headers);
68
+ }
69
+ }
70
+ return Object.keys(merged).length > 0 ? merged : undefined;
71
+ }
72
+ //# sourceMappingURL=provider-attribution.js.map
@@ -1,6 +1,7 @@
1
1
  export const BUILT_IN_PROVIDER_DISPLAY_NAMES = {
2
2
  anthropic: "Anthropic",
3
3
  "amazon-bedrock": "Amazon Bedrock",
4
+ "ant-ling": "Ant Ling",
4
5
  "azure-openai-responses": "Azure OpenAI Responses",
5
6
  cerebras: "Cerebras",
6
7
  "cloudflare-ai-gateway": "Cloudflare AI Gateway",
@@ -17,6 +18,7 @@ export const BUILT_IN_PROVIDER_DISPLAY_NAMES = {
17
18
  "minimax-cn": "MiniMax (China)",
18
19
  moonshotai: "Moonshot AI",
19
20
  "moonshotai-cn": "Moonshot AI (China)",
21
+ nvidia: "NVIDIA NIM",
20
22
  opencode: "OpenCode Zen",
21
23
  "opencode-go": "OpenCode Go",
22
24
  openai: "OpenAI",
@@ -25,6 +27,7 @@ export const BUILT_IN_PROVIDER_DISPLAY_NAMES = {
25
27
  "vercel-ai-gateway": "Vercel AI Gateway",
26
28
  xai: "xAI",
27
29
  zai: "ZAI",
30
+ "zai-coding-cn": "ZAI Coding Plan (China)",
28
31
  xiaomi: "Xiaomi MiMo",
29
32
  "xiaomi-token-plan-cn": "Xiaomi MiMo Token Plan (China)",
30
33
  "xiaomi-token-plan-ams": "Xiaomi MiMo Token Plan (Amsterdam)",