@aku11i/phantom 5.1.0 → 6.1.0

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 (3) hide show
  1. package/README.md +2 -2
  2. package/package.json +5 -5
  3. package/phantom.js +281 -76
package/README.md CHANGED
@@ -7,14 +7,14 @@ Phantom makes Git worktrees simple and intuitive, enabling you to run multiple t
7
7
  ## Installation
8
8
 
9
9
  ```bash
10
- npm install -g @aku11i/phantom
10
+ npm install -g @phantompane/cli
11
11
  ```
12
12
 
13
13
  ## Documentation
14
14
 
15
15
  For detailed documentation, examples, and advanced usage, please visit:
16
16
 
17
- https://github.com/aku11i/phantom
17
+ https://github.com/phantompane/phantom
18
18
 
19
19
  ## License
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aku11i/phantom",
3
- "version": "5.1.0",
3
+ "version": "6.1.0",
4
4
  "description": "A powerful CLI tool for managing Git worktrees for parallel development",
5
5
  "keywords": [
6
6
  "git",
@@ -12,13 +12,13 @@
12
12
  "parallel",
13
13
  "mcp"
14
14
  ],
15
- "homepage": "https://github.com/aku11i/phantom#readme",
15
+ "homepage": "https://github.com/phantompane/phantom#readme",
16
16
  "bugs": {
17
- "url": "https://github.com/aku11i/phantom/issues"
17
+ "url": "https://github.com/phantompane/phantom/issues"
18
18
  },
19
19
  "repository": {
20
20
  "type": "git",
21
- "url": "git+https://github.com/aku11i/phantom.git"
21
+ "url": "git+https://github.com/phantompane/phantom.git"
22
22
  },
23
23
  "license": "MIT",
24
24
  "author": "aku11i",
@@ -35,4 +35,4 @@
35
35
  "node": ">=22.0.0"
36
36
  },
37
37
  "dependencies": {}
38
- }
38
+ }
package/phantom.js CHANGED
@@ -21091,6 +21091,7 @@ var phantomConfigSchema = external_exports.object({
21091
21091
  preDelete: external_exports.object({
21092
21092
  commands: external_exports.array(external_exports.string()).optional()
21093
21093
  }).passthrough().optional(),
21094
+ directoryNameSeparator: external_exports.string().optional(),
21094
21095
  worktreesDirectory: external_exports.string().optional()
21095
21096
  }).passthrough();
21096
21097
  function validateConfig(config2) {
@@ -21151,8 +21152,9 @@ function getWorktreesDirectory(gitRoot, worktreesDirectory) {
21151
21152
  }
21152
21153
  return join(gitRoot, ".git", "phantom", "worktrees");
21153
21154
  }
