thinkwell 0.4.5 → 0.5.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +3 -5
  2. package/bin/thinkwell +130 -174
  3. package/dist/agent.d.ts +82 -56
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/agent.js +178 -174
  6. package/dist/agent.js.map +1 -1
  7. package/dist/cli/build.d.ts +15 -43
  8. package/dist/cli/build.d.ts.map +1 -1
  9. package/dist/cli/build.js +199 -1231
  10. package/dist/cli/build.js.map +1 -1
  11. package/dist/cli/bundle.d.ts +61 -0
  12. package/dist/cli/bundle.d.ts.map +1 -0
  13. package/dist/cli/bundle.js +1299 -0
  14. package/dist/cli/bundle.js.map +1 -0
  15. package/dist/cli/check.d.ts +19 -0
  16. package/dist/cli/check.d.ts.map +1 -0
  17. package/dist/cli/check.js +248 -0
  18. package/dist/cli/check.js.map +1 -0
  19. package/dist/cli/commands.d.ts +30 -0
  20. package/dist/cli/commands.d.ts.map +1 -0
  21. package/dist/cli/commands.js +64 -0
  22. package/dist/cli/commands.js.map +1 -0
  23. package/dist/cli/compiler-host.d.ts +109 -0
  24. package/dist/cli/compiler-host.d.ts.map +1 -0
  25. package/dist/cli/compiler-host.js +173 -0
  26. package/dist/cli/compiler-host.js.map +1 -0
  27. package/dist/cli/fmt.d.ts +13 -0
  28. package/dist/cli/fmt.d.ts.map +1 -0
  29. package/dist/cli/fmt.js +14 -0
  30. package/dist/cli/fmt.js.map +1 -0
  31. package/dist/cli/init-command.js +12 -12
  32. package/dist/cli/init-command.js.map +1 -1
  33. package/dist/cli/loader.d.ts +0 -21
  34. package/dist/cli/loader.d.ts.map +1 -1
  35. package/dist/cli/loader.js +1 -50
  36. package/dist/cli/loader.js.map +1 -1
  37. package/dist/cli/schema.d.ts +2 -0
  38. package/dist/cli/schema.d.ts.map +1 -1
  39. package/dist/cli/schema.js +11 -4
  40. package/dist/cli/schema.js.map +1 -1
  41. package/dist/cli/workspace.d.ts +82 -0
  42. package/dist/cli/workspace.d.ts.map +1 -0
  43. package/dist/cli/workspace.js +248 -0
  44. package/dist/cli/workspace.js.map +1 -0
  45. package/dist/index.d.ts +6 -3
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +3 -3
  48. package/dist/index.js.map +1 -1
  49. package/dist/think-builder.d.ts +50 -2
  50. package/dist/think-builder.d.ts.map +1 -1
  51. package/dist/think-builder.js +137 -14
  52. package/dist/think-builder.js.map +1 -1
  53. package/dist/thought-event.d.ts +80 -0
  54. package/dist/thought-event.d.ts.map +1 -0
  55. package/dist/thought-event.js +2 -0
  56. package/dist/thought-event.js.map +1 -0
  57. package/dist/thought-stream.d.ts +45 -0
  58. package/dist/thought-stream.d.ts.map +1 -0
  59. package/dist/thought-stream.js +99 -0
  60. package/dist/thought-stream.js.map +1 -0
  61. package/dist-pkg/acp.cjs +37 -11
  62. package/dist-pkg/thinkwell.cjs +49 -18
  63. package/package.json +4 -9
  64. package/dist/cli/index.d.ts +0 -11
  65. package/dist/cli/index.d.ts.map +0 -1
  66. package/dist/cli/index.js +0 -11
  67. package/dist/cli/index.js.map +0 -1
  68. package/dist/cli/main-pkg.d.ts +0 -18
  69. package/dist/cli/main-pkg.d.ts.map +0 -1
  70. package/dist/cli/main.d.ts +0 -14
  71. package/dist/cli/main.d.ts.map +0 -1
  72. package/dist/cli/main.js +0 -256
  73. package/dist/cli/main.js.map +0 -1
  74. package/dist/cli/types-command.d.ts +0 -8
  75. package/dist/cli/types-command.d.ts.map +0 -1
  76. package/dist/cli/types-command.js +0 -110
  77. package/dist/cli/types-command.js.map +0 -1
