@cydm/pie 1.0.49 → 1.0.51

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 (31) hide show
  1. package/README.md +1 -1
  2. package/dist/builtin/extensions/ask-user/index.js +4 -11
  3. package/dist/builtin/extensions/ask-user/package.json +0 -7
  4. package/dist/builtin/extensions/changelog/index.js +15 -20
  5. package/dist/builtin/extensions/document-attachments/index.js +51 -1
  6. package/dist/builtin/extensions/document-attachments/package.json +1 -1
  7. package/dist/builtin/extensions/init/index.js +0 -13
  8. package/dist/builtin/extensions/plan-mode/index.js +31 -19
  9. package/dist/builtin/extensions/subagent/index.js +19 -40
  10. package/dist/builtin/extensions/todo/index.js +6 -10
  11. package/dist/builtin/skills/skill-creator/SKILL.md +15 -43
  12. package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.mjs +1 -1
  13. package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +2 -2
  14. package/dist/builtin/skills/skill-creator/references/schemas.md +1 -1
  15. package/dist/builtin/skills/skill-creator/scripts/generate_report.mjs +1 -1
  16. package/dist/builtin/skills/skill-creator/scripts/improve_description.mjs +3 -3
  17. package/dist/builtin/skills/skill-creator/scripts/pie_runner.mjs +32 -4
  18. package/dist/builtin/skills/skill-creator/scripts/run_loop.mjs +1 -1
  19. package/dist/chunks/{chunk-7RYOIXA2.js → chunk-A644H2XX.js} +104 -20
  20. package/dist/chunks/{chunk-FKAO25XH.js → chunk-B3SMW2XW.js} +1 -1
  21. package/dist/chunks/{chunk-J6PEH6ST.js → chunk-KDPAGHYY.js} +2 -2
  22. package/dist/chunks/{chunk-K6ZOCJ4V.js → chunk-S2J3SZZX.js} +44 -1
  23. package/dist/chunks/{src-HYZFAW4V.js → src-UKCIAX6F.js} +2 -2
  24. package/dist/chunks/{test-stream-5T7E7C25.js → test-stream-NCBFPM2I.js} +1 -1
  25. package/dist/cli.js +49 -22
  26. package/package.json +3 -3
  27. package/dist/builtin/extensions/deploy/index.js +0 -11
  28. package/dist/builtin/extensions/deploy/package.json +0 -11
  29. package/dist/builtin/extensions/files/index.js +0 -10
  30. package/dist/builtin/extensions/files/package.json +0 -14
  31. package/dist/builtin/skills/skill-creator/scripts/claude_cli.mjs +0 -115
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  EventStream
4
- } from "./chunk-K6ZOCJ4V.js";
4
+ } from "./chunk-S2J3SZZX.js";
5
5
  import "./chunk-LZQXQOPJ.js";
6
6
 
7
7
  // src/app/test-stream.ts
