@psnext/slingcli 2.5.20260722-2 → 2.5.20260722-3

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 (100) hide show
  1. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +9 -7
  2. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +25 -23
  3. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +32 -19
  4. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +6 -7
  5. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +75 -26
  6. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/utils.js +6 -17
  7. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/jsonl-storage.js +56 -4
  8. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/memory-storage.js +56 -4
  9. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo-utils.js +2 -2
  10. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +30 -14
  11. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +4 -2
  12. package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js +17 -0
  13. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  14. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +2 -7
  15. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +14 -2
  16. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +2 -4
  17. package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js +3 -2
  18. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +249 -0
  19. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +5 -0
  20. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +2 -0
  21. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +2 -0
  22. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +60 -0
  23. package/node_modules/@earendil-works/pi-ai/dist/index.js +2 -0
  24. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +4 -0
  25. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +8 -0
  26. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +3 -2
  27. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -0
  28. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cerebras.json +1 -1
  29. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  30. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  31. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  32. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  33. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  34. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  35. package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -1
  36. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -1
  37. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -1
  38. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
  39. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  40. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  41. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  42. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  43. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -0
  44. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -0
  45. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  46. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -1
  47. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +10 -2
  48. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js +2 -0
  49. package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-cn.js +15 -0
  50. package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-cn.models.js +5 -0
  51. package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan.js +15 -0
  52. package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan.models.js +5 -0
  53. package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js +18 -14
  54. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -0
  55. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +79 -0
  56. package/node_modules/@earendil-works/pi-ai/dist/utils/text.js +10 -0
  57. package/node_modules/@earendil-works/{pi-agent-core/dist/harness/session → pi-ai/dist/utils}/uuid.js +4 -8
  58. package/node_modules/@earendil-works/pi-ai/package.json +8 -5
  59. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +2 -0
  60. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +72 -57
  61. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/branch-summarization.js +8 -11
  62. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +63 -26
  63. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/utils.js +6 -17
  64. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +5 -0
  65. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +2 -0
  66. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.js +18 -15
  67. package/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js +1 -1
  68. package/node_modules/@earendil-works/pi-coding-agent/dist/core/remote-catalog-provider.js +26 -7
  69. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +6 -2
  70. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +100 -24
  71. package/node_modules/@earendil-works/pi-coding-agent/dist/core/usage-totals.js +52 -0
  72. package/node_modules/@earendil-works/pi-coding-agent/dist/extensions/llama/client.js +3 -1
  73. package/node_modules/@earendil-works/pi-coding-agent/dist/extensions/llama/index.js +3 -3
  74. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +1 -1
  75. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +5 -1
  76. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js +20 -21
  77. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +69 -25
  78. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -0
  79. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +4 -0
  80. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +16 -31
  81. package/node_modules/@earendil-works/pi-coding-agent/package.json +4 -4
  82. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/cli.js +5 -5
  83. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/config.js +9 -9
  84. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/client.js +1 -1
  85. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/server.js +1 -1
  86. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/radius.js +8 -8
  87. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/rpc-process.js +1 -1
  88. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/serve.js +3 -3
  89. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/storage.js +7 -7
  90. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/supervisor.js +2 -2
  91. package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/package.json +9 -6
  92. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +16 -10
  93. package/node_modules/@earendil-works/pi-tui/dist/tui.js +4 -2
  94. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  95. package/package.json +7 -7
  96. package/slingshot/index.js +253 -250
  97. /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/handler.js +0 -0
  98. /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/index.js +0 -0
  99. /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/protocol.js +0 -0
  100. /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/types.js +0 -0
@@ -24,6 +24,7 @@ import { SessionManager, sessionEntryToContextMessages } from "../../core/sessio
24
24
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
25
25
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
26
26
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
27
+ import { getUsageCostBreakdown } from "../../core/usage-totals.js";
27
28
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
28
29
  import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
