@psnext/slingcli 2.5.20260607-2 → 2.5.20260615-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 (205) hide show
  1. package/node_modules/@aws-sdk/core/dist-cjs/index.js +47 -2297
  2. package/node_modules/@aws-sdk/core/dist-es/index.js +3 -3
  3. package/node_modules/@aws-sdk/core/dist-types/index.d.ts +5 -5
  4. package/node_modules/@aws-sdk/core/dist-types/ts3.4/index.d.ts +5 -5
  5. package/node_modules/@aws-sdk/core/package.json +8 -8
  6. package/node_modules/@aws-sdk/credential-provider-env/package.json +4 -4
  7. package/node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler/package.json +7 -7
  8. package/node_modules/@aws-sdk/credential-provider-http/package.json +6 -5
  9. package/node_modules/@aws-sdk/credential-provider-ini/package.json +11 -11
  10. package/node_modules/@aws-sdk/credential-provider-login/package.json +5 -5
  11. package/node_modules/@aws-sdk/credential-provider-node/package.json +9 -9
  12. package/node_modules/@aws-sdk/credential-provider-process/package.json +4 -4
  13. package/node_modules/@aws-sdk/credential-provider-sso/dist-cjs/index.js +4 -1
  14. package/node_modules/@aws-sdk/credential-provider-sso/dist-es/resolveSSOCredentials.js +4 -1
  15. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +5 -5
  16. package/node_modules/@aws-sdk/credential-provider-sso/package.json +9 -7
  17. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +5 -5
  18. package/node_modules/@aws-sdk/eventstream-handler-node/package.json +3 -3
  19. package/node_modules/@aws-sdk/middleware-eventstream/package.json +3 -3
  20. package/node_modules/@aws-sdk/middleware-websocket/package.json +5 -5
  21. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
  22. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
  23. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
  24. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
  25. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
  26. package/node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler/package.json +7 -7
  27. package/node_modules/@aws-sdk/nested-clients/package.json +6 -6
  28. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +7 -6
  29. package/node_modules/@aws-sdk/types/package.json +2 -2
  30. package/node_modules/@aws-sdk/util-locate-window/package.json +2 -2
  31. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  32. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +8 -0
  33. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +1 -1
  34. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  35. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +6 -6
  36. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +906 -873
  37. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +25 -8
  38. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +19 -12
  39. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +1 -0
  40. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +8 -4
  41. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +2 -1
  42. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +2 -1
  43. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +1 -0
  44. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +1 -1
  45. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -2
  46. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  47. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +3 -5
  48. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/project-trust.js +48 -0
  49. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/startup-ui.js +133 -0
  50. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +14 -3
  51. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-runtime.js +4 -1
  52. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +2 -2
  53. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +9 -2
  54. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/utils.js +1 -1
  55. package/node_modules/@earendil-works/pi-coding-agent/dist/core/experimental.js +4 -0
  56. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js +4 -4
  57. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +34 -0
  58. package/node_modules/@earendil-works/pi-coding-agent/dist/core/index.js +1 -0
  59. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +5 -57
  60. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +41 -5
  61. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +31 -17
  62. package/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js +58 -0
  63. package/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js +24 -26
  64. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js +0 -4
  65. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js +121 -54
  66. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +11 -2
  67. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +26 -0
  68. package/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js +89 -17
  69. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +2 -2
  70. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +65 -76
  71. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js +1 -118
  72. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/first-time-setup.js +103 -0
  73. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/index.js +1 -0
  74. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +7 -1
  75. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +20 -0
  76. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tree-selector.js +87 -12
  77. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/trust-selector.js +23 -18
  78. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +104 -30
  79. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +19 -41
  80. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js +72 -18
  81. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/changelog.js +78 -0
  82. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/version-check.js +4 -27
  83. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/LICENSE +15 -0
  84. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/bin/semver.js +195 -0
  85. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/classes/comparator.js +143 -0
  86. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/classes/index.js +7 -0
  87. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/classes/range.js +557 -0
  88. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/classes/semver.js +333 -0
  89. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/clean.js +8 -0
  90. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/cmp.js +54 -0
  91. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/coerce.js +62 -0
  92. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/compare-build.js +9 -0
  93. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/compare-loose.js +5 -0
  94. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/compare.js +7 -0
  95. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/diff.js +60 -0
  96. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/eq.js +5 -0
  97. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/gt.js +5 -0
  98. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/gte.js +5 -0
  99. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/inc.js +21 -0
  100. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/lt.js +5 -0
  101. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/lte.js +5 -0
  102. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/major.js +5 -0
  103. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/minor.js +5 -0
  104. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/neq.js +5 -0
  105. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/parse.js +18 -0
  106. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/patch.js +5 -0
  107. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/prerelease.js +8 -0
  108. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/rcompare.js +5 -0
  109. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/rsort.js +5 -0
  110. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/satisfies.js +12 -0
  111. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/sort.js +5 -0
  112. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/truncate.js +48 -0
  113. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/functions/valid.js +8 -0
  114. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/index.js +93 -0
  115. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/constants.js +37 -0
  116. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/debug.js +11 -0
  117. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/identifiers.js +29 -0
  118. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/lrucache.js +42 -0
  119. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/parse-options.js +17 -0
  120. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/internal/re.js +223 -0
  121. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/package.json +78 -0
  122. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/preload.js +4 -0
  123. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/range.bnf +17 -0
  124. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/gtr.js +6 -0
  125. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/intersects.js +9 -0
  126. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/ltr.js +6 -0
  127. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/max-satisfying.js +27 -0
  128. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/min-satisfying.js +26 -0
  129. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/min-version.js +63 -0
  130. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/outside.js +82 -0
  131. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/simplify.js +49 -0
  132. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/subset.js +249 -0
  133. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/to-comparators.js +10 -0
  134. package/node_modules/@earendil-works/pi-coding-agent/node_modules/semver/ranges/valid.js +13 -0
  135. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +25 -12
  136. package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -8
  137. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +102 -43
  138. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +11 -1
  139. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +2 -2
  140. package/node_modules/@earendil-works/pi-tui/dist/index.js +2 -0
  141. package/node_modules/@earendil-works/pi-tui/dist/terminal-colors.js +51 -0
  142. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +38 -77
  143. package/node_modules/@earendil-works/pi-tui/dist/tui.js +145 -21
  144. package/node_modules/@earendil-works/pi-tui/dist/utils.js +44 -16
  145. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  146. package/node_modules/@nodable/entities/package.json +4 -1
  147. package/node_modules/@nodable/entities/src/EntityDecoder.js +104 -3
  148. package/node_modules/@nodable/entities/src/index.d.ts +77 -0
  149. package/node_modules/@nodable/entities/src/index.js +1 -1
  150. package/node_modules/@smithy/core/dist-cjs/submodules/retry/index.browser.js +3 -3
  151. package/node_modules/@smithy/core/dist-cjs/submodules/retry/index.js +3 -3
  152. package/node_modules/@smithy/core/dist-es/submodules/retry/middleware-retry/retry-pre-sra-deprecated/StandardRetryStrategy.js +2 -2
  153. package/node_modules/@smithy/core/dist-es/submodules/retry/util-retry/DefaultRateLimiter.js +1 -1
  154. package/node_modules/@smithy/core/package.json +17 -17
  155. package/node_modules/@smithy/credential-provider-imds/package.json +6 -6
  156. package/node_modules/@smithy/fetch-http-handler/package.json +9 -9
  157. package/node_modules/@smithy/signature-v4/package.json +6 -6
  158. package/node_modules/@smithy/types/package.json +9 -9
  159. package/node_modules/@types/node/README.md +1 -1
  160. package/node_modules/@types/node/http2.d.ts +1 -0
  161. package/node_modules/@types/node/package.json +2 -2
  162. package/node_modules/anynum/LICENSE +21 -0
  163. package/node_modules/anynum/README.md +142 -0
  164. package/node_modules/anynum/anynum.js +135 -0
  165. package/node_modules/anynum/digitTable.js +116 -0
  166. package/node_modules/anynum/package.json +42 -0
  167. package/node_modules/protobufjs/dist/light/protobuf.js +161 -203
  168. package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
  169. package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
  170. package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
  171. package/node_modules/protobufjs/dist/minimal/protobuf.js +34 -77
  172. package/node_modules/protobufjs/dist/minimal/protobuf.js.map +1 -1
  173. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +3 -3
  174. package/node_modules/protobufjs/dist/minimal/protobuf.min.js.map +1 -1
  175. package/node_modules/protobufjs/dist/protobuf.js +181 -223
  176. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  177. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  178. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  179. package/node_modules/protobufjs/index.d.ts +0 -8
  180. package/node_modules/protobufjs/package.json +2 -3
  181. package/node_modules/protobufjs/src/converter.js +5 -4
  182. package/node_modules/protobufjs/src/decoder.js +1 -1
  183. package/node_modules/protobufjs/src/service.js +5 -7
  184. package/node_modules/protobufjs/src/type.js +3 -1
  185. package/node_modules/protobufjs/src/util/minimal.js +1 -4
  186. package/node_modules/protobufjs/src/verifier.js +1 -1
  187. package/node_modules/semver/classes/range.js +11 -2
  188. package/node_modules/semver/package.json +2 -2
  189. package/node_modules/strnum/CHANGELOG.md +8 -0
  190. package/node_modules/strnum/README.md +9 -0
  191. package/node_modules/strnum/package.json +4 -1
  192. package/node_modules/strnum/strnum.js +9 -1
  193. package/package.json +6 -6
  194. package/slingshot/index.js +260 -258
  195. package/node_modules/@protobufjs/inquire/CHANGELOG.md +0 -8
  196. package/node_modules/@protobufjs/inquire/LICENSE +0 -26
  197. package/node_modules/@protobufjs/inquire/README.md +0 -13
  198. package/node_modules/@protobufjs/inquire/index.d.ts +0 -10
  199. package/node_modules/@protobufjs/inquire/index.js +0 -38
  200. package/node_modules/@protobufjs/inquire/package.json +0 -21
  201. package/node_modules/@protobufjs/inquire/tests/data/array.js +0 -1
  202. package/node_modules/@protobufjs/inquire/tests/data/emptyArray.js +0 -1
  203. package/node_modules/@protobufjs/inquire/tests/data/emptyObject.js +0 -1
  204. package/node_modules/@protobufjs/inquire/tests/data/object.js +0 -1
  205. package/node_modules/@protobufjs/inquire/tests/index.js +0 -20
