xling 0.7.0 → 0.7.2

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 (111) hide show
  1. package/dist/{base-ZLSUOdyk.d.ts → base-BxGCoslm.d.ts} +2 -2
  2. package/dist/base-CSwZL00J.js +1 -30
  3. package/dist/{base-B5MGQGLN.d.ts → base-D1BJt9i-.d.ts} +3 -2
  4. package/dist/base-DtcPVpvU.js +1 -68
  5. package/dist/claude-C6lOG2Mk.js +1 -206
  6. package/dist/claude-lgXq7-0w.js +1 -0
  7. package/dist/claudeDefault-ewrEKzlX.js +1 -18
  8. package/dist/client-DTC49Rug.js +1 -88
  9. package/dist/codex-Dl7Rx7Nr.js +1 -83
  10. package/dist/codex-sOnl7pFp.js +1 -0
  11. package/dist/commands/git/index.js +5 -35
  12. package/dist/commands/git/prc.js +2 -121
  13. package/dist/commands/git/prr.js +2 -80
  14. package/dist/commands/git/prv.js +2 -70
  15. package/dist/commands/git/worktree.js +3 -135
  16. package/dist/commands/git/wta.js +3 -78
  17. package/dist/commands/git/wtl.js +3 -42
  18. package/dist/commands/git/wtp.js +3 -42
  19. package/dist/commands/git/wtr.js +3 -77
  20. package/dist/commands/git/wts.js +2 -99
  21. package/dist/commands/p/index.js +15 -380
  22. package/dist/commands/settings/get.js +2 -119
  23. package/dist/commands/settings/inspect.js +3 -85
  24. package/dist/commands/settings/list.js +6 -151
  25. package/dist/commands/settings/set.js +2 -87
  26. package/dist/commands/settings/switch.js +4 -165
  27. package/dist/commands/sx/index.js +12 -93
  28. package/dist/commands/version/index.js +1 -22
  29. package/dist/commands/x/index.js +4 -104
  30. package/dist/config-JHw2hqMN.js +1 -141
  31. package/dist/create-CKUHliul.js +1 -95
  32. package/dist/dispatcher-5y9x6plQ.js +1 -0
  33. package/dist/dispatcher-BYazaYbC.js +1 -75
  34. package/dist/dispatcher-D4bEJonH.js +1 -30
  35. package/dist/domain/git.js +1 -3
  36. package/dist/domain/interfaces.d.ts +2 -2
  37. package/dist/domain/interfaces.js +1 -1
  38. package/dist/domain/types.d.ts +1 -1
  39. package/dist/domain/types.js +1 -1
  40. package/dist/domain/validators.d.ts +1 -1
  41. package/dist/domain/validators.js +1 -57
  42. package/dist/domain/xling/config.js +1 -3
  43. package/dist/domain/xling/template.js +1 -3
  44. package/dist/editor-CUiekAEb.js +1 -31
  45. package/dist/errors-pXKbCKbL.js +1 -115
  46. package/dist/format-a_tYXjv9.js +4 -229
  47. package/dist/fsStore-S8RslR8L.js +1 -122
  48. package/dist/gemini-DQoPiuiw.js +1 -49
  49. package/dist/git-BZvqM5hz.js +1 -12
  50. package/dist/{interfaces-Cy1OFHgI.d.ts → interfaces-D5gBXflS.d.ts} +2 -1
  51. package/dist/pr-DjdO-vJk.js +1 -61
  52. package/dist/providerRegistry-Cljln1eo.js +1 -151
  53. package/dist/router-DX-dIEei.js +1 -177
  54. package/dist/run.js +1 -13
  55. package/dist/runner-Bi5mGd-w.js +1 -203
  56. package/dist/runner-DYk4q6mP.js +1 -145
  57. package/dist/services/git/create.js +1 -6
  58. package/dist/services/git/dispatcher.js +1 -10
  59. package/dist/services/git/pr.js +1 -6
  60. package/dist/services/git/utils.js +1 -5
  61. package/dist/services/git/view.js +1 -6
  62. package/dist/services/git/worktree.js +1 -5
  63. package/dist/services/launch/adapters/base.d.ts +3 -3
  64. package/dist/services/launch/adapters/base.js +1 -4
  65. package/dist/services/launch/adapters/claude.d.ts +6 -3
  66. package/dist/services/launch/adapters/claude.js +1 -5
  67. package/dist/services/launch/adapters/codex.d.ts +6 -3
  68. package/dist/services/launch/adapters/codex.js +1 -5
  69. package/dist/services/launch/dispatcher.d.ts +2 -2
  70. package/dist/services/launch/dispatcher.js +1 -8
  71. package/dist/services/prompt/client.js +1 -3
  72. package/dist/services/prompt/providerRegistry.js +1 -10
  73. package/dist/services/prompt/router.js +1 -13
  74. package/dist/services/prompt/types.js +1 -3
  75. package/dist/services/settings/adapters/base.d.ts +3 -3
  76. package/dist/services/settings/adapters/base.js +1 -5
  77. package/dist/services/settings/adapters/claude.d.ts +3 -3
  78. package/dist/services/settings/adapters/claude.js +1 -9
  79. package/dist/services/settings/adapters/codex.d.ts +3 -3
  80. package/dist/services/settings/adapters/codex.js +1 -6
  81. package/dist/services/settings/adapters/gemini.d.ts +3 -3
  82. package/dist/services/settings/adapters/gemini.js +1 -6
  83. package/dist/services/settings/adapters/xling.d.ts +3 -3
  84. package/dist/services/settings/adapters/xling.js +1 -9
  85. package/dist/services/settings/dispatcher.d.ts +2 -2
  86. package/dist/services/settings/dispatcher.js +1 -15
  87. package/dist/services/settings/fsStore.d.ts +1 -1
  88. package/dist/services/settings/fsStore.js +1 -4
  89. package/dist/services/settings/templates/claudeDefault.d.ts +1 -1
  90. package/dist/services/settings/templates/claudeDefault.js +1 -3
  91. package/dist/services/shortcuts/runner.js +1 -11
  92. package/dist/services/shortcuts/types.js +1 -3
  93. package/dist/template-B19CdPfg.js +1 -164
  94. package/dist/types-99-EmVXg.js +2 -25
  95. package/dist/types-DblJSHMa.js +1 -23
  96. package/dist/{types-5rST51Xi.d.ts → types-RoapPbyI.d.ts} +1 -0
  97. package/dist/utils/editor.js +1 -4
  98. package/dist/utils/errors.js +1 -3
  99. package/dist/utils/format.d.ts +1 -1
  100. package/dist/utils/format.js +1 -3
  101. package/dist/utils/logger.js +1 -42
  102. package/dist/utils/runner.d.ts +1 -1
  103. package/dist/utils/runner.js +1 -3
  104. package/dist/utils-DDnNMPIq.js +1 -35
  105. package/dist/view-JZaEEspp.js +1 -84
  106. package/dist/worktree-BuIXmI0X.js +3 -205
  107. package/dist/xling-BxVsmPja.js +1 -254
  108. package/package.json +1 -1
  109. package/dist/claude-YXQbPr5h.js +0 -29
  110. package/dist/codex-UE8EaZGt.js +0 -30
  111. package/dist/dispatcher-BCISF-Uw.js +0 -87
