@code-yeongyu/senpi 2026.9.8 → 2026.9.9

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 (114) hide show
  1. package/CHANGELOG.md +23 -4
  2. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  3. package/dist/core/agent-session-runtime.js +2 -0
  4. package/dist/core/agent-session-runtime.js.map +1 -1
  5. package/dist/core/compaction/compaction-execution.d.ts.map +1 -1
  6. package/dist/core/compaction/compaction-execution.js +5 -5
  7. package/dist/core/compaction/compaction-execution.js.map +1 -1
  8. package/dist/core/compaction/compaction-settings.d.ts +2 -0
  9. package/dist/core/compaction/compaction-settings.d.ts.map +1 -1
  10. package/dist/core/compaction/compaction-settings.js.map +1 -1
  11. package/dist/core/compaction/compaction.d.ts +3 -3
  12. package/dist/core/compaction/compaction.d.ts.map +1 -1
  13. package/dist/core/compaction/compaction.js +12 -7
  14. package/dist/core/compaction/compaction.js.map +1 -1
  15. package/dist/core/compaction/stream-watchdog.d.ts +29 -0
  16. package/dist/core/compaction/stream-watchdog.d.ts.map +1 -1
  17. package/dist/core/compaction/stream-watchdog.js +35 -0
  18. package/dist/core/compaction/stream-watchdog.js.map +1 -1
  19. package/dist/core/compaction-settings-access.d.ts +6 -0
  20. package/dist/core/compaction-settings-access.d.ts.map +1 -1
  21. package/dist/core/compaction-settings-access.js.map +1 -1
  22. package/dist/core/compaction-settings-resolver.d.ts +2 -0
  23. package/dist/core/compaction-settings-resolver.d.ts.map +1 -1
  24. package/dist/core/compaction-settings-resolver.js +5 -0
  25. package/dist/core/compaction-settings-resolver.js.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +1 -1
  27. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +23 -3
  29. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -1
  30. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +2 -0
  31. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/compaction/speculative-summary.js +5 -2
  33. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/speculative.js +9 -3
  36. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  37. package/dist/core/extensions/builtin/compaction/summarization-retry.d.ts +10 -4
  38. package/dist/core/extensions/builtin/compaction/summarization-retry.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/compaction/summarization-retry.js +14 -5
  40. package/dist/core/extensions/builtin/compaction/summarization-retry.js.map +1 -1
  41. package/dist/core/session-manager.d.ts.map +1 -1
  42. package/dist/core/session-manager.js +11 -1
  43. package/dist/core/session-manager.js.map +1 -1
  44. package/dist/core/session-write-reservation.d.ts +4 -0
  45. package/dist/core/session-write-reservation.d.ts.map +1 -0
  46. package/dist/core/session-write-reservation.js +12 -0
  47. package/dist/core/session-write-reservation.js.map +1 -0
  48. package/dist/main.d.ts +14 -0
  49. package/dist/main.d.ts.map +1 -1
  50. package/dist/main.js +162 -147
  51. package/dist/main.js.map +1 -1
  52. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  53. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  54. package/dist/modes/rpc/connection-handler.js +1 -1
  55. package/dist/modes/rpc/connection-handler.js.map +1 -1
  56. package/dist/modes/rpc/multi-session-host.d.ts +2 -0
  57. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  58. package/dist/modes/rpc/multi-session-host.js +18 -8
  59. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  60. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  61. package/dist/modes/rpc/session-binding.js +3 -0
  62. package/dist/modes/rpc/session-binding.js.map +1 -1
  63. package/dist/modes/rpc/session-command-router.d.ts +1 -1
  64. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  65. package/dist/modes/rpc/session-command-router.js +57 -25
  66. package/dist/modes/rpc/session-command-router.js.map +1 -1
  67. package/dist/modes/rpc/session-event-writer.d.ts +23 -1
  68. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  69. package/dist/modes/rpc/session-event-writer.js +108 -1
  70. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  71. package/dist/modes/rpc/session-registry.d.ts +4 -2
  72. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  73. package/dist/modes/rpc/session-registry.js +1 -1
  74. package/dist/modes/rpc/session-registry.js.map +1 -1
  75. package/dist/modes/rpc/session-worker-client.d.ts +47 -0
  76. package/dist/modes/rpc/session-worker-client.d.ts.map +1 -0
  77. package/dist/modes/rpc/session-worker-client.js +226 -0
  78. package/dist/modes/rpc/session-worker-client.js.map +1 -0
  79. package/dist/modes/rpc/session-worker-protocol.d.ts +103 -0
  80. package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -0
  81. package/dist/modes/rpc/session-worker-protocol.js +12 -0
  82. package/dist/modes/rpc/session-worker-protocol.js.map +1 -0
  83. package/dist/modes/rpc/session-worker-requests.d.ts +24 -0
  84. package/dist/modes/rpc/session-worker-requests.d.ts.map +1 -0
  85. package/dist/modes/rpc/session-worker-requests.js +71 -0
  86. package/dist/modes/rpc/session-worker-requests.js.map +1 -0
  87. package/dist/modes/rpc/session-worker.d.ts +2 -0
  88. package/dist/modes/rpc/session-worker.d.ts.map +1 -0
  89. package/dist/modes/rpc/session-worker.js +229 -0
  90. package/dist/modes/rpc/session-worker.js.map +1 -0
  91. package/dist/modes/rpc/worker-session-registry.d.ts +37 -0
  92. package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -0
  93. package/dist/modes/rpc/worker-session-registry.js +207 -0
  94. package/dist/modes/rpc/worker-session-registry.js.map +1 -0
  95. package/docs/rpc.md +70 -9
  96. package/docs/settings.md +1 -0
  97. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  98. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  99. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  100. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +23 -5
  101. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  102. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +30 -0
  103. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  104. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +30 -0
  105. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  106. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  107. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  108. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  109. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  110. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  111. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  112. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  113. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  114. package/package.json +7 -7