21154
- function getWorktreePathFromDirectory(worktreeDirectory, name) {
21155
- return join(worktreeDirectory, name);
21155
+ function getWorktreePathFromDirectory(worktreeDirectory, name, directoryNameSeparator) {
21156
+ const directoryName = directoryNameSeparator === "/" ? name : name.replaceAll("/", directoryNameSeparator);
21157
+ return join(worktreeDirectory, directoryName);
21156
21158
  }
21157
21159
 
21158
21160
  // ../git/src/executor.ts
@@ -21338,7 +21340,8 @@ var PreferencesValidationError = class extends Error {
21338
21340
  var preferencesSchema = external_exports.object({
21339
21341
  editor: external_exports.string().optional(),
21340
21342
  ai: external_exports.string().optional(),
21341
- worktreesDirectory: external_exports.string().optional()
21343
+ worktreesDirectory: external_exports.string().optional(),
21344
+ directoryNameSeparator: external_exports.string().optional()
21342
21345
  }).passthrough();
21343
21346
  function parsePreferences(output2) {
21344
21347
  if (!output2) {
@@ -21364,6 +21367,8 @@ function parsePreferences(output2) {
21364
21367
  preferences.ai = value;
21365
21368
  } else if (strippedKey === "worktreesdirectory") {
21366
21369
  preferences.worktreesDirectory = value;
21370
+ } else if (strippedKey === "directorynameseparator") {
21371
+ preferences.directoryNameSeparator = value;
21367
21372
  }
21368
21373
  }
21369
21374
  const parsed = preferencesSchema.safeParse(preferences);
@@ -21390,17 +21395,14 @@ async function createContext(gitRoot) {
21390
21395
  const configResult = await loadConfig(gitRoot);
21391
21396
  const config2 = isOk(configResult) ? configResult.value : null;
21392
21397
  const preferences = await loadPreferences();
21393
- const worktreesDirectoryPreference = preferences.worktreesDirectory;
21394
21398
  const worktreesDirectoryConfig = config2?.worktreesDirectory;
21395
- if (worktreesDirectoryConfig !== void 0) {
21396
- console.warn(
21397
- "The 'worktreesDirectory' option in phantom.config.json is deprecated and will be removed in the next version. Configure 'phantom preferences set worktreesDirectory <path-from-repo-root>' instead."
21398
- );
21399
- }
21399
+ const worktreesDirectoryPreference = preferences.worktreesDirectory;
21400
21400
  const worktreesDirectory = worktreesDirectoryPreference ?? worktreesDirectoryConfig;
21401
+ const directoryNameSeparator = preferences.directoryNameSeparator || config2?.directoryNameSeparator || "/";
21401
21402
  return {
21402
21403
  gitRoot,
21403
21404
  worktreesDirectory: getWorktreesDirectory(gitRoot, worktreesDirectory),
21405
+ directoryNameSeparator,
21404
21406
  config: config2,
21405
21407
  preferences
21406
21408
  };
@@ -21850,10 +21852,11 @@ async function executePostCreateCommands(options) {
21850
21852
  }
21851
21853
  return ok({ executedCommands });
21852
21854
  }
21853
- async function copyFilesToWorktree(gitRoot, worktreesDirectory, worktreeName, filesToCopy) {
21855
+ async function copyFilesToWorktree(gitRoot, worktreesDirectory, worktreeName, filesToCopy, directoryNameSeparator) {
21854
21856
  const worktreePath = getWorktreePathFromDirectory(
21855
21857
  worktreesDirectory,
21856
- worktreeName
21858
+ worktreeName,
21859
+ directoryNameSeparator
21857
21860
  );
21858
21861
  const copyResult = await copyFiles(gitRoot, worktreePath, filesToCopy);
21859
21862
  if (isErr(copyResult)) {
@@ -21863,12 +21866,16 @@ async function copyFilesToWorktree(gitRoot, worktreesDirectory, worktreeName, fi
21863
21866
  }
21864
21867
 
21865
21868
  // ../core/src/worktree/attach.ts
21866
- async function attachWorktreeCore(gitRoot, worktreeDirectory, name, postCreateCopyFiles, postCreateCommands) {
21869
+ async function attachWorktreeCore(gitRoot, worktreeDirectory, name, postCreateCopyFiles, postCreateCommands, directoryNameSeparator) {
21867
21870
  const validation = validateWorktreeName(name);
21868
21871
  if (isErr(validation)) {
21869
21872
  return validation;
21870
21873
  }
21871
- const worktreePath = getWorktreePathFromDirectory(worktreeDirectory, name);
21874
+ const worktreePath = getWorktreePathFromDirectory(
21875
+ worktreeDirectory,
21876
+ name,
21877
+ directoryNameSeparator
21878
+ );
21872
21879
  if (existsSync(worktreePath)) {
21873
21880
  return err(new WorktreeAlreadyExistsError(name));
21874
21881
  }
@@ -21888,7 +21895,8 @@ async function attachWorktreeCore(gitRoot, worktreeDirectory, name, postCreateCo
21888
21895
  gitRoot,
21889
21896
  worktreeDirectory,
21890
21897
  name,
21891
- postCreateCopyFiles
21898
+ postCreateCopyFiles,
21899
+ directoryNameSeparator
21892
21900
  );
21893
21901
  if (isErr(copyResult)) {
21894
21902
  console.warn(
@@ -21913,13 +21921,17 @@ async function attachWorktreeCore(gitRoot, worktreeDirectory, name, postCreateCo
21913
21921
 
21914
21922
  // ../core/src/worktree/create.ts
21915
21923
  import fs3 from "node:fs/promises";
21916
- async function createWorktree(gitRoot, worktreeDirectory, name, options, postCreateCopyFiles, postCreateCommands) {
21924
+ async function createWorktree(gitRoot, worktreeDirectory, name, options, postCreateCopyFiles, postCreateCommands, directoryNameSeparator) {
21917
21925
  const nameValidation = validateWorktreeName(name);
21918
21926
  if (isErr(nameValidation)) {
21919
21927
  return nameValidation;
21920
21928
  }
21921
21929
  const { branch = name, base = "HEAD" } = options;
21922
- const worktreePath = getWorktreePathFromDirectory(worktreeDirectory, name);
21930
+ const worktreePath = getWorktreePathFromDirectory(
21931
+ worktreeDirectory,
21932
+ name,
21933
+ directoryNameSeparator
21934
+ );
21923
21935
  try {
21924
21936
  await fs3.access(worktreeDirectory);
21925
21937
  } catch {
@@ -21960,7 +21972,8 @@ async function createWorktree(gitRoot, worktreeDirectory, name, options, postCre
21960
21972
  gitRoot,
21961
21973
  worktreeDirectory,
21962
21974
  name,
21963
- postCreateCopyFiles
21975
+ postCreateCopyFiles,
21976
+ directoryNameSeparator
21964
21977
  );
21965
21978
  if (isErr(copyResult)) {
21966
21979
  if (!copyError) {
@@ -22130,13 +22143,17 @@ var MAX_RETRIES = 10;
22130
22143
  function generate() {
22131
22144
  return (0, import_human_id.humanId)({ separator: "-", capitalize: false });
22132
22145
  }
22133
- async function generateUniqueName(gitRoot, worktreesDirectory) {
22146
+ async function generateUniqueName(gitRoot, worktreesDirectory, directoryNameSeparator) {
22134
22147
  for (let i = 0; i < MAX_RETRIES; i++) {
22135
22148
  const name = generate();
22136
22149
  if (isErr(validateWorktreeName(name))) {
22137
22150
  continue;
22138
22151
  }
22139
- const worktreePath = getWorktreePathFromDirectory(worktreesDirectory, name);
22152
+ const worktreePath = getWorktreePathFromDirectory(
22153
+ worktreesDirectory,
22154
+ name,
22155
+ directoryNameSeparator
22156
+ );
22140
22157
  if (await validateWorktreeDirectoryExists(worktreePath)) {
22141
22158
  continue;
22142
22159
  }
@@ -22394,7 +22411,8 @@ async function attachHandler(args2) {
22394
22411
  context.worktreesDirectory,
22395
22412
  branchName,
22396
22413
  postCreateCopyFiles,
22397
- context.config?.postCreate?.commands
22414
+ context.config?.postCreate?.commands,
22415
+ context.directoryNameSeparator
22398
22416
  );
22399
22417
  if (isErr(result)) {
22400
22418
  const error48 = result.error;
@@ -22725,19 +22743,19 @@ _phantom_completion() {
22725
22743
  return 0
22726
22744
  elif [[ \${words[2]} == "get" ]]; then
22727
22745
  if [[ \${cword} -eq 3 ]]; then
22728
- local keys="editor ai worktreesDirectory"
22746
+ local keys="editor ai worktreesDirectory directoryNameSeparator"
22729
22747
  COMPREPLY=( $(compgen -W "\${keys}" -- "\${cur}") )
22730
22748
  return 0
22731
22749
  fi
22732
22750
  elif [[ \${words[2]} == "set" ]]; then
22733
22751
  if [[ \${cword} -eq 3 ]]; then
22734
- local keys="editor ai worktreesDirectory"
22752
+ local keys="editor ai worktreesDirectory directoryNameSeparator"
22735
22753
  COMPREPLY=( $(compgen -W "\${keys}" -- "\${cur}") )
22736
22754
  return 0
22737
22755
  fi
22738
22756
  elif [[ \${words[2]} == "remove" ]]; then
22739
22757
  if [[ \${cword} -eq 3 ]]; then
22740
- local keys="editor ai worktreesDirectory"
22758
+ local keys="editor ai worktreesDirectory directoryNameSeparator"
22741
22759
  COMPREPLY=( $(compgen -W "\${keys}" -- "\${cur}") )
22742
22760
  return 0
22743
22761
  fi
@@ -22890,7 +22908,7 @@ complete -c phantom -n "__phantom_using_command" -a "exec" -d "Execute a command
22890
22908
  complete -c phantom -n "__phantom_using_command" -a "edit" -d "Open a worktree in your configured editor"
22891
22909
  complete -c phantom -n "__phantom_using_command" -a "ai" -d "Launch your configured AI coding assistant in a worktree"
22892
22910
  complete -c phantom -n "__phantom_using_command" -a "shell" -d "Open an interactive shell in a worktree directory"
22893
- complete -c phantom -n "__phantom_using_command" -a "preferences" -d "Manage editor/ai/worktreesDirectory preferences (stored in git config --global)"
22911
+ complete -c phantom -n "__phantom_using_command" -a "preferences" -d "Manage editor/ai/worktreesDirectory/directoryNameSeparator preferences (stored in git config --global)"
22894
22912
  complete -c phantom -n "__phantom_using_command" -a "github" -d "GitHub integration commands"
22895
22913
  complete -c phantom -n "__phantom_using_command" -a "gh" -d "GitHub integration commands (alias)"
22896
22914
  complete -c phantom -n "__phantom_using_command" -a "version" -d "Display phantom version information"
@@ -22957,9 +22975,9 @@ complete -c phantom -n "__phantom_using_command ai" -a "(__phantom_list_worktree
22957
22975
 
22958
22976
  # preferences command
22959
22977
  complete -c phantom -n "__phantom_using_command preferences" -a "get set remove" -d "Manage preferences"
22960
- complete -c phantom -n "__phantom_using_command preferences get" -a "editor ai worktreesDirectory" -d "Preference key"
22961
- complete -c phantom -n "__phantom_using_command preferences set" -a "editor ai worktreesDirectory" -d "Preference key"
22962
- complete -c phantom -n "__phantom_using_command preferences remove" -a "editor ai worktreesDirectory" -d "Preference key"
22978
+ complete -c phantom -n "__phantom_using_command preferences get" -a "editor ai worktreesDirectory directoryNameSeparator" -d "Preference key"
22979
+ complete -c phantom -n "__phantom_using_command preferences set" -a "editor ai worktreesDirectory directoryNameSeparator" -d "Preference key"
22980
+ complete -c phantom -n "__phantom_using_command preferences remove" -a "editor ai worktreesDirectory directoryNameSeparator" -d "Preference key"
22963
22981
 
22964
22982
  # shell command options
22965
22983
  complete -c phantom -n "__phantom_using_command shell" -l fzf -d "Use fzf for interactive selection"
@@ -23013,7 +23031,7 @@ _phantom() {
23013
23031
  'edit:Open a worktree in your configured editor'
23014
23032
  'ai:Launch your configured AI coding assistant in a worktree'
23015
23033
  'shell:Open an interactive shell in a worktree directory'
23016
- 'preferences:Manage editor/ai/worktreesDirectory preferences (git config --global)'
23034
+ 'preferences:Manage editor/ai/worktreesDirectory/directoryNameSeparator preferences (git config --global)'
23017
23035
  'github:GitHub integration commands'
23018
23036
  'gh:GitHub integration commands (alias)'
23019
23037
  'version:Display phantom version information'
@@ -23069,7 +23087,7 @@ _phantom() {
23069
23087
  _arguments '1:worktree:(\${(q)worktrees[@]})'
23070
23088
  ;;
23071
23089
  preferences)
23072
- _arguments '1:subcommand:(get set remove)' '2:key:(editor ai worktreesDirectory)'
23090
+ _arguments '1:subcommand:(get set remove)' '2:key:(editor ai worktreesDirectory directoryNameSeparator)'
23073
23091
  ;;
23074
23092
  completion)
23075
23093
  _arguments '1:shell:(fish zsh bash)'
@@ -23193,7 +23211,8 @@ async function createHandler(args2) {
23193
23211
  if (!worktreeName) {
23194
23212
  const nameResult = await generateUniqueName(
23195
23213
  gitRoot,
23196
- context.worktreesDirectory
23214
+ context.worktreesDirectory,
23215
+ context.directoryNameSeparator
23197
23216
  );
23198
23217
  if (isErr(nameResult)) {
23199
23218
  exitWithError(nameResult.error.message, exitCodes.generalError);
@@ -23217,7 +23236,8 @@ async function createHandler(args2) {
23217
23236
  base: baseOption
23218
23237
  },
23219
23238
  filesToCopy.length > 0 ? filesToCopy : void 0,
23220
- context.config?.postCreate?.commands
23239
+ context.config?.postCreate?.commands,
23240
+ context.directoryNameSeparator
23221
23241
  );
23222
23242
  if (isErr(result)) {
23223
23243
  const exitCode = result.error instanceof WorktreeAlreadyExistsError ? exitCodes.validationError : exitCodes.generalError;
@@ -27511,7 +27531,8 @@ async function checkoutIssue(issue2, base) {
27511
27531
  base
27512
27532
  },
27513
27533
  context.config?.postCreate?.copyFiles,
27514
- context.config?.postCreate?.commands
27534
+ context.config?.postCreate?.commands,
27535
+ context.directoryNameSeparator
27515
27536
  );
27516
27537
  if (isErr(result)) {
27517
27538
  return err(result.error);
@@ -27573,7 +27594,8 @@ async function checkoutPullRequest(pullRequest, worktreeName = pullRequest.isFro
27573
27594
  context.worktreesDirectory,
27574
27595
  worktreeName,
27575
27596
  context.config?.postCreate?.copyFiles,
27576
- context.config?.postCreate?.commands
27597
+ context.config?.postCreate?.commands,
27598
+ context.directoryNameSeparator
27577
27599
  );
27578
27600
  if (isErr(attachResult)) {
27579
27601
  return err(attachResult.error);
@@ -31679,7 +31701,7 @@ function object2(shape, params) {
31679
31701
  return new ZodMiniObject(def);
31680
31702
  }
31681
31703
 
31682
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
31704
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
31683
31705
  function isZ4Schema(s) {
31684
31706
  const schema5 = s;
31685
31707
  return !!schema5._zod;
@@ -31823,7 +31845,7 @@ function getLiteralValue(schema5) {
31823
31845
  return void 0;
31824
31846
  }
31825
31847
 
31826
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
31848
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
31827
31849
  var LATEST_PROTOCOL_VERSION = "2025-11-25";
31828
31850
  var SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
31829
31851
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
@@ -33341,7 +33363,7 @@ var UrlElicitationRequiredError = class extends McpError {
33341
33363
  }
33342
33364
  };
33343
33365
 
33344
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
33366
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
33345
33367
  function isTerminal(status) {
33346
33368
  return status === "completed" || status === "failed" || status === "cancelled";
33347
33369
  }
@@ -34630,7 +34652,7 @@ var zodToJsonSchema = (schema5, options) => {
34630
34652
  return combined;
34631
34653
  };
34632
34654
 
34633
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
34655
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
34634
34656
  function mapMiniTarget(t) {
34635
34657
  if (!t)
34636
34658
  return "draft-7";
@@ -34672,7 +34694,7 @@ function parseWithCompat(schema5, data) {
34672
34694
  return result.data;
34673
34695
  }
34674
34696
 
34675
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
34697
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
34676
34698
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
34677
34699
  var Protocol = class {
34678
34700
  constructor(_options) {
@@ -35620,7 +35642,7 @@ function mergeCapabilities(base, additional) {
35620
35642
  return result;
35621
35643
  }
35622
35644
 
35623
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
35645
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
35624
35646
  var import_ajv = __toESM(require_ajv(), 1);
35625
35647
  var import_ajv_formats = __toESM(require_dist2(), 1);
35626
35648
  function createDefaultAjvInstance() {
@@ -35688,7 +35710,7 @@ var AjvJsonSchemaValidator = class {
35688
35710
  }
35689
35711
  };
35690
35712
 
35691
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
35713
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
35692
35714
  var ExperimentalServerTasks = class {
35693
35715
  constructor(_server) {
35694
35716
  this._server = _server;
@@ -35710,6 +35732,147 @@ var ExperimentalServerTasks = class {
35710
35732
  requestStream(request2, resultSchema, options) {
35711
35733
  return this._server.requestStream(request2, resultSchema, options);
35712
35734
  }
35735
+ /**
35736
+ * Sends a sampling request and returns an AsyncGenerator that yields response messages.
35737
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
35738
+ *
35739
+ * For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
35740
+ * before the final result.
35741
+ *
35742
+ * @example
35743
+ * ```typescript
35744
+ * const stream = server.experimental.tasks.createMessageStream({
35745
+ * messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
35746
+ * maxTokens: 100
35747
+ * }, {
35748
+ * onprogress: (progress) => {
35749
+ * // Handle streaming tokens via progress notifications
35750
+ * console.log('Progress:', progress.message);
35751
+ * }
35752
+ * });
35753
+ *
35754
+ * for await (const message of stream) {
35755
+ * switch (message.type) {
35756
+ * case 'taskCreated':
35757
+ * console.log('Task created:', message.task.taskId);
35758
+ * break;
35759
+ * case 'taskStatus':
35760
+ * console.log('Task status:', message.task.status);
35761
+ * break;
35762
+ * case 'result':
35763
+ * console.log('Final result:', message.result);
35764
+ * break;
35765
+ * case 'error':
35766
+ * console.error('Error:', message.error);
35767
+ * break;
35768
+ * }
35769
+ * }
35770
+ * ```
35771
+ *
35772
+ * @param params - The sampling request parameters
35773
+ * @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
35774
+ * @returns AsyncGenerator that yields ResponseMessage objects
35775
+ *
35776
+ * @experimental
35777
+ */
35778
+ createMessageStream(params, options) {
35779
+ const clientCapabilities = this._server.getClientCapabilities();
35780
+ if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
35781
+ throw new Error("Client does not support sampling tools capability.");
35782
+ }
35783
+ if (params.messages.length > 0) {
35784
+ const lastMessage = params.messages[params.messages.length - 1];
35785
+ const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
35786
+ const hasToolResults = lastContent.some((c) => c.type === "tool_result");
35787
+ const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
35788
+ const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
35789
+ const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
35790
+ if (hasToolResults) {
35791
+ if (lastContent.some((c) => c.type !== "tool_result")) {
35792
+ throw new Error("The last message must contain only tool_result content if any is present");
35793
+ }
35794
+ if (!hasPreviousToolUse) {
35795
+ throw new Error("tool_result blocks are not matching any tool_use from the previous message");
35796
+ }
35797
+ }
35798
+ if (hasPreviousToolUse) {
35799
+ const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
35800
+ const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
35801
+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
35802
+ throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
35803
+ }
35804
+ }
35805
+ }
35806
+ return this.requestStream({
35807
+ method: "sampling/createMessage",
35808
+ params
35809
+ }, CreateMessageResultSchema, options);
35810
+ }
35811
+ /**
35812
+ * Sends an elicitation request and returns an AsyncGenerator that yields response messages.
35813
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
35814
+ *
35815
+ * For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
35816
+ * and 'taskStatus' messages before the final result.
35817
+ *
35818
+ * @example
35819
+ * ```typescript
35820
+ * const stream = server.experimental.tasks.elicitInputStream({
35821
+ * mode: 'url',
35822
+ * message: 'Please authenticate',
35823
+ * elicitationId: 'auth-123',
35824
+ * url: 'https://example.com/auth'
35825
+ * }, {
35826
+ * task: { ttl: 300000 } // Task-augmented for long-running auth flow
35827
+ * });
35828
+ *
35829
+ * for await (const message of stream) {
35830
+ * switch (message.type) {
35831
+ * case 'taskCreated':
35832
+ * console.log('Task created:', message.task.taskId);
35833
+ * break;
35834
+ * case 'taskStatus':
35835
+ * console.log('Task status:', message.task.status);
35836
+ * break;
35837
+ * case 'result':
35838
+ * console.log('User action:', message.result.action);
35839
+ * break;
35840
+ * case 'error':
35841
+ * console.error('Error:', message.error);
35842
+ * break;
35843
+ * }
35844
+ * }
35845
+ * ```
35846
+ *
35847
+ * @param params - The elicitation request parameters
35848
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
35849
+ * @returns AsyncGenerator that yields ResponseMessage objects
35850
+ *
35851
+ * @experimental
35852
+ */
35853
+ elicitInputStream(params, options) {
35854
+ const clientCapabilities = this._server.getClientCapabilities();
35855
+ const mode = params.mode ?? "form";
35856
+ switch (mode) {
35857
+ case "url": {
35858
+ if (!clientCapabilities?.elicitation?.url) {
35859
+ throw new Error("Client does not support url elicitation.");
35860
+ }
35861
+ break;
35862
+ }
35863
+ case "form": {
35864
+ if (!clientCapabilities?.elicitation?.form) {
35865
+ throw new Error("Client does not support form elicitation.");
35866
+ }
35867
+ break;
35868
+ }
35869
+ }
35870
+ const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
35871
+ return this.requestStream({
35872
+ method: "elicitation/create",
35873
+ params: normalizedParams
35874
+ }, ElicitResultSchema, options);
35875
+ }
35713
35876
  /**
35714
35877
  * Gets the current status of a task.
35715
35878
  *
@@ -35760,7 +35923,7 @@ var ExperimentalServerTasks = class {
35760
35923
  }
35761
35924
  };
35762
35925
 
35763
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
35926
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
35764
35927
  function assertToolsCallTaskCapability(requests, method, entityName) {
35765
35928
  if (!requests) {
35766
35929
  throw new Error(`${entityName} does not support task creation (required for ${method})`);
@@ -35795,7 +35958,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
35795
35958
  }
35796
35959
  }
35797
35960
 
35798
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
35961
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
35799
35962
  var Server = class extends Protocol {
35800
35963
  /**
35801
35964
  * Initializes this server with the given name and version information.
@@ -36175,7 +36338,7 @@ var Server = class extends Protocol {
36175
36338
  }
36176
36339
  };
36177
36340
 
36178
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
36341
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
36179
36342
  var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
36180
36343
  function isCompletable(schema5) {
36181
36344
  return !!schema5 && typeof schema5 === "object" && COMPLETABLE_SYMBOL in schema5;
@@ -36189,7 +36352,7 @@ var McpZodTypeKind;
36189
36352
  McpZodTypeKind2["Completable"] = "McpCompletable";
36190
36353
  })(McpZodTypeKind || (McpZodTypeKind = {}));
36191
36354
 
36192
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
36355
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
36193
36356
  var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
36194
36357
  function validateToolName(name) {
36195
36358
  const warnings = [];
@@ -36247,7 +36410,7 @@ function validateAndWarnToolName(name) {
36247
36410
  return result.isValid;
36248
36411
  }
36249
36412
 
36250
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
36413
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
36251
36414
  var ExperimentalMcpServerTasks = class {
36252
36415
  constructor(_mcpServer) {
36253
36416
  this._mcpServer = _mcpServer;
@@ -36262,7 +36425,7 @@ var ExperimentalMcpServerTasks = class {
36262
36425
  }
36263
36426
  };
36264
36427
 
36265
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
36428
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
36266
36429
  var McpServer = class {
36267
36430
  constructor(serverInfo, options) {
36268
36431
  this._registeredResources = {};
@@ -37048,10 +37211,10 @@ var EMPTY_COMPLETION_RESULT = {
37048
37211
  }
37049
37212
  };
37050
37213
 
37051
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37214
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37052
37215
  import process3 from "node:process";
37053
37216
 
37054
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
37217
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
37055
37218
  var ReadBuffer = class {
37056
37219
  append(chunk) {
37057
37220
  this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
@@ -37079,7 +37242,7 @@ function serializeMessage(message) {
37079
37242
  return JSON.stringify(message) + "\n";
37080
37243
  }
37081
37244
 
37082
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.26.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37245
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37083
37246
  var StdioServerTransport = class {
37084
37247
  constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
37085
37248
  this._stdin = _stdin;
@@ -37142,28 +37305,30 @@ var StdioServerTransport = class {
37142
37305
 
37143
37306
  // ../mcp/package.json
37144
37307
  var package_default = {
37145
- name: "@aku11i/phantom-mcp",
37146
- version: "5.1.0",
37308
+ name: "@phantompane/mcp",
37309
+ version: "6.1.0",
37147
37310
  private: true,
37148
37311
  type: "module",
37149
37312
  main: "./src/index.ts",
37150
37313
  types: "./src/index.ts",
37151
37314
  scripts: {
37315
+ lint: "oxfmt --check . && oxlint .",
37316
+ fix: "oxfmt --write . && oxlint --fix .",
37152
37317
  typecheck: "tsc --noEmit",
37153
37318
  test: 'node --test --experimental-strip-types --experimental-test-module-mocks "src/**/*.test.js"',
37154
37319
  inspect: "npx @modelcontextprotocol/inspector node --no-warnings --experimental-strip-types src/dev.ts"
37155
37320
  },
37156
37321
  dependencies: {
37157
- "@aku11i/phantom-core": "workspace:*",
37158
- "@aku11i/phantom-git": "workspace:*",
37159
- "@aku11i/phantom-github": "workspace:*",
37160
- "@aku11i/phantom-process": "workspace:*",
37161
- "@aku11i/phantom-shared": "workspace:*",
37162
- "@modelcontextprotocol/sdk": "^1.26.0",
37322
+ "@phantompane/core": "workspace:*",
37323
+ "@phantompane/git": "workspace:*",
37324
+ "@phantompane/github": "workspace:*",
37325
+ "@phantompane/process": "workspace:*",
37326
+ "@phantompane/shared": "workspace:*",
37327
+ "@modelcontextprotocol/sdk": "^1.27.1",
37163
37328
  zod: "^4.3.6"
37164
37329
  },
37165
37330
  devDependencies: {
37166
- "@modelcontextprotocol/inspector": "^0.20.0"
37331
+ "@modelcontextprotocol/inspector": "^0.21.1"
37167
37332
  }
37168
37333
  };
37169
37334
 
@@ -37188,7 +37353,8 @@ var createWorktreeTool = {
37188
37353
  base: baseBranch
37189
37354
  },
37190
37355
  context.config?.postCreate?.copyFiles,
37191
- context.config?.postCreate?.commands
37356
+ context.config?.postCreate?.commands,
37357
+ context.directoryNameSeparator
37192
37358
  );
37193
37359
  if (!isOk(result)) {
37194
37360
  throw new Error(result.error.message);
@@ -37440,6 +37606,10 @@ var preferencesHelp = {
37440
37606
  command: "phantom preferences set worktreesDirectory ../phantom-worktrees",
37441
37607
  description: "Store a custom worktreesDirectory (relative to the Git repository root) for all commands"
37442
37608
  },
37609
+ {
37610
+ command: 'phantom preferences set directoryNameSeparator "-"',
37611
+ description: "Store a separator for flattening worktree directory names while keeping branch names unchanged"
37612
+ },
37443
37613
  {
37444
37614
  command: "phantom preferences remove editor",
37445
37615
  description: "Remove the editor preference (fallback to env/default)"
@@ -37455,7 +37625,8 @@ var preferencesHelp = {
37455
37625
  "Supported keys:",
37456
37626
  " editor - used by 'phantom edit', preferred over $EDITOR",
37457
37627
  " ai - used by 'phantom ai'",
37458
- " worktreesDirectory - path relative to the Git repo root for storing worktrees (defaults to .git/phantom/worktrees)"
37628
+ " worktreesDirectory - path relative to the Git repo root for storing worktrees (defaults to .git/phantom/worktrees)",
37629
+ " directoryNameSeparator - replaces '/' in worktree directory names only (defaults to / for nested directories)"
37459
37630
  ]
37460
37631
  };
37461
37632
  var preferencesGetHelp = {
@@ -37474,9 +37645,15 @@ var preferencesGetHelp = {
37474
37645
  {
37475
37646
  command: "phantom preferences get worktreesDirectory",
37476
37647
  description: "Show the preferred worktrees directory (relative to repo root)"
37648
+ },
37649
+ {
37650
+ command: "phantom preferences get directoryNameSeparator",
37651
+ description: "Show the preferred worktree directory name separator"
37477
37652
  }
37478
37653
  ],
37479
- notes: ["Supported keys: editor, ai, worktreesDirectory"]
37654
+ notes: [
37655
+ "Supported keys: editor, ai, worktreesDirectory, directoryNameSeparator"
37656
+ ]
37480
37657
  };
37481
37658
  var preferencesSetHelp = {
37482
37659
  name: "preferences set",
@@ -37494,11 +37671,16 @@ var preferencesSetHelp = {
37494
37671
  {
37495
37672
  command: "phantom preferences set worktreesDirectory ../phantom-worktrees",
37496
37673
  description: "Store worktrees in ../phantom-worktrees relative to the Git repository root"
37674
+ },
37675
+ {
37676
+ command: 'phantom preferences set directoryNameSeparator "-"',
37677
+ description: "Flatten worktree directory names such as feature/test to feature-test"
37497
37678
  }
37498
37679
  ],
37499
37680
  notes: [
37500
- "Supported keys: editor, ai, worktreesDirectory",
37501
- "For worktreesDirectory, provide a path relative to the Git repository root; defaults to .git/phantom/worktrees when unset"
37681
+ "Supported keys: editor, ai, worktreesDirectory, directoryNameSeparator",
37682
+ "For worktreesDirectory, provide a path relative to the Git repository root; defaults to .git/phantom/worktrees when unset",
37683
+ "For directoryNameSeparator, '/' keeps nested directories; any other string replaces '/' only in the directory path"
37502
37684
  ]
37503
37685
  };
37504
37686
  var preferencesRemoveHelp = {
@@ -37517,9 +37699,15 @@ var preferencesRemoveHelp = {
37517
37699
  {
37518
37700
  command: "phantom preferences remove worktreesDirectory",
37519
37701
  description: "Unset the custom worktrees directory preference"
37702
+ },
37703
+ {
37704
+ command: "phantom preferences remove directoryNameSeparator",
37705
+ description: "Restore nested worktree directories that follow branch slashes"
37520
37706
  }
37521
37707
  ],
37522
- notes: ["Supported keys: editor, ai, worktreesDirectory"]
37708
+ notes: [
37709
+ "Supported keys: editor, ai, worktreesDirectory, directoryNameSeparator"
37710
+ ]
37523
37711
  };
37524
37712
 
37525
37713
  // src/handlers/preferences.ts
@@ -37533,7 +37721,12 @@ async function preferencesHandler(args2) {
37533
37721
 
37534
37722
  // src/handlers/preferences-get.ts
37535
37723
  import { parseArgs as parseArgs10 } from "node:util";
37536
- var supportedKeys = ["editor", "ai", "worktreesDirectory"];
37724
+ var supportedKeys = [
37725
+ "editor",
37726
+ "ai",
37727
+ "worktreesDirectory",
37728
+ "directoryNameSeparator"
37729
+ ];
37537
37730
  async function preferencesGetHandler(args2) {
37538
37731
  const { positionals } = parseArgs10({
37539
37732
  args: args2,
@@ -37556,7 +37749,7 @@ async function preferencesGetHandler(args2) {
37556
37749
  }
37557
37750
  try {
37558
37751
  const preferences = await loadPreferences();
37559
- const value = inputKey === "editor" ? preferences.editor : inputKey === "ai" ? preferences.ai : inputKey === "worktreesDirectory" ? preferences.worktreesDirectory : void 0;
37752
+ const value = inputKey === "editor" ? preferences.editor : inputKey === "ai" ? preferences.ai : inputKey === "worktreesDirectory" ? preferences.worktreesDirectory : inputKey === "directoryNameSeparator" ? preferences.directoryNameSeparator : void 0;
37560
37753
  if (value === void 0) {
37561
37754
  output.log(
37562
37755
  `Preference '${inputKey}' is not set (git config --global phantom.${inputKey})`
@@ -37575,7 +37768,12 @@ async function preferencesGetHandler(args2) {
37575
37768
 
37576
37769
  // src/handlers/preferences-remove.ts
37577
37770
  import { parseArgs as parseArgs11 } from "node:util";
37578
- var supportedKeys2 = ["editor", "ai", "worktreesDirectory"];
37771
+ var supportedKeys2 = [
37772
+ "editor",
37773
+ "ai",
37774
+ "worktreesDirectory",
37775
+ "directoryNameSeparator"
37776
+ ];
37579
37777
  async function preferencesRemoveHandler(args2) {
37580
37778
  const { positionals } = parseArgs11({
37581
37779
  args: args2,
@@ -37614,7 +37812,12 @@ async function preferencesRemoveHandler(args2) {
37614
37812
  }
37615
37813
 
37616
37814
  // src/handlers/preferences-set.ts
37617
- var supportedKeys3 = ["editor", "ai", "worktreesDirectory"];
37815
+ var supportedKeys3 = [
37816
+ "editor",
37817
+ "ai",
37818
+ "worktreesDirectory",
37819
+ "directoryNameSeparator"
37820
+ ];
37618
37821
  async function preferencesSetHandler(args2) {
37619
37822
  if (args2.length < 2) {
37620
37823
  exitWithError(
@@ -37781,8 +37984,8 @@ import { parseArgs as parseArgs13 } from "node:util";
37781
37984
 
37782
37985
  // package.json
37783
37986
  var package_default2 = {
37784
- name: "@aku11i/phantom-cli",
37785
- version: "5.1.0",
37987
+ name: "@phantompane/cli-private",
37988
+ version: "6.1.0",
37786
37989
  private: true,
37787
37990
  type: "module",
37788
37991
  scripts: {
@@ -37791,6 +37994,8 @@ var package_default2 = {
37791
37994
  build: "node build.ts",
37792
37995
  precompile: "rm -f output/*",
37793
37996
  compile: "node --no-warnings --experimental-strip-types build-executable.ts",
37997
+ lint: "oxfmt --check . && oxlint .",
37998
+ fix: "oxfmt --write . && oxlint --fix .",
37794
37999
  typecheck: "tsc --noEmit",
37795
38000
  "test:shell": "pnpm run test:shell:bash && pnpm run test:shell:zsh && pnpm run test:shell:fish",
37796
38001
  "test:shell:bash": "node --test --experimental-strip-types --experimental-test-module-mocks src/completions/phantom.bash.test.shell.js",
@@ -37800,12 +38005,12 @@ var package_default2 = {
37800
38005
  prepublishOnly: "pnpm build"
37801
38006
  },
37802
38007
  dependencies: {
37803
- "@aku11i/phantom-core": "workspace:*",
37804
- "@aku11i/phantom-git": "workspace:*",
37805
- "@aku11i/phantom-github": "workspace:*",
37806
- "@aku11i/phantom-mcp": "workspace:*",
37807
- "@aku11i/phantom-process": "workspace:*",
37808
- "@aku11i/phantom-shared": "workspace:*"
38008
+ "@phantompane/core": "workspace:*",
38009
+ "@phantompane/git": "workspace:*",
38010
+ "@phantompane/github": "workspace:*",
38011
+ "@phantompane/mcp": "workspace:*",
38012
+ "@phantompane/process": "workspace:*",
38013
+ "@phantompane/shared": "workspace:*"
37809
38014
  }
37810
38015
  };
37811
38016