29
30
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
@@ -191,8 +192,9 @@ export class InteractiveMode {
191
192
  hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
192
193
  lastSigintTime = 0;
193
194
  lastEscapeTime = 0;
195
+ changelogMarkdown = undefined;
194
196
  startupNoticesShown = false;
195
- Shown = false;
197
+ anthropicSubscriptionWarningShown = false;
196
198
  // Status line tracking (for mutating immediately-sequential status updates)
197
199
  lastStatusSpacer = undefined;
198
200
  lastStatusText = undefined;
@@ -427,6 +429,32 @@ export class InteractiveMode {
427
429
  this.editor.setAutocompleteProvider?.(provider);
428
430
  }
429
431
  }
432
+ showStartupNoticesIfNeeded() {
433
+ if (this.startupNoticesShown) {
434
+ return;
435
+ }
436
+ this.startupNoticesShown = true;
437
+ if (!this.changelogMarkdown) {
438
+ return;
439
+ }
440
+ if (this.chatContainer.children.length > 0) {
441
+ this.chatContainer.addChild(new Spacer(1));
442
+ }
443
+ this.chatContainer.addChild(new DynamicBorder());
444
+ if (this.settingsManager.getCollapseChangelog()) {
445
+ const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
446
+ const latestVersion = versionMatch ? versionMatch[1] : this.version;
447
+ const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
448
+ this.chatContainer.addChild(new Text(condensedText, 1, 0));
449
+ }
450
+ else {
451
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
452
+ this.chatContainer.addChild(new Spacer(1));
453
+ this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
454
+ this.chatContainer.addChild(new Spacer(1));
455
+ }
456
+ this.chatContainer.addChild(new DynamicBorder());
457
+ }
430
458
  async init() {
431
459
  if (this.isInitialized)
432
460
  return;
@@ -553,6 +581,12 @@ export class InteractiveMode {
553
581
  */
554
582
  async run() {
555
583
  await this.init();
584
+ if (!process.env.PI_OFFLINE) {
585
+ void this.session.modelRuntime
586
+ .refresh()
587
+ .then(() => this.updateAvailableProviderCount())
588
+ .catch(() => { });
589
+ }
556
590
  // Start version check asynchronously
557
591
  checkForNewPiVersion(this.version).then((newRelease) => {
558
592
  if (newRelease) {
@@ -679,7 +713,7 @@ export class InteractiveMode {
679
713
  return "tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";
680
714
  }
681
715
  if (extendedKeysFormat === "xterm") {
682
- return "tmux extended-keys-format is xterm. sling works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
716
+ return "tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
683
717
  }
684
718
  return undefined;
685
719
  }
@@ -2488,6 +2522,28 @@ export class InteractiveMode {
2488
2522
  this.ui.requestRender();
2489
2523
  break;
2490
2524
  }
2525
+ case "summarization_retry_scheduled": {
2526
+ this.showError(event.errorMessage);
2527
+ this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
2528
+ this.ui.requestRender();
2529
+ break;
2530
+ }
2531
+ case "summarization_retry_attempt_start": {
2532
+ this.clearStatusIndicator("retry");
2533
+ if (event.source === "branchSummary") {
2534
+ this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
2535
+ }
2536
+ else {
2537
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
2538
+ }
2539
+ this.ui.requestRender();
2540
+ break;
2541
+ }
2542
+ case "summarization_retry_finished": {
2543
+ this.clearStatusIndicator("retry");
2544
+ this.ui.requestRender();
2545
+ break;
2546
+ }
2491
2547
  }
2492
2548
  }
2493
2549
  /** Extract text content from a user message */
@@ -3566,10 +3622,12 @@ export class InteractiveMode {
3566
3622
  return [];
3567
3623
  }
3568
3624
  }
3569
- /** Update the footer's available provider count from current model candidates */
3570
- async updateAvailableProviderCount() {
3571
- const models = await this.getModelCandidates();
3572
- const uniqueProviders = new Set(models.map((m) => m.provider));
3625
+ /** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
3626
+ updateAvailableProviderCount() {
3627
+ const models = this.session.scopedModels.length > 0
3628
+ ? this.session.scopedModels.map((scoped) => scoped.model)
3629
+ : this.session.modelRuntime.getAvailableSnapshot();
3630
+ const uniqueProviders = new Set(models.map((model) => model.provider));
3573
3631
  this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size);
3574
3632
  }
3575
3633
  async maybeWarnAboutAnthropicSubscriptionAuth(model = this.session.model) {
@@ -4657,23 +4715,9 @@ export class InteractiveMode {
4657
4715
  const entries = this.sessionManager.getEntries();
4658
4716
  const cacheWaste = computeCacheWaste(entries, this.session.modelRuntime);
4659
4717
  // Cost/token totals per provider/model actually used (e.g. OpenRouter `auto`
4660
- // resolves to a concrete responseModel), sorted by cost descending.
4661
- const perModelMap = new Map();
4662
- for (const entry of entries) {
4663
- if (entry.type !== "message" || entry.message.role !== "assistant")
4664
- continue;
4665
- const message = entry.message;
4666
- const usage = message.usage;
4667
- const key = `${message.provider}/${message.responseModel ?? message.model}`;
4668
- let bucket = perModelMap.get(key);
4669
- if (!bucket) {
4670
- bucket = { key, cost: 0, tokens: 0 };
4671
- perModelMap.set(key, bucket);
4672
- }
4673
- bucket.cost += usage.cost.total;
4674
- bucket.tokens += usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
4675
- }
4676
- const perModel = Array.from(perModelMap.values()).sort((a, b) => b.cost - a.cost);
4718
+ // resolves to a concrete responseModel). Usage without model attribution is
4719
+ // grouped separately so the breakdown reconciles with the session total.
4720
+ const usageBreakdown = getUsageCostBreakdown(entries);
4677
4721
  let info = `${theme.bold("Session Info")}\n\n`;
4678
4722
  if (sessionName) {
4679
4723
  info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
@@ -4704,8 +4748,8 @@ export class InteractiveMode {
4704
4748
  if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
4705
4749
  info += `\n${theme.bold("Cost")}\n`;
4706
4750
  info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
4707
- if (perModel.length > 1) {
4708
- for (const entry of perModel) {
4751
+ if (usageBreakdown.length > 1) {
4752
+ for (const entry of usageBreakdown) {
4709
4753
  info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
4710
4754
  }
4711
4755
  }
@@ -203,6 +203,13 @@ export class RpcClient {
203
203
  const response = await this.send({ type: "cycle_thinking_level" });
204
204
  return this.getData(response);
205
205
  }
206
+ /**
207
+ * Get list of available thinking levels for the current model.
208
+ */
209
+ async getAvailableThinkingLevels() {
210
+ const response = await this.send({ type: "get_available_thinking_levels" });
211
+ return this.getData(response).levels;
212
+ }
206
213
  /**
207
214
  * Set steering mode.
208
215
  */
@@ -394,6 +394,10 @@ export async function runRpcMode(runtimeHost) {
394
394
  }
395
395
  return success(id, "cycle_thinking_level", { level });
396
396
  }
397
+ case "get_available_thinking_levels": {
398
+ const levels = session.getAvailableThinkingLevels();
399
+ return success(id, "get_available_thinking_levels", { levels });
400
+ }
397
401
  // =================================================================
398
402
  // Queue Modes
399
403
  // =================================================================
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.80.10",
3
+ "version": "0.81.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@earendil-works/pi-coding-agent",
9
- "version": "0.80.10",
9
+ "version": "0.81.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@earendil-works/pi-agent-core": "^0.80.10",
13
- "@earendil-works/pi-ai": "^0.80.10",
14
- "@earendil-works/pi-tui": "^0.80.10",
12
+ "@earendil-works/pi-agent-core": "^0.81.1",
13
+ "@earendil-works/pi-ai": "^0.81.1",
14
+ "@earendil-works/pi-tui": "^0.81.1",
15
15
  "@silvia-odwyer/photon-node": "0.3.4",
16
16
  "chalk": "5.6.2",
17
17
  "cross-spawn": "7.0.6",
@@ -474,11 +474,11 @@
474
474
  }
475
475
  },
