wtagent 0.3.0 → 1.0.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.
Files changed (43) hide show
  1. package/README.md +163 -9
  2. package/package.json +9 -8
  3. package/src/artifacts/artifact-store.js +154 -0
  4. package/src/audio/music-artifact.js +66 -0
  5. package/src/audio/native-music-receiver.js +91 -0
  6. package/src/browser/base-web-adapter.js +2418 -201
  7. package/src/browser/cdp-browser.js +223 -25
  8. package/src/browser/cdp-state.js +8 -5
  9. package/src/browser/chatgpt-dom.js +179 -0
  10. package/src/browser/chatgpt-web-adapter.js +831 -69
  11. package/src/browser/claude-web-adapter.js +13 -0
  12. package/src/browser/fake-web-model-adapter.js +152 -3
  13. package/src/browser/gemini-web-adapter.js +71 -20
  14. package/src/browser/glm-web-adapter.js +2 -2
  15. package/src/browser/grok-web-adapter.js +35 -3
  16. package/src/browser/rendered-text.js +11 -0
  17. package/src/cli/i18n.js +50 -20
  18. package/src/cli/main.js +124 -40
  19. package/src/cli/prompt-input.js +68 -0
  20. package/src/image/browser-image-driver.js +238 -0
  21. package/src/image/browser-image-session-pool.js +96 -0
  22. package/src/image/image-generation-service.js +101 -0
  23. package/src/image/image-provider-driver.js +22 -0
  24. package/src/image/native-image-receiver.js +66 -0
  25. package/src/image/provider-registry.js +23 -0
  26. package/src/image/providers/chatgpt-image-driver.js +211 -0
  27. package/src/image/providers/gemini-image-driver.js +100 -0
  28. package/src/image/providers/grok-image-driver.js +193 -0
  29. package/src/platform/command-launcher.js +1 -1
  30. package/src/platform/paths.js +19 -0
  31. package/src/platform/windows-diagnostics.js +9 -16
  32. package/src/policy/path-guard.js +5 -1
  33. package/src/policy/policy-engine.js +10 -5
  34. package/src/protocol/envelope.js +74 -0
  35. package/src/protocol/markers.js +16 -0
  36. package/src/protocol/prompt-builder.js +12 -9
  37. package/src/protocol/xml-protocol.js +36 -18
  38. package/src/runtime/agent-runtime.js +1383 -238
  39. package/src/session/agent-session.js +1047 -121
  40. package/src/tools/default-tools.js +1 -1
  41. package/src/tools/image-tools.js +92 -0
  42. package/src/tools/registry.js +13 -1
  43. package/docs/technical-design.md +0 -866
@@ -402,7 +402,7 @@ export function createDefaultToolRegistry({
402
402
  }
403
403
  next = edit.replace_all
404
404
  ? next.split(matchedOld).join(edit.new_text)
405
- : next.replace(matchedOld, edit.new_text);
405
+ : next.replace(matchedOld, () => edit.new_text);
406
406
  }
407
407
 
408
408
  await writeTextAtomic(target, next, context);