package/dist/cli.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
3
+ import {
4
+ resolveCliProjectRoot
5
+ } from "./chunks/chunk-WLFOBECN.js";
3
6
  import {
4
7
  VERSION,
5
8
  cleanupBashOutputArtifacts,
@@ -19,10 +22,7 @@ import {
19
22
  getThemesDir,
20
23
  migrateConfigFromAgentDir,
21
24
  truncateHeadTail
22
- } from "./chunks/chunk-J6PEH6ST.js";
23
- import {
24
- resolveCliProjectRoot
25
- } from "./chunks/chunk-WLFOBECN.js";
25
+ } from "./chunks/chunk-KDPAGHYY.js";
26
26
  import {
27
27
  AGENTS_CONTEXT_FILE_NAME,
28
28
  AgentSessionController,
@@ -73,8 +73,8 @@ import {
73
73
  setExtensionEnabledInSettings,
74
74
  shouldPreserveExecutionStateForUserText,
75
75
  supersedeExecutionState
76
- } from "./chunks/chunk-7RYOIXA2.js";
77
- import "./chunks/chunk-FKAO25XH.js";
76
+ } from "./chunks/chunk-A644H2XX.js";
77
+ import "./chunks/chunk-B3SMW2XW.js";
78
78
  import {
79
79
  Deref,
80
80
  EMPTY_ASSISTANT_CONTENT_ERROR,
@@ -110,7 +110,7 @@ import {
110
110
  setLogger,
111
111
  sortToolModelCandidatesByCapability,
112
112
  type_exports
113
- } from "./chunks/chunk-K6ZOCJ4V.js";
113
+ } from "./chunks/chunk-S2J3SZZX.js";
114
114
  import {
115
115
  __commonJS,
116
116
  __require,
@@ -60809,6 +60809,10 @@ var FileManager = class {
60809
60809
  getPlatformName() {
60810
60810
  return this.platform;
60811
60811
  }
60812
+ /** Whether the active platform has a registered upload adapter. */
60813
+ hasAdapter() {
60814
+ return this.sessionManager.getAdapter(this.platform) !== void 0;
60815
+ }
60812
60816
  getPlatformDisplayName() {
60813
60817
  return getProviderDisplayName(this.platform);
60814
60818
  }
@@ -62674,7 +62678,7 @@ function handleExtensionsCommand(host, args) {
62674
62678
 
62675
62679
  // src/slash-commands.ts
62676
62680
  var BUILTIN_SLASH_COMMANDS = [
62677
- { name: "sessions", description: "Pick a saved session to switch to" },
62681
+ { name: "sessions", description: "Manage sessions: resume, new, tree, fork, compact, info" },
62678
62682
  { name: "sessions/compact", description: "Summarize history and add a compact checkpoint to the session" },
62679
62683
  { name: "sessions/new", description: "Start a new session" },
62680
62684
  { name: "sessions/resume", description: "Resume a different session" },
@@ -63111,10 +63115,12 @@ var SessionSelectorComponent = class extends Container {
63111
63115
  }
63112
63116
  createItem(session) {
63113
63117
  const cwdTag = formatSessionCwdTag(session.cwd, this.options.currentCwd, this.options.homeDir);
63118
+ const unknownTag = cwdTag === void 0 && this.options.currentCwd && !(typeof session.cwd === "string" && session.cwd.length > 0) ? "unknown path" : void 0;
63119
+ const tag = cwdTag ?? unknownTag;
63114
63120
  return {
63115
63121
  value: session.id,
63116
63122
  label: session.name || `Session ${session.id.slice(0, 8)}`,
63117
- description: cwdTag ? `${cwdTag} \xB7 ${session.messageCount} messages \xB7 ${formatDate(session.updatedAt)}` : `${session.messageCount} messages \xB7 ${formatDate(session.updatedAt)}`
63123
+ description: tag ? `${tag} \xB7 ${session.messageCount} messages \xB7 ${formatDate(session.updatedAt)}` : `${session.messageCount} messages \xB7 ${formatDate(session.updatedAt)}`
63118
63124
  };
63119
63125
  }
63120
63126
  clearRefreshTimer() {
@@ -64843,6 +64849,7 @@ async function loadSession2(host, sessionId) {
64843
64849
  }
64844
64850
  setControllerBusy(host, false);
64845
64851
  setWaitingForUser(host, false);
64852
+ await host.initializeFileManager();
64846
64853
  const activeSession = host.sessionManager.getActiveSession();
64847
64854
  if (activeSession) {
64848
64855
  host.agent.sessionId = activeSession.id;
@@ -66175,7 +66182,10 @@ async function handleClearCommand(host) {
66175
66182
  if (activeSession) {
66176
66183
  host.agent.sessionId = activeSession.id;
66177
66184
  activeSession.metadata.executionState = host.executionState.createMetadata();
66185
+ activeSession.metadata.cwd = host.options.cwd;
66186
+ activeSession.isDirty = true;
66178
66187
  }
66188
+ await host.initializeFileManager();
66179
66189
  host.syncAgentFromActiveSession();
66180
66190
  host.syncSessionModelMetadata();
66181
66191
  host.planModeEnabled = false;
@@ -66328,8 +66338,7 @@ function createExtensionContextForCommands(host) {
66328
66338
  }
66329
66339
  function registerBuiltinCommands(host) {
66330
66340
  commandTree.register(["sessions"], {
66331
- description: "Pick a saved session to switch to (tree/fork/new below)",
66332
- handler: () => host.handleResumeCommand()
66341
+ description: "Manage sessions: resume, new, tree, fork, compact, info"
66333
66342
  });
66334
66343
  commandTree.register(["sessions", "compact"], {
66335
66344
  description: "Summarize history and replace it with a compact checkpoint",
@@ -68321,7 +68330,11 @@ var MentionHandler = class {
68321
68330
  this.pushPendingStatus(pendingStatusKey, `Preparing ${option.name}...`);
68322
68331
  }
68323
68332
  const mimeType = FileCache.getMimeType(option.path);
68324
- const shouldStageLocally = !mimeType.startsWith("image/") && !mimeType.startsWith("video/");
68333
+ const isMedia = mimeType.startsWith("image/") || mimeType.startsWith("video/");
68334
+ const shouldStageLocally = !isMedia || !this.fileManager.hasAdapter();
68335
+ if (isMedia && shouldStageLocally) {
68336
+ this.pushPendingStatus(pendingStatusKey, `Staging ${option.name} locally (no upload API for this provider)...`);
68337
+ }
68325
68338
  const onProgress = (progress, stage) => {
68326
68339
  this.pushPendingStatus(
68327
68340
  pendingStatusKey,
@@ -68729,7 +68742,7 @@ var MentionHandler = class {
68729
68742
  async function initializeFileManager(host) {
68730
68743
  const sessionId = host.sessionManager.getActiveSession()?.id;
68731
68744
  if (!sessionId) return;
68732
- const platform2 = host.options.model?.filePlatform || "unknown";
68745
+ const platform2 = host.options.model?.filePlatform || host.options.model?.attachmentPlatform || "unknown";
68733
68746
  host.fileManager = new FileManager({
68734
68747
  sessionId,
68735
68748
  platform: platform2,
@@ -68737,7 +68750,7 @@ async function initializeFileManager(host) {
68737
68750
  baseDir: path28.join(host.options.configDir, "files"),
68738
68751
  sessionsDir: path28.join(host.options.configDir, "sessions")
68739
68752
  });
68740
- switch (getFileManagerAdapterKind(host.options.model?.filePlatform)) {
68753
+ switch (getFileManagerAdapterKind(platform2)) {
68741
68754
  case "kimi":
68742
68755
  if (host.options.model?.baseUrl) {
68743
68756
  host.fileManager.registerAdapter(new KimiFileAdapter(host.options.apiKey, host.options.model.baseUrl));
@@ -68746,6 +68759,13 @@ async function initializeFileManager(host) {
68746
68759
  case "gemini":
68747
68760
  host.fileManager.registerAdapter(new GeminiFileAdapter(host.options.apiKey));
68748
68761
  break;
68762
+ case "openai-compatible-files":
68763
+ if (host.options.model?.baseUrl) {
68764
+ host.fileManager.registerAdapter(
68765
+ new OpenAICompatibleFilesAdapter(host.options.apiKey, host.options.model.baseUrl, host.options.model.headers)
68766
+ );
68767
+ }
68768
+ break;
68749
68769
  default:
68750
68770
  break;
68751
68771
  }
@@ -71970,7 +71990,7 @@ var InteractiveMode = class {
71970
71990
  async init() {
71971
71991
  const activeSession = this.sessionManager.getActiveSession();
71972
71992
  this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
71973
- const { Agent } = await import("./chunks/src-HYZFAW4V.js");
71993
+ const { Agent } = await import("./chunks/src-UKCIAX6F.js");
71974
71994
  this.agent = new Agent({
71975
71995
  initialState: {
71976
71996
  systemPrompt: this.buildSystemPrompt(),
@@ -72471,6 +72491,7 @@ async function composeCliRuntime(params) {
72471
72491
  });
72472
72492
  const cwd = params.cwd ?? process.cwd();
72473
72493
  const sessionManager = createSessionManager({ sessionsDir: paths.sessionsDir });
72494
+ let createdNewSession = false;
72474
72495
  if (params.explicitSessionId) {
72475
72496
  const sessionFileExists = params.requireExistingSession ? await sessionManager.hasSession(params.explicitSessionId) : false;
72476
72497
  const loaded = await sessionManager.loadSession(params.explicitSessionId, {
@@ -72484,6 +72505,7 @@ async function composeCliRuntime(params) {
72484
72505
  );
72485
72506
  }
72486
72507
  await sessionManager.createSession(void 0, void 0, params.explicitSessionId);
72508
+ createdNewSession = true;
72487
72509
  } else {
72488
72510
  const restored = restoreSessionModelState({
72489
72511
  activeSession: sessionManager.getActiveSession(),
@@ -72503,10 +72525,11 @@ async function composeCliRuntime(params) {
72503
72525
  }
72504
72526
  } else {
72505
72527
  await sessionManager.createSession();
72528
+ createdNewSession = true;
72506
72529
  }
72507
72530
  const activeSession = sessionManager.getActiveSession();
72508
72531
  syncSessionModelMetadata(sessionManager, model, resolveInitialThinkingLevel({ session: activeSession, settingsManager }));
72509
- if (activeSession && activeSession.metadata.cwd !== cwd) {
72532
+ if (activeSession && createdNewSession) {
72510
72533
  activeSession.metadata.cwd = cwd;
72511
72534
  await sessionManager.save();
72512
72535
  }
@@ -72780,7 +72803,7 @@ async function runPrintMode(params) {
72780
72803
  `);
72781
72804
  console.log("Assistant: ");
72782
72805
  }
72783
- const { Agent: AgentClass } = await import("./chunks/src-HYZFAW4V.js");
72806
+ const { Agent: AgentClass } = await import("./chunks/src-UKCIAX6F.js");
72784
72807
  let agent;
72785
72808
  const printModeExtensions = await loadPrintModeExtensions({
72786
72809
  cwd: runtime.cwd,
@@ -73339,8 +73362,12 @@ async function runJsonEventsMode(params) {
73339
73362
  }
73340
73363
  }
73341
73364
  metadata.name = typeof existing?.name === "string" ? existing.name : `Session ${sessionId.slice(0, 8)}`;
73342
- if (cwd || existing?.cwd || runtime?.cwd) {
73343
- metadata.cwd = cwd ?? existing?.cwd ?? runtime?.cwd;
73365
+ if (existing) {
73366
+ if (existing.cwd) {
73367
+ metadata.cwd = cwd ?? existing.cwd;
73368
+ }
73369
+ } else if (cwd || runtime?.cwd) {
73370
+ metadata.cwd = cwd ?? runtime?.cwd;
73344
73371
  }
73345
73372
  metadata.activeEntryId = activeEntryId;
73346
73373
  metadata.rootEntryId = existing?.rootEntryId ?? rootEntryId;
@@ -73621,7 +73648,7 @@ async function runJsonEventsMode(params) {
73621
73648
  return;
73622
73649
  }
73623
73650
  const parent = agent;
73624
- const { Agent: AgentClass } = await import("./chunks/src-HYZFAW4V.js");
73651
+ const { Agent: AgentClass } = await import("./chunks/src-UKCIAX6F.js");
73625
73652
  const sideAgent = new AgentClass({
73626
73653
  initialState: {
73627
73654
  systemPrompt: parent.state.systemPrompt,
@@ -73947,7 +73974,7 @@ async function runJsonEventsMode(params) {
73947
73974
  if (runtime.initialModel.unconfigured || controller) {
73948
73975
  return;
73949
73976
  }
73950
- const { Agent: AgentClass } = await import("./chunks/src-HYZFAW4V.js");
73977
+ const { Agent: AgentClass } = await import("./chunks/src-UKCIAX6F.js");
73951
73978
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
73952
73979
  const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
73953
73980
  const restoredApiKey = runtime.modelRegistry.getApiKey(runtime.model);
@@ -74536,7 +74563,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
74536
74563
  }
74537
74564
  async function createCliTestStreamFnFromEnv() {
74538
74565
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
74539
- return (await import("./chunks/test-stream-5T7E7C25.js")).createTestStreamFnFromSequenceEnv();
74566
+ return (await import("./chunks/test-stream-NCBFPM2I.js")).createTestStreamFnFromSequenceEnv();
74540
74567
  }
74541
74568
  function resolveJsonEventsDetailFlag() {
74542
74569
  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": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,9 +18,9 @@
18
18
  "test": "npm run test:offline",
19
19
  "pretest:offline": "npm run build --workspace @pie/agent-framework && npm run build --workspace @pie/shared-headless-capabilities && npm run build",
20
20
  "posttest:offline": "node --test --import tsx test/remote-model-catalog.test.ts",
21
- "test:offline": "node --test --import tsx 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/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/hierarchical-command-system.test.ts test/extensions-enablement.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/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/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/code-intel-typescript-provider.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/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/plan-mode-extension.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/calm-mode.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",
21
+ "test:offline": "node --test --import tsx 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/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/hierarchical-command-system.test.ts test/extensions-enablement.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/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/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/code-intel-typescript-provider.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/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/plan-mode-extension.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/calm-mode.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/mention-picker-navigation.test.ts test/pie-unity-rpc-skill.test.ts test/skill-creator-scripts.test.ts",
22
22
  "test:all": "npm run test:offline && npm run test:terminal:vitest",
23
- "test:terminal:vitest": "vitest run test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/viewport-position-final.test.ts test/resume-header.terminal.test.ts --no-file-parallelism",
23
+ "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",
24
24
  "test:todo-tui": "PIE_REAL_TODO_TUI=1 node --test --import tsx test/todo-closure.terminal.test.ts",
25
25
  "test:daily-tui": "npm run test:daily-tui:quick",
26
26
  "test:daily-tui:quick": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_TUI_LEVEL=quick node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
@@ -1,11 +0,0 @@
1
- import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
- import "../../../chunks/chunk-LZQXQOPJ.js";
3
-
4
- // builtin/extensions/deploy/index.ts
5
- function deployExtension(ctx) {
6
- ctx.log("Deploy extension loaded");
7
- ctx.log("Deploy extension ready");
8
- }
9
- export {
10
- deployExtension as default
11
- };
@@ -1,11 +0,0 @@
1
- {
2
- "name": "@pie/extension-deploy",
3
- "version": "1.0.0",
4
- "description": "Deployment assistance commands",
5
- "main": "index.ts",
6
- "type": "module",
7
- "pie": {
8
- "name": "deploy",
9
- "main": "index.ts"
10
- }
11
- }
@@ -1,10 +0,0 @@
1
- import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
- import "../../../chunks/chunk-LZQXQOPJ.js";
3
-
4
- // builtin/extensions/files/index.ts
5
- function filesExtension(ctx) {
6
- ctx.log("Files extension loaded");
7
- }
8
- export {
9
- filesExtension as default
10
- };
@@ -1,14 +0,0 @@
1
- {
2
- "name": "@pie/extension-files",
3
- "version": "1.0.0",
4
- "description": "File browser with git status support",
5
- "main": "index.ts",
6
- "type": "module",
7
- "pie": {
8
- "name": "files",
9
- "main": "index.ts"
10
- },
11
- "keywords": ["pie", "extension", "files", "git"],
12
- "author": "Pie Team",
13
- "license": "MIT"
14
- }
@@ -1,115 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { spawn, spawnSync } from "node:child_process";
4
- import os from "node:os";
5
- import path from "node:path";
6
-
7
- export function findProjectRoot(start = process.cwd()) {
8
- const current = path.resolve(start);
9
- let cursor = current;
10
- while (true) {
11
- if (path.basename(cursor) === ".claude" || existsDir(path.join(cursor, ".claude"))) {
12
- return path.basename(cursor) === ".claude" ? path.dirname(cursor) : cursor;
13
- }
14
- const parent = path.dirname(cursor);
15
- if (parent === cursor) {
16
- return current;
17
- }
18
- cursor = parent;
19
- }
20
- }
21
-
22
- function existsDir(dir) {
23
- try {
24
- return spawnSync("test", ["-d", dir]).status === 0;
25
- } catch {
26
- return false;
27
- }
28
- }
29
-
30
- export function buildClaudeEnv() {
31
- const env = { ...process.env };
32
- delete env.CLAUDECODE;
33
- return env;
34
- }
35
-
36
- export async function callClaudeText(prompt, { model, timeout = 300_000 } = {}) {
37
- const args = ["-p", "--output-format", "text"];
38
- if (model) args.push("--model", model);
39
- return runClaude(args, { stdin: prompt, timeout });
40
- }
41
-
42
- export function runClaudeStream(args, { cwd, timeout = 30_000 } = {}) {
43
- const child = spawn("claude", args, {
44
- cwd,
45
- env: buildClaudeEnv(),
46
- stdio: ["ignore", "pipe", "ignore"],
47
- });
48
-
49
- const timer = setTimeout(() => {
50
- child.kill("SIGKILL");
51
- }, timeout);
52
-
53
- child.once("exit", () => clearTimeout(timer));
54
- child.once("error", () => clearTimeout(timer));
55
- return child;
56
- }
57
-
58
- async function runClaude(args, { stdin, timeout = 300_000, cwd } = {}) {
59
- return new Promise((resolve, reject) => {
60
- const child = spawn("claude", args, {
61
- cwd,
62
- env: buildClaudeEnv(),
63
- stdio: ["pipe", "pipe", "pipe"],
64
- });
65
-
66
- let stdout = "";
67
- let stderr = "";
68
-
69
- const timer = setTimeout(() => {
70
- child.kill("SIGKILL");
71
- reject(new Error(`claude -p timed out after ${Math.round(timeout / 1000)}s`));
72
- }, timeout);
73
-
74
- child.stdout.on("data", (chunk) => {
75
- stdout += String(chunk);
76
- });
77
- child.stderr.on("data", (chunk) => {
78
- stderr += String(chunk);
79
- });
80
- child.on("error", (error) => {
81
- clearTimeout(timer);
82
- reject(error);
83
- });
84
- child.on("close", (code) => {
85
- clearTimeout(timer);
86
- if (code !== 0) {
87
- reject(new Error(`claude -p exited ${code}\nstderr: ${stderr}`));
88
- return;
89
- }
90
- resolve(stdout);
91
- });
92
-
93
- if (stdin) {
94
- child.stdin.write(stdin);
95
- }
96
- child.stdin.end();
97
- });
98
- }
99
-
100
- export function uuidFragment() {
101
- return Math.random().toString(16).slice(2, 10) + Date.now().toString(16).slice(-4);
102
- }
103
-
104
- export function openInBrowser(target) {
105
- const platform = os.platform();
106
- if (platform === "darwin") {
107
- spawn("open", [target], { detached: true, stdio: "ignore" }).unref();
108
- return;
109
- }
110
- if (platform === "win32") {
111
- spawn("cmd", ["/c", "start", "", target], { detached: true, stdio: "ignore" }).unref();
112
- return;
113
- }
114
- spawn("xdg-open", [target], { detached: true, stdio: "ignore" }).unref();
115
- }