@oh-my-pi/pi-coding-agent 17.2.9 → 17.2.11

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 (281) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/{CHANGELOG-8yy8h3bc.md → CHANGELOG-d9xenpn9.md} +83 -0
  3. package/dist/cli.js +10208 -12596
  4. package/dist/types/capability/mcp.d.ts +11 -0
  5. package/dist/types/capability/skill.d.ts +6 -0
  6. package/dist/types/cli/args.d.ts +1 -0
  7. package/dist/types/cli/command-help.d.ts +3 -0
  8. package/dist/types/commands/share.d.ts +25 -0
  9. package/dist/types/commit/agentic/index.d.ts +3 -1
  10. package/dist/types/commit/execute.d.ts +32 -0
  11. package/dist/types/commit/index.d.ts +2 -1
  12. package/dist/types/commit/pipeline.d.ts +7 -1
  13. package/dist/types/config/model-registry.d.ts +4 -0
  14. package/dist/types/config/model-resolver.d.ts +13 -0
  15. package/dist/types/config/settings-schema.d.ts +1 -34
  16. package/dist/types/discovery/agent-plugin-format.d.ts +143 -0
  17. package/dist/types/discovery/agent-plugins.d.ts +1 -0
  18. package/dist/types/discovery/contained-path.d.ts +34 -0
  19. package/dist/types/discovery/index.d.ts +1 -0
  20. package/dist/types/extensibility/custom-commands/types.d.ts +5 -5
  21. package/dist/types/extensibility/custom-tools/types.d.ts +3 -3
  22. package/dist/types/extensibility/extensions/loader.d.ts +9 -2
  23. package/dist/types/extensibility/extensions/types.d.ts +45 -8
  24. package/dist/types/extensibility/hooks/types.d.ts +5 -5
  25. package/dist/types/extensibility/shared-events.d.ts +3 -2
  26. package/dist/types/extensibility/skills.d.ts +5 -0
  27. package/dist/types/index.d.ts +2 -2
  28. package/dist/types/main.d.ts +1 -1
  29. package/dist/types/mcp/transports/header-policy.d.ts +45 -0
  30. package/dist/types/mcp/types.d.ts +15 -0
  31. package/dist/types/modes/acp/acp-agent.d.ts +1 -1
  32. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
  33. package/dist/types/modes/acp/acp-event-mapper.d.ts +1 -1
  34. package/dist/types/modes/acp/acp-mode.d.ts +1 -1
  35. package/dist/types/modes/components/agent-hub-projection.d.ts +38 -0
  36. package/dist/types/modes/components/agent-hub-renderer.d.ts +41 -0
  37. package/dist/types/modes/components/agent-hub.d.ts +14 -5
  38. package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
  39. package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
  40. package/dist/types/modes/components/custom-editor.d.ts +1 -2
  41. package/dist/types/modes/components/model-browser.d.ts +9 -1
  42. package/dist/types/modes/components/status-line/types.d.ts +2 -0
  43. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  44. package/dist/types/modes/interactive-mode.d.ts +8 -1
  45. package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
  46. package/dist/types/registry/agent-registry.d.ts +47 -0
  47. package/dist/types/registry/persisted-agents.d.ts +3 -1
  48. package/dist/types/secrets/index.d.ts +23 -1
  49. package/dist/types/session/agent-session-events.d.ts +2 -2
  50. package/dist/types/session/agent-session.d.ts +4 -2
  51. package/dist/types/session/messages.d.ts +1 -0
  52. package/dist/types/session/prewalk.d.ts +3 -1
  53. package/dist/types/session/session-entries.d.ts +10 -0
  54. package/dist/types/session/session-loader.d.ts +11 -1
  55. package/dist/types/session/session-manager.d.ts +9 -1
  56. package/dist/types/session/session-tools.d.ts +18 -1
  57. package/dist/types/session/turn-recovery.d.ts +7 -2
  58. package/dist/types/slash-commands/acp-builtins.d.ts +1 -1
  59. package/dist/types/slash-commands/available-commands.d.ts +1 -1
  60. package/dist/types/task/executor.d.ts +6 -0
  61. package/dist/types/task/index.d.ts +4 -3
  62. package/dist/types/task/read-only-policy.d.ts +3 -0
  63. package/dist/types/task/structured-subagent.d.ts +2 -0
  64. package/dist/types/task/types.d.ts +4 -0
  65. package/dist/types/tools/bash.d.ts +3 -3
  66. package/dist/types/tools/browser/launch.d.ts +2 -1
  67. package/dist/types/tools/browser/tab-worker.d.ts +2 -2
  68. package/dist/types/tools/path-utils.d.ts +1 -0
  69. package/dist/types/tools/read.d.ts +1 -5
  70. package/dist/types/tools/run-scope.d.ts +27 -1
  71. package/dist/types/tools/shell-tokenize.d.ts +16 -0
  72. package/dist/types/tools/terminal-output.d.ts +1 -1
  73. package/dist/types/utils/turndown.d.ts +1 -1
  74. package/dist/types/vibe/runtime.d.ts +2 -3
  75. package/dist/types/web/scrapers/readthedocs.d.ts +0 -3
  76. package/dist/types/web/search/providers/browser-headers.d.ts +2 -3
  77. package/examples/custom-tools/README.md +1 -1
  78. package/examples/extensions/README.md +1 -1
  79. package/examples/extensions/api-demo.ts +5 -6
  80. package/examples/extensions/chalk-logger.ts +1 -1
  81. package/examples/extensions/hello.ts +2 -2
  82. package/examples/extensions/reload-runtime.ts +1 -1
  83. package/examples/extensions/tools.ts +2 -2
  84. package/examples/extensions/with-deps/index.ts +1 -1
  85. package/examples/sdk/06-extensions.ts +1 -1
  86. package/package.json +15 -31
  87. package/scripts/bundle-dist.ts +1 -11
  88. package/scripts/legacy-pi-virtual-module.ts +4 -1
  89. package/src/advisor/runtime.ts +54 -0
  90. package/src/capability/mcp.ts +11 -0
  91. package/src/capability/skill.ts +6 -0
  92. package/src/cli/agents-cli.ts +1 -1
  93. package/src/cli/args.ts +24 -2
  94. package/src/cli/auth-broker-cli.ts +1 -1
  95. package/src/cli/auth-gateway-cli.ts +1 -1
  96. package/src/cli/bench-cli.ts +1 -1
  97. package/src/cli/claude-trace-cli.ts +1 -1
  98. package/src/cli/command-help.ts +4 -0
  99. package/src/cli/config-cli.ts +1 -1
  100. package/src/cli/dry-balance-cli.ts +1 -1
  101. package/src/cli/file-processor.ts +1 -1
  102. package/src/cli/flag-tables.ts +4 -0
  103. package/src/cli/gallery-cli.ts +1 -1
  104. package/src/cli/grep-cli.ts +1 -1
  105. package/src/cli/grievances-cli.ts +1 -1
  106. package/src/cli/help-extra.ts +1 -1
  107. package/src/cli/models-cli.ts +1 -1
  108. package/src/cli/plugin-cli.ts +1 -1
  109. package/src/cli/read-cli.ts +1 -1
  110. package/src/cli/setup-cli.ts +1 -1
  111. package/src/cli/shell-cli.ts +1 -1
  112. package/src/cli/ssh-cli.ts +1 -1
  113. package/src/cli/stats-cli.ts +1 -1
  114. package/src/cli/tiny-models-cli.ts +1 -1
  115. package/src/cli/ttsr-cli.ts +1 -1
  116. package/src/cli/update-cli.ts +1 -1
  117. package/src/cli/usage-cli.ts +1 -1
  118. package/src/cli/web-search-cli.ts +1 -1
  119. package/src/cli/worktree-cli.ts +1 -1
  120. package/src/cli-commands.ts +5 -0
  121. package/src/commands/commit.ts +16 -3
  122. package/src/commands/say.ts +1 -1
  123. package/src/commands/share.ts +71 -0
  124. package/src/commands/token.ts +1 -1
  125. package/src/commit/agentic/agent.ts +1 -1
  126. package/src/commit/agentic/index.ts +39 -21
  127. package/src/commit/cli.ts +1 -1
  128. package/src/commit/execute.ts +56 -0
  129. package/src/commit/index.ts +2 -1
  130. package/src/commit/pipeline.ts +20 -7
  131. package/src/config/model-discovery.ts +1 -1
  132. package/src/config/model-registry.ts +21 -1
  133. package/src/config/model-resolver.ts +54 -7
  134. package/src/config/settings-schema.ts +2 -33
  135. package/src/config/settings.ts +46 -0
  136. package/src/discovery/agent-plugin-format.ts +551 -0
  137. package/src/discovery/agent-plugins.ts +341 -0
  138. package/src/discovery/agents.ts +4 -2
  139. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +5 -4
  140. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +1 -1
  141. package/src/discovery/claude-plugins.ts +21 -5
  142. package/src/discovery/contained-path.ts +78 -0
  143. package/src/discovery/helpers.ts +23 -9
  144. package/src/discovery/index.ts +1 -0
  145. package/src/discovery/omp-plugins.ts +20 -7
  146. package/src/eval/py/runner.py +38 -1
  147. package/src/exec/non-interactive-env.ts +1 -0
  148. package/src/extensibility/custom-commands/loader.ts +4 -4
  149. package/src/extensibility/custom-commands/types.ts +5 -5
  150. package/src/extensibility/custom-tools/loader.ts +4 -4
  151. package/src/extensibility/custom-tools/types.ts +3 -3
  152. package/src/extensibility/extensions/loader.ts +85 -20
  153. package/src/extensibility/extensions/runner.ts +6 -0
  154. package/src/extensibility/extensions/types.ts +51 -8
  155. package/src/extensibility/hooks/loader.ts +4 -5
  156. package/src/extensibility/hooks/types.ts +5 -5
  157. package/src/extensibility/plugins/legacy-pi-compat.ts +53 -0
  158. package/src/extensibility/plugins/marketplace/manager.ts +2 -1
  159. package/src/extensibility/shared-events.ts +3 -2
  160. package/src/extensibility/skills.ts +9 -0
  161. package/src/index.ts +2 -2
  162. package/src/internal-urls/memory-protocol.ts +5 -1
  163. package/src/internal-urls/skill-protocol.ts +14 -0
  164. package/src/internal-urls/vault-protocol.ts +2 -2
  165. package/src/launch/client.ts +11 -1
  166. package/src/launch/protocol.ts +7 -2
  167. package/src/launch/terminal-output.ts +1 -1
  168. package/src/main.ts +88 -23
  169. package/src/markit/converters/docx.ts +1 -1
  170. package/src/markit/converters/epub.ts +1 -1
  171. package/src/markit/converters/pptx.ts +1 -1
  172. package/src/markit/converters/xlsx.ts +1 -1
  173. package/src/mcp/config.ts +3 -0
  174. package/src/mcp/manager.ts +12 -9
  175. package/src/mcp/transports/header-policy.ts +95 -0
  176. package/src/mcp/transports/http.ts +35 -52
  177. package/src/mcp/transports/sse.ts +20 -27
  178. package/src/mcp/types.ts +15 -0
  179. package/src/modes/acp/acp-agent.ts +20 -9
  180. package/src/modes/acp/acp-client-bridge.ts +1 -1
  181. package/src/modes/acp/acp-event-mapper.ts +1 -1
  182. package/src/modes/acp/acp-mode.ts +1 -1
  183. package/src/modes/components/agent-dashboard.ts +2 -0
  184. package/src/modes/components/agent-hub-projection.ts +248 -0
  185. package/src/modes/components/agent-hub-renderer.ts +194 -0
  186. package/src/modes/components/agent-hub.ts +674 -207
  187. package/src/modes/components/agent-transcript-viewer.ts +3 -0
  188. package/src/modes/components/assistant-message.ts +1 -1
  189. package/src/modes/components/chat-transcript-builder.ts +3 -0
  190. package/src/modes/components/custom-editor.ts +0 -9
  191. package/src/modes/components/extensions/inspector-panel.ts +11 -6
  192. package/src/modes/components/footer.ts +1 -3
  193. package/src/modes/components/model-browser.ts +11 -3
  194. package/src/modes/components/model-hub.ts +4 -1
  195. package/src/modes/components/status-line/component.ts +1 -0
  196. package/src/modes/components/status-line/segments.ts +10 -7
  197. package/src/modes/components/status-line/types.ts +2 -0
  198. package/src/modes/components/tool-execution.ts +13 -16
  199. package/src/modes/components/tree-selector.ts +62 -3
  200. package/src/modes/controllers/command-controller.ts +4 -1
  201. package/src/modes/controllers/event-controller.ts +44 -20
  202. package/src/modes/controllers/extension-ui-controller.ts +2 -2
  203. package/src/modes/controllers/input-controller.ts +20 -2
  204. package/src/modes/controllers/mcp-command-controller.ts +81 -20
  205. package/src/modes/controllers/selector-controller.ts +41 -49
  206. package/src/modes/controllers/streaming-reveal.ts +1 -1
  207. package/src/modes/interactive-mode.ts +13 -2
  208. package/src/modes/rpc/rpc-mode.ts +2 -2
  209. package/src/modes/runtime-init.ts +1 -1
  210. package/src/modes/theme/theme.ts +2 -2
  211. package/src/modes/utils/transcript-render-helpers.ts +4 -2
  212. package/src/modes/utils/ui-helpers.ts +1 -0
  213. package/src/prompts/tools/computer.md +1 -1
  214. package/src/registry/agent-lifecycle.ts +14 -7
  215. package/src/registry/agent-registry.ts +65 -2
  216. package/src/registry/persisted-agents.ts +341 -16
  217. package/src/sdk.ts +6 -49
  218. package/src/secrets/index.ts +52 -1
  219. package/src/session/agent-session-events.ts +2 -2
  220. package/src/session/agent-session.ts +54 -16
  221. package/src/session/messages.ts +1 -0
  222. package/src/session/prewalk.ts +57 -17
  223. package/src/session/session-context.ts +3 -5
  224. package/src/session/session-entries.ts +10 -0
  225. package/src/session/session-handoff.ts +5 -1
  226. package/src/session/session-listing.ts +1 -1
  227. package/src/session/session-loader.ts +74 -8
  228. package/src/session/session-manager.ts +22 -2
  229. package/src/session/session-paths.ts +57 -9
  230. package/src/session/session-tools.ts +65 -4
  231. package/src/session/todo-tracker.ts +11 -1
  232. package/src/session/turn-recovery.ts +96 -74
  233. package/src/slash-commands/acp-builtins.ts +1 -1
  234. package/src/slash-commands/available-commands.ts +1 -1
  235. package/src/slash-commands/builtin-registry.ts +12 -8
  236. package/src/task/executor.ts +70 -20
  237. package/src/task/index.ts +30 -34
  238. package/src/task/isolation-runner.ts +24 -11
  239. package/src/task/persisted-revive.ts +12 -5
  240. package/src/task/read-only-policy.ts +27 -0
  241. package/src/task/structured-subagent.ts +14 -4
  242. package/src/task/types.ts +4 -0
  243. package/src/tools/auto-generated-guard.ts +1 -1
  244. package/src/tools/bash-interactive.ts +4 -4
  245. package/src/tools/bash-skill-urls.ts +15 -0
  246. package/src/tools/bash.ts +16 -17
  247. package/src/tools/browser/cmux/cmux-tab.ts +66 -18
  248. package/src/tools/browser/launch.ts +41 -12
  249. package/src/tools/browser/readable.ts +9 -9
  250. package/src/tools/browser/tab-supervisor.ts +12 -3
  251. package/src/tools/browser/tab-worker-entry.ts +1 -1
  252. package/src/tools/browser/tab-worker.ts +101 -12
  253. package/src/tools/debug.ts +1 -1
  254. package/src/tools/fetch.ts +1 -1
  255. package/src/tools/jtd-to-json-schema.ts +123 -21
  256. package/src/tools/path-utils.ts +9 -2
  257. package/src/tools/read.ts +21 -9
  258. package/src/tools/run-scope.ts +290 -4
  259. package/src/tools/shell-tokenize.ts +98 -0
  260. package/src/tools/terminal-output.ts +1 -1
  261. package/src/tools/todo.ts +1 -1
  262. package/src/utils/clipboard.ts +10 -2
  263. package/src/utils/external-editor.ts +4 -2
  264. package/src/utils/jj.ts +1 -1
  265. package/src/utils/turndown.ts +1 -2
  266. package/src/vibe/runtime.ts +5 -5
  267. package/src/web/scrapers/arxiv.ts +1 -1
  268. package/src/web/scrapers/go-pkg.ts +1 -1
  269. package/src/web/scrapers/iacr.ts +1 -1
  270. package/src/web/scrapers/readthedocs.ts +2 -1
  271. package/src/web/scrapers/twitter.ts +2 -2
  272. package/src/web/scrapers/types.ts +1 -1
  273. package/src/web/scrapers/wikipedia.ts +1 -1
  274. package/src/web/search/providers/browser-headers.ts +12 -39
  275. package/src/web/search/providers/codex.ts +3 -26
  276. package/src/web/search/providers/ecosia.ts +1 -1
  277. package/src/web/search/providers/exa.ts +1 -1
  278. package/src/web/search/providers/google.ts +1 -1
  279. package/src/web/search/providers/mojeek.ts +1 -1
  280. package/src/web/search/providers/startpage.ts +1 -1
  281. package/src/markit/converters/mammoth.d.ts +0 -24
