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,254 +1 @@
1
- import { c as InvalidScopeError, n as ConfigParseError } from "./errors-pXKbCKbL.js";
2
- import { n as resolveEditorCommand, t as openInEditor } from "./editor-CUiekAEb.js";
3
- import { n as ensureDir, s as resolveHome } from "./fsStore-S8RslR8L.js";
4
- import { t as BaseAdapter } from "./base-DtcPVpvU.js";
5
- import { p as validateXlingConfig } from "./config-JHw2hqMN.js";
6
- import { t as DEFAULT_XLING_CONFIG } from "./template-B19CdPfg.js";
7
- import { execSync } from "child_process";
8
- import * as fs from "fs";
9
- import * as path from "path";
10
-
11
- //#region src/services/settings/adapters/xling.ts
12
- /**
13
- * Xling settings adapter
14
- * Manages configuration at ~/.claude/xling.json
15
- */
16
- /**
17
- * Xling adapter for managing prompt providers at ~/.claude/xling.json
18
- */
19
- var XlingAdapter = class extends BaseAdapter {
20
- toolId = "xling";
21
- /**
22
- * Resolve config path - cross-platform
23
- * macOS/Linux: ~/.claude/xling.json
24
- * Windows: %USERPROFILE%\.claude\xling.json
25
- */
26
- resolvePath(scope) {
27
- if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
28
- return "~/.claude/xling.json";
29
- }
30
- /**
31
- * Validate scope - only "user" is supported
32
- */
33
- validateScope(scope) {
34
- return scope === "user";
35
- }
36
- /**
37
- * Read Xling configuration
38
- * Returns default template if file doesn't exist
39
- */
40
- readConfig(configPath) {
41
- const resolvedPath = resolveHome(configPath);
42
- if (!fs.existsSync(resolvedPath)) return DEFAULT_XLING_CONFIG;
43
- try {
44
- const content = fs.readFileSync(resolvedPath, "utf-8");
45
- return validateXlingConfig(JSON.parse(content));
46
- } catch (error) {
47
- throw new ConfigParseError(resolvedPath, error.message);
48
- }
49
- }
50
- /**
51
- * Write Xling configuration with secure permissions
52
- * Unix: chmod 600
53
- * Windows: ACL to restrict access to current user only
54
- */
55
- writeConfig(configPath, data, backup = true) {
56
- const resolvedPath = resolveHome(configPath);
57
- ensureDir(path.dirname(resolvedPath));
58
- if (backup && fs.existsSync(resolvedPath)) {
59
- const backupPath = `${resolvedPath}.bak`;
60
- fs.copyFileSync(resolvedPath, backupPath);
61
- }
62
- try {
63
- const tempPath = `${resolvedPath}.tmp`;
64
- fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), "utf-8");
65
- this.#setSecurePermissions(tempPath);
66
- fs.renameSync(tempPath, resolvedPath);
67
- } catch (error) {
68
- throw new Error(`Failed to write config to ${resolvedPath}: ${error.message}`);
69
- }
70
- }
71
- /**
72
- * Set secure file permissions (cross-platform)
73
- * Unix: chmod 600 (owner read/write only)
74
- * Windows: icacls to restrict access to current user only
75
- */
76
- #setSecurePermissions(filePath) {
77
- try {
78
- if (process.platform === "win32") execSync(`icacls "${filePath}" /inheritance:r /grant:r "%USERNAME%:(F)"`, {
79
- stdio: "ignore",
80
- windowsHide: true
81
- });
82
- else fs.chmodSync(filePath, 384);
83
- } catch (error) {
84
- console.warn(`Warning: Could not set secure permissions on ${filePath}: ${error.message}`);
85
- }
86
- }
87
- /**
88
- * Open xling.json in the specified IDE
89
- */
90
- async edit(scope, options) {
91
- if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
92
- const configPath = this.resolvePath(scope);
93
- const resolvedPath = resolveHome(configPath);
94
- const resolvedEditor = resolveEditorCommand(options.ide);
95
- const directory = path.dirname(resolvedPath);
96
- ensureDir(directory);
97
- if (!fs.existsSync(resolvedPath)) this.writeConfig(configPath, DEFAULT_XLING_CONFIG, false);
98
- await openInEditor(resolvedEditor, resolvedPath);
99
- return {
100
- success: true,
101
- message: `Opened ${configPath} in ${resolvedEditor}`,
102
- filePath: resolvedPath
103
- };
104
- }
105
- /**
106
- * List all providers
107
- */
108
- async list(scope) {
109
- if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
110
- const configPath = this.resolvePath(scope);
111
- const config = this.readConfig(configPath);
112
- return {
113
- type: "entries",
114
- entries: {
115
- prompt: {
116
- defaultModel: config.prompt.defaultModel || null,
117
- retryPolicy: config.prompt.retryPolicy || null,
118
- providers: config.prompt.providers.map((p) => ({
119
- name: p.name,
120
- baseUrl: p.baseUrl,
121
- models: p.models,
122
- priority: p.priority ?? null,
123
- timeout: p.timeout ?? null,
124
- apiKey: this.#maskApiKey(p.apiKey)
125
- }))
126
- },
127
- shortcuts: config.shortcuts || null
128
- },
129
- filePath: resolveHome(configPath)
130
- };
131
- }
132
- /**
133
- * Get all configured shortcuts
134
- */
135
- getShortcuts(scope) {
136
- if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
137
- const configPath = this.resolvePath(scope);
138
- return this.readConfig(configPath).shortcuts || {};
139
- }
140
- /**
141
- * Add a new provider
142
- */
143
- async addProvider(scope, provider) {
144
- const configPath = this.resolvePath(scope);
145
- const config = this.readConfig(configPath);
146
- if (config.prompt.providers.some((p) => p.name === provider.name)) return {
147
- success: false,
148
- message: `Provider "${provider.name}" already exists`,
149
- filePath: resolveHome(configPath)
150
- };
151
- config.prompt.providers.push(provider);
152
- this.writeConfig(configPath, config);
153
- return {
154
- success: true,
155
- message: `Added provider "${provider.name}"`,
156
- filePath: resolveHome(configPath)
157
- };
158
- }
159
- /**
160
- * Remove a provider by name
161
- */
162
- async removeProvider(scope, name) {
163
- const configPath = this.resolvePath(scope);
164
- const config = this.readConfig(configPath);
165
- const index = config.prompt.providers.findIndex((p) => p.name === name);
166
- if (index === -1) return {
167
- success: false,
168
- message: `Provider "${name}" not found`,
169
- filePath: resolveHome(configPath)
170
- };
171
- if (config.prompt.providers.length === 1) return {
172
- success: false,
173
- message: "Cannot remove the last provider. At least one provider is required.",
174
- filePath: resolveHome(configPath)
175
- };
176
- config.prompt.providers.splice(index, 1);
177
- this.writeConfig(configPath, config);
178
- return {
179
- success: true,
180
- message: `Removed provider "${name}"`,
181
- filePath: resolveHome(configPath)
182
- };
183
- }
184
- /**
185
- * Update a provider
186
- */
187
- async updateProvider(scope, name, updates) {
188
- const configPath = this.resolvePath(scope);
189
- const config = this.readConfig(configPath);
190
- const provider = config.prompt.providers.find((p) => p.name === name);
191
- if (!provider) return {
192
- success: false,
193
- message: `Provider "${name}" not found`,
194
- filePath: resolveHome(configPath)
195
- };
196
- Object.assign(provider, {
197
- ...updates,
198
- name
199
- });
200
- this.writeConfig(configPath, config);
201
- return {
202
- success: true,
203
- message: `Updated provider "${name}"`,
204
- filePath: resolveHome(configPath)
205
- };
206
- }
207
- /**
208
- * Set default model
209
- */
210
- async setDefaultModel(scope, model) {
211
- const configPath = this.resolvePath(scope);
212
- const config = this.readConfig(configPath);
213
- config.prompt.defaultModel = model;
214
- this.writeConfig(configPath, config);
215
- return {
216
- success: true,
217
- message: `Set default model to "${model}"`,
218
- filePath: resolveHome(configPath)
219
- };
220
- }
221
- /**
222
- * Mask API key for display (show first 4 and last 4 characters)
223
- */
224
- #maskApiKey(apiKey) {
225
- if (apiKey.length <= 8) return "***";
226
- return `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}`;
227
- }
228
- /**
229
- * Check file permissions and warn if not 600
230
- */
231
- checkPermissions(configPath) {
232
- const resolvedPath = resolveHome(configPath);
233
- if (!fs.existsSync(resolvedPath)) return {
234
- secure: true,
235
- permissions: "N/A"
236
- };
237
- try {
238
- const mode = fs.statSync(resolvedPath).mode & 511;
239
- const permissions = mode.toString(8);
240
- return {
241
- secure: mode === 384,
242
- permissions
243
- };
244
- } catch {
245
- return {
246
- secure: false,
247
- permissions: "unknown"
248
- };
249
- }
250
- }
251
- };
252
-
253
- //#endregion
254
- export { XlingAdapter as t };
1
+ import{c as e,n as t}from"./errors-pXKbCKbL.js";import{n,t as r}from"./editor-CUiekAEb.js";import{n as i,s as a}from"./fsStore-S8RslR8L.js";import{t as o}from"./base-DtcPVpvU.js";import{p as s}from"./config-JHw2hqMN.js";import{t as c}from"./template-B19CdPfg.js";import{execSync as l}from"child_process";import*as u from"fs";import*as d from"path";var f=class extends o{toolId=`xling`;resolvePath(t){if(!this.validateScope(t))throw new e(t);return`~/.claude/xling.json`}validateScope(e){return e===`user`}readConfig(e){let n=a(e);if(!u.existsSync(n))return c;try{let e=u.readFileSync(n,`utf-8`);return s(JSON.parse(e))}catch(e){throw new t(n,e.message)}}writeConfig(e,t,n=!0){let r=a(e);if(i(d.dirname(r)),n&&u.existsSync(r)){let e=`${r}.bak`;u.copyFileSync(r,e)}try{let e=`${r}.tmp`;u.writeFileSync(e,JSON.stringify(t,null,2),`utf-8`),this.#e(e),u.renameSync(e,r)}catch(e){throw Error(`Failed to write config to ${r}: ${e.message}`)}}#e(e){try{process.platform===`win32`?l(`icacls "${e}" /inheritance:r /grant:r "%USERNAME%:(F)"`,{stdio:`ignore`,windowsHide:!0}):u.chmodSync(e,384)}catch(t){console.warn(`Warning: Could not set secure permissions on ${e}: ${t.message}`)}}async edit(t,o){if(!this.validateScope(t))throw new e(t);let s=this.resolvePath(t),l=a(s),f=n(o.ide);return i(d.dirname(l)),u.existsSync(l)||this.writeConfig(s,c,!1),await r(f,l),{success:!0,message:`Opened ${s} in ${f}`,filePath:l}}async list(t){if(!this.validateScope(t))throw new e(t);let n=this.resolvePath(t),r=this.readConfig(n);return{type:`entries`,entries:{prompt:{defaultModel:r.prompt.defaultModel||null,retryPolicy:r.prompt.retryPolicy||null,providers:r.prompt.providers.map(e=>({name:e.name,baseUrl:e.baseUrl,models:e.models,priority:e.priority??null,timeout:e.timeout??null,apiKey:this.#t(e.apiKey)}))},shortcuts:r.shortcuts||null},filePath:a(n)}}getShortcuts(t){if(!this.validateScope(t))throw new e(t);let n=this.resolvePath(t);return this.readConfig(n).shortcuts||{}}async addProvider(e,t){let n=this.resolvePath(e),r=this.readConfig(n);return r.prompt.providers.some(e=>e.name===t.name)?{success:!1,message:`Provider "${t.name}" already exists`,filePath:a(n)}:(r.prompt.providers.push(t),this.writeConfig(n,r),{success:!0,message:`Added provider "${t.name}"`,filePath:a(n)})}async removeProvider(e,t){let n=this.resolvePath(e),r=this.readConfig(n),i=r.prompt.providers.findIndex(e=>e.name===t);return i===-1?{success:!1,message:`Provider "${t}" not found`,filePath:a(n)}:r.prompt.providers.length===1?{success:!1,message:`Cannot remove the last provider. At least one provider is required.`,filePath:a(n)}:(r.prompt.providers.splice(i,1),this.writeConfig(n,r),{success:!0,message:`Removed provider "${t}"`,filePath:a(n)})}async updateProvider(e,t,n){let r=this.resolvePath(e),i=this.readConfig(r),o=i.prompt.providers.find(e=>e.name===t);return o?(Object.assign(o,{...n,name:t}),this.writeConfig(r,i),{success:!0,message:`Updated provider "${t}"`,filePath:a(r)}):{success:!1,message:`Provider "${t}" not found`,filePath:a(r)}}async setDefaultModel(e,t){let n=this.resolvePath(e),r=this.readConfig(n);return r.prompt.defaultModel=t,this.writeConfig(n,r),{success:!0,message:`Set default model to "${t}"`,filePath:a(n)}}#t(e){return e.length<=8?`***`:`${e.substring(0,4)}...${e.substring(e.length-4)}`}checkPermissions(e){let t=a(e);if(!u.existsSync(t))return{secure:!0,permissions:`N/A`};try{let e=u.statSync(t).mode&511,n=e.toString(8);return{secure:e===384,permissions:n}}catch{return{secure:!1,permissions:`unknown`}}}};export{f as t};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xling",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Unified CLI for managing AI tool settings",
5
5
  "homepage": "https://github.com/kingsword09/xling/tree/main#readme",
6
6
  "bugs": {
@@ -1,29 +0,0 @@
1
- import { t as BaseLaunchAdapter } from "./base-CSwZL00J.js";
2
-
3
- //#region src/services/launch/adapters/claude.ts
4
- /**
5
- * Claude Code launch adapter
6
- */
7
- /**
8
- * Applies Claude-specific flags:
9
- * - Yolo mode: --dangerously-skip-permissions
10
- * - Resume picker: -r
11
- * - Continue last conversation: -c
12
- */
13
- var ClaudeLaunchAdapter = class extends BaseLaunchAdapter {
14
- toolId = "claude";
15
- executable = "claude";
16
- buildCommandSpec(payload) {
17
- const baseArgs = [];
18
- if (payload.continue) baseArgs.push("-c");
19
- else if (payload.resume) baseArgs.push("-r");
20
- return {
21
- executable: this.executable,
22
- baseArgs,
23
- yoloArgs: payload.yolo ? ["--dangerously-skip-permissions"] : void 0
24
- };
25
- }
26
- };
27
-
28
- //#endregion
29
- export { ClaudeLaunchAdapter as t };
@@ -1,30 +0,0 @@
1
- import { t as BaseLaunchAdapter } from "./base-CSwZL00J.js";
2
-
3
- //#region src/services/launch/adapters/codex.ts
4
- /**
5
- * Codex launch adapter
6
- */
7
- /**
8
- * Applies Codex-specific behavior:
9
- * - Yolo mode: --dangerously-bypass-approvals-and-sandbox
10
- * - Resume picker: `codex resume`
11
- * - Continue last session: `codex resume --last`
12
- * - Default interactive session: `codex`
13
- */
14
- var CodexLaunchAdapter = class extends BaseLaunchAdapter {
15
- toolId = "codex";
16
- executable = "codex";
17
- buildCommandSpec(payload) {
18
- const baseArgs = [];
19
- if (payload.continue) baseArgs.push("resume", "--last");
20
- else if (payload.resume) baseArgs.push("resume");
21
- return {
22
- executable: this.executable,
23
- baseArgs,
24
- yoloArgs: payload.yolo ? ["--dangerously-bypass-approvals-and-sandbox"] : void 0
25
- };
26
- }
27
- };
28
-
29
- //#endregion
30
- export { CodexLaunchAdapter as t };
@@ -1,87 +0,0 @@
1
- import { d as UnsupportedToolError } from "./errors-pXKbCKbL.js";
2
- import { i as spawnProcess } from "./runner-DYk4q6mP.js";
3
- import { t as ClaudeLaunchAdapter } from "./claude-YXQbPr5h.js";
4
- import { t as CodexLaunchAdapter } from "./codex-UE8EaZGt.js";
5
-
6
- //#region src/services/launch/dispatcher.ts
7
- /**
8
- * Applies SOLID principles:
9
- * - SRP: only handles dispatching and process launch
10
- * - OCP: registerAdapter enables extension
11
- * - DIP: depends on LaunchAdapter, not concrete classes
12
- * - LSP: adapters are interchangeable
13
- */
14
- var LaunchDispatcher = class {
15
- #adapters;
16
- constructor() {
17
- this.#adapters = /* @__PURE__ */ new Map();
18
- this.#adapters.set("claude", new ClaudeLaunchAdapter());
19
- this.#adapters.set("codex", new CodexLaunchAdapter());
20
- }
21
- /**
22
- * Execute a launch request
23
- */
24
- async execute(payload) {
25
- const adapter = this.#getAdapter(payload.tool);
26
- if (!await adapter.validateAvailability()) return {
27
- success: false,
28
- message: `Tool "${payload.tool}" is not installed or not found in PATH`
29
- };
30
- const yolo = payload.yolo ?? true;
31
- const spec = adapter.buildCommandSpec({
32
- yolo,
33
- resume: payload.resume,
34
- continue: payload.continue
35
- });
36
- try {
37
- const { pid, command } = await spawnProcess(spec, {
38
- cwd: payload.cwd,
39
- args: payload.args
40
- });
41
- const telemetry = {
42
- tool: payload.tool,
43
- yolo,
44
- args: payload.args ?? []
45
- };
46
- if (payload.resume !== void 0) telemetry.resume = payload.resume;
47
- if (payload.continue !== void 0) telemetry.continue = payload.continue;
48
- if (payload.cwd) telemetry.cwd = payload.cwd;
49
- return {
50
- success: true,
51
- pid,
52
- command,
53
- message: `Launched ${payload.tool} successfully (PID: ${pid})`,
54
- data: telemetry
55
- };
56
- } catch (error) {
57
- return {
58
- success: false,
59
- message: `Failed to launch ${payload.tool}: ${error.message}`
60
- };
61
- }
62
- }
63
- /**
64
- * Resolve the adapter for a tool
65
- * @throws UnsupportedToolError when the tool is unknown
66
- */
67
- #getAdapter(tool) {
68
- const adapter = this.#adapters.get(tool);
69
- if (!adapter) throw new UnsupportedToolError(tool);
70
- return adapter;
71
- }
72
- /**
73
- * Register a new adapter (OCP extension point)
74
- */
75
- registerAdapter(adapter) {
76
- this.#adapters.set(adapter.toolId, adapter);
77
- }
78
- /**
79
- * Return all supported tool IDs
80
- */
81
- getSupportedTools() {
82
- return Array.from(this.#adapters.keys());
83
- }
84
- };
85
-
86
- //#endregion
87
- export { LaunchDispatcher as t };