@robota-sdk/agent-cli 3.0.0-beta.43 → 3.0.0-beta.45
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/dist/node/bin.js +1 -1
- package/dist/node/{chunk-SYGOHAAL.js → chunk-Y6VSMUKG.js} +328 -413
- package/dist/node/index.cjs +323 -410
- package/dist/node/index.d.cts +10 -23
- package/dist/node/index.d.ts +10 -23
- package/dist/node/index.js +1 -8
- package/package.json +4 -3
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
// src/cli.ts
|
|
2
|
-
import { readFileSync as
|
|
3
|
-
import { join as join5, dirname as
|
|
2
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
-
import {
|
|
6
|
-
loadConfig,
|
|
7
|
-
loadContext,
|
|
8
|
-
detectProject,
|
|
9
|
-
createSession,
|
|
10
|
-
SessionStore,
|
|
11
|
-
FileSessionLogger,
|
|
12
|
-
projectPaths
|
|
13
|
-
} from "@robota-sdk/agent-sdk";
|
|
14
|
-
import { promptForApproval } from "@robota-sdk/agent-sdk";
|
|
5
|
+
import { InteractiveSession as InteractiveSession2 } from "@robota-sdk/agent-sdk";
|
|
15
6
|
|
|
16
7
|
// src/utils/cli-args.ts
|
|
17
8
|
import { parseArgs } from "util";
|
|
@@ -94,56 +85,49 @@ function deleteSettings(path) {
|
|
|
94
85
|
return false;
|
|
95
86
|
}
|
|
96
87
|
|
|
97
|
-
// src/
|
|
98
|
-
import
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async select(options, initialIndex = 0) {
|
|
127
|
-
for (let i = 0; i < options.length; i++) {
|
|
128
|
-
const marker = i === initialIndex ? ">" : " ";
|
|
129
|
-
process.stdout.write(` ${marker} ${i + 1}) ${options[i]}
|
|
130
|
-
`);
|
|
88
|
+
// src/utils/provider-factory.ts
|
|
89
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
90
|
+
import { join as join2 } from "path";
|
|
91
|
+
import { homedir } from "os";
|
|
92
|
+
import { AnthropicProvider } from "@robota-sdk/agent-provider-anthropic";
|
|
93
|
+
function readProviderSettings(cwd) {
|
|
94
|
+
const paths = [
|
|
95
|
+
join2(cwd, ".robota", "settings.local.json"),
|
|
96
|
+
join2(cwd, ".robota", "settings.json"),
|
|
97
|
+
join2(cwd, ".claude", "settings.local.json"),
|
|
98
|
+
join2(cwd, ".claude", "settings.json"),
|
|
99
|
+
join2(homedir(), ".robota", "settings.json"),
|
|
100
|
+
join2(homedir(), ".claude", "settings.json")
|
|
101
|
+
];
|
|
102
|
+
for (const filePath of paths) {
|
|
103
|
+
if (!existsSync2(filePath)) continue;
|
|
104
|
+
try {
|
|
105
|
+
const raw = readFileSync2(filePath, "utf8");
|
|
106
|
+
const parsed = JSON.parse(raw);
|
|
107
|
+
const provider = parsed.provider;
|
|
108
|
+
if (provider?.apiKey && provider?.name) {
|
|
109
|
+
return {
|
|
110
|
+
name: provider.name,
|
|
111
|
+
model: provider.model ?? "claude-sonnet-4-6",
|
|
112
|
+
apiKey: provider.apiKey
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
continue;
|
|
131
117
|
}
|
|
132
|
-
const answer = await this.prompt(
|
|
133
|
-
` Choose [1-${options.length}] (default: ${options[initialIndex]}): `
|
|
134
|
-
);
|
|
135
|
-
const trimmed = answer.trim().toLowerCase();
|
|
136
|
-
if (trimmed === "") return initialIndex;
|
|
137
|
-
const num = parseInt(trimmed, 10);
|
|
138
|
-
if (!isNaN(num) && num >= 1 && num <= options.length) return num - 1;
|
|
139
|
-
return initialIndex;
|
|
140
118
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
119
|
+
throw new Error("No provider configuration found. Run `robota` to set up.");
|
|
120
|
+
}
|
|
121
|
+
function createProviderFromSettings(cwd, modelOverride) {
|
|
122
|
+
const settings = readProviderSettings(cwd);
|
|
123
|
+
const model = modelOverride ?? settings.model;
|
|
124
|
+
switch (settings.name) {
|
|
125
|
+
case "anthropic":
|
|
126
|
+
return new AnthropicProvider({ apiKey: settings.apiKey, defaultModel: model });
|
|
127
|
+
default:
|
|
128
|
+
throw new Error(`Unknown provider: ${settings.name}. Currently supported: anthropic`);
|
|
145
129
|
}
|
|
146
|
-
}
|
|
130
|
+
}
|
|
147
131
|
|
|
148
132
|
// src/ui/render.tsx
|
|
149
133
|
import { render } from "ink";
|
|
@@ -151,238 +135,148 @@ import { render } from "ink";
|
|
|
151
135
|
// src/ui/App.tsx
|
|
152
136
|
import { useState as useState9, useRef as useRef7 } from "react";
|
|
153
137
|
import { Box as Box11, Text as Text13, useApp, useInput as useInput7 } from "ink";
|
|
154
|
-
import { getModelName, createSystemMessage as createSystemMessage2 } from "@robota-sdk/agent-core";
|
|
138
|
+
import { getModelName, createSystemMessage as createSystemMessage2, messageToHistoryEntry as messageToHistoryEntry2 } from "@robota-sdk/agent-core";
|
|
155
139
|
|
|
156
140
|
// src/ui/hooks/useInteractiveSession.ts
|
|
157
141
|
import { useState, useRef, useCallback, useEffect } from "react";
|
|
158
|
-
import { homedir } from "os";
|
|
142
|
+
import { homedir as homedir2 } from "os";
|
|
159
143
|
import { join as join3 } from "path";
|
|
160
144
|
import {
|
|
161
145
|
InteractiveSession,
|
|
162
146
|
CommandRegistry,
|
|
163
147
|
BuiltinCommandSource,
|
|
164
148
|
SkillCommandSource,
|
|
165
|
-
|
|
166
|
-
BundlePluginLoader
|
|
149
|
+
PluginCommandSource,
|
|
150
|
+
BundlePluginLoader,
|
|
151
|
+
buildSkillPrompt
|
|
167
152
|
} from "@robota-sdk/agent-sdk";
|
|
168
|
-
import { createSystemMessage } from "@robota-sdk/agent-core";
|
|
169
|
-
|
|
170
|
-
// src/commands/plugin-source.ts
|
|
171
|
-
var PluginCommandSource = class {
|
|
172
|
-
name = "plugin";
|
|
173
|
-
plugins;
|
|
174
|
-
constructor(plugins) {
|
|
175
|
-
this.plugins = plugins;
|
|
176
|
-
}
|
|
177
|
-
getCommands() {
|
|
178
|
-
const commands = [];
|
|
179
|
-
for (const plugin of this.plugins) {
|
|
180
|
-
for (const skill of plugin.skills) {
|
|
181
|
-
const baseName = skill.name.includes("@") ? skill.name.split("@")[0] : skill.name;
|
|
182
|
-
commands.push({
|
|
183
|
-
name: baseName,
|
|
184
|
-
description: `(${plugin.manifest.name}) ${skill.description}`,
|
|
185
|
-
source: "plugin",
|
|
186
|
-
skillContent: skill.skillContent,
|
|
187
|
-
pluginDir: plugin.pluginDir
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
for (const cmd of plugin.commands) {
|
|
191
|
-
commands.push({
|
|
192
|
-
name: cmd.name,
|
|
193
|
-
description: cmd.description,
|
|
194
|
-
source: "plugin",
|
|
195
|
-
skillContent: cmd.skillContent,
|
|
196
|
-
pluginDir: plugin.pluginDir
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return commands;
|
|
201
|
-
}
|
|
202
|
-
};
|
|
153
|
+
import { createSystemMessage, messageToHistoryEntry } from "@robota-sdk/agent-core";
|
|
154
|
+
import { randomUUID } from "crypto";
|
|
203
155
|
|
|
204
|
-
// src/
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
156
|
+
// src/ui/tui-state-manager.ts
|
|
157
|
+
var MAX_RENDERED_MESSAGES = 100;
|
|
158
|
+
var TuiStateManager = class {
|
|
159
|
+
// ── Rendering state ───────────────────────────────────────────
|
|
160
|
+
history = [];
|
|
161
|
+
streamingText = "";
|
|
162
|
+
activeTools = [];
|
|
163
|
+
isThinking = false;
|
|
164
|
+
isAborting = false;
|
|
165
|
+
pendingPrompt = null;
|
|
166
|
+
contextState = { percentage: 0, usedTokens: 0, maxTokens: 0 };
|
|
167
|
+
/** Called after any state change. React hook sets this to trigger re-render. */
|
|
168
|
+
onChange = null;
|
|
169
|
+
// ── Internal ──────────────────────────────────────────────────
|
|
170
|
+
streamBuf = "";
|
|
171
|
+
notify() {
|
|
172
|
+
this.onChange?.();
|
|
173
|
+
}
|
|
174
|
+
// ── Event handlers (InteractiveSession → state) ───────────────
|
|
175
|
+
onTextDelta = (delta) => {
|
|
176
|
+
this.streamBuf += delta;
|
|
177
|
+
this.streamingText = this.streamBuf;
|
|
178
|
+
this.notify();
|
|
179
|
+
};
|
|
180
|
+
onToolStart = (state) => {
|
|
181
|
+
this.activeTools = [...this.activeTools, state];
|
|
182
|
+
this.notify();
|
|
183
|
+
};
|
|
184
|
+
onToolEnd = (state) => {
|
|
185
|
+
this.activeTools = this.activeTools.map(
|
|
186
|
+
(t) => t.toolName === state.toolName && t.isRunning ? state : t
|
|
187
|
+
);
|
|
188
|
+
this.notify();
|
|
189
|
+
};
|
|
190
|
+
onThinking = (thinking) => {
|
|
191
|
+
this.isThinking = thinking;
|
|
192
|
+
if (thinking) {
|
|
193
|
+
this.streamBuf = "";
|
|
194
|
+
this.streamingText = "";
|
|
195
|
+
this.activeTools = [];
|
|
196
|
+
} else {
|
|
197
|
+
this.isAborting = false;
|
|
242
198
|
}
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
return result;
|
|
246
|
-
}
|
|
247
|
-
async function buildSkillPrompt(input, registry, context) {
|
|
248
|
-
const parts = input.slice(1).split(/\s+/);
|
|
249
|
-
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
250
|
-
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
251
|
-
if (!skillCmd) return null;
|
|
252
|
-
const args = parts.slice(1).join(" ").trim();
|
|
253
|
-
const userInstruction = args || skillCmd.description;
|
|
254
|
-
if (skillCmd.skillContent) {
|
|
255
|
-
let processed = await preprocessShellCommands(skillCmd.skillContent);
|
|
256
|
-
processed = substituteVariables(processed, args, context);
|
|
257
|
-
return `<skill name="${cmd}">
|
|
258
|
-
${processed}
|
|
259
|
-
</skill>
|
|
260
|
-
|
|
261
|
-
Execute the "${cmd}" skill: ${userInstruction}`;
|
|
262
|
-
}
|
|
263
|
-
return `Use the "${cmd}" skill: ${userInstruction}`;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// src/ui/hooks/plugin-hooks-merger.ts
|
|
267
|
-
import { join as join2, dirname as dirname2 } from "path";
|
|
268
|
-
function buildPluginEnv(plugin) {
|
|
269
|
-
const dataDir = join2(dirname2(dirname2(plugin.pluginDir)), "data", plugin.manifest.name);
|
|
270
|
-
return {
|
|
271
|
-
CLAUDE_PLUGIN_ROOT: plugin.pluginDir,
|
|
272
|
-
CLAUDE_PLUGIN_PATH: plugin.pluginDir,
|
|
273
|
-
CLAUDE_PLUGIN_DATA: dataDir
|
|
199
|
+
this.notify();
|
|
274
200
|
};
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
...h,
|
|
284
|
-
command: h.command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, pluginDir)
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
return h;
|
|
288
|
-
})
|
|
201
|
+
onComplete = (result) => {
|
|
202
|
+
this.streamBuf = "";
|
|
203
|
+
this.streamingText = "";
|
|
204
|
+
this.activeTools = [];
|
|
205
|
+
this.contextState = {
|
|
206
|
+
percentage: result.contextState.usedPercentage,
|
|
207
|
+
usedTokens: result.contextState.usedTokens,
|
|
208
|
+
maxTokens: result.contextState.maxTokens
|
|
289
209
|
};
|
|
210
|
+
this.notify();
|
|
211
|
+
};
|
|
212
|
+
onInterrupted = () => {
|
|
213
|
+
this.streamBuf = "";
|
|
214
|
+
this.streamingText = "";
|
|
215
|
+
this.activeTools = [];
|
|
216
|
+
this.notify();
|
|
217
|
+
};
|
|
218
|
+
onError = () => {
|
|
219
|
+
this.streamBuf = "";
|
|
220
|
+
this.streamingText = "";
|
|
221
|
+
this.activeTools = [];
|
|
222
|
+
this.notify();
|
|
223
|
+
};
|
|
224
|
+
// ── State updates from external sources ───────────────────────
|
|
225
|
+
/** Sync history from InteractiveSession */
|
|
226
|
+
syncHistory(entries) {
|
|
227
|
+
if (entries.length === 0) return;
|
|
228
|
+
this.history = entries.length > MAX_RENDERED_MESSAGES ? entries.slice(-MAX_RENDERED_MESSAGES) : [...entries];
|
|
229
|
+
this.notify();
|
|
230
|
+
}
|
|
231
|
+
/** Add a single history entry */
|
|
232
|
+
addEntry(entry) {
|
|
233
|
+
const updated = [...this.history, entry];
|
|
234
|
+
this.history = updated.length > MAX_RENDERED_MESSAGES ? updated.slice(-MAX_RENDERED_MESSAGES) : updated;
|
|
235
|
+
this.notify();
|
|
236
|
+
}
|
|
237
|
+
/** Update pending prompt state */
|
|
238
|
+
setPendingPrompt(prompt) {
|
|
239
|
+
this.pendingPrompt = prompt;
|
|
240
|
+
this.notify();
|
|
241
|
+
}
|
|
242
|
+
/** Set aborting flag */
|
|
243
|
+
setAborting(aborting) {
|
|
244
|
+
this.isAborting = aborting;
|
|
245
|
+
this.notify();
|
|
246
|
+
}
|
|
247
|
+
/** Update context state */
|
|
248
|
+
setContextState(state) {
|
|
249
|
+
this.contextState = state;
|
|
250
|
+
this.notify();
|
|
290
251
|
}
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
function mergePluginHooks(plugins) {
|
|
294
|
-
const merged = {};
|
|
295
|
-
for (const plugin of plugins) {
|
|
296
|
-
const hooksObj = plugin.hooks;
|
|
297
|
-
if (!hooksObj) continue;
|
|
298
|
-
const pluginEnv = buildPluginEnv(plugin);
|
|
299
|
-
const innerHooks = hooksObj.hooks ?? hooksObj;
|
|
300
|
-
for (const [event, groups] of Object.entries(innerHooks)) {
|
|
301
|
-
if (!Array.isArray(groups)) continue;
|
|
302
|
-
if (!merged[event]) merged[event] = [];
|
|
303
|
-
const resolved = groups.map((group) => {
|
|
304
|
-
const r = resolvePluginRoot(group, plugin.pluginDir);
|
|
305
|
-
r.env = pluginEnv;
|
|
306
|
-
return r;
|
|
307
|
-
});
|
|
308
|
-
merged[event].push(...resolved);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
return merged;
|
|
312
|
-
}
|
|
313
|
-
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
314
|
-
const pluginKeys = Object.keys(pluginHooks);
|
|
315
|
-
if (pluginKeys.length === 0) return configHooks;
|
|
316
|
-
const merged = {};
|
|
317
|
-
for (const [event, groups] of Object.entries(pluginHooks)) {
|
|
318
|
-
merged[event] = [...groups];
|
|
319
|
-
}
|
|
320
|
-
if (configHooks) {
|
|
321
|
-
for (const [event, groups] of Object.entries(configHooks)) {
|
|
322
|
-
if (!Array.isArray(groups)) continue;
|
|
323
|
-
if (!merged[event]) merged[event] = [];
|
|
324
|
-
merged[event].push(...groups);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return merged;
|
|
328
|
-
}
|
|
252
|
+
};
|
|
329
253
|
|
|
330
254
|
// src/ui/hooks/useInteractiveSession.ts
|
|
331
|
-
var MAX_RENDERED_MESSAGES = 100;
|
|
332
255
|
function initializeSession(props, permissionHandler) {
|
|
333
|
-
const
|
|
256
|
+
const interactiveSession = new InteractiveSession({
|
|
257
|
+
cwd: props.cwd,
|
|
258
|
+
provider: props.provider,
|
|
259
|
+
permissionMode: props.permissionMode,
|
|
260
|
+
maxTurns: props.maxTurns,
|
|
261
|
+
permissionHandler
|
|
262
|
+
});
|
|
334
263
|
const registry = new CommandRegistry();
|
|
335
264
|
registry.addSource(new BuiltinCommandSource());
|
|
336
|
-
registry.addSource(new SkillCommandSource(cwd));
|
|
337
|
-
|
|
338
|
-
const pluginsDir = join3(homedir(), ".robota", "plugins");
|
|
265
|
+
registry.addSource(new SkillCommandSource(props.cwd));
|
|
266
|
+
const pluginsDir = join3(homedir2(), ".robota", "plugins");
|
|
339
267
|
const loader = new BundlePluginLoader(pluginsDir);
|
|
340
268
|
try {
|
|
341
269
|
const plugins = loader.loadPluginsSync();
|
|
342
270
|
if (plugins.length > 0) {
|
|
343
271
|
registry.addSource(new PluginCommandSource(plugins));
|
|
344
|
-
pluginHooks = mergePluginHooks(plugins);
|
|
345
272
|
}
|
|
346
273
|
} catch {
|
|
347
274
|
}
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
hooks: mergeHooksIntoConfig(
|
|
351
|
-
props.config.hooks,
|
|
352
|
-
pluginHooks
|
|
353
|
-
)
|
|
354
|
-
};
|
|
355
|
-
const interactiveSession = new InteractiveSession({
|
|
356
|
-
config: mergedConfig,
|
|
357
|
-
context: props.context,
|
|
358
|
-
projectInfo: props.projectInfo,
|
|
359
|
-
sessionStore: props.sessionStore,
|
|
360
|
-
permissionMode: props.permissionMode,
|
|
361
|
-
maxTurns: props.maxTurns,
|
|
362
|
-
cwd,
|
|
363
|
-
permissionHandler
|
|
364
|
-
});
|
|
365
|
-
return {
|
|
366
|
-
interactiveSession,
|
|
367
|
-
registry,
|
|
368
|
-
commandExecutor: new SystemCommandExecutor(),
|
|
369
|
-
pluginHooks
|
|
370
|
-
};
|
|
275
|
+
const manager = new TuiStateManager();
|
|
276
|
+
return { interactiveSession, registry, manager };
|
|
371
277
|
}
|
|
372
278
|
function useInteractiveSession(props) {
|
|
373
|
-
const [
|
|
374
|
-
const addMessage = useCallback((msg) => {
|
|
375
|
-
setMessages((prev) => {
|
|
376
|
-
const updated = [...prev, msg];
|
|
377
|
-
return updated.length > MAX_RENDERED_MESSAGES ? updated.slice(-MAX_RENDERED_MESSAGES) : updated;
|
|
378
|
-
});
|
|
379
|
-
}, []);
|
|
380
|
-
const [streamingText, setStreamingText] = useState("");
|
|
381
|
-
const [activeTools, setActiveTools] = useState([]);
|
|
382
|
-
const [isThinking, setIsThinking] = useState(false);
|
|
383
|
-
const [isAborting, setIsAborting] = useState(false);
|
|
384
|
-
const [pendingPrompt, setPendingPrompt] = useState(null);
|
|
385
|
-
const [contextState, setContextState] = useState({ percentage: 0, usedTokens: 0, maxTokens: 0 });
|
|
279
|
+
const [, forceRender] = useState(0);
|
|
386
280
|
const [permissionRequest, setPermissionRequest] = useState(null);
|
|
387
281
|
const permissionQueueRef = useRef([]);
|
|
388
282
|
const processingRef = useRef(false);
|
|
@@ -417,79 +311,54 @@ function useInteractiveSession(props) {
|
|
|
417
311
|
if (stateRef.current === null) {
|
|
418
312
|
stateRef.current = initializeSession(props, permissionHandler);
|
|
419
313
|
}
|
|
420
|
-
const { interactiveSession, registry,
|
|
314
|
+
const { interactiveSession, registry, manager } = stateRef.current;
|
|
315
|
+
manager.onChange = () => forceRender((n) => n + 1);
|
|
421
316
|
useEffect(() => {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
setStreamingText("");
|
|
440
|
-
setActiveTools([]);
|
|
441
|
-
} else {
|
|
442
|
-
setIsAborting(false);
|
|
317
|
+
interactiveSession.on("text_delta", manager.onTextDelta);
|
|
318
|
+
interactiveSession.on("tool_start", manager.onToolStart);
|
|
319
|
+
interactiveSession.on("tool_end", manager.onToolEnd);
|
|
320
|
+
interactiveSession.on("thinking", manager.onThinking);
|
|
321
|
+
interactiveSession.on("complete", manager.onComplete);
|
|
322
|
+
interactiveSession.on("interrupted", manager.onInterrupted);
|
|
323
|
+
interactiveSession.on("error", manager.onError);
|
|
324
|
+
const initCheck = setInterval(() => {
|
|
325
|
+
try {
|
|
326
|
+
const ctx = interactiveSession.getContextState();
|
|
327
|
+
manager.setContextState({
|
|
328
|
+
percentage: ctx.usedPercentage,
|
|
329
|
+
usedTokens: ctx.usedTokens,
|
|
330
|
+
maxTokens: ctx.maxTokens
|
|
331
|
+
});
|
|
332
|
+
clearInterval(initCheck);
|
|
333
|
+
} catch {
|
|
443
334
|
}
|
|
444
|
-
};
|
|
445
|
-
const onComplete = (result) => {
|
|
446
|
-
setContextState({
|
|
447
|
-
percentage: result.contextState.usedPercentage,
|
|
448
|
-
usedTokens: result.contextState.usedTokens,
|
|
449
|
-
maxTokens: result.contextState.maxTokens
|
|
450
|
-
});
|
|
451
|
-
};
|
|
452
|
-
const onInterrupted = () => {
|
|
453
|
-
};
|
|
454
|
-
const onError = () => {
|
|
455
|
-
};
|
|
456
|
-
interactiveSession.on("text_delta", onTextDelta);
|
|
457
|
-
interactiveSession.on("tool_start", onToolStart);
|
|
458
|
-
interactiveSession.on("tool_end", onToolEnd);
|
|
459
|
-
interactiveSession.on("thinking", onThinking);
|
|
460
|
-
interactiveSession.on("complete", onComplete);
|
|
461
|
-
interactiveSession.on("interrupted", onInterrupted);
|
|
462
|
-
interactiveSession.on("error", onError);
|
|
335
|
+
}, 200);
|
|
463
336
|
return () => {
|
|
464
|
-
|
|
465
|
-
interactiveSession.off("
|
|
466
|
-
interactiveSession.off("
|
|
467
|
-
interactiveSession.off("
|
|
468
|
-
interactiveSession.off("
|
|
469
|
-
interactiveSession.off("
|
|
470
|
-
interactiveSession.off("
|
|
337
|
+
clearInterval(initCheck);
|
|
338
|
+
interactiveSession.off("text_delta", manager.onTextDelta);
|
|
339
|
+
interactiveSession.off("tool_start", manager.onToolStart);
|
|
340
|
+
interactiveSession.off("tool_end", manager.onToolEnd);
|
|
341
|
+
interactiveSession.off("thinking", manager.onThinking);
|
|
342
|
+
interactiveSession.off("complete", manager.onComplete);
|
|
343
|
+
interactiveSession.off("interrupted", manager.onInterrupted);
|
|
344
|
+
interactiveSession.off("error", manager.onError);
|
|
471
345
|
};
|
|
472
|
-
}, [interactiveSession]);
|
|
346
|
+
}, [interactiveSession, manager]);
|
|
473
347
|
useEffect(() => {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
setMessages(
|
|
478
|
-
sessionMessages.length > MAX_RENDERED_MESSAGES ? sessionMessages.slice(-MAX_RENDERED_MESSAGES) : [...sessionMessages]
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
348
|
+
manager.syncHistory(interactiveSession.getFullHistory());
|
|
349
|
+
if (!manager.isThinking) {
|
|
350
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
482
351
|
}
|
|
483
|
-
}, [isThinking, interactiveSession]);
|
|
352
|
+
}, [manager.isThinking, interactiveSession, manager]);
|
|
484
353
|
const handleSubmit = useCallback(
|
|
485
354
|
async (input) => {
|
|
486
355
|
if (input.startsWith("/")) {
|
|
487
356
|
const parts = input.slice(1).split(/\s+/);
|
|
488
357
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
489
358
|
const args = parts.slice(1).join(" ");
|
|
490
|
-
const result = await
|
|
359
|
+
const result = await interactiveSession.executeCommand(cmd, args);
|
|
491
360
|
if (result) {
|
|
492
|
-
|
|
361
|
+
manager.addEntry(messageToHistoryEntry(createSystemMessage(result.message)));
|
|
493
362
|
const effects = interactiveSession;
|
|
494
363
|
if (result.data?.modelId) {
|
|
495
364
|
effects._pendingModelId = result.data.modelId;
|
|
@@ -504,7 +373,7 @@ function useInteractiveSession(props) {
|
|
|
504
373
|
return;
|
|
505
374
|
}
|
|
506
375
|
const ctx = interactiveSession.getContextState();
|
|
507
|
-
setContextState({
|
|
376
|
+
manager.setContextState({
|
|
508
377
|
percentage: ctx.usedPercentage,
|
|
509
378
|
usedTokens: ctx.usedTokens,
|
|
510
379
|
maxTokens: ctx.maxTokens
|
|
@@ -513,13 +382,23 @@ function useInteractiveSession(props) {
|
|
|
513
382
|
}
|
|
514
383
|
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
515
384
|
if (skillCmd) {
|
|
516
|
-
|
|
385
|
+
manager.addEntry({
|
|
386
|
+
id: randomUUID(),
|
|
387
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
388
|
+
category: "event",
|
|
389
|
+
type: "skill-invocation",
|
|
390
|
+
data: {
|
|
391
|
+
skillName: cmd,
|
|
392
|
+
source: skillCmd.source,
|
|
393
|
+
message: `Invoking ${skillCmd.source}: ${cmd}`
|
|
394
|
+
}
|
|
395
|
+
});
|
|
517
396
|
const prompt = await buildSkillPrompt(input, registry);
|
|
518
397
|
if (prompt) {
|
|
519
398
|
const qualifiedName = registry.resolveQualifiedName(cmd);
|
|
520
399
|
const hookInput = qualifiedName ? `/${qualifiedName}${input.slice(1 + cmd.length)}` : input;
|
|
521
400
|
await interactiveSession.submit(prompt, input, hookInput);
|
|
522
|
-
setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
401
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
523
402
|
return;
|
|
524
403
|
}
|
|
525
404
|
}
|
|
@@ -531,45 +410,38 @@ function useInteractiveSession(props) {
|
|
|
531
410
|
interactiveSession._triggerPluginTUI = true;
|
|
532
411
|
return;
|
|
533
412
|
}
|
|
534
|
-
|
|
413
|
+
manager.addEntry(
|
|
414
|
+
messageToHistoryEntry(
|
|
415
|
+
createSystemMessage(`Unknown command "/${cmd}". Type /help for help.`)
|
|
416
|
+
)
|
|
417
|
+
);
|
|
535
418
|
return;
|
|
536
419
|
}
|
|
537
420
|
await interactiveSession.submit(input);
|
|
538
|
-
setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
421
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
539
422
|
},
|
|
540
|
-
[interactiveSession,
|
|
423
|
+
[interactiveSession, registry, manager]
|
|
541
424
|
);
|
|
542
425
|
const handleAbort = useCallback(() => {
|
|
543
|
-
|
|
426
|
+
manager.setAborting(true);
|
|
544
427
|
interactiveSession.abort();
|
|
545
|
-
}, [interactiveSession]);
|
|
428
|
+
}, [interactiveSession, manager]);
|
|
546
429
|
const handleCancelQueue = useCallback(() => {
|
|
547
430
|
interactiveSession.cancelQueue();
|
|
548
|
-
setPendingPrompt(null);
|
|
549
|
-
}, [interactiveSession]);
|
|
550
|
-
if (contextState.maxTokens === 0) {
|
|
551
|
-
const ctx = interactiveSession.getContextState();
|
|
552
|
-
setContextState({
|
|
553
|
-
percentage: ctx.usedPercentage,
|
|
554
|
-
usedTokens: ctx.usedTokens,
|
|
555
|
-
maxTokens: ctx.maxTokens
|
|
556
|
-
});
|
|
557
|
-
}
|
|
431
|
+
manager.setPendingPrompt(null);
|
|
432
|
+
}, [interactiveSession, manager]);
|
|
558
433
|
return {
|
|
559
434
|
interactiveSession,
|
|
560
435
|
registry,
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
isThinking,
|
|
569
|
-
isAborting,
|
|
570
|
-
pendingPrompt,
|
|
436
|
+
history: manager.history,
|
|
437
|
+
addEntry: (entry) => manager.addEntry(entry),
|
|
438
|
+
streamingText: manager.streamingText,
|
|
439
|
+
activeTools: manager.activeTools,
|
|
440
|
+
isThinking: manager.isThinking,
|
|
441
|
+
isAborting: manager.isAborting,
|
|
442
|
+
pendingPrompt: manager.pendingPrompt,
|
|
571
443
|
permissionRequest,
|
|
572
|
-
contextState,
|
|
444
|
+
contextState: manager.contextState,
|
|
573
445
|
handleSubmit,
|
|
574
446
|
handleAbort,
|
|
575
447
|
handleCancelQueue
|
|
@@ -578,7 +450,7 @@ function useInteractiveSession(props) {
|
|
|
578
450
|
|
|
579
451
|
// src/ui/hooks/usePluginCallbacks.ts
|
|
580
452
|
import { useMemo } from "react";
|
|
581
|
-
import { homedir as
|
|
453
|
+
import { homedir as homedir3 } from "os";
|
|
582
454
|
import { join as join4 } from "path";
|
|
583
455
|
import {
|
|
584
456
|
PluginSettingsStore,
|
|
@@ -588,7 +460,7 @@ import {
|
|
|
588
460
|
} from "@robota-sdk/agent-sdk";
|
|
589
461
|
function usePluginCallbacks(cwd) {
|
|
590
462
|
return useMemo(() => {
|
|
591
|
-
const home =
|
|
463
|
+
const home = homedir3();
|
|
592
464
|
const pluginsDir = join4(home, ".robota", "plugins");
|
|
593
465
|
const userSettingsPath = join4(home, ".robota", "settings.json");
|
|
594
466
|
const settingsStore = new PluginSettingsStore(userSettingsPath);
|
|
@@ -848,8 +720,45 @@ var MessageItem = React2.memo(function MessageItem2({
|
|
|
848
720
|
/* @__PURE__ */ jsx(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text2, { wrap: "wrap", children: isAssistantMessage(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
|
|
849
721
|
] });
|
|
850
722
|
});
|
|
851
|
-
function
|
|
852
|
-
|
|
723
|
+
function ToolSummaryEntry({ entry }) {
|
|
724
|
+
const data = entry.data;
|
|
725
|
+
const lines = data?.summary?.split("\n") ?? [];
|
|
726
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
|
|
727
|
+
/* @__PURE__ */ jsx(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: "white", bold: true, children: [
|
|
728
|
+
"Tool:",
|
|
729
|
+
" "
|
|
730
|
+
] }) }),
|
|
731
|
+
/* @__PURE__ */ jsx(Text2, { children: " " }),
|
|
732
|
+
lines.map((line, i) => /* @__PURE__ */ jsxs2(Text2, { color: "green", children: [
|
|
733
|
+
" ",
|
|
734
|
+
line
|
|
735
|
+
] }, i))
|
|
736
|
+
] });
|
|
737
|
+
}
|
|
738
|
+
function EventEntry({ entry }) {
|
|
739
|
+
const eventData = entry.data;
|
|
740
|
+
const eventMessage = typeof eventData?.message === "string" ? eventData.message : typeof eventData?.content === "string" ? eventData.content : entry.type;
|
|
741
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
|
|
742
|
+
/* @__PURE__ */ jsx(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
|
|
743
|
+
"System:",
|
|
744
|
+
" "
|
|
745
|
+
] }) }),
|
|
746
|
+
/* @__PURE__ */ jsx(Text2, { children: " " }),
|
|
747
|
+
/* @__PURE__ */ jsx(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text2, { wrap: "wrap", children: eventMessage }) })
|
|
748
|
+
] });
|
|
749
|
+
}
|
|
750
|
+
function EntryItem({ entry }) {
|
|
751
|
+
if (entry.category === "chat") {
|
|
752
|
+
const message = entry.data;
|
|
753
|
+
return /* @__PURE__ */ jsx(MessageItem, { message });
|
|
754
|
+
}
|
|
755
|
+
if (entry.type === "tool-summary") {
|
|
756
|
+
return /* @__PURE__ */ jsx(ToolSummaryEntry, { entry });
|
|
757
|
+
}
|
|
758
|
+
return /* @__PURE__ */ jsx(EventEntry, { entry });
|
|
759
|
+
}
|
|
760
|
+
function MessageList({ history }) {
|
|
761
|
+
return /* @__PURE__ */ jsx(Box2, { flexDirection: "column", children: history.map((entry) => /* @__PURE__ */ jsx(EntryItem, { entry }, entry.id)) });
|
|
853
762
|
}
|
|
854
763
|
|
|
855
764
|
// src/ui/StatusBar.tsx
|
|
@@ -1958,12 +1867,12 @@ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
|
1958
1867
|
var EXIT_DELAY_MS = 500;
|
|
1959
1868
|
function App(props) {
|
|
1960
1869
|
const { exit } = useApp();
|
|
1961
|
-
const cwd = props.cwd
|
|
1870
|
+
const cwd = props.cwd;
|
|
1962
1871
|
const {
|
|
1963
1872
|
interactiveSession,
|
|
1964
1873
|
registry,
|
|
1965
|
-
|
|
1966
|
-
|
|
1874
|
+
history,
|
|
1875
|
+
addEntry,
|
|
1967
1876
|
streamingText,
|
|
1968
1877
|
activeTools,
|
|
1969
1878
|
isThinking,
|
|
@@ -1975,13 +1884,10 @@ function App(props) {
|
|
|
1975
1884
|
handleAbort,
|
|
1976
1885
|
handleCancelQueue
|
|
1977
1886
|
} = useInteractiveSession({
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
projectInfo: props.projectInfo,
|
|
1981
|
-
sessionStore: props.sessionStore,
|
|
1887
|
+
cwd,
|
|
1888
|
+
provider: props.provider,
|
|
1982
1889
|
permissionMode: props.permissionMode,
|
|
1983
|
-
maxTurns: props.maxTurns
|
|
1984
|
-
cwd
|
|
1890
|
+
maxTurns: props.maxTurns
|
|
1985
1891
|
});
|
|
1986
1892
|
const pluginCallbacks = usePluginCallbacks(cwd);
|
|
1987
1893
|
const [pendingModelId, setPendingModelId] = useState9(null);
|
|
@@ -2004,7 +1910,9 @@ function App(props) {
|
|
|
2004
1910
|
const settings = readSettings(settingsPath);
|
|
2005
1911
|
settings.language = lang;
|
|
2006
1912
|
writeSettings(settingsPath, settings);
|
|
2007
|
-
|
|
1913
|
+
addEntry(
|
|
1914
|
+
messageToHistoryEntry2(createSystemMessage2(`Language set to "${lang}". Restarting...`))
|
|
1915
|
+
);
|
|
2008
1916
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2009
1917
|
return;
|
|
2010
1918
|
}
|
|
@@ -2012,9 +1920,9 @@ function App(props) {
|
|
|
2012
1920
|
delete sideEffects._resetRequested;
|
|
2013
1921
|
const settingsPath = getUserSettingsPath();
|
|
2014
1922
|
if (deleteSettings(settingsPath)) {
|
|
2015
|
-
|
|
1923
|
+
addEntry(messageToHistoryEntry2(createSystemMessage2(`Deleted ${settingsPath}. Exiting...`)));
|
|
2016
1924
|
} else {
|
|
2017
|
-
|
|
1925
|
+
addEntry(messageToHistoryEntry2(createSystemMessage2("No user settings found.")));
|
|
2018
1926
|
}
|
|
2019
1927
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2020
1928
|
return;
|
|
@@ -2038,7 +1946,14 @@ function App(props) {
|
|
|
2038
1946
|
},
|
|
2039
1947
|
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2040
1948
|
);
|
|
2041
|
-
|
|
1949
|
+
let permissionMode = props.permissionMode ?? "default";
|
|
1950
|
+
let sessionId = "";
|
|
1951
|
+
try {
|
|
1952
|
+
const session = interactiveSession.getSession();
|
|
1953
|
+
permissionMode = session.getPermissionMode();
|
|
1954
|
+
sessionId = session.getSessionId();
|
|
1955
|
+
} catch {
|
|
1956
|
+
}
|
|
2042
1957
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
2043
1958
|
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2044
1959
|
/* @__PURE__ */ jsx13(Text13, { color: "cyan", bold: true, children: `
|
|
@@ -2054,7 +1969,7 @@ function App(props) {
|
|
|
2054
1969
|
] })
|
|
2055
1970
|
] }),
|
|
2056
1971
|
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2057
|
-
/* @__PURE__ */ jsx13(MessageList, {
|
|
1972
|
+
/* @__PURE__ */ jsx13(MessageList, { history }),
|
|
2058
1973
|
(isThinking || activeTools.length > 0) && /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx13(StreamingIndicator, { text: streamingText, activeTools }) })
|
|
2059
1974
|
] }),
|
|
2060
1975
|
permissionRequest && /* @__PURE__ */ jsx13(PermissionPrompt, { request: permissionRequest }),
|
|
@@ -2069,21 +1984,25 @@ function App(props) {
|
|
|
2069
1984
|
try {
|
|
2070
1985
|
const settingsPath = getUserSettingsPath();
|
|
2071
1986
|
updateModelInSettings(settingsPath, pendingModelId);
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
1987
|
+
addEntry(
|
|
1988
|
+
messageToHistoryEntry2(
|
|
1989
|
+
createSystemMessage2(
|
|
1990
|
+
`Model changed to ${getModelName(pendingModelId)}. Restarting...`
|
|
1991
|
+
)
|
|
2075
1992
|
)
|
|
2076
1993
|
);
|
|
2077
1994
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2078
1995
|
} catch (err) {
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
1996
|
+
addEntry(
|
|
1997
|
+
messageToHistoryEntry2(
|
|
1998
|
+
createSystemMessage2(
|
|
1999
|
+
`Failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2000
|
+
)
|
|
2082
2001
|
)
|
|
2083
2002
|
);
|
|
2084
2003
|
}
|
|
2085
2004
|
} else {
|
|
2086
|
-
|
|
2005
|
+
addEntry(messageToHistoryEntry2(createSystemMessage2("Model change cancelled.")));
|
|
2087
2006
|
}
|
|
2088
2007
|
}
|
|
2089
2008
|
}
|
|
@@ -2093,16 +2012,16 @@ function App(props) {
|
|
|
2093
2012
|
{
|
|
2094
2013
|
callbacks: pluginCallbacks,
|
|
2095
2014
|
onClose: () => setShowPluginTUI(false),
|
|
2096
|
-
addMessage: (msg) =>
|
|
2015
|
+
addMessage: (msg) => addEntry(messageToHistoryEntry2(createSystemMessage2(msg.content)))
|
|
2097
2016
|
}
|
|
2098
2017
|
),
|
|
2099
2018
|
/* @__PURE__ */ jsx13(
|
|
2100
2019
|
StatusBar,
|
|
2101
2020
|
{
|
|
2102
|
-
permissionMode
|
|
2103
|
-
modelName: getModelName(props.
|
|
2104
|
-
sessionId
|
|
2105
|
-
messageCount:
|
|
2021
|
+
permissionMode,
|
|
2022
|
+
modelName: props.modelId ? getModelName(props.modelId) : "",
|
|
2023
|
+
sessionId,
|
|
2024
|
+
messageCount: history.length,
|
|
2106
2025
|
isThinking,
|
|
2107
2026
|
contextPercentage: contextState.percentage,
|
|
2108
2027
|
contextUsedTokens: contextState.usedTokens,
|
|
@@ -2159,9 +2078,9 @@ function renderApp(options) {
|
|
|
2159
2078
|
|
|
2160
2079
|
// src/cli.ts
|
|
2161
2080
|
function checkSettingsFile(filePath) {
|
|
2162
|
-
if (!
|
|
2081
|
+
if (!existsSync3(filePath)) return "missing";
|
|
2163
2082
|
try {
|
|
2164
|
-
const raw =
|
|
2083
|
+
const raw = readFileSync3(filePath, "utf8").trim();
|
|
2165
2084
|
if (raw.length === 0) return "incomplete";
|
|
2166
2085
|
const parsed = JSON.parse(raw);
|
|
2167
2086
|
const provider = parsed.provider;
|
|
@@ -2174,11 +2093,11 @@ function checkSettingsFile(filePath) {
|
|
|
2174
2093
|
function readVersion() {
|
|
2175
2094
|
try {
|
|
2176
2095
|
const thisFile = fileURLToPath(import.meta.url);
|
|
2177
|
-
const dir =
|
|
2096
|
+
const dir = dirname2(thisFile);
|
|
2178
2097
|
const candidates = [join5(dir, "..", "..", "package.json"), join5(dir, "..", "package.json")];
|
|
2179
2098
|
for (const pkgPath of candidates) {
|
|
2180
2099
|
try {
|
|
2181
|
-
const raw =
|
|
2100
|
+
const raw = readFileSync3(pkgPath, "utf-8");
|
|
2182
2101
|
const pkg = JSON.parse(raw);
|
|
2183
2102
|
if (pkg.version !== void 0 && pkg.name !== void 0) {
|
|
2184
2103
|
return pkg.version;
|
|
@@ -2265,7 +2184,7 @@ async function ensureConfig(cwd) {
|
|
|
2265
2184
|
process.exit(1);
|
|
2266
2185
|
}
|
|
2267
2186
|
const language = await promptInput(" Response language (ko/en/ja/zh, default: en): ");
|
|
2268
|
-
const settingsDir =
|
|
2187
|
+
const settingsDir = dirname2(userPath);
|
|
2269
2188
|
mkdirSync2(settingsDir, { recursive: true });
|
|
2270
2189
|
const settings = {
|
|
2271
2190
|
provider: {
|
|
@@ -2305,44 +2224,40 @@ async function startCli() {
|
|
|
2305
2224
|
}
|
|
2306
2225
|
const cwd = process.cwd();
|
|
2307
2226
|
await ensureConfig(cwd);
|
|
2308
|
-
const
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
detectProject(cwd)
|
|
2312
|
-
]);
|
|
2313
|
-
if (args.model !== void 0) {
|
|
2314
|
-
config.provider.model = args.model;
|
|
2315
|
-
}
|
|
2316
|
-
if (args.language !== void 0) {
|
|
2317
|
-
config.language = args.language;
|
|
2318
|
-
}
|
|
2319
|
-
const sessionStore = new SessionStore();
|
|
2227
|
+
const providerSettings = readProviderSettings(cwd);
|
|
2228
|
+
const modelId = args.model ?? providerSettings.model;
|
|
2229
|
+
const provider = createProviderFromSettings(cwd, args.model);
|
|
2320
2230
|
if (args.printMode) {
|
|
2321
2231
|
const prompt = args.positional.join(" ").trim();
|
|
2322
2232
|
if (prompt.length === 0) {
|
|
2323
2233
|
process.stderr.write("Print mode (-p) requires a prompt argument.\n");
|
|
2324
2234
|
process.exit(1);
|
|
2325
2235
|
}
|
|
2326
|
-
const
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2236
|
+
const session = new InteractiveSession2({
|
|
2237
|
+
cwd,
|
|
2238
|
+
provider,
|
|
2239
|
+
permissionMode: args.permissionMode ?? "bypassPermissions",
|
|
2240
|
+
maxTurns: args.maxTurns
|
|
2241
|
+
});
|
|
2242
|
+
await new Promise((resolve, reject) => {
|
|
2243
|
+
session.on("complete", (result) => {
|
|
2244
|
+
process.stdout.write(result.response + "\n");
|
|
2245
|
+
resolve();
|
|
2246
|
+
});
|
|
2247
|
+
session.on("interrupted", (result) => {
|
|
2248
|
+
if (result.response) process.stdout.write(result.response + "\n");
|
|
2249
|
+
resolve();
|
|
2250
|
+
});
|
|
2251
|
+
session.on("error", (err) => reject(err));
|
|
2252
|
+
session.submit(prompt).catch(reject);
|
|
2336
2253
|
});
|
|
2337
|
-
const response = await session.run(prompt);
|
|
2338
|
-
process.stdout.write(response + "\n");
|
|
2339
2254
|
return;
|
|
2340
2255
|
}
|
|
2341
2256
|
renderApp({
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2257
|
+
cwd,
|
|
2258
|
+
provider,
|
|
2259
|
+
modelId,
|
|
2260
|
+
language: args.language,
|
|
2346
2261
|
permissionMode: args.permissionMode,
|
|
2347
2262
|
maxTurns: args.maxTurns,
|
|
2348
2263
|
version: readVersion()
|