@@ -0,0 +1,4 @@
1
+ export declare function installSessionWriteReservation(reservation: (path: string) => void): void;
2
+ /** Synchronous SessionManager entry points must obtain the host grant before touching a writer. */
3
+ export declare function reserveSessionWrite(path: string): void;
4
+ //# sourceMappingURL=session-write-reservation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-write-reservation.d.ts","sourceRoot":"","sources":["../../src/core/session-write-reservation.ts"],"names":[],"mappings":"AAGA,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAGxF;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,12 @@
1
+ /** Installed only inside a shared-host session isolate, before constructing any writer. */
2
+ let reserve;
3
+ export function installSessionWriteReservation(reservation) {
4
+ if (reserve)
5
+ throw new Error("Session write reservation already installed");
6
+ reserve = reservation;
7
+ }
8
+ /** Synchronous SessionManager entry points must obtain the host grant before touching a writer. */
9
+ export function reserveSessionWrite(path) {
10
+ reserve?.(path);
11
+ }
12
+ //# sourceMappingURL=session-write-reservation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-write-reservation.js","sourceRoot":"","sources":["../../src/core/session-write-reservation.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,IAAI,OAA6C,CAAC;AAElD,MAAM,UAAU,8BAA8B,CAAC,WAAmC;IACjF,IAAI,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC5E,OAAO,GAAG,WAAW,CAAC;AACvB,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC/C,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC","sourcesContent":["/** Installed only inside a shared-host session isolate, before constructing any writer. */\nlet reserve: ((path: string) => void) | undefined;\n\nexport function installSessionWriteReservation(reservation: (path: string) => void): void {\n\tif (reserve) throw new Error(\"Session write reservation already installed\");\n\treserve = reservation;\n}\n\n/** Synchronous SessionManager entry points must obtain the host grant before touching a writer. */\nexport function reserveSessionWrite(path: string): void {\n\treserve?.(path);\n}\n"]}
package/dist/main.d.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  * createAgentSession() options. The SDK does the heavy lifting.
6
6
  */
7
7
  import { type Args } from "./cli/args.ts";
8
+ import { createStartupLoadingIndicator } from "./cli/startup-loading-indicator.ts";
9
+ import { type CreateAgentSessionRuntimeFactory } from "./core/agent-session-runtime.ts";
8
10
  import { type AgentSessionRuntimeDiagnostic } from "./core/agent-session-services.ts";
9
11
  import type { InlineExtension } from "./core/extensions/types.ts";
10
12
  import { type AppMode } from "./core/project-trust.ts";