package/README.md CHANGED
@@ -7,9 +7,7 @@ A TypeScript library for easy scripting of AI agents. Thinkwell provides a fluen
7
7
  ## Quick Start
8
8
 
9
9
  ```typescript
10
- import { CLAUDE_CODE } from "thinkwell/connectors";
11
- import { Agent } from "thinkwell";
12
- import { GreetingSchema } from "./greeting.schemas.js";
10
+ import { open } from "thinkwell";
13
11
 
14
12
  /**
15
13
  * A friendly greeting.
@@ -20,11 +18,11 @@ export interface Greeting {
20
18
  message: string;
21
19
  }
22
20
 
23
- const agent = await Agent.connect(CLAUDE_CODE);
21
+ const agent = await open('claude');
24
22
 
25
23
  try {
26
24
  const greeting: Greeting = await agent
27
- .think(GreetingSchema)
25
+ .think(Greeting.Schema)
28
26
  .text(`
29
27
  Use the current_time tool to get the current time, and create a
30
28
  friendly greeting message appropriate for that time of day.
package/bin/thinkwell CHANGED
@@ -7,11 +7,11 @@
7
7
  * It uses Node.js with the pkg-style loader for script execution, requiring
8
8
  * Node 24+ for native TypeScript support via --experimental-transform-types.
9
9
  *
10
- * The pkg binary distribution uses a separate entry point (main-pkg.cjs)
10
+ * The pkg binary distribution uses a separate entry point (main.cjs)
11
11
  * which is compiled directly into the binary.
12
12
  */
13
13
 
14
- import { spawn, spawnSync } from "node:child_process";
14
+ import { spawnSync } from "node:child_process";
15
15
  import { dirname, resolve, isAbsolute } from "node:path";
16
16
  import { fileURLToPath } from "node:url";
17
17
  import { existsSync } from "node:fs";