@@ -1,164 +1 @@
1
- //#region src/domain/xling/template.ts
2
- /**
3
- * Default configuration for Xling prompt command
4
- *
5
- * This template is used when no configuration file exists.
6
- * Users should replace the empty apiKey with their actual key.
7
- */
8
- const DEFAULT_XLING_CONFIG = {
9
- prompt: {
10
- providers: [{
11
- name: "openai-default",
12
- baseUrl: "https://api.openai.com/v1",
13
- apiKey: "",
14
- models: [
15
- "gpt-4",
16
- "gpt-4-turbo",
17
- "gpt-4o",
18
- "gpt-4o-mini",
19
- "gpt-3.5-turbo"
20
- ],
21
- priority: 1,
22
- timeout: 6e4
23
- }],
24
- defaultModel: "gpt-4o-mini",
25
- retryPolicy: {
26
- maxRetries: 2,
27
- backoffMs: 1e3
28
- }
29
- },
30
- shortcuts: {
31
- lc: {
32
- command: "x",
33
- args: [
34
- "-t",
35
- "claude",
36
- "-c"
37
- ],
38
- description: "Launch Claude and continue last conversation"
39
- },
40
- lx: {
41
- command: "x",
42
- args: ["-t", "codex"],
43
- description: "Launch Codex"
44
- },
45
- gdp: {
46
- shell: "git diff | xling p --stdin 'Summarize these changes'",
47
- description: "Git diff with AI summary"
48
- }
49
- }
50
- };
51
- /**
52
- * Example configuration with multiple providers
53
- * This serves as documentation for users
54
- */
55
- const EXAMPLE_MULTI_PROVIDER_CONFIG = {
56
- prompt: {
57
- providers: [
58
- {
59
- name: "openai-primary",
60
- baseUrl: "https://api.openai.com/v1",
61
- apiKey: "sk-proj-xxx",
62
- models: [
63
- "gpt-4",
64
- "gpt-4-turbo",
65
- "gpt-4o",
66
- "gpt-3.5-turbo"
67
- ],
68
- priority: 1,
69
- timeout: 6e4
70
- },
71
- {
72
- name: "openai-backup",
73
- baseUrl: "https://api.openai.com/v1",
74
- apiKey: "sk-proj-yyy",
75
- models: ["gpt-4", "gpt-3.5-turbo"],
76
- priority: 2,
77
- timeout: 3e4
78
- },
79
- {
80
- name: "azure-openai",
81
- baseUrl: "https://your-resource.openai.azure.com/openai/deployments",
82
- apiKey: "azure-api-key",
83
- models: ["gpt-4"],
84
- priority: 3,
85
- timeout: 45e3,
86
- headers: { "api-version": "2024-02-15-preview" }
87
- },
88
- {
89
- name: "custom-provider",
90
- baseUrl: "https://custom-ai.example.com/v1",
91
- apiKey: "custom-key",
92
- models: ["llama-3-70b", "mixtral-8x7b"],
93
- priority: 10
94
- }
95
- ],
96
- defaultModel: "gpt-4",
97
- retryPolicy: {
98
- maxRetries: 3,
99
- backoffMs: 1e3
100
- }
101
- },
102
- shortcuts: {
103
- lc: {
104
- command: "x",
105
- args: [
106
- "-t",
107
- "claude",
108
- "-c"
109
- ],
110
- description: "Launch Claude and continue"
111
- },
112
- lx: {
113
- command: "x",
114
- args: ["-t", "codex"],
115
- description: "Launch Codex"
116
- },
117
- gs: {
118
- command: "settings:list",
119
- args: ["--tool", "claude"],
120
- description: "List Claude settings"
121
- },
122
- gsx: {
123
- command: "settings:list",
124
- args: ["--tool", "codex"],
125
- description: "List Codex settings"
126
- },
127
- gdp: {
128
- shell: "git diff | xling p --stdin 'Summarize these changes'",
129
- description: "Git diff with AI summary"
130
- },
131
- gsp: {
132
- shell: "git status --short | xling p --stdin 'Explain these changes'",
133
- description: "Git status with AI explanation"
134
- },
135
- gcm: {
136
- shell: {
137
- win32: "git add -N . && git diff HEAD | xling p --stdin 'Analyze changes and generate commit message in both Chinese and English'",
138
- default: "git diff HEAD; git ls-files --others --exclude-standard | while read file; do git diff --no-index /dev/null \"$file\" 2>/dev/null || true; done | xling p --stdin 'Analyze changes and generate commit message in both Chinese and English'"
139
- },
140
- description: "Generate commit message for all changes (platform-specific)"
141
- },
142
- pipe: {
143
- pipeline: [{
144
- command: "git",
145
- args: [
146
- "log",
147
- "--oneline",
148
- "-10"
149
- ]
150
- }, {
151
- command: "xling",
152
- args: [
153
- "p",
154
- "--stdin",
155
- "Summarize commits"
156
- ]
157
- }],
158
- description: "Recent commits with AI summary"
159
- }
160
- }
161
- };
162
-
163
- //#endregion
164
- export { EXAMPLE_MULTI_PROVIDER_CONFIG as n, DEFAULT_XLING_CONFIG as t };
1
+ const e={prompt:{providers:[{name:`openai-default`,baseUrl:`https://api.openai.com/v1`,apiKey:``,models:[`gpt-4`,`gpt-4-turbo`,`gpt-4o`,`gpt-4o-mini`,`gpt-3.5-turbo`],priority:1,timeout:6e4}],defaultModel:`gpt-4o-mini`,retryPolicy:{maxRetries:2,backoffMs:1e3}},shortcuts:{lc:{command:`x`,args:[`-t`,`claude`,`-c`],description:`Launch Claude and continue last conversation`},lx:{command:`x`,args:[`-t`,`codex`],description:`Launch Codex`},gdp:{shell:`git diff | xling p --stdin 'Summarize these changes'`,description:`Git diff with AI summary`}}},t={prompt:{providers:[{name:`openai-primary`,baseUrl:`https://api.openai.com/v1`,apiKey:`sk-proj-xxx`,models:[`gpt-4`,`gpt-4-turbo`,`gpt-4o`,`gpt-3.5-turbo`],priority:1,timeout:6e4},{name:`openai-backup`,baseUrl:`https://api.openai.com/v1`,apiKey:`sk-proj-yyy`,models:[`gpt-4`,`gpt-3.5-turbo`],priority:2,timeout:3e4},{name:`azure-openai`,baseUrl:`https://your-resource.openai.azure.com/openai/deployments`,apiKey:`azure-api-key`,models:[`gpt-4`],priority:3,timeout:45e3,headers:{"api-version":`2024-02-15-preview`}},{name:`custom-provider`,baseUrl:`https://custom-ai.example.com/v1`,apiKey:`custom-key`,models:[`llama-3-70b`,`mixtral-8x7b`],priority:10}],defaultModel:`gpt-4`,retryPolicy:{maxRetries:3,backoffMs:1e3}},shortcuts:{lc:{command:`x`,args:[`-t`,`claude`,`-c`],description:`Launch Claude and continue`},lx:{command:`x`,args:[`-t`,`codex`],description:`Launch Codex`},gs:{command:`settings:list`,args:[`--tool`,`claude`],description:`List Claude settings`},gsx:{command:`settings:list`,args:[`--tool`,`codex`],description:`List Codex settings`},gdp:{shell:`git diff | xling p --stdin 'Summarize these changes'`,description:`Git diff with AI summary`},gsp:{shell:`git status --short | xling p --stdin 'Explain these changes'`,description:`Git status with AI explanation`},gcm:{shell:{win32:`git add -N . && git diff HEAD | xling p --stdin 'Analyze changes and generate commit message in both Chinese and English'`,default:`git diff HEAD; git ls-files --others --exclude-standard | while read file; do git diff --no-index /dev/null "$file" 2>/dev/null || true; done | xling p --stdin 'Analyze changes and generate commit message in both Chinese and English'`},description:`Generate commit message for all changes (platform-specific)`},pipe:{pipeline:[{command:`git`,args:[`log`,`--oneline`,`-10`]},{command:`xling`,args:[`p`,`--stdin`,`Summarize commits`]}],description:`Recent commits with AI summary`}}};export{t as n,e as t};
@@ -1,25 +1,2 @@
1
- //#region src/services/prompt/types.ts
2
- /**
3
- * Error thrown when a model is not supported
4
- */
5
- var ModelNotSupportedError = class extends Error {
6
- constructor(model, availableModels) {
7
- super(`Model "${model}" is not supported by any configured provider.\nAvailable models: ${availableModels.join(", ")}`);
8
- this.name = "ModelNotSupportedError";
9
- }
10
- };
11
- /**
12
- * Error thrown when all providers fail
13
- */
14
- var AllProvidersFailedError = class extends Error {
15
- errors;
16
- constructor(model, errors) {
17
- const details = errors.map((e) => ` - ${e.provider}: ${e.error.message}`).join("\n");
18
- super(`All providers failed for model "${model}":\n${details}`);
19
- this.name = "AllProvidersFailedError";
20
- this.errors = errors;
21
- }
22
- };
23
-
24
- //#endregion
25
- export { ModelNotSupportedError as n, AllProvidersFailedError as t };
1
+ var e=class extends Error{constructor(e,t){super(`Model "${e}" is not supported by any configured provider.\nAvailable models: ${t.join(`, `)}`),this.name=`ModelNotSupportedError`}},t=class extends Error{errors;constructor(e,t){let n=t.map(e=>` - ${e.provider}: ${e.error.message}`).join(`
2
+ `);super(`All providers failed for model "${e}":\n${n}`),this.name=`AllProvidersFailedError`,this.errors=t}};export{e as n,t};
@@ -1,23 +1 @@
1
- //#region src/services/shortcuts/types.ts
2
- /**
3
- * Error thrown when a shortcut is not found
4
- */
5
- var ShortcutNotFoundError = class extends Error {
6
- constructor(name, available) {
7
- const availableList = available.length > 0 ? available.join(", ") : "none";
8
- super(`Shortcut "${name}" not found.\n\nAvailable shortcuts: ${availableList}\n\nUse "xling sx --list" to see all shortcuts.`);
9
- this.name = "ShortcutNotFoundError";
10
- }
11
- };
12
- /**
13
- * Error thrown when a circular reference is detected
14
- */
15
- var CircularShortcutError = class extends Error {
16
- constructor(name) {
17
- super(`Circular reference detected: shortcut "${name}" cannot call "sx" command.\n\nThis would create an infinite loop.`);
18
- this.name = "CircularShortcutError";
19
- }
20
- };
21
-
22
- //#endregion
23
- export { ShortcutNotFoundError as n, CircularShortcutError as t };
1
+ var e=class extends Error{constructor(e,t){let n=t.length>0?t.join(`, `):`none`;super(`Shortcut "${e}" not found.\n\nAvailable shortcuts: ${n}\n\nUse "xling sx --list" to see all shortcuts.`),this.name=`ShortcutNotFoundError`}},t=class extends Error{constructor(e){super(`Circular reference detected: shortcut "${e}" cannot call "sx" command.\n\nThis would create an infinite loop.`),this.name=`CircularShortcutError`}};export{e as n,t};
@@ -83,6 +83,7 @@ interface LaunchPayload {
83
83
  cwd?: string;
84
84
  resume?: boolean;
85
85
  continue?: boolean;
86
+ settings?: string;
86
87
  }