@@ -30,5 +32,17 @@ export interface MainOptions {
30
32
  * a theme. Existing settings are always returned first.
31
33
  */
32
34
  export declare function applyGrokNeoThemeFallback(settingsManager: SettingsManager): void;
35
+ export interface CliRuntimeConfiguration {
36
+ parsed: Args;
37
+ cwd: string;
38
+ agentDir: string;
39
+ appMode: AppMode;
40
+ }
41
+ /** Fixed launch data is cloneable; UI callbacks and extension factories stay in their isolate. */
42
+ export declare function createCliRuntimeFactory(configuration: CliRuntimeConfiguration, local?: {
43
+ extensionFactories?: InlineExtension[];
44
+ startupSettingsManager?: SettingsManager;
45
+ startupLoadingIndicator?: ReturnType<typeof createStartupLoadingIndicator>;
46
+ }): CreateAgentSessionRuntimeFactory;
33
47
  export declare function main(args: string[], options?: MainOptions): Promise<void>;
34
48
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAQH,OAAO,EAAE,KAAK,IAAI,EAAyD,MAAM,eAAe,CAAC;AAgCjG,OAAO,EACN,KAAK,6BAA6B,EAGlC,MAAM,kCAAkC,CAAC;AAM1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAUlE,OAAO,EAAE,KAAK,OAAO,EAAyB,MAAM,yBAAyB,CAAC;AAQ9E,OAAO,EAAwB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AA4D7D,wBAAgB,+BAA+B,CAC9C,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GAChD,6BAA6B,EAAE,CAKjC;AAuCD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,IAAI,EACZ,kBAAkB,EAAE,OAAO,EAC3B,kBAAkB,GAAE,SAAS,MAAM,EAAiE,GAClG,OAAO,CAOT;AAsPD,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,IAAI,EACZ,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,cAAc,CAAC,CAoGzB;AA0HD,MAAM,WAAW,WAAW;IAC3B,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAYhF;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,iBAqkB/D"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAQH,OAAO,EAAE,KAAK,IAAI,EAAyD,MAAM,eAAe,CAAC;AAwBjG,OAAO,EACN,6BAA6B,EAG7B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,KAAK,gCAAgC,EAA6B,MAAM,iCAAiC,CAAC;AACnH,OAAO,EACN,KAAK,6BAA6B,EAGlC,MAAM,kCAAkC,CAAC;AAM1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAUlE,OAAO,EAAE,KAAK,OAAO,EAAyB,MAAM,yBAAyB,CAAC;AAQ9E,OAAO,EAAwB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AA4D7D,wBAAgB,+BAA+B,CAC9C,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GAChD,6BAA6B,EAAE,CAKjC;AAuCD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,IAAI,EACZ,kBAAkB,EAAE,OAAO,EAC3B,kBAAkB,GAAE,SAAS,MAAM,EAAiE,GAClG,OAAO,CAOT;AAsPD,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,IAAI,EACZ,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,cAAc,CAAC,CAoGzB;AA0HD,MAAM,WAAW,WAAW;IAC3B,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAYhF;AAED,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,IAAI,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,kGAAkG;AAClG,wBAAgB,uBAAuB,CACtC,aAAa,EAAE,uBAAuB,EACtC,KAAK,GAAE;IACN,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAC;IACvC,sBAAsB,CAAC,EAAE,eAAe,CAAC;IACzC,uBAAuB,CAAC,EAAE,UAAU,CAAC,OAAO,6BAA6B,CAAC,CAAC;CACtE,GACJ,gCAAgC,CA2KlC;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,iBAqa/D"}
package/dist/main.js CHANGED
@@ -533,6 +533,152 @@ export function applyGrokNeoThemeFallback(settingsManager) {
533
533
  setTheme(theme);
534
534
  };
535
535
  }
