wtagent 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/docs/technical-design.md +18 -11
- package/package.json +6 -6
- package/src/browser/base-web-adapter.js +2085 -202
- package/src/browser/cdp-browser.js +223 -25
- package/src/browser/cdp-state.js +8 -5
- package/src/browser/chatgpt-web-adapter.js +803 -218
- package/src/browser/claude-web-adapter.js +13 -0
- package/src/browser/deepseek-web-adapter.js +0 -106
- package/src/browser/fake-web-model-adapter.js +137 -3
- package/src/browser/gemini-web-adapter.js +10 -0
- package/src/browser/glm-web-adapter.js +4 -91
- package/src/browser/grok-web-adapter.js +145 -0
- package/src/browser/kimi-web-adapter.js +2 -74
- package/src/browser/provider-registry.js +8 -50
- package/src/cli/i18n.js +949 -0
- package/src/cli/main.js +217 -223
- package/src/cli/prompt-input.js +349 -151
- package/src/cli/render-events.js +45 -35
- package/src/cli/self-update.js +10 -3
- package/src/platform/command-launcher.js +1 -1
- package/src/platform/paths.js +19 -0
- package/src/platform/windows-diagnostics.js +9 -16
- package/src/policy/path-guard.js +5 -1
- package/src/runtime/agent-runtime.js +1065 -237
- package/src/session/agent-session.js +975 -120
- package/src/shared/limits.js +2 -9
- package/src/tools/default-tools.js +1 -1
- package/src/browser/mode-selection.js +0 -214
- package/src/cli/mode-choice.js +0 -25
package/src/cli/render-events.js
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// A single Renderer instance is shared across every turn of a conversation so
|
|
9
9
|
// spinner state and per-tool timing survive between the model's replies.
|
|
10
10
|
|
|
11
|
+
import { t } from "./i18n.js";
|
|
12
|
+
|
|
11
13
|
const DIM = "\x1b[2m";
|
|
12
14
|
const BOLD = "\x1b[1m";
|
|
13
15
|
const CYAN = "\x1b[36m";
|
|
@@ -109,7 +111,7 @@ export class Renderer {
|
|
|
109
111
|
}
|
|
110
112
|
this.spinner = {
|
|
111
113
|
kind: "processing",
|
|
112
|
-
label: "processing
|
|
114
|
+
label: t("renderer.processing"),
|
|
113
115
|
start: Date.now(),
|
|
114
116
|
bytes: 0,
|
|
115
117
|
};
|
|
@@ -119,7 +121,7 @@ export class Renderer {
|
|
|
119
121
|
beginRunning(name) {
|
|
120
122
|
this.spinner = {
|
|
121
123
|
kind: "running",
|
|
122
|
-
label:
|
|
124
|
+
label: t("renderer.running", { tool: name }),
|
|
123
125
|
start: Date.now(),
|
|
124
126
|
bytes: 0,
|
|
125
127
|
};
|
|
@@ -235,7 +237,7 @@ export class Renderer {
|
|
|
235
237
|
answer(message) {
|
|
236
238
|
this.stopSpinner();
|
|
237
239
|
this.println("");
|
|
238
|
-
this.println(`${GREEN}${BOLD}⏺ assistant${RESET}`);
|
|
240
|
+
this.println(`${GREEN}${BOLD}⏺ ${t("renderer.assistant")}${RESET}`);
|
|
239
241
|
for (const line of String(message ?? "").split(/\r?\n/)) {
|
|
240
242
|
this.println(line);
|
|
241
243
|
}
|
|
@@ -260,36 +262,25 @@ export class Renderer {
|
|
|
260
262
|
break;
|
|
261
263
|
}
|
|
262
264
|
this.lifecycleShown.add(type);
|
|
263
|
-
this.status("
|
|
265
|
+
this.status(t("renderer.chromeStarted"));
|
|
264
266
|
break;
|
|
265
267
|
case "browser.auth_required":
|
|
266
268
|
this.stopSpinner();
|
|
267
|
-
this.println(
|
|
269
|
+
this.println(
|
|
270
|
+
`${YELLOW}${t("renderer.loginRequired", { provider: this.providerLabel })}${RESET}`,
|
|
271
|
+
);
|
|
268
272
|
break;
|
|
269
273
|
case "browser.authenticated":
|
|
270
|
-
this.println(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const { requested, status, selectedLabel } = payload;
|
|
274
|
-
if (status === "select" || status === "already") {
|
|
275
|
-
this.status(`Mode: ${selectedLabel ?? requested}.`);
|
|
276
|
-
} else if (status === "fallback") {
|
|
277
|
-
this.note(`Mode: ${requested} unavailable; using ${selectedLabel}.`);
|
|
278
|
-
} else {
|
|
279
|
-
this.note(`Mode: could not select ${requested}; continuing on current mode.`);
|
|
280
|
-
}
|
|
274
|
+
this.println(
|
|
275
|
+
`${GREEN}${t("renderer.loginDetected", { provider: this.providerLabel })}${RESET}`,
|
|
276
|
+
);
|
|
281
277
|
break;
|
|
282
|
-
}
|
|
283
278
|
case "conversation.started":
|
|
284
279
|
if (this.lifecycleShown.has(type)) {
|
|
285
280
|
break;
|
|
286
281
|
}
|
|
287
282
|
this.lifecycleShown.add(type);
|
|
288
|
-
|
|
289
|
-
this.status(`Conversation ready (${payload.mode}).`);
|
|
290
|
-
} else {
|
|
291
|
-
this.status("Conversation ready (current mode).");
|
|
292
|
-
}
|
|
283
|
+
this.status(t("renderer.conversationReady"));
|
|
293
284
|
break;
|
|
294
285
|
case "model.message_sent":
|
|
295
286
|
this.beginProcessing();
|
|
@@ -305,18 +296,29 @@ export class Renderer {
|
|
|
305
296
|
this.stopSpinner();
|
|
306
297
|
this.note(
|
|
307
298
|
payload.deadRequest
|
|
308
|
-
?
|
|
299
|
+
? t("renderer.noReply", {
|
|
300
|
+
provider: this.providerLabel,
|
|
301
|
+
retry: payload.retry,
|
|
302
|
+
maxRetries: payload.maxRetries,
|
|
303
|
+
})
|
|
309
304
|
: payload.generationFailed
|
|
310
|
-
?
|
|
311
|
-
|
|
305
|
+
? t("renderer.generationFailed", {
|
|
306
|
+
provider: this.providerLabel,
|
|
307
|
+
retry: payload.retry,
|
|
308
|
+
maxRetries: payload.maxRetries,
|
|
309
|
+
})
|
|
310
|
+
: t("renderer.emptyResponse", {
|
|
311
|
+
provider: this.providerLabel,
|
|
312
|
+
retry: payload.retry,
|
|
313
|
+
maxRetries: payload.maxRetries,
|
|
314
|
+
}),
|
|
312
315
|
);
|
|
313
316
|
break;
|
|
314
317
|
case "model.limit_reached":
|
|
315
318
|
this.stopSpinner();
|
|
316
|
-
this.note(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
);
|
|
319
|
+
this.note(t("renderer.limitReached", {
|
|
320
|
+
provider: this.providerLabel,
|
|
321
|
+
}));
|
|
320
322
|
break;
|
|
321
323
|
case "model.progress":
|
|
322
324
|
this.stopSpinner();
|
|
@@ -329,7 +331,7 @@ export class Renderer {
|
|
|
329
331
|
break;
|
|
330
332
|
case "protocol.plain_answer":
|
|
331
333
|
this.stopSpinner();
|
|
332
|
-
this.note("
|
|
334
|
+
this.note(t("renderer.plainAnswer"));
|
|
333
335
|
break;
|
|
334
336
|
case "tool.proposed":
|
|
335
337
|
this.stopSpinner();
|
|
@@ -361,21 +363,25 @@ export class Renderer {
|
|
|
361
363
|
this.stopSpinner();
|
|
362
364
|
if (!payload.id || !this.handled.has(payload.id)) {
|
|
363
365
|
if (payload.id) this.handled.add(payload.id);
|
|
364
|
-
this.println(
|
|
366
|
+
this.println(
|
|
367
|
+
`${this.#hdr()} ${DIM}↺ ${t("renderer.reused", { tool: payload.name })}${RESET}`,
|
|
368
|
+
);
|
|
365
369
|
}
|
|
366
370
|
break;
|
|
367
371
|
case "tool.reused_unknown":
|
|
368
372
|
this.stopSpinner();
|
|
369
373
|
if (!payload.id || !this.handled.has(payload.id)) {
|
|
370
374
|
if (payload.id) this.handled.add(payload.id);
|
|
371
|
-
this.println(
|
|
375
|
+
this.println(
|
|
376
|
+
`${this.#hdr()} ${YELLOW}↺ ${t("renderer.reusedUnknown", { tool: payload.name })}${RESET}`,
|
|
377
|
+
);
|
|
372
378
|
}
|
|
373
379
|
break;
|
|
374
380
|
case "tool.conflict":
|
|
375
381
|
this.stopSpinner();
|
|
376
382
|
if (!payload.id || !this.handled.has(payload.id)) {
|
|
377
383
|
if (payload.id) this.handled.add(payload.id);
|
|
378
|
-
this.note(
|
|
384
|
+
this.note(t("renderer.conflictingReuse", { tool: payload.name }));
|
|
379
385
|
}
|
|
380
386
|
break;
|
|
381
387
|
case "run.completed":
|
|
@@ -383,12 +389,16 @@ export class Renderer {
|
|
|
383
389
|
break;
|
|
384
390
|
case "run.interrupted":
|
|
385
391
|
this.stopSpinner();
|
|
386
|
-
this.println(`${YELLOW}
|
|
392
|
+
this.println(`${YELLOW}${t("renderer.interrupted", {
|
|
393
|
+
message: truncate(payload.message, 160),
|
|
394
|
+
})}${RESET}`);
|
|
387
395
|
break;
|
|
388
396
|
case "run.recovery_required":
|
|
389
397
|
this.stopSpinner();
|
|
390
398
|
this.println(
|
|
391
|
-
`${YELLOW}${
|
|
399
|
+
`${YELLOW}${t("renderer.recoveryOpen", {
|
|
400
|
+
message: truncate(payload.message, 180),
|
|
401
|
+
})}${RESET}`,
|
|
392
402
|
);
|
|
393
403
|
break;
|
|
394
404
|
case "tool.result_sent":
|
package/src/cli/self-update.js
CHANGED
|
@@ -6,12 +6,14 @@ import { getPackageName, getPackageVersion } from "../shared/package-info.js";
|
|
|
6
6
|
export const UPDATE_CHECK_TIMEOUT_MS = NETWORK_TIMEOUT_MS;
|
|
7
7
|
export const UPDATE_COMMAND_TIMEOUT_MS = 10_000;
|
|
8
8
|
export const INSTALL_TIMEOUT_MS = 120_000;
|
|
9
|
-
export const
|
|
9
|
+
export const OFFICIAL_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
10
|
+
export const MANUAL_INSTALL_COMMAND =
|
|
11
|
+
`npm install -g wtagent@latest --registry=${OFFICIAL_NPM_REGISTRY}`;
|
|
10
12
|
|
|
11
13
|
const VERSION_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
12
14
|
|
|
13
15
|
export function npmRegistryLatestUrl(name = getPackageName()) {
|
|
14
|
-
return
|
|
16
|
+
return `${OFFICIAL_NPM_REGISTRY}${encodeURIComponent(name)}/latest`;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export function parseVersion(value) {
|
|
@@ -76,7 +78,12 @@ export async function installLatest({
|
|
|
76
78
|
timeoutMs = INSTALL_TIMEOUT_MS,
|
|
77
79
|
stdio = "inherit",
|
|
78
80
|
} = {}) {
|
|
79
|
-
const plan = planCommandImpl("npm", [
|
|
81
|
+
const plan = planCommandImpl("npm", [
|
|
82
|
+
"install",
|
|
83
|
+
"-g",
|
|
84
|
+
"wtagent@latest",
|
|
85
|
+
`--registry=${OFFICIAL_NPM_REGISTRY}`,
|
|
86
|
+
]);
|
|
80
87
|
return await new Promise((resolve) => {
|
|
81
88
|
let settled = false;
|
|
82
89
|
let timer;
|
package/src/platform/paths.js
CHANGED
|
@@ -7,6 +7,25 @@ import { getEnvCaseInsensitive } from "./command-launcher.js";
|
|
|
7
7
|
const APP_NAME = "wtagent";
|
|
8
8
|
const LEGACY_APP_NAME = "webagent";
|
|
9
9
|
|
|
10
|
+
export function formatHomePath(filePath, {
|
|
11
|
+
platform = process.platform,
|
|
12
|
+
homeDir = os.homedir(),
|
|
13
|
+
} = {}) {
|
|
14
|
+
const pathApi = platform === "win32" ? path.win32 : path.posix;
|
|
15
|
+
if (!pathApi.isAbsolute(filePath)) {
|
|
16
|
+
return filePath;
|
|
17
|
+
}
|
|
18
|
+
const relative = pathApi.relative(homeDir, filePath);
|
|
19
|
+
if (relative === "") {
|
|
20
|
+
return "~";
|
|
21
|
+
}
|
|
22
|
+
if (relative === ".." || relative.startsWith(`..${pathApi.sep}`)
|
|
23
|
+
|| pathApi.isAbsolute(relative)) {
|
|
24
|
+
return filePath;
|
|
25
|
+
}
|
|
26
|
+
return `~${pathApi.sep}${relative}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
10
29
|
function platformAppDataDir(appName, {
|
|
11
30
|
env,
|
|
12
31
|
platform,
|
|
@@ -8,11 +8,12 @@ import { promisify } from "node:util";
|
|
|
8
8
|
import { discoverChromeExecutable } from "./chrome-discovery.js";
|
|
9
9
|
import { resolveLaunchPlan } from "./command-launcher.js";
|
|
10
10
|
import { inspectCdpProfileState } from "../browser/cdp-state.js";
|
|
11
|
+
import { getPackageInfo } from "../shared/package-info.js";
|
|
11
12
|
|
|
12
13
|
const execFileAsync = promisify(execFile);
|
|
13
14
|
|
|
14
15
|
function parseMajorMinorPatch(version) {
|
|
15
|
-
const match = String(version ?? "").replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)
|
|
16
|
+
const match = String(version ?? "").replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
16
17
|
if (!match) {
|
|
17
18
|
return null;
|
|
18
19
|
}
|
|
@@ -24,20 +25,12 @@ export function isSupportedNodeVersion(version = process.version) {
|
|
|
24
25
|
if (!parsed) {
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
27
|
-
const [major, minor
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
if (minor > 17) {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
if (minor < 17) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
return patch >= 0;
|
|
28
|
+
const [major, minor] = parsed;
|
|
29
|
+
// Keep aligned with package.json and Inquirer's supported Node releases.
|
|
30
|
+
return (major === 20 && minor >= 17)
|
|
31
|
+
|| (major === 22 && minor >= 13)
|
|
32
|
+
|| (major === 23 && minor >= 5)
|
|
33
|
+
|| major >= 24;
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
export function detectWsl({
|
|
@@ -126,7 +119,7 @@ export function assertNativeRuntimeSupported(context = {}) {
|
|
|
126
119
|
const version = context.version ?? process.version;
|
|
127
120
|
if (!isSupportedNodeVersion(version)) {
|
|
128
121
|
throw new Error(
|
|
129
|
-
`WTAgent requires Node.js
|
|
122
|
+
`WTAgent requires Node.js ${getPackageInfo().engines.node}; current runtime is ${version}.`,
|
|
130
123
|
);
|
|
131
124
|
}
|
|
132
125
|
|
package/src/policy/path-guard.js
CHANGED
|
@@ -73,7 +73,11 @@ export function isPathInside(rootPath, candidatePath, options = {}) {
|
|
|
73
73
|
};
|
|
74
74
|
const root = normalize(rootPath);
|
|
75
75
|
const candidate = normalize(candidatePath);
|
|
76
|
-
|
|
76
|
+
const relative = path.win32.relative(root, candidate);
|
|
77
|
+
return relative === ""
|
|
78
|
+
|| (relative !== ".."
|
|
79
|
+
&& !relative.startsWith("..\\")
|
|
80
|
+
&& !path.win32.isAbsolute(relative));
|
|
77
81
|
}
|
|
78
82
|
const relative = path.relative(rootPath, candidatePath);
|
|
79
83
|
return relative === ""
|