@@ -30,17 +30,7 @@ const ALWAYS_EXTERNAL = [
30
30
  // import would load the unpatched npm package in users' installs (currently
31
31
  // @ark/schema is patched, so it — and arktype, which pulls @ark/schema — stay
32
32
  // bundled).
33
- const RUNTIME_EXTERNAL = [
34
- "puppeteer-core",
35
- "@puppeteer/browsers",
36
- "@babel/parser",
37
- "@xterm/headless",
38
- "turndown",
39
- "turndown-plugin-gfm",
40
- "@mozilla/readability",
41
- "linkedom",
42
- "@agentclientprotocol/sdk",
43
- ];
33
+ const RUNTIME_EXTERNAL = ["puppeteer-core", "@babel/parser"];
44
34
 
45
35
  async function runCommand(command: string[]): Promise<void> {
46
36
  const proc = Bun.spawn(command, {
@@ -151,7 +151,10 @@ export async function collectBundledPiEntries(): Promise<BundledPiEntry[]> {
151
151
  const glob = new Bun.Glob(`**/*${pattern.sourceSuffix}`);
152
152
  const matches: string[] = [];
153
153
  for await (const match of glob.scan({ cwd: sourceDir, onlyFiles: true })) {
154
- matches.push(match);
154
+ // Bun.Glob yields host separators; the export keys and generated
155
+ // identifiers below are `/`-shaped. Same normalization as
156
+ // `generate-docs-index.ts`.
157
+ matches.push(match.split(path.sep).join("/"));
155
158
  }
156
159
  matches.sort();
157
160
  for (const match of matches) {
@@ -296,6 +296,14 @@ export class AdvisorRuntime {
296
296
  #failureNotified = false;
297
297
  /** Consecutive quarantined turns since the last success/reset (issue #6661). */
298
298
  #consecutiveQuarantines = 0;
299
+ /**
300
+ * Model identities this refusal cascade has already tried. The cascade walks
301
+ * the fallback chain to exhaustion — that is what the chain is for — but
302
+ * visits each model at most once, so a chain whose keys point back at each
303
+ * other (A→B, B→A) cannot ping-pong forever. Cleared when a successful or
304
+ * terminal turn ends the cascade, or on reset, so a later refusal starts fresh.
305
+ */
306
+ readonly #refusalModelsTried = new Set<string>();
299
307
  /** Whether primary reasoning is included in advisor deltas for the current model. */
300
308
  #includeThinking = true;
301
309
  #modelIdentity: string | undefined;
@@ -541,6 +549,7 @@ export class AdvisorRuntime {
541
549
  this.#failing = false;
542
550
  this.#droppedBacklogs = 0;
543
551
  this.#consecutiveQuarantines = 0;
552
+ this.#refusalModelsTried.clear();
544
553
  this.#failureNotified = false;
545
554
  this.#resetAdvisorContext(true, true);
546
555
  }
@@ -936,6 +945,7 @@ export class AdvisorRuntime {
936
945
  this.#failureNotified = false;
937
946
  this.#droppedBacklogs = 0;
938
947
  this.#consecutiveQuarantines = 0;
948
+ this.#refusalModelsTried.clear();
939
949
  if (this.host.onTurnSuccess) {
940
950
  try {
941
951
  await raceWithSignal(Promise.resolve(this.host.onTurnSuccess()), iterationAbort.signal);
@@ -995,6 +1005,50 @@ export class AdvisorRuntime {
995
1005
  continue;
996
1006
  }
997
1007
  }
1008
+ // A refusal that outlives the strip is this model's policy call, not
1009
+ // a malformed request, so hand it to the host's model fallback before
1010
+ // declaring the advisor dead. The cascade walks the chain to
1011
+ // exhaustion (the host returns false once candidates run out); the
1012
+ // tried-set only stops a cyclic chain from revisiting a model. The
1013
+ // primary turn-recovery path already allows fallback on refusals.
1014
+ const refusalModel = this.host.getModelIdentity?.() ?? this.#modelIdentity ?? "";
1015
+ let refusalRecovered = false;
1016
+ try {
1017
+ if (!this.#refusalModelsTried.has(refusalModel)) {
1018
+ this.#refusalModelsTried.add(refusalModel);
1019
+ refusalRecovered =
1020
+ (await raceWithSignal(
1021
+ Promise.resolve(this.host.onTurnError?.(err, failedMessages, iterationAbort.signal)),
1022
+ iterationAbort.signal,
1023
+ )) === true;
1024
+ } else {
1025
+ logger.debug("advisor refusal chain exhausted", { model: refusalModel });
1026
+ }
1027
+ } catch (hookErr) {
1028
+ logger.debug("advisor onTurnError hook failed after refusal", { err: String(hookErr) });
1029
+ }
1030
+ if (this.#epoch !== epoch) continue;
1031
+ if (this.#sessionTransitionPaused) {
1032
+ this.#pending.unshift(...popped);
1033
+ continue;
1034
+ }
1035
+ if (refusalRecovered) {
1036
+ this.#consecutiveFailures = 0;
1037
+ this.#failureNotified = false;
1038
+ this.#pending.unshift({
1039
+ text: batch,
1040
+ rawMessages,
1041
+ renderRevision: this.#renderRevision,
1042
+ turns: finalTurns,
1043
+ wip,
1044
+ overflowRecovery: recoveringOverflow || undefined,
1045
+ });
1046
+ logger.debug("advisor refusal recovered by model fallback");
1047
+ continue;
1048
+ }
1049
+ // The batch is terminal, so the next primary update is a new
1050
+ // refusal cascade and must be allowed to try the chain again.
1051
+ this.#refusalModelsTried.clear();
998
1052
  this.#notifyFailureOnce(err);
999
1053
  this.#clearSeenContext();
1000
1054
  this.#backlog = Math.max(0, this.#backlog - finalTurns);
@@ -27,12 +27,23 @@ export interface MCPServer {
27
27
  args?: string[];
28
28
  /** Environment variables */
29
29
  env?: Record<string, string>;
30
+ /**
31
+ * `literal`: env values are opaque plugin package data (Agent Plugins
32
+ * §§4.1/9.2) — exempt from env-name lookup and `!command` resolution.
33
+ */
34
+ envPolicy?: "literal";
30
35
  /** Working directory for stdio transport */
31
36
  cwd?: string;
32
37
  /** URL (for HTTP/SSE transport) */
33
38
  url?: string;
34
39
  /** HTTP headers (for HTTP transport) */
35
40
  headers?: Record<string, string>;
41
+ /**
42
+ * `origin-locked`: configured headers are literal package data pinned to the
43
+ * configured URL's origin (Agent Plugins §7.2.1) — never expanded, never
44
+ * forwarded cross-origin, and client-generated headers win case-insensitively.
45
+ */
46
+ headerPolicy?: "origin-locked";
36
47
  /** Authentication configuration */
37
48
  auth?: {
38
49
  type: "oauth" | "apikey";
@@ -43,6 +43,12 @@ export interface Skill {
43
43
  content: string;
44
44
  /** Parsed frontmatter */
45
45
  frontmatter?: SkillFrontmatter;
46
+ /**
47
+ * Filesystem-resolved plugin root this skill was packaged in (Agent Plugins
48
+ * §4.1). When set, every `skill://` resource access must realpath-resolve
49
+ * within this directory; symlinks may target other files inside it.
50
+ */
51
+ containRoot?: string;
46
52
  /** Source level */
47
53
  level: "user" | "project";
48
54
  /** Source metadata */
@@ -6,8 +6,8 @@
6
6
  import * as fs from "node:fs/promises";
7
7
  import * as path from "node:path";
8
8
  import { getAgentDir, getProjectDir, isEnoent } from "@oh-my-pi/pi-utils";
9
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
10
  import { YAML } from "bun";
10
- import chalk from "chalk";
11
11
  import { theme } from "../modes/theme/theme";
12
12
  import { loadBundledAgents } from "../task/agents";
13
13
  import type { AgentDefinition } from "../task/types";
package/src/cli/args.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * CLI argument parsing and help display
3
3
  */
4
+ import * as path from "node:path";
4
5
  import { $env, APP_NAME, logger } from "@oh-my-pi/pi-utils";
5
- import chalk from "chalk";
6
+ import chalk from "@oh-my-pi/pi-utils/chalk";
6
7
  import type { ServiceTierOpenAISettingValue } from "../config/service-tier";
7
8
  import { CLI_THINKING_LEVELS, type ConfiguredThinkingLevel, parseCliThinkingLevel } from "../thinking";
8
9
  import { BUILTIN_TOOL_NAMES, HIDDEN_TOOL_NAMES, normalizeToolNames } from "../tools/builtin-names";
@@ -68,6 +69,7 @@ export interface Args {
68
69
  noPty?: boolean;
69
70
  hooks?: string[];
70
71
  extensions?: string[];
72
+ trustedExtensions?: string[];
71
73
  noExtensions?: boolean;
72
74
  pluginDirs?: string[];
73
75
  print?: boolean;
@@ -110,7 +112,7 @@ const PARSE_DEPS: ParseDeps = {
110
112
  thinkingEfforts: CLI_THINKING_LEVELS,
111
113
  };
112
114
 
113
- const WINDOWS_PATH_VALUE_FLAGS: ReadonlySet<string> = new Set(["--extension", "-e", "--hook"]);
115
+ const WINDOWS_PATH_VALUE_FLAGS = new Set(["--extension", "-e", "--hook", "--trusted-extension"]);
114
116
  const WINDOWS_PATH_START_RE =
115
117
  /^(?:[A-Za-z]:[\\/]|\\\\[?]\\(?:[A-Za-z]:[\\/]|UNC[\\/])|\\\\[^\\/]+[\\/][^\\/]+[\\/]|\/\/[?]\/(?:[A-Za-z]:\/|UNC\/)|\/\/[^/]+\/[^/]+\/)/;
116
118
  const WINDOWS_MODULE_PATH_SUFFIX_RE = /\.(?:[cm]?[jt]sx?)$/i;
@@ -156,6 +158,7 @@ export function parseArgs(inputArgs: string[], extensionFlags?: Map<string, { ty
156
158
  // `--` ends option parsing (POSIX end-of-options). Everything after it is
157
159
  // literal positional text, so flag-shaped messages are not parsed or rejected.
158
160
  let sawSeparator = false;
161
+ let trustedFlagCount = 0;
159
162
  for (let i = 0; i < args.length; i++) {
160
163
  let arg = args[i];
161
164
  if (sawSeparator) {
@@ -200,6 +203,7 @@ export function parseArgs(inputArgs: string[], extensionFlags?: Map<string, { ty
200
203
  }
201
204
  }
202
205
  } else if (STRING_VALUE_FLAGS.has(arg)) {
206
+ if (arg === "--trusted-extension") trustedFlagCount++;
203
207
  // Built-in string flags consume the next token even when it is flag-looking
204
208
  // (`--system-prompt --profile foo` ⇒ the prompt is the literal "--profile").
205
209
  // The one token they must never absorb is the profile bootstrap's internal
@@ -304,6 +308,24 @@ export function parseArgs(inputArgs: string[], extensionFlags?: Map<string, { ty
304
308
  }
305
309
  }
306
310
 
311
+ const swallowedTrustedFlag = [...(result.extensions ?? []), ...(result.hooks ?? [])].some(
312
+ value => value === "--trusted-extension" || value.startsWith("--trusted-extension="),
313
+ );
314
+ if ((result.trustedExtensions?.length ?? 0) !== trustedFlagCount || swallowedTrustedFlag) {
315
+ throw new CliUsageError("--trusted-extension requires a non-empty, non-flag value");
316
+ }
317
+ if (trustedFlagCount > 0 && ((result.extensions?.length ?? 0) > 0 || (result.hooks?.length ?? 0) > 0)) {
318
+ throw new CliUsageError("--trusted-extension cannot be combined with --extension, -e, or --hook");
319
+ }
320
+ for (const trustedPath of result.trustedExtensions ?? []) {
321
+ if (trustedPath.length === 0) {
322
+ throw new CliUsageError("--trusted-extension requires a non-empty, non-flag value");
323
+ }
324
+ if (!path.isAbsolute(trustedPath)) {
325
+ throw new CliUsageError(`--trusted-extension requires an absolute path: ${trustedPath}`);
326
+ }
327
+ }
328
+
307
329
  return result;
308
330
  }
309
331
 
@@ -34,9 +34,9 @@ import {
34
34
  } from "@oh-my-pi/pi-ai";
35
35
  import { AuthBrokerClient, DEFAULT_AUTH_BROKER_BIND, startAuthBroker } from "@oh-my-pi/pi-ai/auth-broker";
36
36
  import { $which, APP_NAME, getAgentDbPath, getConfigRootDir, isEnoent, logger, VERSION } from "@oh-my-pi/pi-utils";
37
+ import chalk from "@oh-my-pi/pi-utils/chalk";
37
38
  import { setTransports as setLoggerTransports } from "@oh-my-pi/pi-utils/logger";
38
39
  import { $ } from "bun";
39
- import chalk from "chalk";
40
40
  import { resolveAuthBrokerConfig } from "../session/auth-broker-config";
41
41
 
42
42
  export type AuthBrokerAction = "serve" | "token" | "login" | "logout" | "status" | "import" | "migrate" | "list";
@@ -33,7 +33,7 @@ import {
33
33
  import { DEFAULT_AUTH_GATEWAY_BIND, startAuthGateway } from "@oh-my-pi/pi-ai/auth-gateway";
34
34
  import { type GeneratedProvider, getBundledModels } from "@oh-my-pi/pi-catalog/models";
35
35
  import { getConfigRootDir, isEnoent, logger, VERSION } from "@oh-my-pi/pi-utils";
36
- import chalk from "chalk";
36
+ import chalk from "@oh-my-pi/pi-utils/chalk";
37
37
  import { ModelRegistry } from "../config/model-registry";
38
38
  import { type AuthBrokerClientConfig, resolveAuthBrokerConfig } from "../session/auth-broker-config";
39
39
 
@@ -17,7 +17,7 @@ import { resolveModelServiceTier, streamSimple } from "@oh-my-pi/pi-ai";
17
17
  import { buildModelProviderPriorityRank } from "@oh-my-pi/pi-catalog/identity";
18
18
  import { replaceTabs, truncateToWidth } from "@oh-my-pi/pi-tui";
19
19
  import { formatDuration, getProjectDir, prompt } from "@oh-my-pi/pi-utils";
20
- import chalk from "chalk";
20
+ import chalk from "@oh-my-pi/pi-utils/chalk";
21
21
  import type { ApiKeyResolverModel } from "../config/api-key-resolver";
22
22
  import { ModelRegistry } from "../config/model-registry";
23
23
  import {
@@ -10,7 +10,7 @@ import * as path from "node:path";
10
10
  import * as tls from "node:tls";
11
11
  import * as zlib from "node:zlib";
12
12
  import { PtySession } from "@oh-my-pi/pi-natives";
13
- import xterm from "@xterm/headless";
13
+ import xterm from "@oh-my-pi/pi-utils/vterm";
14
14
 
15
15
  const DEFAULT_PROXY_HOST = "127.0.0.1";
16
16
  const DEFAULT_PROXY_PORT = 8080;
@@ -72,6 +72,10 @@ export const sayHelp = {
72
72
 
73
73
  export const searchHelp = { description: "Test web search providers" } satisfies CommandMetadata;
74
74
 
75
+ export const shareHelp = {
76
+ description: "Share a saved session via an encrypted link (same as /share)",
77
+ } satisfies CommandMetadata;
78
+
75
79
  export const setupHelp = {
76
80
  description: "Run onboarding setup or install dependencies for optional features",
77
81
  } satisfies CommandMetadata;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { APP_NAME, getAgentDir } from "@oh-my-pi/pi-utils";
9
- import chalk from "chalk";
9
+ import chalk from "@oh-my-pi/pi-utils/chalk";
10
10
  import {
11
11
  getDefault,
12
12
  getEnumValues,
@@ -14,7 +14,7 @@ import type {
14
14
  import { streamSimple } from "@oh-my-pi/pi-ai";
15
15
  import { replaceTabs, truncateToWidth } from "@oh-my-pi/pi-tui";
16
16
  import { formatDuration, getProjectDir } from "@oh-my-pi/pi-utils";
17
- import chalk from "chalk";
17
+ import chalk from "@oh-my-pi/pi-utils/chalk";
18
18
  import { ModelRegistry } from "../config/model-registry";
19
19
  import {
20
20
  formatModelString,
@@ -5,7 +5,7 @@ import * as fs from "node:fs";
5
5
  import * as path from "node:path";
6
6
  import type { ImageContent } from "@oh-my-pi/pi-ai";
7
7
  import { getProjectDir, isEnoent, readImageMetadata } from "@oh-my-pi/pi-utils";
8
- import chalk from "chalk";
8
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
9
  import { resolveReadPath } from "../tools/path-utils";
10
10
  import { formatBytes } from "../tools/render-utils";
11
11
  import { formatDimensionNote, resizeImage } from "../utils/image-resize";
@@ -220,6 +220,10 @@ export const STRING_SETTERS: Record<string, StringSetter> = {
220
220
  },
221
221
  "--extension": setExtension,
222
222
  "-e": setExtension,
223
+ "--trusted-extension": (result, value) => {
224
+ result.trustedExtensions = result.trustedExtensions ?? [];
225
+ result.trustedExtensions.push(value);
226
+ },
223
227
  "--plugin-dir": (result, value) => {
224
228
  result.pluginDirs = result.pluginDirs ?? [];
225
229
  result.pluginDirs.push(value);
@@ -153,7 +153,7 @@ export async function renderGalleryState(
153
153
  const component = new ToolExecutionComponent(
154
154
  componentName,
155
155
  streamingArgs,
156
- { showImages: false },
156
+ { showImages: false, useBuiltInRenderer: !fixture.customRendered },
157
157
  tool,
158
158
  ui,
159
159
  getProjectDir(),
@@ -6,7 +6,7 @@
6
6
  import * as path from "node:path";
7
7
  import { GrepOutputMode, grep } from "@oh-my-pi/pi-natives";
8
8
  import { APP_NAME } from "@oh-my-pi/pi-utils";
9
- import chalk from "chalk";
9
+ import chalk from "@oh-my-pi/pi-utils/chalk";
10
10
  import { expandPath } from "../tools/path-utils";
11
11
 
12
12
  export interface GrepCommandArgs {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * CLI handler for `omp grievances` — view, clean, and manually push reported tool issues.
3
3
  */
4
- import chalk from "chalk";
4
+ import chalk from "@oh-my-pi/pi-utils/chalk";
5
5
  import { Settings } from "../config/settings";
6
6
  import { flushGrievances, openAutoQaDb } from "../tools/report-tool-issue";
7
7
 
@@ -1,6 +1,6 @@
1
1
  import "@oh-my-pi/pi-utils/env";
2
+ import chalk from "@oh-my-pi/pi-utils/chalk";
2
3
  import { APP_NAME, CONFIG_DIR_NAME } from "@oh-my-pi/pi-utils/dirs";
3
- import chalk from "chalk";
4
4
 
5
5
  export function getExtraHelpText(): string {
6
6
  return `${chalk.bold("Environment Variables:")}
@@ -14,7 +14,7 @@
14
14
  import type { Api, Effort, Model } from "@oh-my-pi/pi-ai";
15
15
  import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
16
16
  import { formatNumber, getProjectDir } from "@oh-my-pi/pi-utils";
17
- import chalk from "chalk";
17
+ import chalk from "@oh-my-pi/pi-utils/chalk";
18
18
  import { ModelRegistry } from "../config/model-registry";
19
19
  import { Settings } from "../config/settings";
20
20
  import { discoverAndLoadExtensions, ExtensionRunner, emitSessionShutdownEvent } from "../extensibility/extensions";
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { APP_NAME, getProjectDir } from "@oh-my-pi/pi-utils";
8
- import chalk from "chalk";
8
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
9
  import { resolveOrDefaultProjectRegistryPath } from "../discovery/helpers";
10
10
  import { PluginManager, parseSettingValue, validateSetting } from "../extensibility/plugins";
11
11
  import {
@@ -6,7 +6,7 @@
6
6
  * (including truncation/limit notices appended by the meta-notice wrapper).
7
7
  */
8
8
  import { getProjectDir } from "@oh-my-pi/pi-utils";
9
- import chalk from "chalk";
9
+ import chalk from "@oh-my-pi/pi-utils/chalk";
10
10
  import { Settings } from "../config/settings";
11
11
  import { extractUriScheme } from "../internal-urls/parse";
12
12
  import { InternalUrlRouter } from "../internal-urls/router";
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import * as path from "node:path";
7
7
  import { APP_NAME, getProjectDir, getPythonEnvDir } from "@oh-my-pi/pi-utils";
8
- import chalk from "chalk";
8
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
9
  import { Settings, settings } from "../config/settings";
10
10
  import { checkPythonKernelAvailability } from "../eval/py/kernel";
11
11
  import { theme } from "../modes/theme/theme";
@@ -7,7 +7,7 @@ import * as path from "node:path";
7
7
  import { createInterface } from "node:readline/promises";
8
8
  import { Shell } from "@oh-my-pi/pi-natives";
9
9
  import { APP_NAME, getProjectDir } from "@oh-my-pi/pi-utils";
10
- import chalk from "chalk";
10
+ import chalk from "@oh-my-pi/pi-utils/chalk";
11
11
  import { Settings } from "../config/settings";
12
12
  import { buildMinimizerOptions } from "../exec/bash-executor";
13
13
  import { getOrCreateSnapshot } from "../utils/shell-snapshot";
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { getSSHConfigPath } from "@oh-my-pi/pi-utils";
8
- import chalk from "chalk";
8
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
9
  import { addSSHHost, readSSHConfigFile, removeSSHHost, type SSHHostConfig } from "../ssh/config-writer";
10
10
 
11
11
  // =============================================================================
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { truncateToWidth } from "@oh-my-pi/pi-tui/utils";
8
8
  import { APP_NAME, formatDuration, formatNumber, formatPercent } from "@oh-my-pi/pi-utils";
9
- import chalk from "chalk";
9
+ import chalk from "@oh-my-pi/pi-utils/chalk";
10
10
  import { openPath } from "../utils/open";
11
11
 
12
12
  /**
@@ -1,5 +1,5 @@
1
1
  import { formatBytes } from "@oh-my-pi/pi-utils";
2
- import chalk from "chalk";
2
+ import chalk from "@oh-my-pi/pi-utils/chalk";
3
3
  import {
4
4
  DEFAULT_TINY_TITLE_LOCAL_MODEL_KEY,
5
5
  getTinyLocalModelSpec,
@@ -13,8 +13,8 @@
13
13
  import * as fs from "node:fs";
14
14
  import * as path from "node:path";
15
15
  import { AstMatchStrictness, astMatch, FileType, type GlobMatch, glob } from "@oh-my-pi/pi-natives";
16
+ import chalk from "@oh-my-pi/pi-utils/chalk";
16
17
  import { getProjectDir } from "@oh-my-pi/pi-utils/dirs";
17
- import chalk from "chalk";
18
18
  import { BUILTIN_DEFAULTS_PROVIDER_ID, compileRuleCondition, type Rule, ruleCapability } from "../capability/rule";
19
19
  import { bucketRules } from "../capability/rule-buckets";
20
20
  import { Settings } from "../config/settings";
@@ -11,8 +11,8 @@ import * as path from "node:path";
11
11
  import { Transform } from "node:stream";
12
12
  import { pipeline } from "node:stream/promises";
13
13
  import { $env, $which, APP_NAME, compareVersions, isEnoent, VERSION } from "@oh-my-pi/pi-utils";
14
+ import chalk from "@oh-my-pi/pi-utils/chalk";
14
15
  import { $ } from "bun";
15
- import chalk from "chalk";
16
16
  import { theme } from "../modes/theme/theme";
17
17
  import { isTimeoutError, withTimeoutSignal } from "../utils/fetch-timeout";
18
18
 
@@ -18,7 +18,7 @@ import {
18
18
  type UsageUnit,
19
19
  } from "@oh-my-pi/pi-ai";
20
20
  import { formatDuration, formatNumber, sanitizeText } from "@oh-my-pi/pi-utils";
21
- import chalk from "chalk";
21
+ import chalk from "@oh-my-pi/pi-utils/chalk";
22
22
  import { ModelRegistry } from "../config/model-registry";
23
23
  import { discoverAuthStorage } from "../sdk";
24
24
 
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { APP_NAME, getProjectDir } from "@oh-my-pi/pi-utils";
8
- import chalk from "chalk";
8
+ import chalk from "@oh-my-pi/pi-utils/chalk";
9
9
  import { applyProviderGlobalsFromSettings } from "../config/provider-globals";
10
10
  import { Settings } from "../config/settings";
11
11
  import { initTheme, theme } from "../modes/theme/theme";
@@ -19,7 +19,7 @@
19
19
  import * as fs from "node:fs/promises";
20
20
  import * as path from "node:path";
21
21
  import { getWorktreesDir, isEnoent } from "@oh-my-pi/pi-utils";
22
- import chalk from "chalk";
22
+ import chalk from "@oh-my-pi/pi-utils/chalk";
23
23
  import { hasLiveIsolationOwner, ISOLATION_OWNER_FILE } from "../task/isolation-ownership";
24
24
  import * as git from "../utils/git";
25
25
 
@@ -120,6 +120,11 @@ export const commands: CommandEntry[] = [
120
120
  load: () => import("./commands/say").then(m => m.default),
121
121
  help: commandHelp.sayHelp,
122
122
  },
123
+ {
124
+ name: "share",
125
+ load: () => import("./commands/share").then(m => m.default),
126
+ help: commandHelp.shareHelp,
127
+ },
123
128
  {
124
129
  name: "setup",
125
130
  load: () => import("./commands/setup").then(m => m.default),
@@ -5,7 +5,7 @@
5
5
  import { postmortem } from "@oh-my-pi/pi-utils";
6
6
  import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
7
7
  import { commitHelp as commandHelp } from "../cli/command-help";
8
- import { runCommitCommand } from "../commit";
8
+ import { CommitAbortedError, runCommitCommand } from "../commit";
9
9
  import type { CommitCommandArgs } from "../commit/types";
10
10
  import { initTheme } from "../modes/theme/theme";
11
11
 
@@ -41,7 +41,20 @@ export default class Commit extends Command {
41
41
  // is already written. Mirror the `runPrintMode` exit pattern from
42
42
  // `main.ts` so the CLI returns to the shell instead of stranding the user
43
43
  // on Ctrl+C (issue #1041).
44
- await runCommitCommand(cmd);
45
- await postmortem.quit(0);
44
+ let exitCode = 0;
45
+ try {
46
+ const { usedFallback } = await runCommitCommand(cmd);
47
+ // A commit written by the mechanical fallback is a degraded outcome:
48
+ // the agent did not do the work it was asked to do, so the command
49
+ // reports non-zero so callers can distinguish it from a real
50
+ // single-commit decision (issue #7835).
51
+ if (usedFallback) exitCode = 1;
52
+ } catch (error) {
53
+ if (!(error instanceof CommitAbortedError)) throw error;
54
+ // Failure already reported with a readable message; exit non-zero
55
+ // without letting the runtime dump a stack/minified-source blob.
56
+ exitCode = 1;
57
+ }
58
+ await postmortem.quit(exitCode);
46
59
  }
47
60
  }
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import { getProjectDir } from "@oh-my-pi/pi-utils";
13
+ import chalk from "@oh-my-pi/pi-utils/chalk";
13
14
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
14
- import chalk from "chalk";
15
15
  import { sayHelp as commandHelp } from "../cli/command-help";
16
16
  import { Settings, settings } from "../config/settings";
17
17
  import { TTS_LOCAL_VOICE_VALUES } from "../tts/models";
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Share a saved session as an encrypted link without launching the agent.
3
+ *
4
+ * `omp share <session>` accepts a session id (prefix) or a path to a session
5
+ * `.jsonl` and uploads the sealed snapshot exactly like the `/share` slash
6
+ * command, honoring `share.serverUrl`, `share.store`, and
7
+ * `share.redactSecrets`.
8
+ */
9
+
10
+ import { getAgentDir } from "@oh-my-pi/pi-utils";
11
+ import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
12
+ import { shareHelp as commandHelp } from "../cli/command-help";
13
+ import { Settings } from "../config/settings";
14
+ import { shareSession } from "../export/share";
15
+ import { buildSecretObfuscator } from "../secrets";
16
+ import { resolveResumableSession } from "../session/session-listing";
17
+ import { SessionManager } from "../session/session-manager";
18
+
19
+ export default class Share extends Command {
20
+ static description = commandHelp.description;
21
+ static args = {
22
+ session: Args.string({
23
+ description: "Session id (prefix) or path to a session .jsonl",
24
+ required: true,
25
+ }),
26
+ };
27
+ static flags = {
28
+ gist: Flags.boolean({
29
+ description: "Upload to a secret GitHub gist instead of the share server",
30
+ default: false,
31
+ }),
32
+ };
33
+
34
+ async run(): Promise<void> {
35
+ const { args, flags } = await this.parse(Share);
36
+
37
+ const sessionArg = args.session ?? "";
38
+ let sessionPath = sessionArg;
39
+ if (!sessionArg.includes("/") && !sessionArg.includes("\\") && !sessionArg.endsWith(".jsonl")) {
40
+ const match = await resolveResumableSession(sessionArg, process.cwd());
41
+ if (!match) {
42
+ process.stderr.write(`Session "${sessionArg}" not found.\n`);
43
+ process.exitCode = 1;
44
+ return;
45
+ }
46
+ sessionPath = match.session.path;
47
+ }
48
+
49
+ const sm = await SessionManager.open(sessionPath);
50
+ // Settings resolve against the session's own project so its
51
+ // share.redactSecrets/secrets.enabled policy governs, not the invoking cwd's.
52
+ const settings = await Settings.loadReadOnly({ cwd: sm.getCwd() });
53
+ // Same leak boundary as /share: a share blob leaves the machine, so honor
54
+ // share.redactSecrets with the full obfuscator built against the session's
55
+ // own project directory (its secrets.yml, not the invoking cwd's).
56
+ const obfuscator =
57
+ settings.get("share.redactSecrets") && settings.get("secrets.enabled")
58
+ ? await buildSecretObfuscator(sm.getCwd(), getAgentDir())
59
+ : undefined;
60
+
61
+ const result = await shareSession(sm, {
62
+ serverUrl: settings.get("share.serverUrl"),
63
+ store: flags.gist ? "gist" : settings.get("share.store"),
64
+ obfuscator,
65
+ });
66
+ const lines = [`Share URL: ${result.url}`];
67
+ if (result.gistUrl) lines.push(`Gist: ${result.gistUrl}`);
68
+ if (result.truncated) lines.push("Note: large content was trimmed to fit the share size limit.");
69
+ console.log(lines.join("\n"));
70
+ }
71
+ }
@@ -3,8 +3,8 @@
3
3
  */
4
4
 
5
5
  import { PROVIDER_REGISTRY } from "@oh-my-pi/pi-ai";
6
+ import chalk from "@oh-my-pi/pi-utils/chalk";
6
7
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
7
- import chalk from "chalk";
8
8
  import { tokenHelp as commandHelp } from "../cli/command-help";
9
9
  import { isAuthenticated, ModelRegistry } from "../config/model-registry";
10
10
  import { discoverAuthStorage } from "../sdk";