87
88
  /**
88
89
  * Launch result
@@ -1,4 +1 @@
1
- import "../errors-pXKbCKbL.js";
2
- import { n as resolveEditorCommand, t as openInEditor } from "../editor-CUiekAEb.js";
3
-
4
- export { openInEditor, resolveEditorCommand };
1
+ import"../errors-pXKbCKbL.js";import{n as e,t}from"../editor-CUiekAEb.js";export{t as openInEditor,e as resolveEditorCommand};
@@ -1,3 +1 @@
1
- import { a as FileWriteError, c as InvalidScopeError, d as UnsupportedToolError, f as XlingError, i as ExecutableNotFoundError, l as ProfileNotFoundError, n as ConfigParseError, o as GitCommandError, r as EditorLaunchError, s as GitRepositoryError, t as ConfigFileNotFoundError, u as SettingsVariantNotFoundError } from "../errors-pXKbCKbL.js";
2
-
3
- export { ConfigFileNotFoundError, ConfigParseError, EditorLaunchError, ExecutableNotFoundError, FileWriteError, GitCommandError, GitRepositoryError, InvalidScopeError, ProfileNotFoundError, SettingsVariantNotFoundError, UnsupportedToolError, XlingError };
1
+ import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"../errors-pXKbCKbL.js";export{u as ConfigFileNotFoundError,o as ConfigParseError,c as EditorLaunchError,i as ExecutableNotFoundError,e as FileWriteError,s as GitCommandError,l as GitRepositoryError,t as InvalidScopeError,a as ProfileNotFoundError,d as SettingsVariantNotFoundError,n as UnsupportedToolError,r as XlingError};
@@ -1,4 +1,4 @@
1
- import { d as SettingsFileEntry, n as ConfigValue, t as ConfigObject } from "../types-5rST51Xi.js";
1
+ import { d as SettingsFileEntry, n as ConfigValue, t as ConfigObject } from "../types-RoapPbyI.js";
2
2
 
3
3
  //#region src/utils/format.d.ts
4
4
 
@@ -1,3 +1 @@
1
- import { i as formatTable, n as formatFilesTable, r as formatJson, t as formatDiff } from "../format-a_tYXjv9.js";
2
-
3
- export { formatDiff, formatFilesTable, formatJson, formatTable };
1
+ import{i as e,n as t,r as n,t as r}from"../format-a_tYXjv9.js";export{r as formatDiff,t as formatFilesTable,n as formatJson,e as formatTable};
@@ -1,42 +1 @@
1
- //#region src/utils/logger.ts
2
- /**
3
- * Logging utilities
4
- */
5
- /**
6
- * Log levels
7
- */
8
- let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
9
- LogLevel$1[LogLevel$1["DEBUG"] = 0] = "DEBUG";
10
- LogLevel$1[LogLevel$1["INFO"] = 1] = "INFO";
11
- LogLevel$1[LogLevel$1["WARN"] = 2] = "WARN";
12
- LogLevel$1[LogLevel$1["ERROR"] = 3] = "ERROR";
13
- return LogLevel$1;
14
- }({});
15
- var Logger = class {
16
- #level;
17
- constructor(level = LogLevel.INFO) {
18
- this.#level = level;
19
- }
20
- setLevel(level) {
21
- this.#level = level;
22
- }
23
- debug(message, ...args) {
24
- if (this.#level <= LogLevel.DEBUG) console.debug(`[DEBUG] ${message}`, ...args);
25
- }
26
- info(message, ...args) {
27
- if (this.#level <= LogLevel.INFO) console.info(`[INFO] ${message}`, ...args);
28
- }
29
- warn(message, ...args) {
30
- if (this.#level <= LogLevel.WARN) console.warn(`[WARN] ${message}`, ...args);
31
- }
32
- error(message, ...args) {
33
- if (this.#level <= LogLevel.ERROR) console.error(`[ERROR] ${message}`, ...args);
34
- }
35
- };
36
- /**
37
- * Default logger instance
38
- */
39
- const logger = new Logger();
40
-
41
- //#endregion
42
- export { LogLevel, Logger, logger };
1
+ let e=function(e){return e[e.DEBUG=0]=`DEBUG`,e[e.INFO=1]=`INFO`,e[e.WARN=2]=`WARN`,e[e.ERROR=3]=`ERROR`,e}({});var t=class{#e;constructor(t=e.INFO){this.#e=t}setLevel(e){this.#e=e}debug(t,...n){this.#e<=e.DEBUG&&console.debug(`[DEBUG] ${t}`,...n)}info(t,...n){this.#e<=e.INFO&&console.info(`[INFO] ${t}`,...n)}warn(t,...n){this.#e<=e.WARN&&console.warn(`[WARN] ${t}`,...n)}error(t,...n){this.#e<=e.ERROR&&console.error(`[ERROR] ${t}`,...n)}};const n=new t;export{e as LogLevel,t as Logger,n as logger};
@@ -1,4 +1,4 @@
1
- import { a as LaunchCommandSpec } from "../types-5rST51Xi.js";
1
+ import { a as LaunchCommandSpec } from "../types-RoapPbyI.js";
2
2
 
3
3
  //#region src/utils/runner.d.ts
4
4
  interface SpawnOptions {
@@ -1,3 +1 @@
1
- import { i as spawnProcess, n as getExecutableVersion, r as runCommand, t as checkExecutable } from "../runner-DYk4q6mP.js";
2
-
3
- export { checkExecutable, getExecutableVersion, runCommand, spawnProcess };
1
+ import{i as e,n as t,r as n,t as r}from"../runner-DYk4q6mP.js";export{r as checkExecutable,t as getExecutableVersion,n as runCommand,e as spawnProcess};
@@ -1,35 +1 @@
1
- import { s as GitRepositoryError } from "./errors-pXKbCKbL.js";
2
- import { r as runCommand, t as checkExecutable } from "./runner-DYk4q6mP.js";
3
-
4
- //#region src/services/git/utils.ts
5
- /**
6
- * Git utility functions
7
- * Shared helpers for git operations
8
- */
9
- /**
10
- * Ensure we're in a git repository
11
- * @param cwd Working directory to check
12
- * @throws GitRepositoryError if not in a git repo
13
- */
14
- async function ensureGitRepo(cwd = process.cwd()) {
15
- try {
16
- const result = await runCommand("git", ["rev-parse", "--is-inside-work-tree"], {
17
- cwd,
18
- silent: true,
19
- throwOnError: false
20
- });
21
- if (!result.success || result.stdout.trim() !== "true") throw new GitRepositoryError(cwd);
22
- } catch {
23
- throw new GitRepositoryError(cwd);
24
- }
25
- }
26
- /**
27
- * Check if GitHub CLI is available
28
- * @returns True if gh CLI is installed
29
- */
30
- async function detectGhCli() {
31
- return await checkExecutable("gh");
32
- }
33
-
34
- //#endregion
35
- export { ensureGitRepo as n, detectGhCli as t };
1
+ import{s as e}from"./errors-pXKbCKbL.js";import{r as t,t as n}from"./runner-DYk4q6mP.js";async function r(n=process.cwd()){try{let r=await t(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:n,silent:!0,throwOnError:!1});if(!r.success||r.stdout.trim()!==`true`)throw new e(n)}catch{throw new e(n)}}async function i(){return await n(`gh`)}export{r as n,i as t};
@@ -1,84 +1 @@
1
- import { i as ExecutableNotFoundError } from "./errors-pXKbCKbL.js";
2
- import { r as runCommand } from "./runner-DYk4q6mP.js";
3
- import { t as detectGhCli } from "./utils-DDnNMPIq.js";
4
-
5
- //#region src/services/git/view.ts
6
- /**
7
- * Browser launch command mapping for different platforms
8
- */
9
- const BROWSER_COMMANDS = {
10
- chrome: {
11
- darwin: "Google Chrome",
12
- linux: "google-chrome",
13
- win32: "chrome"
14
- },
15
- safari: { darwin: "Safari" },
16
- firefox: {
17
- darwin: "Firefox",
18
- linux: "firefox",
19
- win32: "firefox"
20
- },
21
- arc: {
22
- darwin: "Arc",
23
- win32: "Arc"
24
- },
25
- edge: {
26
- darwin: "Microsoft Edge",
27
- linux: "microsoft-edge",
28
- win32: "msedge"
29
- },
30
- dia: {
31
- darwin: "Dia",
32
- linux: "dia",
33
- win32: "dia"
34
- }
35
- };
36
- /**
37
- * Get browser launch command for current platform
38
- * @param browser Browser identifier
39
- * @returns Launch command or null if not available
40
- */
41
- function getBrowserCommand(browser) {
42
- const platform = process.platform;
43
- const command = BROWSER_COMMANDS[browser]?.[platform];
44
- if (!command) return null;
45
- if (platform === "darwin") return `open -a "${command}"`;
46
- return command;
47
- }
48
- /**
49
- * Open PR in web browser
50
- * @param request View request with PR ID and browser preference
51
- * @param cwd Working directory
52
- * @returns Command result
53
- */
54
- async function viewPr(request, cwd) {
55
- const { id, browser = "chrome", openFlags = [] } = request;
56
- if (!await detectGhCli()) throw new ExecutableNotFoundError("gh", "Install GitHub CLI: https://cli.github.com/");
57
- const browserCmd = getBrowserCommand(browser);
58
- if (!browserCmd) throw new Error(`Browser "${browser}" is not available on ${process.platform}. Supported browsers: chrome, safari (macOS only), firefox, arc, edge, dia`);
59
- const env = { GH_BROWSER: browserCmd };
60
- const result = await runCommand("gh", [
61
- "pr",
62
- "view",
63
- id,
64
- "--web",
65
- ...openFlags
66
- ], {
67
- cwd,
68
- env,
69
- throwOnError: false
70
- });
71
- if (!result.success) throw new Error(`Failed to open PR #${id}: ${result.stderr}`);
72
- return {
73
- success: true,
74
- message: `Opened PR #${id} in ${browser}`,
75
- details: {
76
- id,
77
- browser,
78
- platform: process.platform
79
- }
80
- };
81
- }
82
-
83
- //#endregion
84
- export { viewPr as t };
1
+ import{i as e}from"./errors-pXKbCKbL.js";import{r as t}from"./runner-DYk4q6mP.js";import{t as n}from"./utils-DDnNMPIq.js";const r={chrome:{darwin:`Google Chrome`,linux:`google-chrome`,win32:`chrome`},safari:{darwin:`Safari`},firefox:{darwin:`Firefox`,linux:`firefox`,win32:`firefox`},arc:{darwin:`Arc`,win32:`Arc`},edge:{darwin:`Microsoft Edge`,linux:`microsoft-edge`,win32:`msedge`},dia:{darwin:`Dia`,linux:`dia`,win32:`dia`}};function i(e){let t=process.platform,n=r[e]?.[t];return n?t===`darwin`?`open -a "${n}"`:n:null}async function a(r,a){let{id:o,browser:s=`chrome`,openFlags:c=[]}=r;if(!await n())throw new e(`gh`,`Install GitHub CLI: https://cli.github.com/`);let l=i(s);if(!l)throw Error(`Browser "${s}" is not available on ${process.platform}. Supported browsers: chrome, safari (macOS only), firefox, arc, edge, dia`);let u={GH_BROWSER:l},d=await t(`gh`,[`pr`,`view`,o,`--web`,...c],{cwd:a,env:u,throwOnError:!1});if(!d.success)throw Error(`Failed to open PR #${o}: ${d.stderr}`);return{success:!0,message:`Opened PR #${o} in ${s}`,details:{id:o,browser:s,platform:process.platform}}}export{a as t};
@@ -1,206 +1,4 @@
1
- import { o as GitCommandError } from "./errors-pXKbCKbL.js";
2
- import { r as runCommand } from "./runner-DYk4q6mP.js";
3
- import path from "node:path";
4
- import { existsSync } from "node:fs";
1
+ import{o as e}from"./errors-pXKbCKbL.js";import{r as t}from"./runner-DYk4q6mP.js";import n from"node:path";import{existsSync as r}from"node:fs";function i(e){return n.basename(e)}function a(e,t){let r=i(e),a=t.replace(/\//g,`-`);return n.join(e,`..`,`${r}-${a}`)}function o(e,t){t.path&&e.push({path:t.path,branch:t.branch,head:t.head})}function s(e){let t=[],n=e.trim().split(`
2
+ `),r={};for(let e of n)e.startsWith(`worktree `)?(o(t,r),r={path:e.substring(9)}):e.startsWith(`HEAD `)?r.head=e.substring(5):e.startsWith(`branch `)?r.branch=e.substring(7).replace(`refs/heads/`,``):e===``&&(o(t,r),r={});return o(t,r),t}async function c(e,r){let i=await t(`git`,[`worktree`,`list`,`--porcelain`],{cwd:r,throwOnError:!1});if(!i.success)return null;let a=s(i.stdout),o=a.find(t=>t.branch===e);if(o)return o.path;let c=a.find(t=>{let r=n.basename(t.path);return r===e||r.endsWith(`-${e}`)});if(c)return c.path;let l=a.find(t=>t.path.includes(e));return l?l.path:null}async function l(n,i){let o=i||process.cwd(),{action:l,path:u,branch:d,force:f,detach:p}=n;switch(l){case`list`:{let n=await t(`git`,[`worktree`,`list`,`--porcelain`],{cwd:o,throwOnError:!1});if(!n.success)throw new e(`git worktree list`,n.stderr);let r=s(n.stdout);return{success:!0,message:`Available worktrees:`,details:{output:r.map((e,t)=>` [${t+1}] ${e.path}\n Branch: ${e.branch||`detached`}`).join(`
5
3
 
6
- //#region src/services/git/worktree.ts
7
- /**
8
- * Get repository name from current directory
9
- * @param cwd Current working directory
10
- * @returns Repository name
11
- */
12
- function getRepoName(cwd) {
13
- return path.basename(cwd);
14
- }
15
- /**
16
- * Generate default worktree path
17
- * Format: ../repo-name-branch-name (following xlaude convention)
18
- * @param cwd Current working directory
19
- * @param branch Branch name
20
- * @returns Generated path
21
- */
22
- function generateWorktreePath(cwd, branch) {
23
- const repoName = getRepoName(cwd);
24
- const sanitizedBranch = branch.replace(/\//g, "-");
25
- return path.join(cwd, "..", `${repoName}-${sanitizedBranch}`);
26
- }
27
- function pushWorktreeRecord(collection, record) {
28
- if (record.path) collection.push({
29
- path: record.path,
30
- branch: record.branch,
31
- head: record.head
32
- });
33
- }
34
- function parseWorktreeList(output) {
35
- const worktrees = [];
36
- const lines = output.trim().split("\n");
37
- let current = {};
38
- for (const line of lines) if (line.startsWith("worktree ")) {
39
- pushWorktreeRecord(worktrees, current);
40
- current = { path: line.substring(9) };
41
- } else if (line.startsWith("HEAD ")) current.head = line.substring(5);
42
- else if (line.startsWith("branch ")) current.branch = line.substring(7).replace("refs/heads/", "");
43
- else if (line === "") {
44
- pushWorktreeRecord(worktrees, current);
45
- current = {};
46
- }
47
- pushWorktreeRecord(worktrees, current);
48
- return worktrees;
49
- }
50
- /**
51
- * Find worktree by branch name or path pattern
52
- * @param identifier Branch name or path pattern
53
- * @param cwd Working directory
54
- * @returns Worktree path if found
55
- */
56
- async function findWorktree(identifier, cwd) {
57
- const listResult = await runCommand("git", [
58
- "worktree",
59
- "list",
60
- "--porcelain"
61
- ], {
62
- cwd,
63
- throwOnError: false
64
- });
65
- if (!listResult.success) return null;
66
- const worktrees = parseWorktreeList(listResult.stdout);
67
- const exactMatch = worktrees.find((wt) => wt.branch === identifier);
68
- if (exactMatch) return exactMatch.path;
69
- const basenameMatch = worktrees.find((wt) => {
70
- const basename = path.basename(wt.path);
71
- return basename === identifier || basename.endsWith(`-${identifier}`);
72
- });
73
- if (basenameMatch) return basenameMatch.path;
74
- const partialMatch = worktrees.find((wt) => wt.path.includes(identifier));
75
- if (partialMatch) return partialMatch.path;
76
- return null;
77
- }
78
- /**
79
- * Manage git worktrees
80
- * @param request Worktree operation request
81
- * @param cwd Working directory
82
- * @returns Command result
83
- */
84
- async function manageWorktree(request, cwd) {
85
- const currentCwd = cwd || process.cwd();
86
- const { action, path: userPath, branch, force, detach } = request;
87
- switch (action) {
88
- case "list": {
89
- const result = await runCommand("git", [
90
- "worktree",
91
- "list",
92
- "--porcelain"
93
- ], {
94
- cwd: currentCwd,
95
- throwOnError: false
96
- });
97
- if (!result.success) throw new GitCommandError("git worktree list", result.stderr);
98
- const worktrees = parseWorktreeList(result.stdout);
99
- return {
100
- success: true,
101
- message: "Available worktrees:",
102
- details: {
103
- output: worktrees.map((wt, idx) => ` [${idx + 1}] ${wt.path}\n Branch: ${wt.branch || "detached"}`).join("\n\n"),
104
- worktrees
105
- }
106
- };
107
- }
108
- case "switch": {
109
- const listResult = await runCommand("git", [
110
- "worktree",
111
- "list",
112
- "--porcelain"
113
- ], {
114
- cwd: currentCwd,
115
- throwOnError: false
116
- });
117
- if (!listResult.success) throw new GitCommandError("git worktree list", listResult.stderr);
118
- if (parseWorktreeList(listResult.stdout).length === 0) throw new Error("No worktrees found");
119
- const targetBranch = branch || "main";
120
- const foundPath = await findWorktree(targetBranch, currentCwd);
121
- if (!foundPath) throw new Error(`Could not find worktree matching "${targetBranch}". Use --list to see available worktrees.`);
122
- return {
123
- success: true,
124
- message: foundPath,
125
- details: {
126
- path: foundPath,
127
- branch: targetBranch
128
- }
129
- };
130
- }
131
- case "add": {
132
- let targetBranch = branch || "main";
133
- const listResult = await runCommand("git", [
134
- "worktree",
135
- "list",
136
- "--porcelain"
137
- ], {
138
- cwd: currentCwd,
139
- throwOnError: false
140
- });
141
- if (listResult.success) {
142
- const existingWorktree = parseWorktreeList(listResult.stdout).find((wt) => wt.branch === targetBranch);
143
- if (existingWorktree) throw new Error(`Branch "${targetBranch}" is already used by worktree at "${existingWorktree.path}".\nChoose a different branch name, or switch that worktree to another branch first.`);
144
- }
145
- const worktreePath = userPath || generateWorktreePath(currentCwd, targetBranch);
146
- if (existsSync(worktreePath) && !force) throw new Error(`Path "${worktreePath}" already exists. Use --force to override or specify a different path with --path`);
147
- const args = ["worktree", "add"];
148
- if (force) args.push("--force");
149
- if (detach) args.push("--detach");
150
- args.push(worktreePath, targetBranch);
151
- const result = await runCommand("git", args, {
152
- cwd: currentCwd,
153
- throwOnError: false
154
- });
155
- if (!result.success) throw new GitCommandError(`git worktree add ${worktreePath} ${targetBranch}`, result.stderr);
156
- return {
157
- success: true,
158
- message: `Created worktree at ${worktreePath} for branch ${targetBranch}`,
159
- details: {
160
- path: worktreePath,
161
- branch: targetBranch
162
- }
163
- };
164
- }
165
- case "remove": {
166
- let targetPath;
167
- if (branch) {
168
- const foundPath = await findWorktree(branch, currentCwd);
169
- if (!foundPath) throw new Error(`Could not find worktree matching "${branch}". Use --list to see available worktrees.`);
170
- targetPath = foundPath;
171
- } else if (userPath) {
172
- if (!existsSync(userPath)) throw new Error(`Path "${userPath}" does not exist. Use --branch (-b) to remove by name, or --list to see available worktrees.`);
173
- targetPath = userPath;
174
- } else throw new Error("--branch (-b) or --path (-p) is required for remove action.");
175
- const args = ["worktree", "remove"];
176
- if (force) args.push("--force");
177
- args.push(targetPath);
178
- const result = await runCommand("git", args, {
179
- cwd: currentCwd,
180
- throwOnError: false
181
- });
182
- if (!result.success) throw new GitCommandError(`git worktree remove ${targetPath}`, result.stderr);
183
- return {
184
- success: true,
185
- message: `Removed worktree at ${targetPath}`,
186
- details: { path: targetPath }
187
- };
188
- }
189
- case "prune": {
190
- const result = await runCommand("git", ["worktree", "prune"], {
191
- cwd: currentCwd,
192
- throwOnError: false
193
- });
194
- if (!result.success) throw new GitCommandError("git worktree prune", result.stderr);
195
- return {
196
- success: true,
197
- message: "Pruned stale worktrees",
198
- details: { output: result.stdout }
199
- };
200
- }
201
- default: throw new Error(`Unknown worktree action: ${action}`);
202
- }
203
- }
204
-
205
- //#endregion
206
- export { manageWorktree as t };
4
+ `),worktrees:r}}}case`switch`:{let n=await t(`git`,[`worktree`,`list`,`--porcelain`],{cwd:o,throwOnError:!1});if(!n.success)throw new e(`git worktree list`,n.stderr);if(s(n.stdout).length===0)throw Error(`No worktrees found`);let r=d||`main`,i=await c(r,o);if(!i)throw Error(`Could not find worktree matching "${r}". Use --list to see available worktrees.`);return{success:!0,message:i,details:{path:i,branch:r}}}case`add`:{let n=d||`main`,i=await t(`git`,[`worktree`,`list`,`--porcelain`],{cwd:o,throwOnError:!1});if(i.success){let e=s(i.stdout).find(e=>e.branch===n);if(e)throw Error(`Branch "${n}" is already used by worktree at "${e.path}".\nChoose a different branch name, or switch that worktree to another branch first.`)}let c=u||a(o,n);if(r(c)&&!f)throw Error(`Path "${c}" already exists. Use --force to override or specify a different path with --path`);let l=[`worktree`,`add`];f&&l.push(`--force`),p&&l.push(`--detach`),l.push(c,n);let m=await t(`git`,l,{cwd:o,throwOnError:!1});if(!m.success)throw new e(`git worktree add ${c} ${n}`,m.stderr);return{success:!0,message:`Created worktree at ${c} for branch ${n}`,details:{path:c,branch:n}}}case`remove`:{let n;if(d){let e=await c(d,o);if(!e)throw Error(`Could not find worktree matching "${d}". Use --list to see available worktrees.`);n=e}else if(u){if(!r(u))throw Error(`Path "${u}" does not exist. Use --branch (-b) to remove by name, or --list to see available worktrees.`);n=u}else throw Error(`--branch (-b) or --path (-p) is required for remove action.`);let i=[`worktree`,`remove`];f&&i.push(`--force`),i.push(n);let a=await t(`git`,i,{cwd:o,throwOnError:!1});if(!a.success)throw new e(`git worktree remove ${n}`,a.stderr);return{success:!0,message:`Removed worktree at ${n}`,details:{path:n}}}case`prune`:{let n=await t(`git`,[`worktree`,`prune`],{cwd:o,throwOnError:!1});if(!n.success)throw new e(`git worktree prune`,n.stderr);return{success:!0,message:`Pruned stale worktrees`,details:{output:n.stdout}}}default:throw Error(`Unknown worktree action: ${l}`)}}export{l as t};