@@ -0,0 +1,92 @@
1
+ import path from "node:path";
2
+ import { z } from "zod";
3
+ import { resolveToolPath } from "../policy/path-guard.js";
4
+
5
+ const xmlStringArray = z.preprocess((value) => {
6
+ if (value == null || value === "") return [];
7
+ if (Array.isArray(value)) return value;
8
+ if (typeof value === "object" && value.item != null) {
9
+ return Array.isArray(value.item) ? value.item : [value.item];
10
+ }
11
+ if (typeof value === "string" && value.trim().startsWith("[")) {
12
+ try {
13
+ const parsed = JSON.parse(value);
14
+ if (Array.isArray(parsed)) return parsed;
15
+ } catch {
16
+ // Treat malformed JSON-looking input as one path; Zod will validate it.
17
+ }
18
+ }
19
+ return [value];
20
+ }, z.array(z.string().min(1)));
21
+
22
+ export const imageGenerateInputSchema = z.object({
23
+ prompt: z.string().min(1),
24
+ output_path: z.string().min(1),
25
+ provider: z.enum(["auto", "chatgpt", "gemini", "grok"]).default("auto"),
26
+ aspect_ratio: z.enum(["auto", "1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16"])
27
+ .default("auto"),
28
+ reference_images: xmlStringArray.default([]),
29
+ timeout_ms: z.coerce.number().int().min(30_000).max(30 * 60_000)
30
+ .default(10 * 60_000),
31
+ });
32
+
33
+ export function registerImageTools(registry, { imageService }) {
34
+ if (!imageService) return registry;
35
+ registry.register({
36
+ name: "image.generate",
37
+ description: [
38
+ "Generate one raster image through a supported web provider and download it to the local project.",
39
+ "The operation succeeds only after a verified PNG, JPEG, or WebP artifact is atomically saved.",
40
+ "If the provider finishes with text instead of an image, its reply is returned as a failed image result; read that reply before deciding the next step.",
41
+ "Use provider=auto to use this session's provider when image-capable, otherwise ChatGPT;",
42
+ "or choose chatgpt, gemini, or grok explicitly.",
43
+ "Prefer aspect_ratio=auto. Unsupported ratios fall back to auto instead of failing.",
44
+ ].join(" "),
45
+ inputDescription:
46
+ "<args><prompt><![CDATA[...]]></prompt><output_path>images/result.png</output_path><provider>auto</provider><aspect_ratio>auto|1:1|3:2|2:3|4:3|3:4|16:9|9:16</aspect_ratio><reference_images><item>references/style.png</item></reference_images><timeout_ms>600000</timeout_ms></args>",
47
+ risk: "write",
48
+ managesTimeout: true,
49
+ requiresVisibleBrowser: true,
50
+ inputSchema: imageGenerateInputSchema,
51
+ execute: async (args, context) => {
52
+ const referenceImages = [];
53
+ for (const rawPath of args.reference_images) {
54
+ const info = await resolveToolPath(context.projectRoot, rawPath);
55
+ if (!info.inside && !context.allowOutside) {
56
+ throw new Error(`Path is outside project root: ${info.path}`);
57
+ }
58
+ referenceImages.push(info.path);
59
+ }
60
+ const artifact = await imageService.generate({
61
+ prompt: args.prompt,
62
+ outputPath: args.output_path,
63
+ provider: args.provider,
64
+ aspectRatio: args.aspect_ratio,
65
+ referenceImages,
66
+ timeoutMs: args.timeout_ms,
67
+ }, context);
68
+ if (artifact.type === "text") {
69
+ return {
70
+ ok: false,
71
+ message: `Image provider returned text instead of an image:\n\n${artifact.text}`,
72
+ data: { response: artifact },
73
+ meta: { code: "IMAGE_TEXT_RESPONSE", completionUnknown: false },
74
+ };
75
+ }
76
+ const relative = path.relative(context.projectRoot, artifact.localPath);
77
+ const location = relative && !relative.startsWith("..")
78
+ ? relative
79
+ : artifact.localPath;
80
+ let message = `Generated image at ${location}.`;
81
+ if (artifact.provenance?.requestedAspectRatio) {
82
+ message += ` Requested aspect_ratio ${artifact.provenance.requestedAspectRatio} is not supported by ${artifact.provenance.provider}; used ${artifact.provenance.aspectRatio}.`;
83
+ }
84
+ return {
85
+ ok: true,
86
+ message,
87
+ data: { artifact },
88
+ };
89
+ },
90
+ });
91
+ return registry;
92
+ }
@@ -114,16 +114,28 @@ export class ToolRegistry {
114
114
  meta: result.meta,
115
115
  };
116
116
  } catch (error) {
117
+ const meta = {
118
+ ...(error?.meta ?? {}),
119
+ ...(error?.code ? {
120
+ code: error.code,
121
+ recoverable: error.recoverable ?? false,
122
+ ...(error.details ? { details: error.details } : {}),
123
+ } : {}),
124
+ ...(error?.completionUnknown ? {
125
+ completionUnknown: true,
126
+ recoverable: error.recoverable ?? true,
127
+ } : {}),
128
+ };
117
129
  return {
118
130
  callId: preparedCall.id,
119
131
  name: preparedCall.name,
120
132
  ok: false,
121
133
  message: error.message,
122
134
  stderr: error.stack,
135
+ meta: Object.keys(meta).length ? meta : undefined,
123
136
  };
124
137
  } finally {
125
138
  clearTimeout(timer);
126
139
  }
127
140
  }
128
141
  }
129
-