@cydm/pie 2.7.13 → 2.7.14

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.
package/dist/cli.js CHANGED
@@ -29,10 +29,7 @@ import {
29
29
  migrateConfigFromAgentDir,
30
30
  setYoloGrantListener,
31
31
  truncateHeadTail
32
- } from "./chunks/chunk-D7RMNFVM.js";
33
- import {
34
- resolveCliProjectRoot
35
- } from "./chunks/chunk-WLFOBECN.js";
32
+ } from "./chunks/chunk-FOE2AW4L.js";
36
33
  import {
37
34
  AGENTS_CONTEXT_FILE_NAME,
38
35
  AgentSessionController,
@@ -94,8 +91,8 @@ import {
94
91
  shouldPreserveExecutionStateForUserText,
95
92
  supersedeExecutionState,
96
93
  verifyPreparedCompactionCommit
97
- } from "./chunks/chunk-CIFC6QVB.js";
98
- import "./chunks/chunk-HGUYS5SF.js";
94
+ } from "./chunks/chunk-VPTLDLI6.js";
95
+ import "./chunks/chunk-5YU6MU2N.js";
99
96
  import {
100
97
  Deref,
101
98
  Errors,
@@ -118,7 +115,13 @@ import {
118
115
  sortToolModelCandidatesByCapability,
119
116
  streamSimple,
120
117
  type_exports
121
- } from "./chunks/chunk-R46YPPTU.js";
118
+ } from "./chunks/chunk-N4252GH3.js";
119
+ import {
120
+ readImageFormat
121
+ } from "./chunks/chunk-F7EBZTZO.js";
122
+ import {
123
+ resolveCliProjectRoot
124
+ } from "./chunks/chunk-WLFOBECN.js";
122
125
  import {
123
126
  IsArray,
124
127
  IsBigInt,
@@ -56533,6 +56536,15 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
56533
56536
  sendUserMessage(content) {
56534
56537
  actions?.sendUserMessage(content);
56535
56538
  },
56539
+ ...actions?.attachLocalFile ? {
56540
+ attachLocalFile: (path34, displayName) => actions.attachLocalFile(path34, displayName)
56541
+ } : {},
56542
+ ...actions?.beginUserInput ? {
56543
+ beginUserInput: (isCurrent) => actions.beginUserInput(isCurrent)
56544
+ } : {},
56545
+ ...actions?.attachLocalFileAndSubmit ? {
56546
+ attachLocalFileAndSubmit: (path34, displayName, submitText) => actions.attachLocalFileAndSubmit(path34, displayName, submitText)
56547
+ } : {},
56536
56548
  setPlanMode(enabled, options) {
56537
56549
  actions?.setPlanMode(enabled, options);
56538
56550
  },
@@ -64637,6 +64649,15 @@ var ExtensionRunner = class {
64637
64649
  setActiveTools: (toolNames) => this.actions.setActiveTools(toolNames),
64638
64650
  getActiveTools: () => this.actions.getActiveTools(),
64639
64651
  sendUserMessage: (content) => this.actions.sendUserMessage(content),
64652
+ ...this.actions.attachLocalFile ? {
64653
+ attachLocalFile: (path34, displayName) => this.actions.attachLocalFile(path34, displayName)
64654
+ } : {},
64655
+ ...this.actions.beginUserInput ? {
64656
+ beginUserInput: (isCurrent) => this.actions.beginUserInput(isCurrent)
64657
+ } : {},
64658
+ ...this.actions.attachLocalFileAndSubmit ? {
64659
+ attachLocalFileAndSubmit: (path34, displayName, submitText) => this.actions.attachLocalFileAndSubmit(path34, displayName, submitText)
64660
+ } : {},
64640
64661
  setPlanMode: (enabled, options) => this.actions.setPlanMode(enabled, options),
64641
64662
  setExecutionReminder: (text) => this.actions.setExecutionReminder(text),
64642
64663
  getExecutionState: () => this.actions.getExecutionState(),
@@ -68160,6 +68181,20 @@ var FileCache = class _FileCache {
68160
68181
  getByHash(hash) {
68161
68182
  return this.index.files[hash];
68162
68183
  }
68184
+ /** Repair historical image MIME labels using the cached bytes. Content
68185
+ * deduplication must not keep an old .png-derived label when the same
68186
+ * Feishu JPEG is staged again with the corrected .jpg name. The hash,
68187
+ * bytes and platform upload records stay unchanged. */
68188
+ refreshImageMimeType(hash) {
68189
+ const entry = this.index.files[hash];
68190
+ if (!entry || !entry.mimeType.startsWith("image/")) return;
68191
+ const localPath = this.getLocalPath(hash);
68192
+ if (!localPath) return;
68193
+ const detected = readImageFormat(localPath);
68194
+ if (detected.ext === ".bin" || detected.mime === entry.mimeType) return;
68195
+ entry.mimeType = detected.mime;
68196
+ this.saveIndex();
68197
+ }
68163
68198
  getByFileId(fileId, platform2) {
68164
68199
  for (const entry of Object.values(this.index.files)) {
68165
68200
  const platformRecord = entry.platforms[platform2];
@@ -69263,6 +69298,7 @@ var FileManager = class {
69263
69298
  if (!cached) {
69264
69299
  await this.fileCache.storeFile(resolvedPath, sourceName, mimeType);
69265
69300
  }
69301
+ this.fileCache.refreshImageMimeType(hash);
69266
69302
  this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
69267
69303
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
69268
69304
  const entry = this.fileCache.getByHash(hash);
@@ -78889,7 +78925,23 @@ var MentionHandler = class {
78889
78925
  * behave identically.
78890
78926
  */
78891
78927
  async attachLocalFile(path34, displayName, pendingMention, isCurrent) {
78892
- await this.attachFileFromPath(path34, { sourceName: displayName, queryToken: pendingMention, isCurrent });
78928
+ return this.attachFileFromPath(path34, { sourceName: displayName, queryToken: pendingMention, isCurrent });
78929
+ }
78930
+ /** Prepare a message-owned mention without reading or mutating the editor.
78931
+ * Errors propagate to the caller; no caption-only submission on failure. */
78932
+ async prepareLocalFile(filePath, displayName, isCurrent = () => true) {
78933
+ if (!isCurrent()) return void 0;
78934
+ const sourceName = displayName ?? path28.basename(filePath);
78935
+ const result = await this.prepareFile(filePath, sourceName);
78936
+ if (!isCurrent() || !result.success) return void 0;
78937
+ return this.formatMention(result.name, result.fileId);
78938
+ }
78939
+ prepareFile(filePath, sourceName, onProgress) {
78940
+ const mimeType = FileCache.getMimeType(filePath);
78941
+ const isMedia = mimeType.startsWith("image/") || mimeType.startsWith("video/");
78942
+ if (!isMedia || !this.fileManager.hasAdapter()) return this.fileManager.stageLocal(filePath, { sourceName });
78943
+ if (mimeType.startsWith("video/")) return this.fileManager.uploadVideo(filePath, { sourceName, onProgress });
78944
+ return this.fileManager.uploadPic(filePath, { sourceName, onProgress });
78893
78945
  }
78894
78946
  /** Reserve a real queue-replaceable token before asynchronous clipboard IO. */
78895
78947
  beginPendingAttachment(name) {
@@ -78942,29 +78994,22 @@ var MentionHandler = class {
78942
78994
  this.formatUploadProgress(sourceName, progress, stage)
78943
78995
  );
78944
78996
  };
78945
- const result = shouldStageLocally ? await this.fileManager.stageLocal(path34, { sourceName }) : mimeType.startsWith("video/") ? await this.fileManager.uploadVideo(path34, {
78946
- sourceName,
78947
- onProgress
78948
- }) : mimeType.startsWith("image/") ? await this.fileManager.uploadPic(path34, {
78949
- sourceName,
78950
- onProgress
78951
- }) : await this.fileManager.upload(path34, {
78952
- sourceName,
78953
- onProgress
78954
- });
78955
- if (options.isCurrent && !options.isCurrent()) return;
78997
+ const result = await this.prepareFile(path34, sourceName, onProgress);
78998
+ if (options.isCurrent && !options.isCurrent()) return false;
78956
78999
  if (result.success) {
78957
79000
  const mention = this.formatMention(result.name, result.fileId);
78958
79001
  this.onInsertMention(mention, pendingMention);
78959
79002
  this.clearPendingStatus(pendingStatusKey);
78960
79003
  this.onStatus?.(shouldStageLocally ? `Added local file ${result.name}` : `Added ${result.name}`);
79004
+ return true;
78961
79005
  } else {
78962
79006
  this.onInsertMention("", pendingMention);
78963
79007
  this.clearPendingStatus(pendingStatusKey);
78964
79008
  this.onError?.("File upload failed. Please try again.");
79009
+ return false;
78965
79010
  }
78966
79011
  } catch (err) {
78967
- if (options.isCurrent && !options.isCurrent()) return;
79012
+ if (options.isCurrent && !options.isCurrent()) return false;
78968
79013
  this.onInsertMention("", pendingMention);
78969
79014
  this.clearPendingStatus(pendingStatusKey);
78970
79015
  const errorMessage5 = err instanceof Error ? err.message : String(err);
@@ -78979,6 +79024,7 @@ var MentionHandler = class {
78979
79024
  } else {
78980
79025
  this.onError?.(`Upload failed: ${errorMessage5}`);
78981
79026
  }
79027
+ return false;
78982
79028
  } finally {
78983
79029
  this.clearPendingStatus(pendingStatusKey);
78984
79030
  this.pendingUploadCount = Math.max(0, this.pendingUploadCount - 1);
@@ -79746,6 +79792,15 @@ function setupInteractiveKeybindings(host) {
79746
79792
  host.handleFollowUp();
79747
79793
  return { consume: true };
79748
79794
  }
79795
+ const shortcuts = host.getExtensionShortcuts?.();
79796
+ if (shortcuts && shortcuts.size > 0 && mainEditorOwnsInput(host)) {
79797
+ for (const shortcut of shortcuts.values()) {
79798
+ if (matchesKey(data, shortcut.key)) {
79799
+ void shortcut.handler();
79800
+ return { consume: true };
79801
+ }
79802
+ }
79803
+ }
79749
79804
  return { consume: false };
79750
79805
  });
79751
79806
  }
@@ -81839,6 +81894,11 @@ function createInteractiveAgentSessionController(host) {
81839
81894
  lastShownCompactionError = null;
81840
81895
  host.setControllerBusy(false);
81841
81896
  } else if (event.type === "turn_cancelled") {
81897
+ host.emitExtensionEvent({
81898
+ type: "turn:cancelled",
81899
+ turnIndex: host._semanticTurnIndex,
81900
+ reason: event.reason
81901
+ });
81842
81902
  const outcome = host.executionState.abort();
81843
81903
  host.logDebug("execution:turn_cancelled", {
81844
81904
  turnIndex: host._semanticTurnIndex,
@@ -82747,6 +82807,51 @@ function summarizeToolNames(tools) {
82747
82807
  return tools.map((tool) => tool.name).join(", ");
82748
82808
  }
82749
82809
 
82810
+ // src/extensions/user-input-scope.ts
82811
+ function beginUserInput(host, extensionIsCurrent = () => true) {
82812
+ const session = host.sessionManager.getActiveSession();
82813
+ const controller = host.agentSessionController;
82814
+ const runner = host.extensionRunner;
82815
+ const handler = host.attachmentMentionHandler?.();
82816
+ if (!session || !controller || !runner || !handler) return void 0;
82817
+ let retired = false;
82818
+ let used = false;
82819
+ const unsubscribe = controller.subscribe((event) => {
82820
+ if (event.type === "session_invalidated") retired = true;
82821
+ });
82822
+ const dispose = runner.trackUnregisterHandle(() => {
82823
+ retired = true;
82824
+ unsubscribe();
82825
+ });
82826
+ const isCurrent = () => !retired && host.sessionManager.getActiveSession() === session && host.agentSessionController === controller && host.extensionRunner === runner && host.attachmentMentionHandler?.() === handler && extensionIsCurrent();
82827
+ return {
82828
+ isCurrent,
82829
+ dispose,
82830
+ async submit(text, files = []) {
82831
+ if (used || !isCurrent() || !text.trim() && !files.length) return false;
82832
+ used = true;
82833
+ try {
82834
+ const mentions = [];
82835
+ for (const file of files) {
82836
+ if (!isCurrent()) return false;
82837
+ const mention = await handler.prepareLocalFile(file.path, file.displayName, isCurrent);
82838
+ if (!mention || !isCurrent()) return false;
82839
+ mentions.push(mention.trim());
82840
+ }
82841
+ let content = [text.trim(), ...mentions].filter(Boolean).join("\n");
82842
+ const decision = await runner.emitTerminalInput({ type: "terminal:input", text: content });
82843
+ if (!isCurrent() || decision.action === "consume") return false;
82844
+ if (decision.action === "transform") content = decision.text.trim();
82845
+ if (!content || mentions.some((mention) => !content.includes(mention))) return false;
82846
+ host.queueMessage(content, "followUp", { clearEditor: false, deliverWhileStreaming: false });
82847
+ return true;
82848
+ } catch {
82849
+ return false;
82850
+ }
82851
+ }
82852
+ };
82853
+ }
82854
+
82750
82855
  // src/extensions/interactive-extension-loader.ts
82751
82856
  async function loadInteractiveExtensions(host) {
82752
82857
  const extensionActions = {
@@ -82768,6 +82873,21 @@ async function loadInteractiveExtensions(host) {
82768
82873
  void host.editor.onSubmit(content);
82769
82874
  }
82770
82875
  },
82876
+ attachLocalFile: async (path34, displayName) => {
82877
+ const handler = host.attachmentMentionHandler?.();
82878
+ if (!handler) return false;
82879
+ return handler.attachLocalFile(path34, displayName);
82880
+ },
82881
+ beginUserInput: (isCurrent) => beginUserInput(host, isCurrent),
82882
+ attachLocalFileAndSubmit: async (path34, displayName, submitText) => {
82883
+ const scope = beginUserInput(host);
82884
+ if (!scope) return false;
82885
+ try {
82886
+ return await scope.submit(submitText, [{ path: path34, displayName }]);
82887
+ } finally {
82888
+ scope.dispose();
82889
+ }
82890
+ },
82771
82891
  setPlanMode: (enabled, options) => {
82772
82892
  const shouldEmitTransition = host.planModeEnabled !== enabled || options?.forcePromptInjection;
82773
82893
  if (shouldEmitTransition) {
@@ -83302,7 +83422,7 @@ var InteractiveMode = class {
83302
83422
  async init() {
83303
83423
  const activeSession = this.sessionManager.getActiveSession();
83304
83424
  this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
83305
- const { Agent } = await import("./chunks/src-5JJZZ5H7.js");
83425
+ const { Agent } = await import("./chunks/src-4PG3KZUS.js");
83306
83426
  this.agent = new Agent({
83307
83427
  initialState: {
83308
83428
  systemPrompt: this.buildSystemPrompt(),
@@ -83669,9 +83789,41 @@ var InteractiveMode = class {
83669
83789
  return interactiveCommands.some((cmd) => commandPath.startsWith(cmd));
83670
83790
  }
83671
83791
  toggleToolsExpansion() {
83792
+ if (this.calmMode) {
83793
+ this.setCalmMode(false);
83794
+ if (this.toolOutputExpanded) toggleToolsExpansion(this.uiHelperHost);
83795
+ this.options.settingsManager.setToolOutputExpanded(this.toolOutputExpanded);
83796
+ return;
83797
+ }
83798
+ if (this.toolOutputExpanded) {
83799
+ this.setCalmMode(true);
83800
+ return;
83801
+ }
83672
83802
  toggleToolsExpansion(this.uiHelperHost);
83673
83803
  this.options.settingsManager.setToolOutputExpanded(this.toolOutputExpanded);
83674
83804
  }
83805
+ /** Aggregated extension shortcut registrations for the keybinding
83806
+ * dispatcher (duck-typed onto InteractiveKeybindingsHost). Handlers are
83807
+ * bound to the extension runner context here. */
83808
+ getExtensionShortcuts() {
83809
+ const merged = /* @__PURE__ */ new Map();
83810
+ for (const extension of this.extensions) {
83811
+ for (const [key, shortcut] of extension.shortcuts) {
83812
+ if (merged.has(key)) continue;
83813
+ const context = this.extensionRunner?.createContext();
83814
+ merged.set(key, {
83815
+ key,
83816
+ handler: () => shortcut.handler(context)
83817
+ });
83818
+ }
83819
+ }
83820
+ return merged;
83821
+ }
83822
+ /** Live mention handler for extension-driven attachments (duck-typed onto
83823
+ * InteractiveExtensionLoaderHost); undefined while attachments init. */
83824
+ attachmentMentionHandler() {
83825
+ return this.mentionHandler;
83826
+ }
83675
83827
  showSelector(create) {
83676
83828
  return showSelector(this.uiHelperHost, create);
83677
83829
  }
@@ -84194,7 +84346,7 @@ async function runPrintMode(params) {
84194
84346
  `);
84195
84347
  console.log("Assistant: ");
84196
84348
  }
84197
- const { Agent: AgentClass } = await import("./chunks/src-5JJZZ5H7.js");
84349
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
84198
84350
  let agent;
84199
84351
  const printModeExtensions = await loadPrintModeExtensions({
84200
84352
  cwd: runtime.cwd,
@@ -85089,7 +85241,7 @@ async function runJsonEventsMode(params) {
85089
85241
  const sideTrace = trace;
85090
85242
  const sideApiKey = runtime.apiKey;
85091
85243
  const snapshot = structuredClone(parent.state.messages);
85092
- const { Agent: AgentClass } = await import("./chunks/src-5JJZZ5H7.js");
85244
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
85093
85245
  const sideAgent = new AgentClass({
85094
85246
  initialState: {
85095
85247
  systemPrompt: parent.state.systemPrompt,
@@ -85453,7 +85605,7 @@ async function runJsonEventsMode(params) {
85453
85605
  if (runtime.initialModel.unconfigured || controller) {
85454
85606
  return;
85455
85607
  }
85456
- const { Agent: AgentClass } = await import("./chunks/src-5JJZZ5H7.js");
85608
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
85457
85609
  if (runtimeClosing) return;
85458
85610
  const compositionRegistry = createCliHostEnvelopeRegistry();
85459
85611
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, envelopeRegistry: compositionRegistry, getAgent: () => agent });
@@ -86141,7 +86293,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
86141
86293
  }
86142
86294
  async function createCliTestStreamFnFromEnv() {
86143
86295
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
86144
- return (await import("./chunks/test-stream-ZBTSPU7J.js")).createTestStreamFnFromSequenceEnv();
86296
+ return (await import("./chunks/test-stream-OTKTTZ72.js")).createTestStreamFnFromSequenceEnv();
86145
86297
  }
86146
86298
  function resolveJsonEventsDetailFlag() {
86147
86299
  for (let index = 0; index < process.argv.length; index += 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "2.7.13",
3
+ "version": "2.7.14",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,8 +20,9 @@
20
20
  "test:skill-regressions": "node --test --import tsx test/bash-lifecycle.test.ts test/bash-powershell-display.test.ts test/skill-creator-runner.test.ts test/tui-use-contract.test.ts test/tui-use-runtime.test.ts test/browser-runtime.test.ts test/axi-stop-semantics.test.ts test/computer-use-axi.test.ts test/computer-evidence.test.ts test/interactive-lifecycle.test.ts",
21
21
  "test:offline:post": "node --test --import tsx test/remote-model-catalog.test.ts",
22
22
  "test:offline": "node ../../scripts/run-cli-offline.mjs",
23
- "test:offline:main": "node --test --test-concurrency=2 --import tsx test/cli-attention.test.ts test/builtin-extensions.test.ts test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/todo-steering-ownership.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-provider.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/auto-compaction-ui.test.ts test/tool-compaction-dogfood.terminal.test.ts test/hierarchical-command-system.test.ts test/mcp-adapter.test.ts test/herdr-agent-state.test.ts test/extensions-enablement.test.ts test/extension-selector-shortcuts.test.ts test/skill-tool-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/json-events-sidechat-diagnostics.test.ts test/json-events-prewarm-shutdown.test.ts test/json-envelope-composition.test.ts test/subagent-session-store.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/footer-waiting-for-user.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/skills-agents-discovery.test.ts test/skills-symlink.test.ts test/model-overrides.test.ts test/auth-storage.test.ts test/extension-register-provider.test.ts test/extension-reload.test.ts test/extension-terminal-input.test.ts test/extension-session-before-events.test.ts test/extension-widgets.test.ts test/extension-render-hint.test.ts test/extension-oauth-restore.test.ts test/cross-host-parity.test.ts test/tool-name-rendering.test.ts test/session-selector.test.ts test/tree-selector-pagination.test.ts test/context-report.test.ts test/context-signals.test.ts test/plan-cache-stability.test.ts test/cache-invalidation-trace.test.ts test/cache-retention.test.ts test/trace-report.test.ts test/boot-report.test.ts test/compaction-diff.test.ts test/entry-body-and-usage.test.ts test/session-control.test.ts test/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/host-envelope-dogfood.terminal.test.ts test/host-envelope-cross-mode.test.ts test/host-envelope-registry-lifecycle.test.ts test/host-envelope-migration-roundtrip.test.ts test/host-envelope-intake-order.test.ts test/plan-mode-extension.test.ts test/extension-interaction-signals.test.ts test/rendered-page-reader.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/bash-yolo.test.ts test/bash-contract.test.ts test/bash-confirm-pending.test.ts test/interaction-status-lifecycle.test.ts test/bash-process-group.test.ts test/bash-artifact-sink.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/ctrl-d-exit.test.ts test/session-display-title.test.ts test/calm-mode.test.ts test/stream-render-throttle.test.ts test/message-display-resync.test.ts test/project-root.test.ts test/guard-advisory-context.test.ts test/clear-command-usage.test.ts test/daily-agent-smoke.terminal.test.ts test/slash-menu-toggles.terminal.test.ts test/cli-args.test.ts test/extensions-configured-paths.test.ts test/extensions-loader-path.test.ts test/file-picker.test.ts test/interrupt-recovery.test.ts test/mention-insert-regression.test.ts test/image-paste.test.ts test/clipboard-read-image.test.ts test/clipboard-races.test.ts test/clipboard-dogfood.terminal.test.ts test/mention-picker-navigation.test.ts test/pie-unity-rpc-skill.test.ts test/skill-creator-scripts.test.ts test/interactive-compact-command.test.ts test/computer-use-broker.test.ts test/computer-use-review-regressions.test.ts test/computer-use-safety.test.ts ../../scripts/node-test-diagnostics.test.js ../../scripts/offline-test-runner.test.js ../../scripts/unity-consumer.test.mjs ../../scripts/owned-process-cleanup.test.mjs",
23
+ "test:offline:main": "node --test --test-concurrency=2 --import tsx test/cli-attention.test.ts test/builtin-extensions.test.ts test/im-forward.test.ts test/im-forward-cli.test.ts test/im-forward-integration.test.ts test/im-forward-dogfood.terminal.test.ts test/extension-user-input.test.ts test/pie-ipc-pure.test.ts test/pie-ipc-discovery.test.ts test/pie-ipc-transport.test.ts test/pie-ipc-delivery.test.ts test/pie-ipc-extension.test.ts test/pie-ipc-e2e.test.ts test/pie-ipc-security.test.ts test/pie-ipc-dogfood.test.ts test/pie-ipc-host.terminal.test.ts test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/todo-steering-ownership.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-provider.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/auto-compaction-ui.test.ts test/tool-compaction-dogfood.terminal.test.ts test/hierarchical-command-system.test.ts test/mcp-adapter.test.ts test/herdr-agent-state.test.ts test/extensions-enablement.test.ts test/extension-selector-shortcuts.test.ts test/skill-tool-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/json-events-sidechat-diagnostics.test.ts test/json-events-prewarm-shutdown.test.ts test/json-envelope-composition.test.ts test/subagent-session-store.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/footer-waiting-for-user.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/skills-agents-discovery.test.ts test/skills-symlink.test.ts test/model-overrides.test.ts test/auth-storage.test.ts test/extension-register-provider.test.ts test/extension-reload.test.ts test/extension-terminal-input.test.ts test/extension-session-before-events.test.ts test/extension-widgets.test.ts test/extension-render-hint.test.ts test/extension-oauth-restore.test.ts test/cross-host-parity.test.ts test/tool-name-rendering.test.ts test/session-selector.test.ts test/tree-selector-pagination.test.ts test/context-report.test.ts test/context-signals.test.ts test/plan-cache-stability.test.ts test/cache-invalidation-trace.test.ts test/cache-retention.test.ts test/trace-report.test.ts test/boot-report.test.ts test/compaction-diff.test.ts test/entry-body-and-usage.test.ts test/session-control.test.ts test/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/host-envelope-dogfood.terminal.test.ts test/host-envelope-cross-mode.test.ts test/host-envelope-registry-lifecycle.test.ts test/host-envelope-migration-roundtrip.test.ts test/host-envelope-intake-order.test.ts test/plan-mode-extension.test.ts test/extension-interaction-signals.test.ts test/rendered-page-reader.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/bash-yolo.test.ts test/bash-contract.test.ts test/bash-confirm-pending.test.ts test/interaction-status-lifecycle.test.ts test/bash-process-group.test.ts test/bash-artifact-sink.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/ctrl-d-exit.test.ts test/session-display-title.test.ts test/calm-mode.test.ts test/stream-render-throttle.test.ts test/message-display-resync.test.ts test/project-root.test.ts test/guard-advisory-context.test.ts test/clear-command-usage.test.ts test/daily-agent-smoke.terminal.test.ts test/slash-menu-toggles.terminal.test.ts test/cli-args.test.ts test/extensions-configured-paths.test.ts test/extensions-loader-path.test.ts test/file-picker.test.ts test/interrupt-recovery.test.ts test/mention-insert-regression.test.ts test/image-paste.test.ts test/clipboard-read-image.test.ts test/clipboard-races.test.ts test/clipboard-dogfood.terminal.test.ts test/mention-picker-navigation.test.ts test/pie-unity-rpc-skill.test.ts test/skill-creator-scripts.test.ts test/interactive-compact-command.test.ts test/computer-use-broker.test.ts test/computer-use-review-regressions.test.ts test/computer-use-safety.test.ts ../../scripts/node-test-diagnostics.test.js ../../scripts/offline-test-runner.test.js ../../scripts/unity-consumer.test.mjs ../../scripts/owned-process-cleanup.test.mjs",
24
24
  "test:all": "npm run test:offline && npm run test:terminal:vitest",
25
+ "test:ipc:tui": "node ../../scripts/run-with-env.mjs PIE_REAL_IPC_TUI=1 -- --test --import tsx test/pie-ipc-host.terminal.test.ts",
25
26
  "test:terminal:vitest": "vitest run test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/footer-plan-mode.test.ts test/viewport-position-final.test.ts test/resume-header.terminal.test.ts --no-file-parallelism",
26
27
  "test:todo-tui": "node ../../scripts/run-with-env.mjs PIE_REAL_TODO_TUI=1 -- --test --import tsx test/todo-closure.terminal.test.ts",
27
28
  "test:daily-tui": "npm run test:daily-tui:quick",