@@ -44,31 +44,37 @@ if (!process.env[REEXEC_FLAG]) {
44
44
  // Minimum Node.js version for native TypeScript support
45
45
  const MIN_NODE_VERSION = 24;
46
46
 
47
+ // ============================================================================
48
+ // Shared Imports (from compiled TypeScript)
49
+ // ============================================================================
50
+
51
+ const commandsPath = resolve(__dirname, "../dist/cli/commands.js");
52
+ const { showMainHelp, showNoScriptError, hasHelpFlag, fmtError } = await import(commandsPath);
53
+
47
54
  // ============================================================================
48
55
  // Path Helpers
49
56
  // ============================================================================
50
57
 
51
- // Get the path to the init command script
52
58
  function getInitCommandPath() {
53
59
  return resolve(__dirname, "../dist/cli/init-command.js");
54
60
  }
55
61
 
56
- // Get the path to the types command script
57
- function getTypesCommandPath() {
58
- return resolve(__dirname, "../dist/cli/types-command.js");
59
- }
60
-
61
- // Get the path to the build command script
62
62
  function getBuildCommandPath() {
63
63
  return resolve(__dirname, "../dist/cli/build.js");
64
64
  }
65
65
 
66
- // Get the path to the bundled CLI loader
66
+ function getCheckCommandPath() {
67
+ return resolve(__dirname, "../dist/cli/check.js");
68
+ }
69
+
70
+ function getBundleCommandPath() {
71
+ return resolve(__dirname, "../dist/cli/bundle.js");
72
+ }
73
+
67
74
  function getLoaderPath() {
68
75
  return resolve(__dirname, "../dist-pkg/cli-loader.cjs");
69
76
  }
70
77
 
71
- // Get paths to the bundled thinkwell packages
72
78
  function getBundledPackagesPath() {
73
79
  return {
74
80
  thinkwell: resolve(__dirname, "../dist-pkg/thinkwell.cjs"),
@@ -81,7 +87,6 @@ function getBundledPackagesPath() {
81
87
  // Runtime Detection
82
88
  // ============================================================================
83
89
 
84
- // Get Node.js major version
85
90
  function getNodeMajorVersion() {
86
91
  const match = process.version.match(/^v(\d+)/);
87
92
  return match ? parseInt(match[1], 10) : 0;
@@ -91,11 +96,10 @@ function getNodeMajorVersion() {
91
96
  // Validation
92
97
  // ============================================================================
93
98
 
94
- // Validate Node.js version
95
99
  function validateNodeVersion() {
96
100
  const nodeMajor = getNodeMajorVersion();
97
101
  if (nodeMajor < MIN_NODE_VERSION) {
98
- console.error(`Error: thinkwell requires Node.js ${MIN_NODE_VERSION} or later.`);
102
+ console.error(fmtError(`thinkwell requires Node.js ${MIN_NODE_VERSION} or later.`));
99
103
  console.error(`Current version: ${process.version}`);
100
104
  console.error("");
101
105
  console.error("Node.js 24+ is required for native TypeScript support.");
@@ -104,7 +108,6 @@ function validateNodeVersion() {
104
108
  }
105
109
  }
106
110
 
107
- // Validate that required files exist for script execution
108
111
  function validateInstallation() {
109
112
  const loaderPath = getLoaderPath();
110
113
  const bundledPaths = getBundledPackagesPath();
@@ -121,7 +124,7 @@ function validateInstallation() {
121
124
  }
122
125
 
123
126
  if (errors.length > 0) {
124
- console.error("Error: thinkwell installation appears to be corrupted.");
127
+ console.error(fmtError("thinkwell installation appears to be corrupted."));
125
128
  for (const error of errors) {
126
129
  console.error(` - ${error}`);
127
130
  }
@@ -130,28 +133,16 @@ function validateInstallation() {
130
133
  }
131
134
  }
132
135
 
133
- // Validate init command is available
134
136
  function validateInitCommand() {
135
137
  const initCommandPath = getInitCommandPath();
136
138
  if (!existsSync(initCommandPath)) {
137
- console.error("Error: thinkwell installation appears to be corrupted.");
139
+ console.error(fmtError("thinkwell installation appears to be corrupted."));
138
140
  console.error(` - Init command not found: ${initCommandPath}`);
139
141
  console.error("\nTry reinstalling with: npm install thinkwell");
140
142
  process.exit(1);
141
143
  }
142
144
  }
143
145
 
144
- // Validate types command is available
145
- function validateTypesCommand() {
146
- const typesCommandPath = getTypesCommandPath();
147
- if (!existsSync(typesCommandPath)) {
148
- console.error("Error: thinkwell installation appears to be corrupted.");
149
- console.error(` - Types command not found: ${typesCommandPath}`);
150
- console.error("\nTry reinstalling with: npm install thinkwell");
151
- process.exit(1);
152
- }
153
- }
154
-
155
146
  // Parse version from package.json
156
147
  async function getVersion() {
157
148
  const packagePath = resolve(__dirname, "../package.json");
@@ -159,43 +150,6 @@ async function getVersion() {
159
150
  return pkg.version;
160
151
  }
161
152
 
162
- // ============================================================================
163
- // Help
164
- // ============================================================================
165
-
166
- function showHelp() {
167
- console.log(`
168
- thinkwell - Run TypeScript scripts with automatic schema generation
169
-
170
- Usage:
171
- thinkwell <script.ts> [args...] Run a TypeScript script
172
- thinkwell run <script.ts> [args...] Explicit run command
173
- thinkwell build <script.ts> Compile to standalone executable
174
- thinkwell init [project-name] Initialize a new project
175
- thinkwell types [dir] Generate .d.ts files for IDE support
176
- thinkwell types --watch [dir] Watch and regenerate .d.ts files
177
- thinkwell --help Show this help message
178
- thinkwell --version Show version
179
-
180
- Examples:
181
- thinkwell hello.ts Run hello.ts
182
- thinkwell run hello.ts --verbose Run with arguments
183
- thinkwell build src/agent.ts Compile to binary
184
- thinkwell init my-agent Create a new project
185
- ./script.ts Via shebang: #!/usr/bin/env thinkwell
186
- thinkwell types Generate declarations in current dir
187
- thinkwell types src Generate declarations in src/
188
- thinkwell types --watch Watch for changes and regenerate
189
-
190
- The thinkwell CLI automatically:
191
- - Generates JSON Schema for types marked with @JSONSchema
192
- - Resolves thinkwell:* imports to built-in modules
193
- - Creates .thinkwell.d.ts files for IDE autocomplete (types command)
194
-
195
- For more information, visit: https://github.com/dherman/thinkwell
196
- `);
197
- }
198
-
199
153
  // ============================================================================
200
154
  // Bundled Module Registration
201
155
  // ============================================================================
@@ -204,7 +158,7 @@ For more information, visit: https://github.com/dherman/thinkwell
204
158
  * Register bundled thinkwell packages to global.__bundled__.
205
159
  *
206
160
  * For the npm distribution, we load the pre-bundled CJS packages from dist-pkg/.
207
- * This mirrors what main-pkg.cjs does for the pkg binary distribution.
161
+ * This mirrors what main.cjs does for the pkg binary distribution.
208
162
  */
209
163
  async function registerBundledModules() {
210
164
  const bundledPaths = getBundledPackagesPath();
@@ -222,7 +176,7 @@ async function registerBundledModules() {
222
176
  "@thinkwell/protocol": protocolModule.default || protocolModule,
223
177
  };
224
178
  } catch (error) {
225
- console.error("Error: Failed to load bundled modules.");
179
+ console.error(fmtError("Failed to load bundled modules."));
226
180
  console.error("");
227
181
  if (process.env.DEBUG) {
228
182
  console.error("Debug info:");
@@ -235,116 +189,128 @@ async function registerBundledModules() {
235
189
  }
236
190
 
237
191
  // ============================================================================
238
- // Script Execution
192
+ // CLI Commands
239
193
  // ============================================================================
240
194
 
195
+ /**
196
+ * Run the init command to scaffold a new project.
197
+ */
198
+ async function runInitCommand(args) {
199
+ validateInitCommand();
200
+ const initCommandPath = getInitCommandPath();
201
+ const { runInit } = await import(initCommandPath);
202
+ await runInit(args);
203
+ }
204
+
205
+ /**
206
+ * Run the build command (tsc-based compilation with @JSONSchema transformation).
207
+ */
208
+ async function runBuildCommand(args) {
209
+ const buildCommandPath = getBuildCommandPath();
210
+ const { parseBuildArgs, runBuild, showBuildHelp } = await import(buildCommandPath);
211
+
212
+ if (hasHelpFlag(args)) {
213
+ showBuildHelp();
214
+ return;
215
+ }
216
+
217
+ try {
218
+ const options = parseBuildArgs(args);
219
+ await runBuild(options);
220
+ } catch (error) {
221
+ console.error(fmtError(error.message));
222
+ process.exit(1);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Run the check command (type-check with @JSONSchema transformation, no emit).
228
+ */
229
+ async function runCheckCommand(args) {
230
+ const checkCommandPath = getCheckCommandPath();
231
+ const { parseCheckArgs, runCheck, showCheckHelp } = await import(checkCommandPath);
232
+
233
+ if (hasHelpFlag(args)) {
234
+ showCheckHelp();
235
+ return;
236
+ }
237
+
238
+ try {
239
+ const options = parseCheckArgs(args);
240
+ await runCheck(options);
241
+ } catch (error) {
242
+ console.error(fmtError(error.message));
243
+ process.exit(1);
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Run the bundle command to compile scripts into standalone executables.
249
+ */
250
+ async function runBundleCommand(args) {
251
+ const bundleCommandPath = getBundleCommandPath();
252
+ if (!existsSync(bundleCommandPath)) {
253
+ console.error(fmtError("thinkwell installation appears to be corrupted."));
254
+ console.error(` - Bundle command not found: ${bundleCommandPath}`);
255
+ console.error("\nTry reinstalling with: npm install thinkwell");
256
+ process.exit(1);
257
+ }
258
+
259
+ const { parseBundleArgs, runBundle, showBundleHelp } = await import(bundleCommandPath);
260
+
261
+ if (hasHelpFlag(args)) {
262
+ showBundleHelp();
263
+ return;
264
+ }
265
+
266
+ try {
267
+ const options = parseBundleArgs(args);
268
+ await runBundle(options);
269
+ } catch (error) {
270
+ console.error(fmtError(error.message));
271
+ process.exit(1);
272
+ }
273
+ }
274
+
241
275
  /**
242
276
  * Run a user script using the CLI loader.
243
277
  */
244
278
  async function runUserScript(scriptPath, args) {
245
- // Resolve the script path
246
279
  const resolvedPath = isAbsolute(scriptPath)
247
280
  ? scriptPath
248
281
  : resolve(process.cwd(), scriptPath);
249
282
 
250
- // Check if the script file exists
251
283
  if (!existsSync(resolvedPath)) {
252
- console.error(`Error: Script not found: ${scriptPath}`);
284
+ console.error(fmtError(`Script not found: ${scriptPath}`));
253
285
  console.error("");
254
286
  console.error("Make sure the file exists and the path is correct.");
255
287
  process.exit(1);
256
288
  }
257
289
 
258
- // Import the loader
259
290
  const loaderPath = getLoaderPath();
260
291
  const { runScript } = await import(loaderPath);
261
292
 
262
293
  try {
263
294
  await runScript(resolvedPath, args);
264
295
  } catch (error) {
265
- // Handle common error cases with helpful messages
266
296
  if (error.message && error.message.includes("Cannot find module")) {
267
- console.error(`Error: ${error.message}`);
297
+ console.error(fmtError(error.message));
268
298
  console.error("");
269
299
  console.error("Make sure the module is installed in your project's node_modules.");
270
300
  process.exit(1);
271
301
  }
272
302
 
273
303
  if (error.message && error.message.includes("Cannot find package")) {
274
- console.error(`Error: ${error.message}`);
304
+ console.error(fmtError(error.message));
275
305
  console.error("");
276
306
  console.error("Run 'npm install' or 'pnpm install' to install dependencies.");
277
307
  process.exit(1);
278
308
  }
279
309
 
280
- // Re-throw other errors
281
310
  throw error;
282
311
  }
283
312
  }
284
313
 
285
- /**
286
- * Run the build command to compile scripts into standalone executables.
287
- */
288
- async function runBuildCommand(args) {
289
- const buildCommandPath = getBuildCommandPath();
290
- if (!existsSync(buildCommandPath)) {
291
- console.error("Error: thinkwell installation appears to be corrupted.");
292
- console.error(` - Build command not found: ${buildCommandPath}`);
293
- console.error("\nTry reinstalling with: npm install thinkwell");
294
- process.exit(1);
295
- }
296
-
297
- // Import and run the build command
298
- const { parseBuildArgs, runBuild, showBuildHelp } = await import(buildCommandPath);
299
-
300
- // Check for help flag
301
- if (args.includes("--help") || args.includes("-h")) {
302
- showBuildHelp();
303
- process.exit(0);
304
- }
305
-
306
- try {
307
- const options = parseBuildArgs(args);
308
- await runBuild(options);
309
- } catch (error) {
310
- console.error(`Error: ${error.message}`);
311
- process.exit(1);
312
- }
313
- process.exit(0);
314
- }
315
-
316
- /**
317
- * Run the types command.
318
- *
319
- * The types command uses the same loader infrastructure to process
320
- * TypeScript files and generate .d.ts declarations.
321
- */
322
- async function runTypesCommand(args) {
323
- validateTypesCommand();
324
- const typesCommandPath = getTypesCommandPath();
325
-
326
- // Spawn Node.js with the types command
327
- const child = spawn(process.execPath, [
328
- "--experimental-transform-types",
329
- "--disable-warning=ExperimentalWarning",
330
- typesCommandPath,
331
- ...args,
332
- ], {
333
- stdio: "inherit",
334
- env: process.env,
335
- });
336
-
337
- child.on("error", (err) => {
338
- console.error(`Error: Failed to run types command.`);
339
- console.error(` ${err.message}`);
340
- process.exit(1);
341
- });
342
-
343
- child.on("exit", (code) => {
344
- process.exit(code ?? 0);
345
- });
346
- }
347
-
348
314
  // ============================================================================
349
315
  // Main Entry Point
350
316
  // ============================================================================
@@ -352,26 +318,33 @@ async function runTypesCommand(args) {
352
318
  async function main() {
353
319
  const args = process.argv.slice(2);
354
320
 
355
- // Handle "init" subcommand first - does NOT require bundled modules
356
- // Must be before global --help so "init --help" shows init-specific help
321
+ // Handle "init" subcommand - does NOT require bundled modules
357
322
  if (args[0] === "init") {
358
- validateInitCommand();
359
- const initArgs = args.slice(1);
360
- const initCommandPath = getInitCommandPath();
323
+ await runInitCommand(args.slice(1));
324
+ process.exit(0);
325
+ }
326
+
327
+ // Handle "bundle" subcommand
328
+ if (args[0] === "bundle") {
329
+ await runBundleCommand(args.slice(1));
330
+ process.exit(0);
331
+ }
332
+
333
+ // Handle "build" subcommand — tsc-based build with @JSONSchema transformation
334
+ if (args[0] === "build") {
335
+ await runBuildCommand(args.slice(1));
336
+ process.exit(0);
337
+ }
361
338
 
362
- // Import and run the init command
363
- const { runInit } = await import(initCommandPath);
364
- await runInit(initArgs);
339
+ // Handle "check" subcommand type-check with @JSONSchema transformation (no emit)
340
+ if (args[0] === "check") {
341
+ await runCheckCommand(args.slice(1));
365
342
  process.exit(0);
366
343
  }
367
344
 
368
- // Handle --help (global) - but not if it's a subcommand's help
369
- // e.g., "thinkwell build --help" should show build help, not global help
370
- const subcommands = ["init", "build", "types", "run"];
371
- const firstArg = args[0];
372
- const isSubcommandHelp = subcommands.includes(firstArg) && (args.includes("--help") || args.includes("-h"));
373
- if (!isSubcommandHelp && (args.includes("--help") || args.includes("-h") || args.length === 0)) {
374
- showHelp();
345
+ // Handle --help (global) - after subcommand checks
346
+ if (hasHelpFlag(args) || args.length === 0) {
347
+ showMainHelp();
375
348
  process.exit(0);
376
349
  }
377
350
 
@@ -382,18 +355,6 @@ async function main() {
382
355
  process.exit(0);
383
356
  }
384
357
 
385
- // Handle "types" subcommand
386
- if (args[0] === "types") {
387
- await runTypesCommand(args.slice(1));
388
- return;
389
- }
390
-
391
- // Handle "build" subcommand
392
- if (args[0] === "build") {
393
- await runBuildCommand(args.slice(1));
394
- return;
395
- }
396
-
397
358
  // All script execution requires Node 24+ and proper installation
398
359
  validateNodeVersion();
399
360
  validateInstallation();
@@ -401,12 +362,8 @@ async function main() {
401
362
  // Handle "run" subcommand - just strip it
402
363
  const runArgs = args[0] === "run" ? args.slice(1) : args;
403
364
 
404
- // If no script provided after "run", show help
405
365
  if (runArgs.length === 0) {
406
- console.error("Error: No script provided.");
407
- console.error("");
408
- console.error("Usage: thinkwell <script.ts> [args...]");
409
- process.exit(1);
366
+ showNoScriptError();
410
367
  }
411
368
 
412
369
  // Register bundled modules before loading user scripts
@@ -419,8 +376,7 @@ async function main() {
419
376
  }
420
377
 
421
378
  main().catch((error) => {
422
- console.error("Unexpected error:");
423
- console.error(` ${error.message || error}`);
379
+ console.error(fmtError(`Unexpected error: ${error.message || error}`));
424
380
  if (process.env.DEBUG) {
425
381
  console.error(error.stack);
426
382
  }