476
476
  "node_modules/@earendil-works/pi-agent-core": {
477
- "version": "0.80.10",
478
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.80.10.tgz",
477
+ "version": "0.81.1",
478
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.81.1.tgz",
479
479
  "license": "MIT",
480
480
  "dependencies": {
481
- "@earendil-works/pi-ai": "^0.80.10",
481
+ "@earendil-works/pi-ai": "^0.81.1",
482
482
  "ignore": "7.0.5",
483
483
  "typebox": "1.1.38",
484
484
  "yaml": "2.9.0"
@@ -488,8 +488,8 @@
488
488
  }
489
489
  },
490
490
  "node_modules/@earendil-works/pi-ai": {
491
- "version": "0.80.10",
492
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.80.10.tgz",
491
+ "version": "0.81.1",
492
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.81.1.tgz",
493
493
  "license": "MIT",
494
494
  "dependencies": {
495
495
  "@anthropic-ai/sdk": "0.91.1",
@@ -505,15 +505,15 @@
505
505
  "typebox": "1.1.38"
506
506
  },
507
507
  "bin": {
508
- "pi-ai": "./dist/cli.js"
508
+ "pi-ai": "dist/cli.js"
509
509
  },
510
510
  "engines": {
511
511
  "node": ">=22.19.0"
512
512
  }
513
513
  },
