xling 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -101
- package/dist/{base-Bq6x0S5a.d.ts → base-ZLSUOdyk.d.ts} +3 -3
- package/dist/{claude-Bagw5C6H.js → claude-C6lOG2Mk.js} +15 -15
- package/dist/{client-BQFhUvFV.js → client-DTC49Rug.js} +10 -10
- package/dist/{codex-CKkfM5YP.js → codex-Dl7Rx7Nr.js} +2 -2
- package/dist/commands/git/wts.d.ts +1 -2
- package/dist/commands/git/wts.js +4 -4
- package/dist/commands/p/index.d.ts +1 -26
- package/dist/commands/p/index.js +25 -22
- package/dist/commands/settings/get.d.ts +1 -3
- package/dist/commands/settings/get.js +13 -13
- package/dist/commands/settings/inspect.js +7 -7
- package/dist/commands/settings/list.d.ts +1 -5
- package/dist/commands/settings/list.js +17 -17
- package/dist/commands/settings/set.js +7 -7
- package/dist/commands/settings/switch.d.ts +1 -3
- package/dist/commands/settings/switch.js +13 -13
- package/dist/commands/sx/index.js +4 -4
- package/dist/commands/version/index.d.ts +12 -0
- package/dist/commands/version/index.js +22 -0
- package/dist/commands/x/index.js +1 -1
- package/dist/config-DmuPKkuB.d.ts +137 -0
- package/dist/{config-Dczzq4SM.js → config-JHw2hqMN.js} +45 -13
- package/dist/{dispatcher-D9_qKIrf.js → dispatcher-BCISF-Uw.js} +9 -9
- package/dist/{dispatcher-BdmRTD6Y.js → dispatcher-BYazaYbC.js} +15 -15
- package/dist/domain/xling/config.d.ts +2 -2
- package/dist/domain/xling/config.js +2 -2
- package/dist/domain/xling/template.d.ts +1 -1
- package/dist/domain/xling/template.js +1 -1
- package/dist/{gemini-DH25nZbZ.js → gemini-DQoPiuiw.js} +2 -2
- package/dist/{providerRegistry-DHpmEw-0.d.ts → providerRegistry-Bn9hIwS3.d.ts} +2 -14
- package/dist/{providerRegistry-B5nMOLDr.js → providerRegistry-Cljln1eo.js} +26 -26
- package/dist/{router-5CxWCzk1.js → router-DX-dIEei.js} +38 -38
- package/dist/runner-Bi5mGd-w.js +203 -0
- package/dist/services/launch/dispatcher.d.ts +1 -6
- package/dist/services/launch/dispatcher.js +1 -1
- package/dist/services/prompt/client.d.ts +2 -7
- package/dist/services/prompt/client.js +1 -1
- package/dist/services/prompt/providerRegistry.d.ts +2 -2
- package/dist/services/prompt/providerRegistry.js +4 -4
- package/dist/services/prompt/router.d.ts +3 -37
- package/dist/services/prompt/router.js +6 -6
- package/dist/services/settings/adapters/base.d.ts +1 -1
- package/dist/services/settings/adapters/claude.d.ts +2 -7
- package/dist/services/settings/adapters/claude.js +1 -1
- package/dist/services/settings/adapters/codex.d.ts +2 -2
- package/dist/services/settings/adapters/codex.js +1 -1
- package/dist/services/settings/adapters/gemini.d.ts +2 -5
- package/dist/services/settings/adapters/gemini.js +1 -1
- package/dist/services/settings/adapters/xling.d.ts +11 -10
- package/dist/services/settings/adapters/xling.js +3 -3
- package/dist/services/settings/dispatcher.d.ts +1 -5
- package/dist/services/settings/dispatcher.js +7 -7
- package/dist/services/shortcuts/runner.d.ts +3 -21
- package/dist/services/shortcuts/runner.js +4 -4
- package/dist/services/shortcuts/types.d.ts +2 -2
- package/dist/{template-Dzsf2dA-.js → template-B19CdPfg.js} +7 -0
- package/dist/{types-DJmn_Vo_.d.ts → types-DEhRpmh5.d.ts} +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +7 -7
- package/dist/{xling-C4d8WD7l.js → xling-BxVsmPja.js} +28 -7
- package/package.json +1 -1
- package/dist/config-BNmU7SZX.d.ts +0 -118
- package/dist/runner-C8lK--xo.js +0 -135
package/README.md
CHANGED
|
@@ -46,6 +46,16 @@ bun run build
|
|
|
46
46
|
npm link
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
### Platform Requirements
|
|
50
|
+
|
|
51
|
+
**Windows Users:**
|
|
52
|
+
- PowerShell 7+ is required for shell shortcuts (`sx` command with shell type)
|
|
53
|
+
- Install from: https://github.com/PowerShell/PowerShell/releases
|
|
54
|
+
|
|
55
|
+
**All Platforms:**
|
|
56
|
+
- Node.js >= 20.19.0
|
|
57
|
+
- Git (for git-related commands)
|
|
58
|
+
|
|
49
59
|
## Usage
|
|
50
60
|
|
|
51
61
|
`xling` bundles a quick launcher, configuration helpers, and git productivity
|
|
@@ -116,104 +126,3 @@ place.
|
|
|
116
126
|
- User: `~/.gemini/settings.json`
|
|
117
127
|
- Project: `.gemini/settings.json`
|
|
118
128
|
- System: Platform-dependent
|
|
119
|
-
|
|
120
|
-
## Architecture
|
|
121
|
-
|
|
122
|
-
The project follows SOLID principles:
|
|
123
|
-
|
|
124
|
-
- **Single Responsibility**: Each adapter handles one tool
|
|
125
|
-
- **Open/Closed**: Easy to add new tools without modifying existing code
|
|
126
|
-
- **Liskov Substitution**: All adapters implement the same interface
|
|
127
|
-
- **Interface Segregation**: Clean, focused interfaces
|
|
128
|
-
- **Dependency Inversion**: Commands depend on abstractions, not implementations
|
|
129
|
-
|
|
130
|
-
### Directory Structure
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
xling/
|
|
134
|
-
|- bin/ # CLI entry point (compiled)
|
|
135
|
-
| |- run.js
|
|
136
|
-
|- src/
|
|
137
|
-
| |- commands/ # oclif commands
|
|
138
|
-
| | |- git/ # Git workflow commands
|
|
139
|
-
| | |- settings/ # Settings management commands
|
|
140
|
-
| | |- x/ # Quick launcher
|
|
141
|
-
| |- domain/ # Types and interfaces
|
|
142
|
-
| |- services/ # Business logic
|
|
143
|
-
| | |- git/ # Git services (pr, worktree, view)
|
|
144
|
-
| | |- settings/
|
|
145
|
-
| | |- adapters/ # Tool adapters
|
|
146
|
-
| | |- fsStore.ts # File system operations
|
|
147
|
-
| | |- dispatcher.ts
|
|
148
|
-
| |- utils/ # Utilities
|
|
149
|
-
|- test/ # Tests and fixtures
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Development
|
|
153
|
-
|
|
154
|
-
```bash
|
|
155
|
-
# Install dependencies
|
|
156
|
-
bun install
|
|
157
|
-
|
|
158
|
-
# Build (using tsdown)
|
|
159
|
-
bun run build
|
|
160
|
-
|
|
161
|
-
# Watch mode (tsdown --watch)
|
|
162
|
-
bun run dev
|
|
163
|
-
|
|
164
|
-
# Code quality
|
|
165
|
-
bun run lint # Lint with oxlint
|
|
166
|
-
bun run lint:fix # Auto-fix lint issues
|
|
167
|
-
bun run format # Format with oxfmt
|
|
168
|
-
bun run format:check # Check formatting
|
|
169
|
-
bun run typecheck # Type check with tsc
|
|
170
|
-
|
|
171
|
-
# Run tests
|
|
172
|
-
bun test
|
|
173
|
-
bun test:watch
|
|
174
|
-
bun test:coverage
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Toolchain
|
|
178
|
-
|
|
179
|
-
**Build System**
|
|
180
|
-
|
|
181
|
-
This project uses [tsdown](https://tsdown.vercel.app/) for fast TypeScript compilation and bundling:
|
|
182
|
-
|
|
183
|
-
- **Fast builds**: Powered by rolldown (Rust-based bundler)
|
|
184
|
-
- **ESM output**: Generates `.js` files for modern Node.js
|
|
185
|
-
- **Type definitions**: Automatically generates `.d.ts` files
|
|
186
|
-
- **Source maps**: Includes source maps for debugging
|
|
187
|
-
- **Tree shaking**: Optimized bundle size
|
|
188
|
-
|
|
189
|
-
**Code Quality**
|
|
190
|
-
|
|
191
|
-
- **Linting**: [oxlint](https://oxc.rs/) - Rust-based linter, 50-100x faster than ESLint
|
|
192
|
-
- **Formatting**: [oxfmt](https://oxc.rs/) - Fast formatter compatible with Prettier config
|
|
193
|
-
- **Type Checking**: TypeScript compiler for strict type safety
|
|
194
|
-
|
|
195
|
-
## Testing
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
# Run all tests
|
|
199
|
-
bun test
|
|
200
|
-
|
|
201
|
-
# Run with coverage
|
|
202
|
-
bun test:coverage
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Contributing
|
|
206
|
-
|
|
207
|
-
1. Fork the repository
|
|
208
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
209
|
-
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
210
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
211
|
-
5. Open a Pull Request
|
|
212
|
-
|
|
213
|
-
## License
|
|
214
|
-
|
|
215
|
-
Apache-2.0
|
|
216
|
-
|
|
217
|
-
## Author
|
|
218
|
-
|
|
219
|
-
Kingsword <kingsword09@gmail.com>
|
|
@@ -6,7 +6,7 @@ import { n as SettingsAdapter } from "./interfaces-Cy1OFHgI.js";
|
|
|
6
6
|
/**
|
|
7
7
|
* Abstract adapter implementation
|
|
8
8
|
*/
|
|
9
|
-
declare abstract class BaseAdapter implements SettingsAdapter {
|
|
9
|
+
declare abstract class BaseAdapter<TConfig = ConfigObject> implements SettingsAdapter {
|
|
10
10
|
abstract readonly toolId: ToolId;
|
|
11
11
|
/**
|
|
12
12
|
* Methods every adapter must implement
|
|
@@ -32,11 +32,11 @@ declare abstract class BaseAdapter implements SettingsAdapter {
|
|
|
32
32
|
/**
|
|
33
33
|
* Read the configuration file (subclasses may override)
|
|
34
34
|
*/
|
|
35
|
-
protected readConfig(path: string):
|
|
35
|
+
protected readConfig(path: string): TConfig;
|
|
36
36
|
/**
|
|
37
37
|
* Write the configuration file (subclasses may override)
|
|
38
38
|
*/
|
|
39
|
-
protected writeConfig(path: string, data:
|
|
39
|
+
protected writeConfig(path: string, data: TConfig, backup?: boolean): void;
|
|
40
40
|
}
|
|
41
41
|
//#endregion
|
|
42
42
|
export { BaseAdapter as t };
|
|
@@ -27,20 +27,20 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
27
27
|
const activePath = resolveHome(this.resolvePath(scope));
|
|
28
28
|
const directory = path.dirname(activePath);
|
|
29
29
|
const activeFilename = path.basename(activePath);
|
|
30
|
-
const files = [this
|
|
30
|
+
const files = [this.#buildEntry(activePath, scope, true)];
|
|
31
31
|
if (fs.existsSync(directory)) {
|
|
32
32
|
const entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
33
33
|
for (const entry of entries) {
|
|
34
34
|
if (!entry.isFile()) continue;
|
|
35
35
|
if (entry.name === activeFilename) continue;
|
|
36
|
-
if (!this
|
|
36
|
+
if (!this.#isSettingsFile(entry.name)) continue;
|
|
37
37
|
const entryPath = path.join(directory, entry.name);
|
|
38
|
-
files.push(this
|
|
38
|
+
files.push(this.#buildEntry(entryPath, scope, false));
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
return {
|
|
42
42
|
type: "files",
|
|
43
|
-
files: this
|
|
43
|
+
files: this.#sortFiles(files)
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
@@ -73,7 +73,7 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
73
73
|
if (!variant) throw new Error("Variant name cannot be empty");
|
|
74
74
|
const targetPath = resolveHome(this.resolvePath(scope));
|
|
75
75
|
const directory = path.dirname(targetPath);
|
|
76
|
-
const sourcePath = this
|
|
76
|
+
const sourcePath = this.#findVariantPath(directory, variant, targetPath);
|
|
77
77
|
if (!sourcePath) throw new SettingsVariantNotFoundError(variant);
|
|
78
78
|
const nextConfig = this.readConfig(sourcePath);
|
|
79
79
|
let currentConfig = {};
|
|
@@ -122,18 +122,18 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
122
122
|
let targetPath = basePath;
|
|
123
123
|
let label = "default";
|
|
124
124
|
if (variantName && variantName !== "" && variantName !== "default") {
|
|
125
|
-
const existingPath = this
|
|
125
|
+
const existingPath = this.#findVariantPath(directory, variantName, basePath);
|
|
126
126
|
if (existingPath) targetPath = existingPath;
|
|
127
127
|
else {
|
|
128
128
|
targetPath = path.join(directory, `settings.${variantName}.json`);
|
|
129
129
|
if (!fs.existsSync(targetPath)) {
|
|
130
|
-
const seed = this
|
|
130
|
+
const seed = this.#buildSeedConfig(basePath);
|
|
131
131
|
writeJSON(targetPath, seed, false);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
label = variantName;
|
|
135
135
|
} else if (!fs.existsSync(targetPath)) {
|
|
136
|
-
const seed = this
|
|
136
|
+
const seed = this.#buildSeedConfig(basePath);
|
|
137
137
|
writeJSON(targetPath, seed, false);
|
|
138
138
|
}
|
|
139
139
|
await openInEditor(resolvedEditor, targetPath);
|
|
@@ -147,11 +147,11 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
147
147
|
}
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
-
buildEntry(filePath, scope, active) {
|
|
150
|
+
#buildEntry(filePath, scope, active) {
|
|
151
151
|
const info = getFileInfo(filePath);
|
|
152
152
|
return {
|
|
153
153
|
filename: path.basename(filePath),
|
|
154
|
-
variant: this
|
|
154
|
+
variant: this.#extractVariant(filePath),
|
|
155
155
|
path: filePath,
|
|
156
156
|
scope,
|
|
157
157
|
active,
|
|
@@ -160,13 +160,13 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
160
160
|
lastModified: info?.lastModified
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
|
-
extractVariant(filePath) {
|
|
163
|
+
#extractVariant(filePath) {
|
|
164
164
|
const filename = path.basename(filePath);
|
|
165
165
|
const match = filename.match(/^settings(?:[._-](.+))?\.json$/);
|
|
166
166
|
if (!match) return filename.replace(/\.json$/, "");
|
|
167
167
|
return match[1] ?? "default";
|
|
168
168
|
}
|
|
169
|
-
buildSeedConfig(basePath) {
|
|
169
|
+
#buildSeedConfig(basePath) {
|
|
170
170
|
try {
|
|
171
171
|
if (fs.existsSync(basePath)) {
|
|
172
172
|
const content = fs.readFileSync(basePath, "utf-8");
|
|
@@ -175,17 +175,17 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
175
175
|
} catch {}
|
|
176
176
|
return { ...CLAUDE_SETTINGS_TEMPLATE };
|
|
177
177
|
}
|
|
178
|
-
isSettingsFile(filename) {
|
|
178
|
+
#isSettingsFile(filename) {
|
|
179
179
|
return /^settings[._-].+\.json$/.test(filename);
|
|
180
180
|
}
|
|
181
|
-
sortFiles(files) {
|
|
181
|
+
#sortFiles(files) {
|
|
182
182
|
return files.sort((a, b) => {
|
|
183
183
|
if (a.active && !b.active) return -1;
|
|
184
184
|
if (!a.active && b.active) return 1;
|
|
185
185
|
return a.variant.localeCompare(b.variant);
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
|
-
findVariantPath(directory, profile, defaultPath) {
|
|
188
|
+
#findVariantPath(directory, profile, defaultPath) {
|
|
189
189
|
const candidates = [];
|
|
190
190
|
const pushCandidate = (value) => {
|
|
191
191
|
if (!candidates.includes(value)) candidates.push(value);
|
|
@@ -10,11 +10,11 @@ import { generateText, streamText } from "ai";
|
|
|
10
10
|
* Client for a single provider using AI SDK
|
|
11
11
|
*/
|
|
12
12
|
var PromptClient = class {
|
|
13
|
-
provider;
|
|
14
|
-
config;
|
|
13
|
+
#provider;
|
|
14
|
+
#config;
|
|
15
15
|
constructor(config) {
|
|
16
|
-
this
|
|
17
|
-
this
|
|
16
|
+
this.#config = config;
|
|
17
|
+
this.#provider = createOpenAICompatible({
|
|
18
18
|
name: config.name,
|
|
19
19
|
baseURL: config.baseUrl,
|
|
20
20
|
apiKey: config.apiKey,
|
|
@@ -24,7 +24,7 @@ var PromptClient = class {
|
|
|
24
24
|
/**
|
|
25
25
|
* Convert AI SDK v2 usage to our internal format
|
|
26
26
|
*/
|
|
27
|
-
convertUsage(usage) {
|
|
27
|
+
#convertUsage(usage) {
|
|
28
28
|
if (!usage) return;
|
|
29
29
|
return {
|
|
30
30
|
promptTokens: usage.inputTokens ?? 0,
|
|
@@ -37,7 +37,7 @@ var PromptClient = class {
|
|
|
37
37
|
*/
|
|
38
38
|
async generate(request) {
|
|
39
39
|
const baseParams = {
|
|
40
|
-
model: this
|
|
40
|
+
model: this.#provider(request.model || ""),
|
|
41
41
|
temperature: request.temperature,
|
|
42
42
|
maxOutputTokens: request.maxTokens,
|
|
43
43
|
maxRetries: 2,
|
|
@@ -54,8 +54,8 @@ var PromptClient = class {
|
|
|
54
54
|
return {
|
|
55
55
|
content: result.text,
|
|
56
56
|
model: request.model || "",
|
|
57
|
-
provider: this
|
|
58
|
-
usage: this
|
|
57
|
+
provider: this.#config.name,
|
|
58
|
+
usage: this.#convertUsage(result.usage),
|
|
59
59
|
finishReason: result.finishReason
|
|
60
60
|
};
|
|
61
61
|
}
|
|
@@ -64,7 +64,7 @@ var PromptClient = class {
|
|
|
64
64
|
*/
|
|
65
65
|
async stream(request) {
|
|
66
66
|
const baseParams = {
|
|
67
|
-
model: this
|
|
67
|
+
model: this.#provider(request.model || ""),
|
|
68
68
|
temperature: request.temperature,
|
|
69
69
|
maxOutputTokens: request.maxTokens,
|
|
70
70
|
maxRetries: 2,
|
|
@@ -80,7 +80,7 @@ var PromptClient = class {
|
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
getProviderName() {
|
|
83
|
-
return this
|
|
83
|
+
return this.#config.name;
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
|
|
@@ -17,7 +17,7 @@ var CodexAdapter = class extends BaseAdapter {
|
|
|
17
17
|
const config = this.readConfig(path);
|
|
18
18
|
return {
|
|
19
19
|
type: "entries",
|
|
20
|
-
entries: this
|
|
20
|
+
entries: this.#extractProviders(config),
|
|
21
21
|
filePath: path
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -71,7 +71,7 @@ var CodexAdapter = class extends BaseAdapter {
|
|
|
71
71
|
writeConfig(path, data) {
|
|
72
72
|
writeTOML(path, data);
|
|
73
73
|
}
|
|
74
|
-
extractProviders(config) {
|
|
74
|
+
#extractProviders(config) {
|
|
75
75
|
const providers = config.model_providers;
|
|
76
76
|
if (isConfigObject(providers)) return providers;
|
|
77
77
|
return {};
|
|
@@ -3,13 +3,12 @@ import { Command, Interfaces } from "@oclif/core";
|
|
|
3
3
|
//#region src/commands/git/wts.d.ts
|
|
4
4
|
|
|
5
5
|
declare class Wts extends Command {
|
|
6
|
+
#private;
|
|
6
7
|
static summary: string;
|
|
7
8
|
static description: string;
|
|
8
9
|
static examples: Command.Example[];
|
|
9
10
|
static flags: Interfaces.FlagInput;
|
|
10
11
|
run(): Promise<void>;
|
|
11
|
-
private resolveShell;
|
|
12
|
-
private openShell;
|
|
13
12
|
}
|
|
14
13
|
//#endregion
|
|
15
14
|
export { Wts as default };
|
package/dist/commands/git/wts.js
CHANGED
|
@@ -65,12 +65,12 @@ var Wts = class Wts extends Command {
|
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
67
|
this.log(`Switching to worktree at ${targetPath}. Exit the shell to return.`);
|
|
68
|
-
await this
|
|
68
|
+
await this.#openShell(targetPath);
|
|
69
69
|
} catch (error) {
|
|
70
70
|
this.error(error.message, { exit: 1 });
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
resolveShell() {
|
|
73
|
+
#resolveShell() {
|
|
74
74
|
if (process.platform === "win32") return {
|
|
75
75
|
command: process.env.COMSPEC || "cmd.exe",
|
|
76
76
|
args: []
|
|
@@ -80,8 +80,8 @@ var Wts = class Wts extends Command {
|
|
|
80
80
|
args: []
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
async openShell(cwd) {
|
|
84
|
-
const { command, args } = this
|
|
83
|
+
async #openShell(cwd) {
|
|
84
|
+
const { command, args } = this.#resolveShell();
|
|
85
85
|
await new Promise((resolve, reject) => {
|
|
86
86
|
const child = spawn(command, args, {
|
|
87
87
|
cwd,
|
|
@@ -3,37 +3,12 @@ import { Command, Interfaces } from "@oclif/core";
|
|
|
3
3
|
//#region src/commands/p/index.d.ts
|
|
4
4
|
|
|
5
5
|
declare class PCommand extends Command {
|
|
6
|
+
#private;
|
|
6
7
|
static description: string;
|
|
7
8
|
static examples: Command.Example[];
|
|
8
9
|
static flags: Interfaces.FlagInput;
|
|
9
10
|
static args: Interfaces.ArgInput;
|
|
10
11
|
run(): Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Determine if should enter interactive mode
|
|
13
|
-
*/
|
|
14
|
-
private shouldEnterInteractive;
|
|
15
|
-
/**
|
|
16
|
-
* Ask user if they want to continue conversation
|
|
17
|
-
* Uses /dev/tty to read from terminal even when stdin is piped
|
|
18
|
-
*/
|
|
19
|
-
private askContinueConversation;
|
|
20
|
-
/**
|
|
21
|
-
* Enter interactive REPL mode
|
|
22
|
-
* Uses /dev/tty for proper terminal behavior when stdin is piped
|
|
23
|
-
*/
|
|
24
|
-
private enterInteractiveMode;
|
|
25
|
-
/**
|
|
26
|
-
* Display streaming output and return full text
|
|
27
|
-
*/
|
|
28
|
-
private displayStream;
|
|
29
|
-
/**
|
|
30
|
-
* Build prompt from various sources
|
|
31
|
-
*/
|
|
32
|
-
private buildPrompt;
|
|
33
|
-
/**
|
|
34
|
-
* Read from stdin
|
|
35
|
-
*/
|
|
36
|
-
private readStdin;
|
|
37
12
|
}
|
|
38
13
|
//#endregion
|
|
39
14
|
export { PCommand as default };
|
package/dist/commands/p/index.js
CHANGED
|
@@ -2,13 +2,13 @@ import "../../errors-pXKbCKbL.js";
|
|
|
2
2
|
import "../../editor-CUiekAEb.js";
|
|
3
3
|
import "../../fsStore-S8RslR8L.js";
|
|
4
4
|
import "../../base-DtcPVpvU.js";
|
|
5
|
-
import "../../config-
|
|
6
|
-
import "../../template-
|
|
7
|
-
import { t as XlingAdapter } from "../../xling-
|
|
8
|
-
import "../../providerRegistry-
|
|
9
|
-
import "../../client-
|
|
5
|
+
import "../../config-JHw2hqMN.js";
|
|
6
|
+
import "../../template-B19CdPfg.js";
|
|
7
|
+
import { t as XlingAdapter } from "../../xling-BxVsmPja.js";
|
|
8
|
+
import "../../providerRegistry-Cljln1eo.js";
|
|
9
|
+
import "../../client-DTC49Rug.js";
|
|
10
10
|
import { n as ModelNotSupportedError, t as AllProvidersFailedError } from "../../types-99-EmVXg.js";
|
|
11
|
-
import { n as createRouter } from "../../router-
|
|
11
|
+
import { n as createRouter } from "../../router-DX-dIEei.js";
|
|
12
12
|
import { Args, Command, Flags } from "@oclif/core";
|
|
13
13
|
import * as fs from "fs";
|
|
14
14
|
import * as readline from "readline";
|
|
@@ -106,7 +106,7 @@ var PCommand = class PCommand extends Command {
|
|
|
106
106
|
try {
|
|
107
107
|
const configPath = new XlingAdapter().resolvePath("user");
|
|
108
108
|
if (!fs.existsSync(configPath.replace("~", process.env.HOME || ""))) this.error(`Configuration not found at ${configPath}\n\nPlease create a configuration file with at least one provider.\nExample:\n{\n "prompt": {\n "providers": [\n {\n "name": "openai",\n "baseUrl": "https://api.openai.com/v1",\n "apiKey": "sk-...",\n "models": ["gpt-4", "gpt-4-turbo"]\n }\n ],\n "defaultModel": "gpt-4"\n }\n}`);
|
|
109
|
-
const prompt = await this
|
|
109
|
+
const prompt = await this.#buildPrompt(args, flags);
|
|
110
110
|
if (!prompt.trim()) this.error("No prompt provided. Use argument, --prompt, --file, or --stdin");
|
|
111
111
|
const request = {
|
|
112
112
|
prompt,
|
|
@@ -122,7 +122,7 @@ var PCommand = class PCommand extends Command {
|
|
|
122
122
|
let providerInfo;
|
|
123
123
|
if (flags.stream && !flags.json) {
|
|
124
124
|
const streamResult = await router.executeStream(request);
|
|
125
|
-
firstResponse = await this
|
|
125
|
+
firstResponse = await this.#displayStream(streamResult);
|
|
126
126
|
const finalResult = await streamResult.usage;
|
|
127
127
|
usage = finalResult ? {
|
|
128
128
|
promptTokens: finalResult.inputTokens ?? 0,
|
|
@@ -145,10 +145,10 @@ var PCommand = class PCommand extends Command {
|
|
|
145
145
|
else this.log(result.content);
|
|
146
146
|
}
|
|
147
147
|
if (!flags.json && usage && providerInfo) this.log(`\n[${providerInfo.provider}/${providerInfo.model}] ${usage.totalTokens} tokens (${usage.promptTokens} prompt + ${usage.completionTokens} completion)`);
|
|
148
|
-
const shouldInteract = this
|
|
148
|
+
const shouldInteract = this.#shouldEnterInteractive(flags);
|
|
149
149
|
let willEnterInteractive = shouldInteract;
|
|
150
|
-
if (!shouldInteract && !flags.json && process.stdout.isTTY) willEnterInteractive = await this
|
|
151
|
-
if (willEnterInteractive) await this
|
|
150
|
+
if (!shouldInteract && !flags.json && process.stdout.isTTY) willEnterInteractive = await this.#askContinueConversation();
|
|
151
|
+
if (willEnterInteractive) await this.#enterInteractiveMode(prompt, firstResponse, flags, router);
|
|
152
152
|
} catch (error) {
|
|
153
153
|
if (error instanceof ModelNotSupportedError) this.error(error.message);
|
|
154
154
|
else if (error instanceof AllProvidersFailedError) this.error(`All providers failed:\n${error.errors.map((e) => ` ${e.provider}: ${e.error.message}`).join("\n")}`);
|
|
@@ -158,7 +158,7 @@ var PCommand = class PCommand extends Command {
|
|
|
158
158
|
/**
|
|
159
159
|
* Determine if should enter interactive mode
|
|
160
160
|
*/
|
|
161
|
-
shouldEnterInteractive(flags) {
|
|
161
|
+
#shouldEnterInteractive(flags) {
|
|
162
162
|
if (flags.interactive) return true;
|
|
163
163
|
if (process.stdout.isTTY && process.stdin.isTTY) return false;
|
|
164
164
|
return false;
|
|
@@ -167,7 +167,7 @@ var PCommand = class PCommand extends Command {
|
|
|
167
167
|
* Ask user if they want to continue conversation
|
|
168
168
|
* Uses /dev/tty to read from terminal even when stdin is piped
|
|
169
169
|
*/
|
|
170
|
-
async askContinueConversation() {
|
|
170
|
+
async #askContinueConversation() {
|
|
171
171
|
return new Promise((resolve) => {
|
|
172
172
|
let answered = false;
|
|
173
173
|
try {
|
|
@@ -180,12 +180,14 @@ var PCommand = class PCommand extends Command {
|
|
|
180
180
|
});
|
|
181
181
|
rl.question("\nContinue conversation? (y/N): ", (answer) => {
|
|
182
182
|
answered = true;
|
|
183
|
+
const normalized = answer.trim().toLowerCase();
|
|
184
|
+
const shouldContinue = normalized === "y" || normalized === "yes";
|
|
185
|
+
if (!shouldContinue) (ttyWriteStream ?? process.stdout).write("\nOkay, not continuing the conversation.\n");
|
|
183
186
|
rl.close();
|
|
184
187
|
ttyReadStream.destroy();
|
|
185
188
|
ttyWriteStream.destroy();
|
|
186
189
|
fs.closeSync(ttyFd);
|
|
187
|
-
|
|
188
|
-
resolve(normalized === "y" || normalized === "yes");
|
|
190
|
+
resolve(shouldContinue);
|
|
189
191
|
});
|
|
190
192
|
setTimeout(() => {
|
|
191
193
|
if (!answered) {
|
|
@@ -193,11 +195,12 @@ var PCommand = class PCommand extends Command {
|
|
|
193
195
|
ttyReadStream.destroy();
|
|
194
196
|
ttyWriteStream.destroy();
|
|
195
197
|
fs.closeSync(ttyFd);
|
|
196
|
-
process.stdout.write("\n");
|
|
198
|
+
process.stdout.write("\nNo response received. Ending conversation prompt.\n");
|
|
197
199
|
resolve(false);
|
|
198
200
|
}
|
|
199
201
|
}, 1e4);
|
|
200
202
|
} catch {
|
|
203
|
+
this.log("Skipping interactive follow-up (TTY not available).");
|
|
201
204
|
resolve(false);
|
|
202
205
|
}
|
|
203
206
|
});
|
|
@@ -206,7 +209,7 @@ var PCommand = class PCommand extends Command {
|
|
|
206
209
|
* Enter interactive REPL mode
|
|
207
210
|
* Uses /dev/tty for proper terminal behavior when stdin is piped
|
|
208
211
|
*/
|
|
209
|
-
async enterInteractiveMode(initialPrompt, initialResponse, flags, router) {
|
|
212
|
+
async #enterInteractiveMode(initialPrompt, initialResponse, flags, router) {
|
|
210
213
|
const messages = [];
|
|
211
214
|
if (flags.system) messages.push({
|
|
212
215
|
role: "system",
|
|
@@ -293,7 +296,7 @@ var PCommand = class PCommand extends Command {
|
|
|
293
296
|
stream: true
|
|
294
297
|
};
|
|
295
298
|
const streamResult = await router.executeStream(request);
|
|
296
|
-
const responseText = await this
|
|
299
|
+
const responseText = await this.#displayStream(streamResult, outputStream);
|
|
297
300
|
messages.push({
|
|
298
301
|
role: "assistant",
|
|
299
302
|
content: responseText
|
|
@@ -326,7 +329,7 @@ var PCommand = class PCommand extends Command {
|
|
|
326
329
|
/**
|
|
327
330
|
* Display streaming output and return full text
|
|
328
331
|
*/
|
|
329
|
-
async displayStream(streamResult, outputStream = process.stdout) {
|
|
332
|
+
async #displayStream(streamResult, outputStream = process.stdout) {
|
|
330
333
|
let fullText = "";
|
|
331
334
|
outputStream.write("\n");
|
|
332
335
|
for await (const chunk of streamResult.textStream) {
|
|
@@ -340,7 +343,7 @@ var PCommand = class PCommand extends Command {
|
|
|
340
343
|
/**
|
|
341
344
|
* Build prompt from various sources
|
|
342
345
|
*/
|
|
343
|
-
async buildPrompt(args, flags) {
|
|
346
|
+
async #buildPrompt(args, flags) {
|
|
344
347
|
const parts = [];
|
|
345
348
|
if (args.prompt) parts.push(args.prompt);
|
|
346
349
|
if (flags.prompt) parts.push(flags.prompt);
|
|
@@ -351,7 +354,7 @@ var PCommand = class PCommand extends Command {
|
|
|
351
354
|
this.warn(`Failed to read file ${file}: ${error.message}`);
|
|
352
355
|
}
|
|
353
356
|
if (flags.stdin) {
|
|
354
|
-
const stdin = await this
|
|
357
|
+
const stdin = await this.#readStdin();
|
|
355
358
|
if (stdin) parts.push(stdin);
|
|
356
359
|
}
|
|
357
360
|
return parts.join("\n").trim();
|
|
@@ -359,7 +362,7 @@ var PCommand = class PCommand extends Command {
|
|
|
359
362
|
/**
|
|
360
363
|
* Read from stdin
|
|
361
364
|
*/
|
|
362
|
-
async readStdin() {
|
|
365
|
+
async #readStdin() {
|
|
363
366
|
return new Promise((resolve) => {
|
|
364
367
|
const chunks = [];
|
|
365
368
|
process.stdin.setEncoding("utf-8");
|
|
@@ -2,15 +2,13 @@ import { Command, Interfaces } from "@oclif/core";
|
|
|
2
2
|
|
|
3
3
|
//#region src/commands/settings/get.d.ts
|
|
4
4
|
declare class SettingsGet extends Command {
|
|
5
|
+
#private;
|
|
5
6
|
static summary: string;
|
|
6
7
|
static description: string;
|
|
7
8
|
static examples: Command.Example[];
|
|
8
9
|
static args: Interfaces.ArgInput;
|
|
9
10
|
static flags: Interfaces.FlagInput;
|
|
10
11
|
run(): Promise<void>;
|
|
11
|
-
private inspectViaDispatcher;
|
|
12
|
-
private inspectClaudeVariant;
|
|
13
|
-
private findVariantPath;
|
|
14
12
|
}
|
|
15
13
|
//#endregion
|
|
16
14
|
export { SettingsGet as default };
|
|
@@ -3,14 +3,14 @@ import "../../editor-CUiekAEb.js";
|
|
|
3
3
|
import { r as formatJson } from "../../format-a_tYXjv9.js";
|
|
4
4
|
import { s as resolveHome } from "../../fsStore-S8RslR8L.js";
|
|
5
5
|
import "../../base-DtcPVpvU.js";
|
|
6
|
-
import "../../config-
|
|
7
|
-
import "../../template-
|
|
8
|
-
import "../../xling-
|
|
6
|
+
import "../../config-JHw2hqMN.js";
|
|
7
|
+
import "../../template-B19CdPfg.js";
|
|
8
|
+
import "../../xling-BxVsmPja.js";
|
|
9
9
|
import "../../claudeDefault-ewrEKzlX.js";
|
|
10
|
-
import { t as ClaudeAdapter } from "../../claude-
|
|
11
|
-
import "../../codex-
|
|
12
|
-
import "../../gemini-
|
|
13
|
-
import { t as SettingsDispatcher } from "../../dispatcher-
|
|
10
|
+
import { t as ClaudeAdapter } from "../../claude-C6lOG2Mk.js";
|
|
11
|
+
import "../../codex-Dl7Rx7Nr.js";
|
|
12
|
+
import "../../gemini-DQoPiuiw.js";
|
|
13
|
+
import { t as SettingsDispatcher } from "../../dispatcher-BYazaYbC.js";
|
|
14
14
|
import { Args, Command, Flags } from "@oclif/core";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import fs from "node:fs";
|
|
@@ -60,7 +60,7 @@ var SettingsGet = class SettingsGet extends Command {
|
|
|
60
60
|
try {
|
|
61
61
|
const tool = flags.tool;
|
|
62
62
|
const scope = flags.scope;
|
|
63
|
-
const data = tool === "claude" && args.name ? await this
|
|
63
|
+
const data = tool === "claude" && args.name ? await this.#inspectClaudeVariant(scope, args.name) : await this.#inspectViaDispatcher(tool, scope);
|
|
64
64
|
if (flags.json) {
|
|
65
65
|
this.log(formatJson({
|
|
66
66
|
success: true,
|
|
@@ -78,22 +78,22 @@ var SettingsGet = class SettingsGet extends Command {
|
|
|
78
78
|
this.error(error.message, { exit: 1 });
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
async inspectViaDispatcher(tool, scope) {
|
|
81
|
+
async #inspectViaDispatcher(tool, scope) {
|
|
82
82
|
return (await new SettingsDispatcher().execute({
|
|
83
83
|
tool,
|
|
84
84
|
scope,
|
|
85
85
|
action: "inspect"
|
|
86
86
|
})).data;
|
|
87
87
|
}
|
|
88
|
-
async inspectClaudeVariant(scope, name) {
|
|
88
|
+
async #inspectClaudeVariant(scope, name) {
|
|
89
89
|
const adapter = new ClaudeAdapter();
|
|
90
90
|
if (!adapter.validateScope(scope)) throw new Error(`Invalid scope for Claude: ${scope}`);
|
|
91
91
|
const normalized = name.trim();
|
|
92
|
-
if (!normalized || normalized === "default") return this
|
|
92
|
+
if (!normalized || normalized === "default") return this.#inspectViaDispatcher("claude", scope);
|
|
93
93
|
const basePath = adapter.resolvePath(scope);
|
|
94
94
|
const resolvedBase = resolveHome(basePath);
|
|
95
95
|
const directory = path.dirname(resolvedBase);
|
|
96
|
-
const variantPath = this
|
|
96
|
+
const variantPath = this.#findVariantPath(directory, normalized) ?? path.join(directory, `settings.${normalized}.json`);
|
|
97
97
|
if (!fs.existsSync(variantPath)) return {
|
|
98
98
|
path: variantPath,
|
|
99
99
|
exists: false
|
|
@@ -107,7 +107,7 @@ var SettingsGet = class SettingsGet extends Command {
|
|
|
107
107
|
lastModified: stats.mtime
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
|
-
findVariantPath(directory, name) {
|
|
110
|
+
#findVariantPath(directory, name) {
|
|
111
111
|
const candidates = [`settings.${name}.json`, `settings-${name}.json`];
|
|
112
112
|
for (const candidate of candidates) {
|
|
113
113
|
const fullPath = path.join(directory, candidate);
|
|
@@ -3,14 +3,14 @@ import "../../editor-CUiekAEb.js";
|
|
|
3
3
|
import { r as formatJson } from "../../format-a_tYXjv9.js";
|
|
4
4
|
import "../../fsStore-S8RslR8L.js";
|
|
5
5
|
import "../../base-DtcPVpvU.js";
|
|
6
|
-
import "../../config-
|
|
7
|
-
import "../../template-
|
|
8
|
-
import "../../xling-
|
|
6
|
+
import "../../config-JHw2hqMN.js";
|
|
7
|
+
import "../../template-B19CdPfg.js";
|
|
8
|
+
import "../../xling-BxVsmPja.js";
|
|
9
9
|
import "../../claudeDefault-ewrEKzlX.js";
|
|
10
|
-
import "../../claude-
|
|
11
|
-
import "../../codex-
|
|
12
|
-
import "../../gemini-
|
|
13
|
-
import { t as SettingsDispatcher } from "../../dispatcher-
|
|
10
|
+
import "../../claude-C6lOG2Mk.js";
|
|
11
|
+
import "../../codex-Dl7Rx7Nr.js";
|
|
12
|
+
import "../../gemini-DQoPiuiw.js";
|
|
13
|
+
import { t as SettingsDispatcher } from "../../dispatcher-BYazaYbC.js";
|
|
14
14
|
import { Command, Flags } from "@oclif/core";
|
|
15
15
|
|
|
16
16
|
//#region src/commands/settings/inspect.ts
|