@@ -47,10 +47,14 @@ export const streamBedrock = (model, context, options = {}) => {
47
47
  const useBearerToken = bearerToken !== undefined && process.env.AWS_BEDROCK_SKIP_AUTH !== "1";
48
48
  // in Node.js/Bun environment only
49
49
  if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
50
- // Region resolution: explicit option > env vars > SDK default chain.
51
- // When AWS_PROFILE is set, we leave region undefined so the SDK can
52
- // resovle it from aws profile configs. Otherwise fall back to us-east-1.
53
- if (configuredRegion) {
50
+ // Region resolution: ARN-embedded > explicit option > env vars > SDK default chain.
51
+ // When the model ID is an inference profile ARN, extract the region from it.
52
+ // This avoids conflicts with AWS_REGION set for other services.
53
+ const arnRegionMatch = model.id.match(/^arn:aws(?:-[a-z0-9-]+)?:bedrock:([a-z0-9-]+):/);
54
+ if (arnRegionMatch) {
55
+ config.region = arnRegionMatch[1];
56
+ }
57
+ else if (configuredRegion) {
54
58
  config.region = configuredRegion;
55
59
  }
56
60
  else if (endpointRegion && useExplicitEndpoint) {
@@ -194,6 +198,12 @@ const BEDROCK_ERROR_PREFIXES = {
194
198
  ThrottlingException: "Throttling error",
195
199
  ServiceUnavailableException: "Service unavailable",
196
200
  };
201
+ /**
202
+ * Some models reject the account/profile's configured Bedrock data retention mode
203
+ * (e.g. "data retention mode 'default' is not available for this model"). Point
204
+ * users at the AWS docs explaining how to configure a supported mode.
205
+ */
206
+ const BEDROCK_DATA_RETENTION_DOCS_URL = "https://docs.aws.amazon.com/bedrock/latest/userguide/data-retention.html";
197
207
  /**
198
208
  * Format a Bedrock error with a human-readable prefix.
199
209
  * AWS SDK exceptions (both from `client.send()` and from stream event items)
@@ -203,11 +213,14 @@ const BEDROCK_ERROR_PREFIXES = {
203
213
  */
204
214
  function formatBedrockError(error) {
205
215
  const message = error instanceof Error ? error.message : JSON.stringify(error);
216
+ const dataRetentionHint = /data retention mode/i.test(message)
217
+ ? ` See ${BEDROCK_DATA_RETENTION_DOCS_URL} for supported data retention modes.`
218
+ : "";
206
219
  if (error instanceof BedrockRuntimeServiceException) {
207
220
  const prefix = BEDROCK_ERROR_PREFIXES[error.name] ?? error.name;
208
- return `${prefix}: ${message}`;
221
+ return `${prefix}: ${message}${dataRetentionHint}`;
209
222
  }
210
- return message;
223
+ return `${message}${dataRetentionHint}`;
211
224
  }
212
225
  /**
213
226
  * Header keys that must never be overwritten by caller-supplied headers.
@@ -387,11 +400,15 @@ function getModelMatchCandidates(modelId, modelName) {
387
400
  }
388
401
  function supportsAdaptiveThinking(modelId, modelName) {
389
402
  const candidates = getModelMatchCandidates(modelId, modelName);
390
- return candidates.some((s) => s.includes("opus-4-6") || s.includes("opus-4-7") || s.includes("opus-4-8") || s.includes("sonnet-4-6"));
403
+ return candidates.some((s) => s.includes("opus-4-6") ||
404
+ s.includes("opus-4-7") ||
405
+ s.includes("opus-4-8") ||
406
+ s.includes("sonnet-4-6") ||
407
+ s.includes("fable-5"));
391
408
  }
392
409
  function supportsNativeXhighEffort(model) {
393
410
  const candidates = getModelMatchCandidates(model.id, model.name);
394
- return candidates.some((s) => s.includes("opus-4-7") || s.includes("opus-4-8"));
411
+ return candidates.some((s) => s.includes("opus-4-7") || s.includes("opus-4-8") || s.includes("fable-5"));
395
412
  }
396
413
  function mapThinkingLevelToEffort(model, level) {
397
414
  if (level === "xhigh" && supportsNativeXhighEffort(model))
@@ -486,7 +486,11 @@ export const streamAnthropic = (model, context, options) => {
486
486
  }
487
487
  else if (event.type === "message_delta") {
488
488
  if (event.delta.stop_reason) {
489
- output.stopReason = mapStopReason(event.delta.stop_reason);
489
+ const stopReasonResult = mapStopReason(event.delta.stop_reason, event.delta.stop_details);
490
+ output.stopReason = stopReasonResult.stopReason;
491
+ if (stopReasonResult.errorMessage) {
492
+ output.errorMessage = stopReasonResult.errorMessage;
493
+ }
490
494
  }
491
495
  // Only update usage fields if present (not null).
492
496
  // Preserves input_tokens from message_start when proxies omit it in message_delta.
@@ -512,7 +516,7 @@ export const streamAnthropic = (model, context, options) => {
512
516
  throw new Error("Request was aborted");
513
517
  }
514
518
  if (output.stopReason === "aborted" || output.stopReason === "error") {
515
- throw new Error("An unknown error occurred");
519
+ throw new Error(output.errorMessage || "An unknown error occurred");
516
520
  }
517
521
  stream.push({ type: "done", reason: output.stopReason, message: output });
518
522
  stream.end();
@@ -533,7 +537,7 @@ export const streamAnthropic = (model, context, options) => {
533
537
  };
534
538
  /**
535
539
  * Map ThinkingLevel to Anthropic effort levels for adaptive thinking.
536
- * Note: effort "max" is only valid on Opus 4.6, while Opus 4.7 supports "xhigh".
540
+ * Note: effort "max" is only valid on Opus 4.6, while Opus 4.7+ and Fable 5 support "xhigh".
537
541
  */
538
542
  function mapThinkingLevelToEffort(model, level) {
539
543
  const mapped = level ? model.thinkingLevelMap?.[level] : undefined;
@@ -726,7 +730,7 @@ function buildParams(model, context, isOAuthToken, options) {
726
730
  };
727
731
  }
728
732
  }
729
- else if (options?.thinkingEnabled === false) {
733
+ else if (options?.thinkingEnabled === false && model.thinkingLevelMap?.off !== null) {
730
734
  params.thinking = { type: "disabled" };
731
735
  }
732
736
  }
@@ -935,22 +939,25 @@ function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, cach
935
939
  };
936
940
  });