514
514
  "node_modules/@earendil-works/pi-tui": {
515
- "version": "0.80.10",
516
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.10.tgz",
515
+ "version": "0.81.1",
516
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.81.1.tgz",
517
517
  "license": "MIT",
518
518
  "dependencies": {
519
519
  "get-east-asian-width": "1.6.0",
@@ -628,9 +628,6 @@
628
628
  "cpu": [
629
629
  "arm64"
630
630
  ],
631
- "libc": [
632
- "glibc"
633
- ],
634
631
  "optional": true
635
632
  },
636
633
  "node_modules/@mariozechner/clipboard-linux-arm64-musl": {
@@ -647,9 +644,6 @@
647
644
  "cpu": [
648
645
  "arm64"
649
646
  ],
650
- "libc": [
651
- "musl"
652
- ],
653
647
  "optional": true
654
648
  },
655
649
  "node_modules/@mariozechner/clipboard-linux-riscv64-gnu": {
@@ -666,9 +660,6 @@
666
660
  "cpu": [
667
661
  "riscv64"
668
662
  ],
669
- "libc": [
670
- "glibc"
671
- ],
672
663
  "optional": true
673
664
  },
674
665
  "node_modules/@mariozechner/clipboard-linux-x64-gnu": {
@@ -685,9 +676,6 @@
685
676
  "cpu": [
686
677
  "x64"
687
678
  ],
688
- "libc": [
689
- "glibc"
690
- ],
691
679
  "optional": true
692
680
  },
693
681
  "node_modules/@mariozechner/clipboard-linux-x64-musl": {
@@ -704,9 +692,6 @@
704
692
  "cpu": [
705
693
  "x64"
706
694
  ],
707
- "libc": [
708
- "musl"
709
- ],
710
695
  "optional": true
711
696
  },
712
697
  "node_modules/@mariozechner/clipboard-win32-arm64-msvc": {
@@ -1037,9 +1022,9 @@
1037
1022
  "license": "MIT"
1038
1023
  },
1039
1024
  "node_modules/brace-expansion": {
1040
- "version": "5.0.6",
1041
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
1042
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
1025
+ "version": "5.0.7",
1026
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
1027
+ "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
1043
1028
  "license": "MIT",
1044
1029
  "dependencies": {
1045
1030
  "balanced-match": "^4.0.2"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.80.10",
3
+ "version": "0.81.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -40,9 +40,9 @@
40
40
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
41
41
  },
42
42
  "dependencies": {
43
- "@earendil-works/pi-agent-core": "^0.80.10",
44
- "@earendil-works/pi-ai": "^0.80.10",
45
- "@earendil-works/pi-tui": "^0.80.10",
43
+ "@earendil-works/pi-agent-core": "^0.81.1",
44
+ "@earendil-works/pi-ai": "^0.81.1",
45
+ "@earendil-works/pi-tui": "^0.81.1",
46
46
  "@silvia-odwyer/photon-node": "0.3.4",
47
47
  "chalk": "5.6.2",
48
48
  "cross-spawn": "7.0.6",
@@ -12,7 +12,7 @@ const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
13
13
  const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
14
14
  function printHelp() {
15
- console.log(`orchestrator v${packageJson.version}\n\nUsage:\n orchestrator serve\n orchestrator list\n orchestrator spawn [--cwd <path>] [--label <label>]\n orchestrator status <instance-id>\n orchestrator stop <instance-id>\n orchestrator rpc <instance-id> <json-command>\n orchestrator rpc-stream <instance-id>\n orchestrator --help\n orchestrator --version\n\nRPC stream stdin expects JSONL RpcCommand or extension_ui_response messages.`);
15
+ console.log(`server v${packageJson.version}\n\nUsage:\n server serve\n server list\n server spawn [--cwd <path>] [--label <label>]\n server status <instance-id>\n server stop <instance-id>\n server rpc <instance-id> <json-command>\n server rpc-stream <instance-id>\n server --help\n server --version\n\nRPC stream stdin expects JSONL RpcCommand or extension_ui_response messages.`);
16
16
  }
17
17
  function printResponse(response) {
18
18
  console.log(JSON.stringify(response, null, 2));
@@ -90,7 +90,7 @@ async function main() {
90
90
  if (args[0] === "status") {
91
91
  const instanceId = args[1];
92
92
  if (!instanceId) {
93
- console.error("Usage: orchestrator status <instance-id>");
93
+ console.error("Usage: server status <instance-id>");
94
94
  process.exit(1);
95
95
  }
96
96
  printResponse(await sendIpcRequest({ type: "status", instanceId }));
@@ -99,7 +99,7 @@ async function main() {
99
99
  if (args[0] === "stop") {
100
100
  const instanceId = args[1];
101
101
  if (!instanceId) {
102
- console.error("Usage: orchestrator stop <instance-id>");
102
+ console.error("Usage: server stop <instance-id>");
103
103
  process.exit(1);
104
104
  }
105
105
  printResponse(await sendIpcRequest({ type: "stop", instanceId }));
@@ -109,7 +109,7 @@ async function main() {
109
109
  const instanceId = args[1];
110
110
  const commandJson = args[2];
111
111
  if (!instanceId || !commandJson) {
112
- console.error("Usage: orchestrator rpc <instance-id> <json-command>");
112
+ console.error("Usage: server rpc <instance-id> <json-command>");
113
113
  process.exit(1);
114
114
  }
115
115
  printResponse(await sendIpcRequest({
@@ -122,7 +122,7 @@ async function main() {
122
122
  if (args[0] === "rpc-stream") {
123
123
  const instanceId = args[1];
124
124
  if (!instanceId) {
125
- console.error("Usage: orchestrator rpc-stream <instance-id>");
125
+ console.error("Usage: server rpc-stream <instance-id>");
126
126
  process.exit(1);
127
127
  }
128
128
  await rpcStream(instanceId);
@@ -2,8 +2,8 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- const CONFIG_DIR_NAME = ".sling";
6
- const ENV_ORCHESTRATOR_DIR = "PI_ORCHESTRATOR_DIR";
5
+ const CONFIG_DIR_NAME = ".pi";
6
+ const ENV_SERVER_DIR = "PI_SERVER_DIR";
7
7
  const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = dirname(__filename);
9
9
  /**
@@ -32,24 +32,24 @@ catch (e) {
32
32
  throw e;
33
33
  }
34
34
  export const VERSION = pkg.version || "0.0.0";
35
- export function getOrchestratorDir() {
36
- const envDir = process.env[ENV_ORCHESTRATOR_DIR];
35
+ export function getServerDir() {
36
+ const envDir = process.env[ENV_SERVER_DIR];
37
37
  if (envDir) {
38
38
  return envDir;
39
39
  }
40
40
  const piDir = process.env.PI_CONFIG_DIR || join(homedir(), CONFIG_DIR_NAME);
41
- return join(piDir, "orchestrator");
41
+ return join(piDir, "server");
42
42
  }
43
43
  export function getAuthPath() {
44
- return join(getOrchestratorDir(), "auth.json");
44
+ return join(getServerDir(), "auth.json");
45
45
  }
46
46
  export function getMachinePath() {
47
- return join(getOrchestratorDir(), "machine.json");
47
+ return join(getServerDir(), "machine.json");
48
48
  }
49
49
  export function getInstancesPath() {
50
- return join(getOrchestratorDir(), "instances.json");
50
+ return join(getServerDir(), "instances.json");
51
51
  }
52
52
  export function getSocketPath() {
53
- return join(getOrchestratorDir(), "orchestrator.sock");
53
+ return join(getServerDir(), "server.sock");
54
54
  }
55
55
  //# sourceMappingURL=config.js.map
@@ -48,7 +48,7 @@ export async function sendIpcRequest(request) {
48
48
  return;
49
49
  }
50
50
  settled = true;
51
- reject(new Error(`Orchestrator socket closed before a response was received: ${socketPath}`));
51
+ reject(new Error(`Server socket closed before a response was received: ${socketPath}`));
52
52
  cleanup();
53
53
  });
54
54
  });
@@ -105,7 +105,7 @@ async function removeStaleSocketIfNeeded(socketPath) {
105
105
  }
106
106
  const isLive = await isSocketLive(socketPath);
107
107
  if (isLive) {
108
- throw new Error(`orchestrator is already running: ${socketPath}`);
108
+ throw new Error(`server is already running: ${socketPath}`);
109
109
  }
110
110
  unlinkSync(socketPath);
111
111
  }
@@ -1,9 +1,9 @@
1
1
  import { hostname, platform } from "node:os";
2
2
  import { readStoredCredential } from "@earendil-works/pi-coding-agent";
3
- import { getOrchestratorDir, getSocketPath, VERSION } from "./config.js";
3
+ import { getServerDir, getSocketPath, VERSION } from "./config.js";
4
4
  import { loadMachine, saveMachine } from "./storage.js";
5
5
  const DEFAULT_RADIUS_URL = "https://radius.pi.dev/";
6
- const DEFAULT_ORCHESTRATOR_BASE_PATH = "/v1/";
6
+ const DEFAULT_SERVER_BASE_PATH = "/v1/";
7
7
  const NOT_FOUND_RETRY_THRESHOLD = 3;
8
8
  const HEARTBEAT_BACKOFF_BASE_MS = 1_000;
9
9
  const HEARTBEAT_BACKOFF_MAX_MS = 30_000;
@@ -17,7 +17,7 @@ class RadiusHttpError extends Error {
17
17
  }
18
18
  }
19
19
  async function post(path, body) {
20
- const response = await fetch(new URL(path, getRadiusOrchestratorBaseUrl()), {
20
+ const response = await fetch(new URL(path, getRadiusServerBaseUrl()), {
21
21
  method: "POST",
22
22
  headers: {
23
23
  Authorization: `Bearer ${getRadiusAccessToken()}`,
@@ -31,7 +31,7 @@ async function post(path, body) {
31
31
  return (await response.json());
32
32
  }
33
33
  async function maybePost(path, body) {
34
- const response = await fetch(new URL(path, getRadiusOrchestratorBaseUrl()), {
34
+ const response = await fetch(new URL(path, getRadiusServerBaseUrl()), {
35
35
  method: "POST",
36
36
  headers: {
37
37
  Authorization: `Bearer ${getRadiusAccessToken()}`,
@@ -66,12 +66,12 @@ function logRadiusRetry(scope, action, delayMs, failureCount, error) {
66
66
  export function getRadiusUrl() {
67
67
  return process.env.PI_RADIUS_URL || DEFAULT_RADIUS_URL;
68
68
  }
69
- export function getRadiusOrchestratorBaseUrl() {
70
- const explicitUrl = process.env.PI_RADIUS_ORCHESTRATOR_URL;
69
+ export function getRadiusServerBaseUrl() {
70
+ const explicitUrl = process.env.PI_RADIUS_SERVER_URL;
71
71
  if (explicitUrl) {
72
72
  return explicitUrl;
73
73
  }
74
- return new URL(DEFAULT_ORCHESTRATOR_BASE_PATH, getRadiusUrl()).toString();
74
+ return new URL(DEFAULT_SERVER_BASE_PATH, getRadiusUrl()).toString();
75
75
  }
76
76
  function getStoredRadiusCredential() {
77
77
  const credential = readStoredCredential(RADIUS_PROVIDER);
@@ -246,7 +246,7 @@ export class RadiusPresence {
246
246
  }
247
247
  try {
248
248
  await maybePost(`machines/${this.machine.id}/heartbeat`, {
249
- cwd: getOrchestratorDir(),
249
+ cwd: getServerDir(),
250
250
  socketPath: getSocketPath(),
251
251
  });
252
252
  this.machineConsecutiveNotFoundCount = 0;
@@ -116,7 +116,7 @@ export class RpcProcessInstance {
116
116
  if (this.exited) {
117
117
  throw new Error(`RPC process is not running. Stderr: ${this.stderrBuffer}`);
118
118
  }
119
- const id = command.id ?? `orchestrator_${++this.nextRequestId}_${randomUUID()}`;
119
+ const id = command.id ?? `server_${++this.nextRequestId}_${randomUUID()}`;
120
120
  const fullCommand = { ...command, id };
121
121
  return new Promise((resolve, reject) => {
122
122
  this.pendingRequests.set(id, { resolve, reject });
@@ -3,7 +3,7 @@ import { dirname } from "node:path";
3
3
  import { getSocketPath } from "./config.js";
4
4
  import { handleIpcRequest, openRpcStream } from "./handler.js";
5
5
  import { startIpcServer } from "./ipc/server.js";
6
- import { getRadiusOrchestratorBaseUrl, isRadiusEnabled, radiusPresence } from "./radius.js";
6
+ import { getRadiusServerBaseUrl, isRadiusEnabled, radiusPresence } from "./radius.js";
7
7
  import { supervisor } from "./supervisor.js";
8
8
  export async function serve() {
9
9
  const socketPath = getSocketPath();
@@ -15,7 +15,7 @@ export async function serve() {
15
15
  await supervisor.recoverAfterRestart();
16
16
  if (isRadiusEnabled()) {
17
17
  const machine = await radiusPresence.start();
18
- console.log(`radius integration enabled: ${socketPath} -> ${getRadiusOrchestratorBaseUrl()}`);
18
+ console.log(`radius integration enabled: ${socketPath} -> ${getRadiusServerBaseUrl()}`);
19
19
  if (machine) {
20
20
  console.log(`radius machine id: ${machine.id}`);
21
21
  }
@@ -31,7 +31,7 @@ export async function serve() {
31
31
  }
32
32
  throw error;
33
33
  }
34
- console.log(`orchestrator listening on ${socketPath}`);
34
+ console.log(`server listening on ${socketPath}`);
35
35
  let shutdownPromise;
36
36
  const shutdown = async (exitCode) => {
37
37
  if (shutdownPromise) {
@@ -1,9 +1,9 @@
1
1
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
- import { getInstancesPath, getMachinePath, getOrchestratorDir } from "./config.js";
3
- function ensureOrchestratorDir() {
4
- const orchestratorDir = getOrchestratorDir();
5
- if (!existsSync(orchestratorDir)) {
6
- mkdirSync(orchestratorDir, { recursive: true });
2
+ import { getInstancesPath, getMachinePath, getServerDir } from "./config.js";
3
+ function ensureServerDir() {
4
+ const serverDir = getServerDir();
5
+ if (!existsSync(serverDir)) {
6
+ mkdirSync(serverDir, { recursive: true });
7
7
  }
8
8
  }
9
9
  export function loadMachine() {
@@ -15,7 +15,7 @@ export function loadMachine() {
15
15
  return JSON.parse(data);
16
16
  }
17
17
  export function saveMachine(machine) {
18
- ensureOrchestratorDir();
18
+ ensureServerDir();
19
19
  writeFileSync(getMachinePath(), JSON.stringify(machine, null, 2));
20
20
  }
21
21
  export function deleteMachine() {
@@ -34,7 +34,7 @@ export function loadInstances() {
34
34
  return JSON.parse(data);
35
35
  }
36
36
  export function saveInstances(instances) {
37
- ensureOrchestratorDir();
37
+ ensureServerDir();
38
38
  writeFileSync(getInstancesPath(), JSON.stringify(instances, null, 2));
39
39
  }
40
40
  export function getInstance(instanceId) {
@@ -26,7 +26,7 @@ function shouldRefreshSessionMetadata(command) {
26
26
  function isGetStateSuccess(response) {
27
27
  return response.success === true && response.command === "get_state" && "data" in response;
28
28
  }
29
- export class OrchestratorSupervisor {
29
+ export class ServerSupervisor {
30
30
  liveInstances = new Map();
31
31
  setStatus(live, status) {
32
32
  live.record = {
@@ -275,7 +275,7 @@ export class OrchestratorSupervisor {
275
275
  }
276
276
  }
277
277
  }
278
- export const supervisor = new OrchestratorSupervisor();
278
+ export const supervisor = new ServerSupervisor();
279
279
  radiusPresence.setCoordinator({
280
280
  getLiveInstance(instanceId) {
281
281
  return supervisor.getLiveInstance(instanceId);
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "@earendil-works/pi-orchestrator",
3
- "version": "0.80.10",
4
- "description": "experimental orchestrator package for pi",
2
+ "name": "@earendil-works/pi-server",
3
+ "version": "0.81.1",
4
+ "description": "experimental server package for pi",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -11,6 +11,9 @@
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
14
+ "bin": {
15
+ "server": "./dist/cli.js"
16
+ },
14
17
  "files": [
15
18
  "dist",
16
19
  "README.md",
@@ -24,20 +27,20 @@
24
27
  },
25
28
  "keywords": [
26
29
  "pi",
27
- "orchestrator"
30
+ "server"
28
31
  ],
29
32
  "author": "Earendil Works",
30
33
  "license": "MIT",
31
34
  "repository": {
32
35
  "type": "git",
33
36
  "url": "git+https://github.com/earendil-works/pi.git",
34
- "directory": "packages/orchestrator"
37
+ "directory": "packages/server"
35
38
  },
36
39
  "engines": {
37
40
  "node": ">=22.19.0"
38
41
  },
39
42
  "dependencies": {
40
- "@earendil-works/pi-coding-agent": "^0.80.10"
43
+ "@earendil-works/pi-coding-agent": "^0.81.1"
41
44
  },
42
45
  "devDependencies": {
43
46
  "shx": "0.4.0"