536
+ /** Fixed launch data is cloneable; UI callbacks and extension factories stay in their isolate. */
537
+ export function createCliRuntimeFactory(configuration, local = {}) {
538
+ const { parsed, cwd, agentDir, appMode } = configuration;
539
+ const extensionFactories = local.extensionFactories ?? builtInExtensions;
540
+ const startupSettingsManager = local.startupSettingsManager ?? SettingsManager.create(cwd, agentDir);
541
+ const startupLoadingIndicator = local.startupLoadingIndicator ??
542
+ createStartupLoadingIndicator({
543
+ writer: () => { },
544
+ isTTY: false,
545
+ label: `Loading ${APP_NAME}`,
546
+ });
547
+ const trustStore = new ProjectTrustStore(agentDir);
548
+ const projectTrustByCwd = new Map();
549
+ const trustPromptMode = parsed.help || parsed.listModels !== undefined || parsed.listTips ? "print" : toProjectTrustMode(appMode);
550
+ const resolvedExtensionPaths = resolveCliPaths(cwd, parsed.extensions);
551
+ const resolvedSkillPaths = resolveCliPaths(cwd, parsed.skills);
552
+ const resolvedPromptTemplatePaths = resolveCliPaths(cwd, parsed.promptTemplates);
553
+ const resolvedThemePaths = resolveCliPaths(cwd, parsed.themes);
554
+ return async ({ cwd, agentDir, sessionManager, sessionStartEvent, projectTrustContext, launchProfile }) => {
555
+ const isInitialRuntime = sessionStartEvent === undefined;
556
+ const projectTrustDiagnostics = [];
557
+ const cachedProjectTrust = projectTrustByCwd.get(cwd);
558
+ const hasTrustRequiringResources = hasTrustRequiringProjectResources(cwd);
559
+ const shouldResolveProjectTrust = parsed.projectTrustOverride === undefined && cachedProjectTrust === undefined && hasTrustRequiringResources;
560
+ const projectTrusted = shouldResolveProjectTrust
561
+ ? false
562
+ : (cachedProjectTrust ??
563
+ parsed.projectTrustOverride ??
564
+ (!hasTrustRequiringResources || trustStore.get(cwd) === true));
565
+ const runtimeSettingsManager = SettingsManager.create(cwd, agentDir, { projectTrusted });
566
+ const services = await createAgentSessionServices({
567
+ cwd,
568
+ agentDir,
569
+ settingsManager: runtimeSettingsManager,
570
+ modelRuntimeSignal: AbortSignal.timeout(15_000),
571
+ extensionFlagValues: parsed.unknownFlags,
572
+ resourceLoaderReloadOptions: shouldResolveProjectTrust
573
+ ? {
574
+ resolveProjectTrust: async ({ extensionsResult }) => {
575
+ const trusted = await resolveProjectTrusted({
576
+ cwd,
577
+ trustStore,
578
+ trustOverride: parsed.projectTrustOverride,
579
+ defaultProjectTrust: startupSettingsManager.getDefaultProjectTrust(),
580
+ extensionsResult,
581
+ projectTrustContext: projectTrustContext ??
582
+ pauseIndicatorDuringPrompts(createProjectTrustContext({
583
+ cwd,
584
+ mode: isInitialRuntime ? trustPromptMode : toProjectTrustMode(appMode),
585
+ settingsManager: startupSettingsManager,
586
+ hasUI: isInitialRuntime && trustPromptMode === "interactive",
587
+ }), startupLoadingIndicator),
588
+ onExtensionError: (message) => projectTrustDiagnostics.push({ type: "warning", message }),
589
+ });
590
+ projectTrustByCwd.set(cwd, trusted);
591
+ return trusted;
592
+ },
593
+ }
594
+ : undefined,
595
+ resourceLoaderOptions: {
596
+ additionalExtensionPaths: resolvedExtensionPaths,
597
+ additionalSkillPaths: resolvedSkillPaths,
598
+ additionalPromptTemplatePaths: resolvedPromptTemplatePaths,
599
+ additionalThemePaths: resolvedThemePaths,
600
+ noExtensions: parsed.noExtensions,
601
+ noSkills: parsed.noSkills,
602
+ noPromptTemplates: parsed.noPromptTemplates,
603
+ noThemes: parsed.noThemes,
604
+ noContextFiles: parsed.noContextFiles,
605
+ systemPrompt: parsed.systemPrompt,
606
+ appendSystemPrompt: parsed.appendSystemPrompt,
607
+ extensionFactories,
608
+ },
609
+ });
610
+ const { settingsManager, modelRuntime, resourceLoader } = services;
611
+ const diagnostics = [
612
+ ...projectTrustDiagnostics,
613
+ ...services.diagnostics,
614
+ ...collectSettingsDiagnostics(settingsManager, "runtime creation"),
615
+ ...collectExtensionLoadDiagnostics(resourceLoader.getExtensions().errors),
616
+ ];
617
+ const modelPatterns = getModelNarrowingPatterns({
618
+ cliPatterns: parsed.models,
619
+ legacyEnabledPatterns: settingsManager.getEnabledModels(),
620
+ });
621
+ const scopedModels = modelPatterns && modelPatterns.length > 0
622
+ ? await resolveModelScope(modelPatterns, modelRuntime, { signal: AbortSignal.timeout(15_000) })
623
+ : [];
624
+ // Multi-session opens carry their per-session startup choices here rather
625
+ // than through process argv. This deliberately feeds the same resolver as
626
+ // --provider/--model/--thinking, preserving classic flag semantics.
627
+ const runtimeParsed = launchProfile === undefined
628
+ ? parsed
629
+ : {
630
+ ...parsed,
631
+ ...(launchProfile.creationModel === undefined
632
+ ? {}
633
+ : {
634
+ provider: launchProfile.creationModel.provider,
635
+ model: launchProfile.creationModel.modelId,
636
+ }),
637
+ ...(launchProfile.initialThinkingLevel === undefined
638
+ ? {}
639
+ : { thinking: launchProfile.initialThinkingLevel }),
640
+ };
641
+ const { options: sessionOptions, cliThinkingFromModel, diagnostics: sessionOptionDiagnostics, } = buildSessionOptions(runtimeParsed, scopedModels, sessionManager.hasContextMessages(), modelRuntime, settingsManager);
642
+ diagnostics.push(...sessionOptionDiagnostics);
643
+ if (parsed.apiKey) {
644
+ if (!sessionOptions.model) {
645
+ diagnostics.push({
646
+ type: "error",
647
+ message: "--api-key requires a model to be specified via --model, --provider/--model, or --models",
648
+ });
649
+ }
650
+ else {
651
+ await modelRuntime.setRuntimeApiKey(sessionOptions.model.provider, parsed.apiKey);
652
+ }
653
+ }
654
+ if (isInitialRuntime) {
655
+ startupLoadingIndicator.setPhase("opening session");
656
+ }
657
+ const created = await createAgentSessionFromServices({
658
+ services,
659
+ sessionManager,
660
+ sessionStartEvent,
661
+ model: sessionOptions.model,
662
+ thinkingLevel: sessionOptions.thinkingLevel,
663
+ thinkingSelection: sessionOptions.thinkingSelection,
664
+ scopedModels: sessionOptions.scopedModels,
665
+ tools: sessionOptions.tools,
666
+ excludeTools: sessionOptions.excludeTools,
667
+ noTools: sessionOptions.noTools,
668
+ customTools: sessionOptions.customTools,
669
+ autoTitleSessions: resolveAutoTitleSessions(appMode, parsed, sessionManager.hasContextMessages(), parseClientCapabilities(envValue("RPC_CLIENT_CAPABILITIES"))),
670
+ });
671
+ const cliThinkingOverride = runtimeParsed.thinking !== undefined || cliThinkingFromModel;
672
+ if (created.session.model && cliThinkingOverride) {
673
+ created.session.setThinkingLevel(created.session.thinkingLevel);
674
+ }
675
+ return {
676
+ ...created,
677
+ services,
678
+ diagnostics,
679
+ };
680
+ };
681
+ }
536
682
  export async function main(args, options) {
537
683
  resetTimings();
538
684
  const extensionFactories = [...builtInExtensions, ...(options?.extensionFactories ?? [])];
@@ -691,6 +837,21 @@ export async function main(args, options) {
691
837
  if (appMode === "interactive" && parsed.useTheme !== undefined) {
692
838
  startupSettingsManager.applyOverrides({ theme: parsed.useTheme });
693
839
  }
840
+ if (appMode === "rpc" && parsed.multiSession) {
841
+ if (options?.extensionFactories?.length)
842
+ throw new Error("Shared RPC workers require file-backed extensions; inline factories cannot cross isolates");
843
+ const workerConfiguration = { parsed, cwd, agentDir, appMode };
844
+ printTimings();
845
+ await runMultiSessionHost({
846
+ agentDir,
847
+ createRuntime: createCliRuntimeFactory(workerConfiguration),
848
+ workerConfiguration,
849
+ cwd,
850
+ creationModel: parsed.provider && parsed.model ? { provider: parsed.provider, modelId: parsed.model } : undefined,
851
+ initialThinkingLevel: parsed.thinking,
852
+ listen: parsed.listen,
853
+ });
854
+ }
694
855
  // Decide the final runtime cwd before creating cwd-bound runtime services.
695
856
  // --session and --resume may select a session from another project, so project-local
696
857
  // settings, resources, provider registrations, and models must be resolved only after
@@ -724,13 +885,10 @@ export async function main(args, options) {
724
885
  sessionManager.appendSessionInfo(name);
725
886
  }
726
887
  time("createSessionManager");
727
- const trustStore = new ProjectTrustStore(agentDir);
728
888
  const sessionCwd = sessionManager.getCwd();
729
889
  const autoTrustOnReloadCwd = parsed.projectTrustOverride === undefined && !hasTrustRequiringProjectResources(sessionCwd)
730
890
  ? sessionCwd
731
891
  : undefined;
732
- const trustPromptMode = parsed.help || parsed.listModels !== undefined || parsed.listTips ? "print" : toProjectTrustMode(appMode);
733
- const projectTrustByCwd = new Map();
734
892
  // Immediate feedback while the heavy runtime (extensions, models, trust) is
735
893
  // created; without it the terminal stays blank and looks stuck (codex-style
736
894
  // UI-first startup). Stopped before any other surface writes to stdout.
@@ -747,151 +905,8 @@ export async function main(args, options) {
747
905
  startupLoadingIndicator.start();
748
906
  startupLoadingIndicator.setPhase("extensions & models");
749
907
  }
750
- const createRuntime = async ({ cwd, agentDir, sessionManager, sessionStartEvent, projectTrustContext, launchProfile, }) => {
751
- const isInitialRuntime = sessionStartEvent === undefined;
752
- const projectTrustDiagnostics = [];
753
- const cachedProjectTrust = projectTrustByCwd.get(cwd);
754
- const hasTrustRequiringResources = hasTrustRequiringProjectResources(cwd);
755
- const shouldResolveProjectTrust = parsed.projectTrustOverride === undefined && cachedProjectTrust === undefined && hasTrustRequiringResources;
756
- const projectTrusted = shouldResolveProjectTrust
757
- ? false
758
- : (cachedProjectTrust ??
759
- parsed.projectTrustOverride ??
760
- (!hasTrustRequiringResources || trustStore.get(cwd) === true));
761
- const runtimeSettingsManager = SettingsManager.create(cwd, agentDir, { projectTrusted });
762
- const services = await createAgentSessionServices({
763
- cwd,
764
- agentDir,
765
- settingsManager: runtimeSettingsManager,
766
- modelRuntimeSignal: AbortSignal.timeout(15_000),
767
- extensionFlagValues: parsed.unknownFlags,
768
- resourceLoaderReloadOptions: shouldResolveProjectTrust
769
- ? {
770
- resolveProjectTrust: async ({ extensionsResult }) => {
771
- const trusted = await resolveProjectTrusted({
772
- cwd,
773
- trustStore,
774
- trustOverride: parsed.projectTrustOverride,
775
- defaultProjectTrust: startupSettingsManager.getDefaultProjectTrust(),
776
- extensionsResult,
777
- projectTrustContext: projectTrustContext ??
778
- pauseIndicatorDuringPrompts(createProjectTrustContext({
779
- cwd,
780
- mode: isInitialRuntime ? trustPromptMode : toProjectTrustMode(appMode),
781
- settingsManager: startupSettingsManager,
782
- hasUI: isInitialRuntime && trustPromptMode === "interactive",
783
- }), startupLoadingIndicator),
784
- onExtensionError: (message) => projectTrustDiagnostics.push({ type: "warning", message }),
785
- });
786
- projectTrustByCwd.set(cwd, trusted);
787
- return trusted;
788
- },
789
- }
790
- : undefined,
791
- resourceLoaderOptions: {
792
- additionalExtensionPaths: resolvedExtensionPaths,
793
- additionalSkillPaths: resolvedSkillPaths,
794
- additionalPromptTemplatePaths: resolvedPromptTemplatePaths,
795
- additionalThemePaths: resolvedThemePaths,
796
- noExtensions: parsed.noExtensions,
797
- noSkills: parsed.noSkills,
798
- noPromptTemplates: parsed.noPromptTemplates,
799
- noThemes: parsed.noThemes,
800
- noContextFiles: parsed.noContextFiles,
801
- systemPrompt: parsed.systemPrompt,
802
- appendSystemPrompt: parsed.appendSystemPrompt,
803
- extensionFactories,
804
- },
805
- });
806
- const { settingsManager, modelRuntime, resourceLoader } = services;
807
- const diagnostics = [
808
- ...projectTrustDiagnostics,
809
- ...services.diagnostics,
810
- ...collectSettingsDiagnostics(settingsManager, "runtime creation"),
811
- ...collectExtensionLoadDiagnostics(resourceLoader.getExtensions().errors),
812
- ];
813
- const modelPatterns = getModelNarrowingPatterns({
814
- cliPatterns: parsed.models,
815
- legacyEnabledPatterns: settingsManager.getEnabledModels(),
816
- });
817
- const scopedModels = modelPatterns && modelPatterns.length > 0
818
- ? await resolveModelScope(modelPatterns, modelRuntime, { signal: AbortSignal.timeout(15_000) })
819
- : [];
820
- // Multi-session opens carry their per-session startup choices here rather
821
- // than through process argv. This deliberately feeds the same resolver as
822
- // --provider/--model/--thinking, preserving classic flag semantics.
823
- const runtimeParsed = launchProfile === undefined
824
- ? parsed
825
- : {
826
- ...parsed,
827
- ...(launchProfile.creationModel === undefined
828
- ? {}
829
- : {
830
- provider: launchProfile.creationModel.provider,
831
- model: launchProfile.creationModel.modelId,
832
- }),
833
- ...(launchProfile.initialThinkingLevel === undefined
834
- ? {}
835
- : { thinking: launchProfile.initialThinkingLevel }),
836
- };
837
- const { options: sessionOptions, cliThinkingFromModel, diagnostics: sessionOptionDiagnostics, } = buildSessionOptions(runtimeParsed, scopedModels, sessionManager.hasContextMessages(), modelRuntime, settingsManager);
838
- diagnostics.push(...sessionOptionDiagnostics);
839
- if (parsed.apiKey) {
840
- if (!sessionOptions.model) {
841
- diagnostics.push({
842
- type: "error",
843
- message: "--api-key requires a model to be specified via --model, --provider/--model, or --models",
844
- });
845
- }
846
- else {
847
- await modelRuntime.setRuntimeApiKey(sessionOptions.model.provider, parsed.apiKey);
848
- }
849
- }
850
- if (isInitialRuntime) {
851
- startupLoadingIndicator.setPhase("opening session");
852
- }
853
- const created = await createAgentSessionFromServices({
854
- services,
855
- sessionManager,
856
- sessionStartEvent,
857
- model: sessionOptions.model,
858
- thinkingLevel: sessionOptions.thinkingLevel,
859
- thinkingSelection: sessionOptions.thinkingSelection,
860
- scopedModels: sessionOptions.scopedModels,
861
- tools: sessionOptions.tools,
862
- excludeTools: sessionOptions.excludeTools,
863
- noTools: sessionOptions.noTools,
864
- customTools: sessionOptions.customTools,
865
- autoTitleSessions: resolveAutoTitleSessions(appMode, parsed, sessionManager.hasContextMessages(), parseClientCapabilities(envValue("RPC_CLIENT_CAPABILITIES"))),
866
- });
867
- const cliThinkingOverride = runtimeParsed.thinking !== undefined || cliThinkingFromModel;
868
- if (created.session.model && cliThinkingOverride) {
869
- created.session.setThinkingLevel(created.session.thinkingLevel);
870
- }
871
- return {
872
- ...created,
873
- services,
874
- diagnostics,
875
- };
876
- };
908
+ const createRuntime = createCliRuntimeFactory({ parsed, cwd, agentDir, appMode }, { extensionFactories, startupSettingsManager, startupLoadingIndicator });
877
909
  time("createRuntime");
878
- if (appMode === "rpc" && parsed.multiSession) {
879
- // The multi-session host never returns, so the initTheme() call further down
880
- // is unreachable on this path. Extensions loaded per open_session (and any
881
- // tool render helper) read the theme proxy and would otherwise crash with
882
- // "Theme not initialized. Call initTheme() first." (surfaced in embedders
883
- // like T3 Code as transcript errors).
884
- initTheme(startupSettingsManager.getTheme(), false);
885
- printTimings();
886
- await runMultiSessionHost({
887
- agentDir,
888
- createRuntime,
889
- cwd,
890
- creationModel: parsed.provider && parsed.model ? { provider: parsed.provider, modelId: parsed.model } : undefined,
891
- initialThinkingLevel: parsed.thinking,
892
- listen: parsed.listen,
893
- });
894
- }
895
910
  const runtime = await createAgentSessionRuntime(createRuntime, {
896
911
  cwd: sessionManager.getCwd(),
897
912
  agentDir,