937
941
  }
938
- function mapStopReason(reason) {
942
+ function mapStopReason(reason, stopDetails) {
939
943
  switch (reason) {
940
944
  case "end_turn":
941
- return "stop";
945
+ return { stopReason: "stop" };
942
946
  case "max_tokens":
943
- return "length";
947
+ return { stopReason: "length" };
944
948
  case "tool_use":
945
- return "toolUse";
949
+ return { stopReason: "toolUse" };
946
950
  case "refusal":
947
- return "error";
951
+ return {
952
+ stopReason: "error",
953
+ errorMessage: stopDetails?.explanation || `The model refused to complete the request`,
954
+ };
948
955
  case "pause_turn": // Stop is good enough -> resubmit
949
- return "stop";
956
+ return { stopReason: "stop" };
950
957
  case "stop_sequence":
951
- return "stop"; // We don't supply stop sequences, so this should never happen
958
+ return { stopReason: "stop" }; // We don't supply stop sequences, so this should never happen
952
959
  case "sensitive": // Content flagged by safety filters (not yet in SDK types)
953
- return "error";
960
+ return { stopReason: "error" };
954
961
  default:
955
962
  // Handle unknown stop reasons gracefully (API may add new values)
956
963
  throw new Error(`Unhandled stop reason: ${reason}`);
@@ -189,6 +189,7 @@ function buildParams(model, context, options, deploymentName) {
189
189
  input: messages,
190
190
  stream: true,
191
191
  prompt_cache_key: clampOpenAIPromptCacheKey(options?.sessionId),
192
+ store: false,
192
193
  };
193
194
  if (options?.maxTokens) {
194
195
  params.max_output_tokens = options?.maxTokens;
@@ -32,7 +32,9 @@ const JWT_CLAIM_PATH = "https://api.openai.com/auth";
32
32
  const DEFAULT_MAX_RETRIES = 0;
33
33
  const BASE_DELAY_MS = 1000;
34
34
  const DEFAULT_MAX_RETRY_DELAY_MS = 60_000;
35
- const DEFAULT_SSE_HEADER_TIMEOUT_MS = 10_000;
35
+ // Keep a bounded pre-header timeout so zero-event Codex SSE stalls fail instead of
36
+ // leaving callers stuck on "Working..." indefinitely. See #4945.
37
+ const DEFAULT_SSE_HEADER_TIMEOUT_MS = 20_000;
36
38
  const DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS = 15_000;
37
39
  const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
38
40
  const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009;
@@ -1116,7 +1118,9 @@ function extractAccountId(token) {
1116
1118
  return null;
1117
1119
  const payload = JSON.parse(atob(parts[1]));
1118
1120
  const accountId = payload?.[JWT_CLAIM_PATH]?.chatgpt_account_id;
1119
- return accountId || null;
1121
+ if (!accountId)
1122
+ throw new Error("No account ID in token");
1123
+ return accountId;
1120
1124
  }
1121
1125
  catch {
1122
1126
  return null;
@@ -1137,8 +1141,8 @@ function buildBaseCodexHeaders(initHeaders, additionalHeaders, accountId, token)
1137
1141
  if (accountId) {
1138
1142
  headers.set("chatgpt-account-id", accountId);
1139
1143
  }
1140
- headers.set("originator", "pi");
1141
- const userAgent = _os ? `pi (${_os.platform()} ${_os.release()}; ${_os.arch()})` : "pi (browser)";
1144
+ headers.set("originator", "sling");
1145
+ const userAgent = _os ? `sling (${_os.platform()} ${_os.release()}; ${_os.arch()})` : "sling (browser)";
1142
1146
  headers.set("User-Agent", userAgent);
1143
1147
  return headers;
1144
1148
  }
@@ -431,7 +431,8 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
431
431
  params.tool_choice = options.toolChoice;
432
432
  }
433
433
  if (compat.thinkingFormat === "zai" && model.reasoning) {
434
- params.enable_thinking = !!options?.reasoningEffort;
434
+ const zaiParams = params;
435
+ zaiParams.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
435
436
  }
436
437
  else if (compat.thinkingFormat === "qwen" && model.reasoning) {
437
438
  params.enable_thinking = !!options?.reasoningEffort;
@@ -63,7 +63,8 @@ export function convertResponsesMessages(model, context, allowedToolCallProvider
63
63
  const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
64
64
  const includeSystemPrompt = options?.includeSystemPrompt ?? true;
65
65
  if (includeSystemPrompt && context.systemPrompt) {
66
- const role = model.reasoning ? "developer" : "system";
66
+ const compat = model.compat;
67
+ const role = model.reasoning && compat?.supportsDeveloperRole !== false ? "developer" : "system";
67
68
  messages.push({
68
69
  role,
69
70
  content: sanitizeSurrogates(context.systemPrompt),
@@ -23,6 +23,7 @@ function resolveCacheRetention(cacheRetention) {
23
23
  }
24
24
  function getCompat(model) {
25
25
  return {
26
+ supportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,
26
27
  sendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,
27
28
  supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,
28
29
  };
@@ -224,7 +224,7 @@ async function pollOpenAICodexDeviceAuth(device, signal) {
224
224
  },
225
225
  });
226
226
  }
227
- async function createAuthorizationFlow(originator = "pi") {
227
+ async function createAuthorizationFlow(originator = "sling") {
228
228
  const { verifier, challenge } = await generatePKCE();
229
229
  const state = createState();
230
230
  const url = new URL(AUTHORIZE_URL);
@@ -10,6 +10,7 @@
10
10
  * - Anthropic: "413 {\"error\":{\"type\":\"request_too_large\",\"message\":\"Request exceeds the maximum size\"}}"
11
11
  * - OpenAI: "Your input exceeds the context window of this model"
12
12
  * - OpenAI/LiteLLM: "Requested token count exceeds the model's maximum context length of 131072 tokens"
13
+ * - OpenAI-compatible: "Input length (265330) exceeds model's maximum context length (262144)."
13
14
  * - Google: "The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)"
14
15
  * - xAI: "This model's maximum prompt length is 131072 but the request contains 537812 tokens"
15
16
  * - Groq: "Please reduce the length of the messages or completion"
@@ -34,7 +35,7 @@ const OVERFLOW_PATTERNS = [
34
35
  /request_too_large/i, // Anthropic request byte-size overflow (HTTP 413)
35
36
  /input is too long for requested model/i, // Amazon Bedrock
36
37
  /exceeds the context window/i, // OpenAI (Completions & Responses API)
37
- /exceeds (?:the )?(?:model'?s )?maximum context length of [\d,]+ tokens?/i, // OpenAI-compatible proxies (LiteLLM)
38
+ /exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i, // OpenAI-compatible proxies (LiteLLM)
38
39
  /input token count.*exceeds the maximum/i, // Google (Gemini)
39
40
  /maximum prompt length is \d+/i, // xAI (Grok)
40
41
  /reduce the length of the messages/i, // Groq
@@ -81,7 +82,7 @@ const NON_OVERFLOW_PATTERNS = [
81
82
  *
82
83
  * **Reliable detection (returns error with detectable message):**
83
84
  * - Anthropic: "prompt is too long: X tokens > Y maximum" or "request_too_large"
84
- * - OpenAI (Completions & Responses): "exceeds the context window" or "exceeds the model's maximum context length of X tokens"
85
+ * - OpenAI (Completions & Responses): "exceeds the context window", "exceeds the model's maximum context length of X tokens", or "exceeds model's maximum context length (X)"
85
86
  * - Google Gemini: "input token count exceeds the maximum"
86
87
  * - xAI (Grok): "maximum prompt length is X but request contains Y"
87
88
  * - Groq: "reduce the length of the messages"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-ai",
3
- "version": "0.78.1",
3
+ "version": "0.79.3",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -217,11 +217,9 @@ ${chalk.bold("Commands:")}
217
217
  ${APP_NAME} install <source> [-l] Install extension source and add to settings
218
218
  ${APP_NAME} remove <source> [-l] Remove extension source from settings
219
219
  ${APP_NAME} uninstall <source> [-l] Alias for remove
220
- ${APP_NAME} update [source|self|pi] Update pi and installed extensions
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
220
+ ${APP_NAME} update [source|self|sling] Update sling and installed extensions
221
+ ${APP_NAME} list List installed extensions from settings
222
+ ${APP_NAME} config Open TUI to enable/disable package resources
225
223
  ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list
226
224
 
227
225
  ${chalk.bold("Options:")}
@@ -0,0 +1,48 @@
1
+ import chalk from "chalk";
2
+ import { showStartupInput, showStartupSelector } from "./startup-ui.js";
3
+ export function createProjectTrustContext(options) {
4
+ return {
5
+ cwd: options.cwd,
6
+ mode: options.mode === "interactive" ? "tui" : options.mode,
7
+ hasUI: options.hasUI,
8
+ ui: {
9
+ select: async (title, selectOptions) => {
10
+ if (!options.hasUI) {
11
+ return undefined;
12
+ }
13
+ if (options.mode !== "interactive") {
14
+ return undefined;
15
+ }
16
+ return showStartupSelector(options.settingsManager, title, selectOptions.map((option) => ({ label: option, value: option })));
17
+ },
18
+ confirm: async (title, message) => {
19
+ if (!options.hasUI) {
20
+ return false;
21
+ }
22
+ if (options.mode !== "interactive") {
23
+ return false;
24
+ }
25
+ return ((await showStartupSelector(options.settingsManager, `${title}\n${message}`, [
26
+ { label: "Yes", value: true },
27
+ { label: "No", value: false },
28
+ ])) ?? false);
29
+ },
30
+ input: async (title, placeholder) => {
31
+ if (!options.hasUI) {
32
+ return undefined;
33
+ }
34
+ if (options.mode !== "interactive") {
35
+ return undefined;
36
+ }
37
+ return showStartupInput(options.settingsManager, title, placeholder);
38
+ },
39
+ notify: (message, type = "info") => {
40
+ if (options.mode !== "interactive") {
41
+ const color = type === "error" ? chalk.red : type === "warning" ? chalk.yellow : chalk.cyan;
42
+ console.error(color(message));
43
+ }
44
+ },
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=project-trust.js.map
@@ -0,0 +1,133 @@
1
+ import { ProcessTerminal, setKeybindings, TUI } from "@earendil-works/pi-tui";
2
+ import { existsSync } from "fs";
3
+ import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, getSettingsPath, PACKAGE_NAME } from "../config.js";
4
+ import { areExperimentalFeaturesEnabled } from "../core/experimental.js";
5
+ import { KeybindingsManager } from "../core/keybindings.js";
6
+ import { ExtensionInputComponent } from "../modes/interactive/components/extension-input.js";
7
+ import { ExtensionSelectorComponent } from "../modes/interactive/components/extension-selector.js";
8
+ import { FirstTimeSetupComponent, } from "../modes/interactive/components/first-time-setup.js";
9
+ import { detectTerminalBackgroundTheme, initTheme, setTheme } from "../modes/interactive/theme/theme.js";
10
+ const OFFICIAL_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
11
+ const OFFICIAL_APP_NAME = "pi";
12
+ const OFFICIAL_CONFIG_DIR_NAME = ".pi";
13
+ function isOfficialDistribution({ packageName, appName, configDirName }) {
14
+ return (packageName === OFFICIAL_PACKAGE_NAME &&
15
+ appName === OFFICIAL_APP_NAME &&
16
+ configDirName === OFFICIAL_CONFIG_DIR_NAME);
17
+ }
18
+ function createStartupTui(settingsManager) {
19
+ initTheme(settingsManager.getTheme());
20
+ setKeybindings(KeybindingsManager.create());
21
+ const ui = new TUI(new ProcessTerminal(), settingsManager.getShowHardwareCursor());
22
+ ui.setClearOnShrink(settingsManager.getClearOnShrink());
23
+ return ui;
24
+ }
25
+ async function clearStartupTui(ui) {
26
+ ui.clear();
27
+ ui.requestRender();
28
+ await new Promise((resolve) => setTimeout(resolve, 25));
29
+ }
30
+ /**
31
+ * First-time setup runs when all of these hold:
32
+ * - this is the official Pi distribution (not a fork/rebrand)
33
+ * - experimental features are enabled (PI_EXPERIMENTAL=1)
34
+ * - the default agent directory is used (no custom agent dir override)
35
+ * - setup was not completed before (settings.json does not exist)
36
+ */
37
+ export function shouldRunFirstTimeSetup(settingsPath = getSettingsPath()) {
38
+ if (!isOfficialDistribution({
39
+ packageName: PACKAGE_NAME,
40
+ appName: APP_NAME,
41
+ configDirName: CONFIG_DIR_NAME,
42
+ })) {
43
+ return false;
44
+ }
45
+ if (!areExperimentalFeaturesEnabled()) {
46
+ return false;
47
+ }
48
+ if (process.env[ENV_AGENT_DIR]) {
49
+ return false;
50
+ }
51
+ return !existsSync(settingsPath);
52
+ }
53
+ export async function showStartupSelector(settingsManager, title, options) {
54
+ return new Promise((resolve) => {
55
+ const ui = createStartupTui(settingsManager);
56
+ let settled = false;
57
+ const finish = async (result) => {
58
+ if (settled) {
59
+ return;
60
+ }
61
+ settled = true;
62
+ await clearStartupTui(ui);
63
+ ui.stop();
64
+ resolve(result);
65
+ };
66
+ const selector = new ExtensionSelectorComponent(title, options.map((option) => option.label), (option) => void finish(options.find((entry) => entry.label === option)?.value), () => void finish(undefined), { tui: ui });
67
+ ui.addChild(selector);
68
+ ui.setFocus(selector);
69
+ ui.start();
70
+ });
71
+ }
72
+ /** Show the first-time setup dialog and persist the result */
73
+ export async function showFirstTimeSetup(settingsManager) {
74
+ return new Promise((resolve) => {
75
+ const ui = createStartupTui(settingsManager);
76
+ let settled = false;
77
+ const finish = async (result) => {
78
+ if (settled) {
79
+ return;
80
+ }
81
+ settled = true;
82
+ if (result) {
83
+ settingsManager.setTheme(result.theme);
84
+ settingsManager.setEnableAnalytics(result.shareAnalytics);
85
+ await settingsManager.flush();
86
+ }
87
+ await clearStartupTui(ui);
88
+ ui.stop();
89
+ resolve();
90
+ };
91
+ const showSetup = async () => {
92
+ ui.start();
93
+ const detection = await detectTerminalBackgroundTheme({ ui, timeoutMs: 100 });
94
+ setTheme(detection.theme);
95
+ const component = new FirstTimeSetupComponent({
96
+ detectedTheme: detection.theme,
97
+ onThemePreview: (themeName) => {
98
+ setTheme(themeName);
99
+ ui.requestRender();
100
+ },
101
+ onSubmit: (result) => void finish(result),
102
+ onCancel: () => void finish(undefined),
103
+ });
104
+ ui.addChild(component);
105
+ ui.setFocus(component);
106
+ ui.requestRender();
107
+ };
108
+ void showSetup();
109
+ });
110
+ }
111
+ export async function showStartupInput(settingsManager, title, placeholder) {
112
+ return new Promise((resolve) => {
113
+ const ui = createStartupTui(settingsManager);
114
+ let settled = false;
115
+ const finish = async (result) => {
116
+ if (settled) {
117
+ return;
118
+ }
119
+ settled = true;
120
+ input.dispose();
121
+ await clearStartupTui(ui);
122
+ ui.stop();
123
+ resolve(result);
124
+ };
125
+ const input = new ExtensionInputComponent(title, placeholder, (value) => void finish(value), () => void finish(undefined), {
126
+ tui: ui,
127
+ });
128
+ ui.addChild(input);
129
+ ui.setFocus(input);
130
+ ui.start();
131
+ });
132
+ }
133
+ //# sourceMappingURL=startup-ui.js.map
@@ -76,16 +76,24 @@ function getSelfUpdateCommandForMethod(method, installedPackageName, updatePacka
76
76
  switch (method) {
77
77
  case "bun-binary":
78
78
  return undefined;
79
- case "pnpm":
79
+ case "pnpm": {
80
+ const match = readCommandOutput("pnpm", ["root", "-g"])
81
+ ? undefined
82
+ : /^(.*[\\/]global[\\/][^\\/]+)[\\/]\.pnpm[\\/]/.exec(getPackageDir());
83
+ const binDirArgs = match
84
+ ? [`--config.global-bin-dir=${process.env.PNPM_HOME || dirname(dirname(match[1]))}`]
85
+ : [];
80
86
  return makeSelfUpdateCommand(makeSelfUpdateCommandStep("pnpm", [
81
87
  "install",
82
88
  "-g",
83
89
  "--ignore-scripts",
84
90
  "--config.minimumReleaseAge=0",
91
+ ...binDirArgs,
85
92
  updatePackageName,
86
93
  ]), updatePackageName === installedPackageName
87
94
  ? undefined
88
- : makeSelfUpdateCommandStep("pnpm", ["remove", "-g", installedPackageName]));
95
+ : makeSelfUpdateCommandStep("pnpm", ["remove", "-g", ...binDirArgs, installedPackageName]));
96
+ }
89
97
  case "yarn":
90
98
  return makeSelfUpdateCommand(makeSelfUpdateCommandStep("yarn", ["global", "add", "--ignore-scripts", updatePackageName]), updatePackageName === installedPackageName
91
99
  ? undefined
@@ -157,7 +165,10 @@ function getGlobalPackageRoots(method, _packageName, npmCommand) {
157
165
  }
158
166
  case "pnpm": {
159
167
  const root = readCommandOutput("pnpm", ["root", "-g"]);
160
- return root ? [root, dirname(root)] : [];
168
+ if (root)
169
+ return [root, dirname(root)];
170
+ const match = /^(.*[\\/]global[\\/][^\\/]+)[\\/]\.pnpm[\\/]/.exec(getPackageDir());
171
+ return match ? [match[1]] : [];
161
172
  }
162
173
  case "yarn": {
163
174
  const dir = readCommandOutput("yarn", ["global", "dir"]);
@@ -136,6 +136,7 @@ export class AgentSessionRuntime {
136
136
  agentDir: this.services.agentDir,
137
137
  sessionManager,
138
138
  sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
139
+ projectTrustContext: options?.projectTrustContextFactory?.(sessionManager.getCwd()),
139
140
  }));
140
141
  await this.finishSessionReplacement(options?.withSession);
141
142
  return { cancelled: false };
@@ -147,7 +148,9 @@ export class AgentSessionRuntime {
147
148
  }
148
149
  const previousSessionFile = this.session.sessionFile;
149
150
  const sessionDir = this.session.sessionManager.getSessionDir();
150
- const sessionManager = SessionManager.create(this.cwd, sessionDir);
151
+ const sessionManager = this.session.sessionManager.isPersisted()
152
+ ? SessionManager.create(this.cwd, sessionDir)
153
+ : SessionManager.inMemory(this.cwd);
151
154
  if (options?.parentSession) {
152
155
  sessionManager.newSession({ parentSession: options.parentSession });
153
156
  }
@@ -3,7 +3,7 @@ import { getAgentDir } from "../config.js";
3
3
  import { resolvePath } from "../utils/paths.js";
4
4
  import { AuthStorage } from "./auth-storage.js";
5
5
  import { ModelRegistry } from "./model-registry.js";
6
- import { DefaultResourceLoader } from "./resource-loader.js";
6
+ import { DefaultResourceLoader, } from "./resource-loader.js";
7
7
  import { createAgentSession } from "./sdk.js";
8
8
  import { SettingsManager } from "./settings-manager.js";
9
9
  function applyExtensionFlagValues(resourceLoader, extensionFlagValues) {
@@ -63,7 +63,7 @@ export async function createAgentSessionServices(options) {
63
63
  agentDir,
64
64
  settingsManager,
65
65
  });
66
- await resourceLoader.reload();
66
+ await resourceLoader.reload(options.resourceLoaderReloadOptions);
67
67
  const diagnostics = [];
68
68
  const extensionsResult = resourceLoader.getExtensions();
69
69
  for (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {
@@ -15,7 +15,7 @@
15
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
16
16
  import { basename, dirname } from "node:path";
17
17
  import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai";
18
- import { theme } from "../modes/interactive/theme/theme.js";
18
+ import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
19
19
  import { stripFrontmatter } from "../utils/frontmatter.js";
20
20
  import { resolvePath } from "../utils/paths.js";
21
21
  import { sleep } from "../utils/sleep.js";
@@ -1236,6 +1236,10 @@ export class AgentSession {
1236
1236
  // =========================================================================
1237
1237
  // Queue Mode Management
1238
1238
  // =========================================================================
1239
+ syncQueueModesFromSettings() {
1240
+ this.agent.steeringMode = this.settingsManager.getSteeringMode();
1241
+ this.agent.followUpMode = this.settingsManager.getFollowUpMode();
1242
+ }
1239
1243
  /**
1240
1244
  * Set steering message mode.
1241
1245
  * Saves to settings.
@@ -1777,6 +1781,7 @@ export class AgentSession {
1777
1781
  }, {
1778
1782
  getModel: () => this.model,
1779
1783
  isIdle: () => !this.isStreaming,
1784
+ isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
1780
1785
  getSignal: () => this.agent.signal,
1781
1786
  abort: () => {
1782
1787
  if (this._extensionAbortHandler) {
@@ -1931,6 +1936,7 @@ export class AgentSession {
1931
1936
  const previousFlagValues = this._extensionRunner.getFlagValues();
1932
1937
  await emitSessionShutdownEvent(this._extensionRunner, { type: "session_shutdown", reason: "reload" });
1933
1938
  await this.settingsManager.reload();
1939
+ this.syncQueueModesFromSettings();
1934
1940
  resetApiProviders();
1935
1941
  await this._resourceLoader.reload();
1936
1942
  this._buildRuntime({
@@ -2428,7 +2434,8 @@ export class AgentSession {
2428
2434
  * @returns Path to exported file
2429
2435
  */
2430
2436
  async exportToHtml(outputPath) {
2431
- const themeName = this.settingsManager.getTheme();
2437
+ const configuredThemeName = this.settingsManager.getTheme();
2438
+ const themeName = configuredThemeName && getThemeByName(configuredThemeName) ? configuredThemeName : undefined;
2432
2439
  // Create tool renderer if we have an extension runner (for custom tool HTML rendering)
2433
2440
  const toolRenderer = createToolHtmlRenderer({
2434
2441
  getToolDefinition: (name) => this.getToolDefinition(name),
@@ -147,7 +147,7 @@ export function serializeConversation(messages) {
147
147
  // ============================================================================
148
148
  // Summarization System Prompt
149
149
  // ============================================================================
150
- export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
150
+ export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.
151
151
 
152
152
  Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;
153
153
  //# sourceMappingURL=utils.js.map
@@ -0,0 +1,4 @@
1
+ export function areExperimentalFeaturesEnabled() {
2
+ return process.env.PI_EXPERIMENTAL === "1";
3
+ }
4
+ //# sourceMappingURL=experimental.js.map
@@ -323,14 +323,14 @@ export async function loadExtensionFromFactory(factory, cwd, eventBus, runtime,
323
323
  /**
324
324
  * Load extensions from paths.
325
325
  */
326
- export async function loadExtensions(paths, cwd, eventBus) {
326
+ export async function loadExtensions(paths, cwd, eventBus, runtime) {
327
327
  const extensions = [];
328
328
  const errors = [];
329
329
  const resolvedCwd = resolvePath(cwd);
330
330
  const resolvedEventBus = eventBus ?? createEventBus();
331
- const runtime = createExtensionRuntime();
331
+ const resolvedRuntime = runtime ?? createExtensionRuntime();
332
332
  for (const extPath of paths) {
333
- const { extension, error } = await loadExtension(extPath, resolvedCwd, resolvedEventBus, runtime);
333
+ const { extension, error } = await loadExtension(extPath, resolvedCwd, resolvedEventBus, resolvedRuntime);
334
334
  if (error) {
335
335
  errors.push({ path: extPath, error });
336
336
  continue;
@@ -342,7 +342,7 @@ export async function loadExtensions(paths, cwd, eventBus) {
342
342
  return {
343
343
  extensions,
344
344
  errors,
345
- runtime,
345
+ runtime: resolvedRuntime,
346
346
  };
347
347
  }
348
348
  function readPiManifest(packageJsonPath) {