thinkwell 0.5.5 → 0.5.6
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/agent.d.ts.map +1 -1
- package/dist/agent.js +207 -279
- package/dist/agent.js.map +1 -1
- package/dist/build.js +44 -98
- package/dist/cli/build.js +92 -227
- package/dist/cli/bundle.js +570 -1136
- package/dist/cli/check.js +125 -214
- package/dist/cli/commands.js +63 -177
- package/dist/cli/compiler-host.js +81 -190
- package/dist/cli/dependency-check.js +125 -269
- package/dist/cli/dependency-errors.js +12 -84
- package/dist/cli/fmt.js +1 -13
- package/dist/cli/init-command.js +21 -68
- package/dist/cli/init.js +90 -220
- package/dist/cli/loader.js +95 -361
- package/dist/cli/new-command.js +25 -73
- package/dist/cli/package-manager.js +50 -117
- package/dist/cli/schema.js +89 -245
- package/dist/cli/workspace.js +92 -226
- package/dist/connectors/index.js +1 -7
- package/dist/generated/features.d.ts +5 -0
- package/dist/generated/features.d.ts.map +1 -0
- package/dist/generated/features.js +4 -0
- package/dist/generated/features.js.map +1 -0
- package/dist/index.js +0 -5
- package/dist/schema.js +3 -36
- package/dist/session.js +50 -82
- package/dist/think-builder.d.ts.map +1 -1
- package/dist/think-builder.js +269 -370
- package/dist/think-builder.js.map +1 -1
- package/dist/thought-event.d.ts +1 -0
- package/dist/thought-event.d.ts.map +1 -1
- package/dist/thought-event.js +0 -1
- package/dist/thought-stream.js +60 -96
- package/dist-pkg/acp.cjs +13385 -1876
- package/dist-pkg/cli-build.cjs +171 -369
- package/dist-pkg/cli-bundle.cjs +289 -690
- package/dist-pkg/cli-check.cjs +202 -415
- package/dist-pkg/cli-dependency-check.cjs +39 -82
- package/dist-pkg/cli-dependency-errors.cjs +9 -41
- package/dist-pkg/cli-loader.cjs +90 -173
- package/dist-pkg/protocol.cjs +2 -8
- package/dist-pkg/thinkwell.cjs +876 -1842
- package/package.json +7 -6
package/dist/cli/loader.js
CHANGED
|
@@ -1,395 +1,129 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom script loader for the compiled binary.
|
|
3
|
-
*
|
|
4
|
-
* This module provides the runtime infrastructure for loading and executing
|
|
5
|
-
* user scripts in the compiled binary. It handles:
|
|
6
|
-
*
|
|
7
|
-
* 1. **Module Resolution**: Routes imports to the appropriate source:
|
|
8
|
-
* - thinkwell packages → bundled packages via `global.__bundled__`
|
|
9
|
-
* - External packages → user's node_modules via `require.resolve()`
|
|
10
|
-
*
|
|
11
|
-
* 2. **Import Transformation**: Rewrites user script imports before execution:
|
|
12
|
-
* - `import { Agent } from "thinkwell"` → bundled thinkwell
|
|
13
|
-
*
|
|
14
|
-
* 3. **@JSONSchema Processing**: Generates JSON schemas for marked types and
|
|
15
|
-
* injects namespace declarations with SchemaProvider implementations.
|
|
16
|
-
*
|
|
17
|
-
* 4. **Script Loading**: Uses Node's require() with temp files for transformed scripts
|
|
18
|
-
*
|
|
19
|
-
* Unlike the Bun plugin which runs at bundle time, this loader operates at
|
|
20
|
-
* runtime when the user script is executed.
|
|
21
|
-
*/
|
|
22
1
|
import { readFileSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
23
2
|
import { dirname, join, isAbsolute, resolve, basename } from "node:path";
|
|
24
3
|
import { randomBytes } from "node:crypto";
|
|
25
4
|
import { createRequire } from "node:module";
|
|
26
5
|
import { hasJsonSchemaMarkers, transformJsonSchemas } from "./schema.js";
|
|
27
|
-
/**
|
|
28
|
-
* Package names that should be resolved from bundled modules.
|
|
29
|
-
*/
|
|
30
6
|
const BUNDLED_PACKAGES = ["thinkwell", "@thinkwell/acp", "@thinkwell/protocol"];
|
|
31
|
-
/**
|
|
32
|
-
* Initialize the bundled module registry.
|
|
33
|
-
*
|
|
34
|
-
* This should be called from main.cjs with the bundled package exports.
|
|
35
|
-
* The registry is used by createCustomRequire to route thinkwell imports.
|
|
36
|
-
*
|
|
37
|
-
* @param modules - Map of package names to their exports
|
|
38
|
-
*/
|
|
39
7
|
export function initializeBundledRegistry(modules) {
|
|
40
|
-
|
|
8
|
+
global.__bundled__ = modules;
|
|
41
9
|
}
|
|
42
|
-
|
|
43
|
-
* When set, thinkwell imports resolve from the project's node_modules
|
|
44
|
-
* instead of the bundled modules in global.__bundled__.
|
|
45
|
-
*
|
|
46
|
-
* Contains the project root directory path (for resolving project-local
|
|
47
|
-
* dependencies like ts-json-schema-generator), or undefined in zero-config mode.
|
|
48
|
-
*
|
|
49
|
-
* Set by main.cjs when a project has an explicit thinkwell dependency
|
|
50
|
-
* in its package.json (i.e., it's not using the zero-config binary mode).
|
|
51
|
-
*/
|
|
52
|
-
let __projectDir = undefined;
|
|
53
|
-
/**
|
|
54
|
-
* Enable explicit config mode.
|
|
55
|
-
*
|
|
56
|
-
* When called with a project directory, the loader skips bundled module lookups
|
|
57
|
-
* and virtual import transforms, allowing thinkwell packages to resolve from
|
|
58
|
-
* node_modules. The project directory is also used to resolve project-local
|
|
59
|
-
* ts-json-schema-generator for @JSONSchema processing.
|
|
60
|
-
*/
|
|
10
|
+
let __projectDir;
|
|
61
11
|
export function setExplicitConfig(projectDir) {
|
|
62
|
-
|
|
12
|
+
__projectDir = projectDir;
|
|
63
13
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Check if a module name refers to a bundled package.
|
|
66
|
-
*/
|
|
67
14
|
function isBundledPackage(moduleName) {
|
|
68
|
-
|
|
15
|
+
return BUNDLED_PACKAGES.includes(moduleName);
|
|
69
16
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Strip shebang line from source if present.
|
|
72
|
-
*
|
|
73
|
-
* Shebangs are valid for executable scripts but not valid JS/TS syntax.
|
|
74
|
-
* We need to strip them before Module._compile processes the source.
|
|
75
|
-
*
|
|
76
|
-
* @param source - The script source code
|
|
77
|
-
* @returns Tuple of [shebang line or empty string, rest of source]
|
|
78
|
-
*/
|
|
79
17
|
export function extractShebang(source) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
return ["", source];
|
|
18
|
+
if (source.startsWith("#!")) {
|
|
19
|
+
const newlineIndex = source.indexOf(`
|
|
20
|
+
`);
|
|
21
|
+
return newlineIndex !== -1 ? [source.slice(0, newlineIndex + 1), source.slice(newlineIndex + 1)] : [source, ""];
|
|
22
|
+
}
|
|
23
|
+
return ["", source];
|
|
88
24
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Transform imports to use the bundled module registry.
|
|
91
|
-
*
|
|
92
|
-
* In the compiled binary, we can't rely on Node's normal module resolution
|
|
93
|
-
* for bundled packages (they're in the /snapshot/ virtual filesystem).
|
|
94
|
-
* This transform rewrites imports to use global.__bundled__ directly.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```typescript
|
|
98
|
-
* // Input:
|
|
99
|
-
* import { Agent } from "thinkwell";
|
|
100
|
-
*
|
|
101
|
-
* // Output:
|
|
102
|
-
* const { Agent } = global.__bundled__["thinkwell"];
|
|
103
|
-
* ```
|
|
104
|
-
*
|
|
105
|
-
* @param source - The script source code
|
|
106
|
-
* @returns The source with bundled package imports transformed
|
|
107
|
-
*/
|
|
108
25
|
export function transformVirtualImports(source) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// Pattern: import Foo from "thinkwell" or import Foo from "@thinkwell/acp"
|
|
118
|
-
const defaultImportPattern = /import\s+(\w+)\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]/g;
|
|
119
|
-
source = source.replace(defaultImportPattern, (_, importName, packageName) => {
|
|
120
|
-
return `const ${importName} = global.__bundled__["${packageName}"].default || global.__bundled__["${packageName}"]`;
|
|
121
|
-
});
|
|
122
|
-
// Match namespace imports from thinkwell packages
|
|
123
|
-
// Pattern: import * as Foo from "thinkwell"
|
|
124
|
-
const namespaceImportPattern = /import\s+\*\s+as\s+(\w+)\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]/g;
|
|
125
|
-
source = source.replace(namespaceImportPattern, (_, importName, packageName) => {
|
|
126
|
-
return `const ${importName} = global.__bundled__["${packageName}"]`;
|
|
127
|
-
});
|
|
128
|
-
// Match type-only imports (remove them - they're only for TypeScript)
|
|
129
|
-
// Pattern: import type { Foo } from "thinkwell"
|
|
130
|
-
const typeImportPattern = /import\s+type\s+\{[^}]+\}\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]\s*;?/g;
|
|
131
|
-
source = source.replace(typeImportPattern, "");
|
|
132
|
-
return source;
|
|
26
|
+
const importPattern = /import\s+\{([^}]+)\}\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]/g;
|
|
27
|
+
source = source.replace(importPattern, (_, imports, packageName) => `const {${imports.trim()}} = global.__bundled__["${packageName}"]`);
|
|
28
|
+
const defaultImportPattern = /import\s+(\w+)\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]/g;
|
|
29
|
+
source = source.replace(defaultImportPattern, (_, importName, packageName) => `const ${importName} = global.__bundled__["${packageName}"].default || global.__bundled__["${packageName}"]`);
|
|
30
|
+
const namespaceImportPattern = /import\s+\*\s+as\s+(\w+)\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]/g;
|
|
31
|
+
source = source.replace(namespaceImportPattern, (_, importName, packageName) => `const ${importName} = global.__bundled__["${packageName}"]`);
|
|
32
|
+
const typeImportPattern = /import\s+type\s+\{[^}]+\}\s+from\s+['"](@thinkwell\/(?:acp|protocol)|thinkwell)['"]\s*;?/g;
|
|
33
|
+
return source = source.replace(typeImportPattern, ""), source;
|
|
133
34
|
}
|
|
134
|
-
/**
|
|
135
|
-
* Create a custom require function that routes imports appropriately.
|
|
136
|
-
*
|
|
137
|
-
* This function creates a require implementation that:
|
|
138
|
-
* 1. Checks bundled modules first (thinkwell packages)
|
|
139
|
-
* 2. Falls back to require.resolve from the script's directory
|
|
140
|
-
* 3. Falls back to global require for built-in modules
|
|
141
|
-
*
|
|
142
|
-
* @param scriptPath - Absolute path to the user script
|
|
143
|
-
* @returns A require function bound to the script's directory
|
|
144
|
-
*/
|
|
145
35
|
export function createCustomRequire(scriptPath) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (!__projectDir && global.__bundled__ && isBundledPackage(moduleName)) {
|
|
153
|
-
const bundled = global.__bundled__[moduleName];
|
|
154
|
-
if (bundled) {
|
|
155
|
-
return bundled;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// Try to resolve from the script's directory using baseRequire
|
|
159
|
-
try {
|
|
160
|
-
const resolved = baseRequire.resolve(moduleName, {
|
|
161
|
-
paths: [scriptDir, nodeModulesPath],
|
|
162
|
-
});
|
|
163
|
-
return baseRequire(resolved);
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
// Fall back to the base require without custom paths
|
|
167
|
-
return baseRequire(moduleName);
|
|
168
|
-
}
|
|
36
|
+
const scriptDir = dirname(scriptPath), nodeModulesPath = join(scriptDir, "node_modules"), baseRequire = createRequire(scriptPath);
|
|
37
|
+
function customRequire(moduleName) {
|
|
38
|
+
if (!__projectDir && global.__bundled__ && isBundledPackage(moduleName)) {
|
|
39
|
+
const bundled = global.__bundled__[moduleName];
|
|
40
|
+
if (bundled)
|
|
41
|
+
return bundled;
|
|
169
42
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// Try script directory paths first
|
|
178
|
-
const paths = options?.paths ?? [scriptDir, nodeModulesPath];
|
|
179
|
-
try {
|
|
180
|
-
return baseRequire.resolve(id, { paths });
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
return baseRequire.resolve(id, options);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
// Stub paths property
|
|
187
|
-
customRequire.resolve.paths = baseRequire.resolve.paths;
|
|
188
|
-
customRequire.cache = baseRequire.cache;
|
|
189
|
-
customRequire.extensions = baseRequire.extensions;
|
|
190
|
-
customRequire.main = baseRequire.main;
|
|
191
|
-
return customRequire;
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Check if source code needs transformation.
|
|
195
|
-
*
|
|
196
|
-
* In zero-config mode, thinkwell imports require transformation to use
|
|
197
|
-
* global.__bundled__. In explicit-config mode, thinkwell imports are left
|
|
198
|
-
* as-is (they resolve from node_modules), so they don't trigger transformation.
|
|
199
|
-
*
|
|
200
|
-
* @JSONSchema markers always require transformation regardless of mode.
|
|
201
|
-
*
|
|
202
|
-
* @param source - The script source code
|
|
203
|
-
* @returns true if the source needs transformation before loading
|
|
204
|
-
*/
|
|
205
|
-
function needsTransformation(source) {
|
|
206
|
-
// Check for @JSONSchema markers (always needs transformation)
|
|
207
|
-
if (hasJsonSchemaMarkers(source)) {
|
|
208
|
-
return true;
|
|
43
|
+
try {
|
|
44
|
+
const resolved = baseRequire.resolve(moduleName, {
|
|
45
|
+
paths: [scriptDir, nodeModulesPath]
|
|
46
|
+
});
|
|
47
|
+
return baseRequire(resolved);
|
|
48
|
+
} catch {
|
|
49
|
+
return baseRequire(moduleName);
|
|
209
50
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
51
|
+
}
|
|
52
|
+
return customRequire.resolve = ((id, options) => {
|
|
53
|
+
if (!__projectDir && global.__bundled__ && isBundledPackage(id))
|
|
54
|
+
return `/__bundled__/${id}`;
|
|
55
|
+
const paths = options?.paths ?? [scriptDir, nodeModulesPath];
|
|
56
|
+
try {
|
|
57
|
+
return baseRequire.resolve(id, { paths });
|
|
58
|
+
} catch {
|
|
59
|
+
return baseRequire.resolve(id, options);
|
|
213
60
|
}
|
|
214
|
-
|
|
61
|
+
}), customRequire.resolve.paths = baseRequire.resolve.paths, customRequire.cache = baseRequire.cache, customRequire.extensions = baseRequire.extensions, customRequire.main = baseRequire.main, customRequire;
|
|
62
|
+
}
|
|
63
|
+
function needsTransformation(source) {
|
|
64
|
+
return !!(hasJsonSchemaMarkers(source) || !__projectDir && /from\s+['"](?:thinkwell|@thinkwell\/(?:acp|protocol))['"]/.test(source));
|
|
215
65
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Generate a short random ID for temp file names.
|
|
218
|
-
*/
|
|
219
66
|
function randomId() {
|
|
220
|
-
|
|
67
|
+
return randomBytes(6).toString("base64url");
|
|
221
68
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Rewrite .js extensions to .ts in relative import specifiers when the .ts file exists.
|
|
224
|
-
*
|
|
225
|
-
* TypeScript convention allows importing `./foo.js` even when the source file is
|
|
226
|
-
* `./foo.ts` (since tsc compiles .ts to .js). Node's --experimental-transform-types
|
|
227
|
-
* does not perform this remapping, so we do it here to support the common convention.
|
|
228
|
-
*
|
|
229
|
-
* @param originalPath - Absolute path to the original script (used to resolve relative paths)
|
|
230
|
-
* @param source - The script source code
|
|
231
|
-
* @returns The source with .js extensions rewritten to .ts where the .ts file exists
|
|
232
|
-
*/
|
|
233
69
|
export function rewriteJsToTsExtensions(originalPath, source) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
});
|
|
243
|
-
// Match dynamic imports: import("./foo.js") or import('../bar.js')
|
|
244
|
-
source = source.replace(/(import\s*\(\s*['"])(\.\.?\/[^'"]*?)\.js(['"]\s*\))/g, (match, prefix, specifierBase, suffix) => {
|
|
245
|
-
const tsPath = resolve(scriptDir, `${specifierBase}.ts`);
|
|
246
|
-
if (existsSync(tsPath)) {
|
|
247
|
-
return `${prefix}${specifierBase}.ts${suffix}`;
|
|
248
|
-
}
|
|
249
|
-
return match;
|
|
250
|
-
});
|
|
251
|
-
return source;
|
|
70
|
+
const scriptDir = dirname(originalPath);
|
|
71
|
+
return source = source.replace(/(from\s+['"])(\.\.?\/[^'"]*?)\.js(['"])/g, (match, prefix, specifierBase, suffix) => {
|
|
72
|
+
const tsPath = resolve(scriptDir, `${specifierBase}.ts`);
|
|
73
|
+
return existsSync(tsPath) ? `${prefix}${specifierBase}.ts${suffix}` : match;
|
|
74
|
+
}), source = source.replace(/(import\s*\(\s*['"])(\.\.?\/[^'"]*?)\.js(['"]\s*\))/g, (match, prefix, specifierBase, suffix) => {
|
|
75
|
+
const tsPath = resolve(scriptDir, `${specifierBase}.ts`);
|
|
76
|
+
return existsSync(tsPath) ? `${prefix}${specifierBase}.ts${suffix}` : match;
|
|
77
|
+
}), source;
|
|
252
78
|
}
|
|
253
|
-
/**
|
|
254
|
-
* Generate a preamble that patches import.meta properties to point to the original script.
|
|
255
|
-
*
|
|
256
|
-
* When we transform a script and write it to a temp file, import.meta.url, dirname,
|
|
257
|
-
* and filename would point to the temp file instead of the original. This breaks
|
|
258
|
-
* scripts that use these properties to locate sibling files.
|
|
259
|
-
*
|
|
260
|
-
* We patch import.meta by redefining these properties to return values based on
|
|
261
|
-
* the original script's location.
|
|
262
|
-
*
|
|
263
|
-
* @param originalPath - Absolute path to the original script
|
|
264
|
-
* @returns JavaScript code to prepend to the transformed script
|
|
265
|
-
*/
|
|
266
79
|
function generateImportMetaPatch(originalPath) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
`Object.defineProperty(import.meta, 'url', { value: '${escape(fileUrl)}', writable: false, configurable: true });`,
|
|
276
|
-
`Object.defineProperty(import.meta, 'dirname', { value: '${escape(originalDir)}', writable: false, configurable: true });`,
|
|
277
|
-
`Object.defineProperty(import.meta, 'filename', { value: '${escape(originalFilename)}', writable: false, configurable: true });`,
|
|
278
|
-
"",
|
|
279
|
-
].join("\n");
|
|
80
|
+
const fileUrl = `file://${originalPath}`, originalDir = dirname(originalPath), originalFilename = originalPath, escape = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
81
|
+
return [
|
|
82
|
+
`Object.defineProperty(import.meta, 'url', { value: '${escape(fileUrl)}', writable: false, configurable: true });`,
|
|
83
|
+
`Object.defineProperty(import.meta, 'dirname', { value: '${escape(originalDir)}', writable: false, configurable: true });`,
|
|
84
|
+
`Object.defineProperty(import.meta, 'filename', { value: '${escape(originalFilename)}', writable: false, configurable: true });`,
|
|
85
|
+
""
|
|
86
|
+
].join(`
|
|
87
|
+
`);
|
|
280
88
|
}
|
|
281
|
-
/**
|
|
282
|
-
* Load and execute a user script with custom module resolution.
|
|
283
|
-
*
|
|
284
|
-
* This function handles two loading strategies:
|
|
285
|
-
*
|
|
286
|
-
* 1. **Direct require()** - For scripts that don't use thinkwell imports.
|
|
287
|
-
* This leverages Node's --experimental-strip-types for TypeScript support.
|
|
288
|
-
*
|
|
289
|
-
* 2. **Transform and compile** - For scripts that use thinkwell:* imports
|
|
290
|
-
* or import from bundled packages. The script is transformed and written
|
|
291
|
-
* to a temp file, then required (which applies type stripping).
|
|
292
|
-
*
|
|
293
|
-
* @param scriptPath - Absolute path to the script to load
|
|
294
|
-
* @returns The module exports from the script
|
|
295
|
-
* @throws Error if the script cannot be loaded or executed
|
|
296
|
-
*/
|
|
297
89
|
export function loadScript(scriptPath) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!needsTransformation(sourceWithoutShebang)) {
|
|
308
|
-
// No transformation needed - use direct require()
|
|
309
|
-
// This preserves Node's type stripping for TypeScript files
|
|
310
|
-
const baseRequire = createRequire(absolutePath);
|
|
311
|
-
return baseRequire(absolutePath);
|
|
312
|
-
}
|
|
313
|
-
// Source needs transformation - apply transforms and use a temp file
|
|
314
|
-
// Process @JSONSchema types (must happen before import transformation
|
|
315
|
-
// because it adds an import statement that also needs transformation)
|
|
316
|
-
let source = transformJsonSchemas(absolutePath, sourceWithoutShebang, __projectDir);
|
|
317
|
-
// In zero-config mode, rewrite thinkwell imports to use global.__bundled__.
|
|
318
|
-
// In explicit-config mode, leave imports as-is so they resolve from node_modules.
|
|
319
|
-
if (!__projectDir) {
|
|
320
|
-
source = transformVirtualImports(source);
|
|
321
|
-
}
|
|
322
|
-
// Rewrite .js → .ts in relative imports for TypeScript convention compatibility
|
|
323
|
-
source = rewriteJsToTsExtensions(absolutePath, source);
|
|
324
|
-
// Prepend import.meta.url patch so scripts can locate sibling files
|
|
325
|
-
source = generateImportMetaPatch(absolutePath) + source;
|
|
326
|
-
// Write transformed source as a sibling of the original script so that
|
|
327
|
-
// relative imports resolve correctly through Node's module loader.
|
|
328
|
-
const ext = absolutePath.endsWith(".ts") ? ".ts" : ".js";
|
|
329
|
-
const scriptDir = dirname(absolutePath);
|
|
330
|
-
const tempFile = join(scriptDir, `.thinkwell-${basename(absolutePath, ext)}-${randomId()}${ext}`);
|
|
90
|
+
const absolutePath = isAbsolute(scriptPath) ? scriptPath : resolve(process.cwd(), scriptPath), rawSource = readFileSync(absolutePath, "utf-8"), [, sourceWithoutShebang] = extractShebang(rawSource);
|
|
91
|
+
if (!needsTransformation(sourceWithoutShebang))
|
|
92
|
+
return createRequire(absolutePath)(absolutePath);
|
|
93
|
+
let source = transformJsonSchemas(absolutePath, sourceWithoutShebang, __projectDir);
|
|
94
|
+
__projectDir || (source = transformVirtualImports(source)), source = rewriteJsToTsExtensions(absolutePath, source), source = generateImportMetaPatch(absolutePath) + source;
|
|
95
|
+
const ext = absolutePath.endsWith(".ts") ? ".ts" : ".js", scriptDir = dirname(absolutePath), tempFile = join(scriptDir, `.thinkwell-${basename(absolutePath, ext)}-${randomId()}${ext}`);
|
|
96
|
+
try {
|
|
97
|
+
return writeFileSync(tempFile, source, "utf-8"), createRequire(absolutePath)(tempFile);
|
|
98
|
+
} finally {
|
|
331
99
|
try {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
// Require the transformed file - this uses Node's type stripping
|
|
335
|
-
const baseRequire = createRequire(absolutePath);
|
|
336
|
-
const result = baseRequire(tempFile);
|
|
337
|
-
return result;
|
|
338
|
-
}
|
|
339
|
-
finally {
|
|
340
|
-
// Clean up temp file
|
|
341
|
-
try {
|
|
342
|
-
rmSync(tempFile);
|
|
343
|
-
}
|
|
344
|
-
catch {
|
|
345
|
-
// Ignore cleanup errors
|
|
346
|
-
}
|
|
100
|
+
rmSync(tempFile);
|
|
101
|
+
} catch {
|
|
347
102
|
}
|
|
103
|
+
}
|
|
348
104
|
}
|
|
349
|
-
/**
|
|
350
|
-
* Load and execute a user script, handling both sync and async exports.
|
|
351
|
-
*
|
|
352
|
-
* After loading, this function checks if the script exports a main function
|
|
353
|
-
* or default export and executes it if present.
|
|
354
|
-
*
|
|
355
|
-
* @param scriptPath - Absolute path to the script to load
|
|
356
|
-
* @param args - Additional arguments to pass to the script's argv
|
|
357
|
-
* @returns Promise that resolves when script execution completes
|
|
358
|
-
*/
|
|
359
105
|
export async function runScript(scriptPath, args = []) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
// Pattern 3: run function
|
|
379
|
-
if (typeof mod.run === "function") {
|
|
380
|
-
await mod.run();
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
// Pattern 4: direct function export
|
|
385
|
-
if (typeof exports === "function") {
|
|
386
|
-
await exports();
|
|
387
|
-
}
|
|
388
|
-
// Otherwise, the script executed its code at module level
|
|
389
|
-
}
|
|
390
|
-
finally {
|
|
391
|
-
// Restore original argv
|
|
392
|
-
process.argv = originalArgv;
|
|
106
|
+
const originalArgv = process.argv;
|
|
107
|
+
process.argv = [process.execPath, scriptPath, ...args];
|
|
108
|
+
try {
|
|
109
|
+
const exports = loadScript(scriptPath);
|
|
110
|
+
if (exports && typeof exports == "object") {
|
|
111
|
+
const mod = exports;
|
|
112
|
+
if (typeof mod.default == "function") {
|
|
113
|
+
await mod.default();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (typeof mod.main == "function") {
|
|
117
|
+
await mod.main();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (typeof mod.run == "function") {
|
|
121
|
+
await mod.run();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
393
124
|
}
|
|
125
|
+
typeof exports == "function" && await exports();
|
|
126
|
+
} finally {
|
|
127
|
+
process.argv = originalArgv;
|
|
128
|
+
}
|
|
394
129
|
}
|
|
395
|
-
//# sourceMappingURL=loader.js.map
|
package/dist/cli/new-command.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI command for creating a new thinkwell project in a new directory.
|
|
3
|
-
*
|
|
4
|
-
* This command scaffolds a new project with the necessary configuration
|
|
5
|
-
* and example files.
|
|
6
|
-
*
|
|
7
|
-
* Following Cargo's design: "new" creates a new directory, while "init"
|
|
8
|
-
* modifies existing state in the current directory.
|
|
9
|
-
*/
|
|
10
1
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
11
2
|
import { join, resolve } from "node:path";
|
|
12
3
|
import { cyan, cyanBold, greenBold, whiteBold, dim, redBold } from "./fmt.js";
|
|
@@ -22,8 +13,7 @@ const PACKAGE_JSON_TEMPLATE = (name) => `{
|
|
|
22
13
|
"thinkwell": "^0.2.0"
|
|
23
14
|
}
|
|
24
15
|
}
|
|
25
|
-
|
|
26
|
-
const MAIN_TS_TEMPLATE = `import { open } from "thinkwell";
|
|
16
|
+
`, MAIN_TS_TEMPLATE = `import { open } from "thinkwell";
|
|
27
17
|
|
|
28
18
|
/**
|
|
29
19
|
* A greeting response from the agent.
|
|
@@ -46,8 +36,7 @@ async function main() {
|
|
|
46
36
|
}
|
|
47
37
|
|
|
48
38
|
main().catch(console.error);
|
|
49
|
-
|
|
50
|
-
const TSCONFIG_TEMPLATE = `{
|
|
39
|
+
`, TSCONFIG_TEMPLATE = `{
|
|
51
40
|
"compilerOptions": {
|
|
52
41
|
"target": "ES2022",
|
|
53
42
|
"module": "NodeNext",
|
|
@@ -60,30 +49,20 @@ const TSCONFIG_TEMPLATE = `{
|
|
|
60
49
|
},
|
|
61
50
|
"include": ["src/**/*"]
|
|
62
51
|
}
|
|
63
|
-
|
|
64
|
-
const GITIGNORE_TEMPLATE = `node_modules/
|
|
52
|
+
`, GITIGNORE_TEMPLATE = `node_modules/
|
|
65
53
|
dist/
|
|
66
54
|
*.thinkwell.d.ts
|
|
67
55
|
.env
|
|
68
|
-
|
|
69
|
-
const ENV_EXAMPLE_TEMPLATE = `# Configure your agent command
|
|
56
|
+
`, ENV_EXAMPLE_TEMPLATE = `# Configure your agent command
|
|
70
57
|
# Example for Claude Code:
|
|
71
58
|
# THINKWELL_AGENT_CMD=claude --dangerously-skip-permissions
|
|
72
59
|
`;
|
|
73
60
|
function createProject(options) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
mkdirSync(targetDir, { recursive: true });
|
|
77
|
-
mkdirSync(join(targetDir, "src"), { recursive: true });
|
|
78
|
-
// Write files
|
|
79
|
-
writeFileSync(join(targetDir, "package.json"), PACKAGE_JSON_TEMPLATE(name));
|
|
80
|
-
writeFileSync(join(targetDir, "src/main.ts"), MAIN_TS_TEMPLATE);
|
|
81
|
-
writeFileSync(join(targetDir, "tsconfig.json"), TSCONFIG_TEMPLATE);
|
|
82
|
-
writeFileSync(join(targetDir, ".gitignore"), GITIGNORE_TEMPLATE);
|
|
83
|
-
writeFileSync(join(targetDir, ".env.example"), ENV_EXAMPLE_TEMPLATE);
|
|
61
|
+
const { name, targetDir } = options;
|
|
62
|
+
mkdirSync(targetDir, { recursive: !0 }), mkdirSync(join(targetDir, "src"), { recursive: !0 }), writeFileSync(join(targetDir, "package.json"), PACKAGE_JSON_TEMPLATE(name)), writeFileSync(join(targetDir, "src/main.ts"), MAIN_TS_TEMPLATE), writeFileSync(join(targetDir, "tsconfig.json"), TSCONFIG_TEMPLATE), writeFileSync(join(targetDir, ".gitignore"), GITIGNORE_TEMPLATE), writeFileSync(join(targetDir, ".env.example"), ENV_EXAMPLE_TEMPLATE);
|
|
84
63
|
}
|
|
85
64
|
function showHelp() {
|
|
86
|
-
|
|
65
|
+
console.log(`
|
|
87
66
|
${cyanBold("thinkwell new")} - ${whiteBold("Create a new thinkwell project in a new directory")}
|
|
88
67
|
|
|
89
68
|
${greenBold("Usage:")}
|
|
@@ -104,52 +83,25 @@ ${greenBold("This command creates:")}
|
|
|
104
83
|
|
|
105
84
|
${greenBold("To initialize the current directory instead:")}
|
|
106
85
|
${cyanBold("thinkwell init")}
|
|
107
|
-
`.trim() +
|
|
86
|
+
`.trim() + `
|
|
87
|
+
`);
|
|
108
88
|
}
|
|
109
89
|
export async function runNew(args) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
console.error(
|
|
123
|
-
|
|
124
|
-
console.error(` ${cyanBold("thinkwell init")}`);
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
const targetDir = resolve(projectArg);
|
|
128
|
-
const name = projectArg;
|
|
129
|
-
// Check if directory exists and is not empty
|
|
130
|
-
if (existsSync(targetDir)) {
|
|
131
|
-
const files = ["package.json", "tsconfig.json", "src/main.ts"];
|
|
132
|
-
const existingFiles = files.filter((f) => existsSync(join(targetDir, f)));
|
|
133
|
-
if (existingFiles.length > 0) {
|
|
134
|
-
console.error(`${redBold("Error:")} Directory already contains project files:`);
|
|
135
|
-
for (const file of existingFiles) {
|
|
136
|
-
console.error(` - ${file}`);
|
|
137
|
-
}
|
|
138
|
-
console.error("");
|
|
139
|
-
console.error("Use a different directory or remove existing files.");
|
|
140
|
-
process.exit(1);
|
|
141
|
-
}
|
|
90
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
91
|
+
showHelp();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const projectArg = args.find((arg) => !arg.startsWith("-"));
|
|
95
|
+
projectArg || (console.error(`${redBold("Error:")} Project name is required.`), console.error(""), console.error("Usage:"), console.error(` ${cyanBold("thinkwell new")} ${cyan("<project-name>")}`), console.error(""), console.error("To initialize the current directory instead:"), console.error(` ${cyanBold("thinkwell init")}`), process.exit(1));
|
|
96
|
+
const targetDir = resolve(projectArg), name = projectArg;
|
|
97
|
+
if (existsSync(targetDir)) {
|
|
98
|
+
const existingFiles = ["package.json", "tsconfig.json", "src/main.ts"].filter((f) => existsSync(join(targetDir, f)));
|
|
99
|
+
if (existingFiles.length > 0) {
|
|
100
|
+
console.error(`${redBold("Error:")} Directory already contains project files:`);
|
|
101
|
+
for (const file of existingFiles)
|
|
102
|
+
console.error(` - ${file}`);
|
|
103
|
+
console.error(""), console.error("Use a different directory or remove existing files."), process.exit(1);
|
|
142
104
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
createProject({ name, targetDir });
|
|
146
|
-
console.log(greenBold("Next steps:"));
|
|
147
|
-
console.log("");
|
|
148
|
-
console.log(` ${cyanBold("cd")} ${cyan(projectArg)}`);
|
|
149
|
-
console.log(` ${cyanBold("npm install")} ${dim("# or: pnpm install")}`);
|
|
150
|
-
console.log(` ${cyanBold("cp")} ${cyan(".env.example .env")}`);
|
|
151
|
-
console.log(` ${dim("# Edit .env to configure your agent")}`);
|
|
152
|
-
console.log(` ${cyanBold("thinkwell")} ${cyan("src/main.ts")}`);
|
|
153
|
-
console.log("");
|
|
105
|
+
}
|
|
106
|
+
console.log(`${greenBold("Creating")} thinkwell project in ${targetDir}...`), console.log(""), createProject({ name, targetDir }), console.log(greenBold("Next steps:")), console.log(""), console.log(` ${cyanBold("cd")} ${cyan(projectArg)}`), console.log(` ${cyanBold("npm install")} ${dim("# or: pnpm install")}`), console.log(` ${cyanBold("cp")} ${cyan(".env.example .env")}`), console.log(` ${dim("# Edit .env to configure your agent")}`), console.log(` ${cyanBold("thinkwell")} ${cyan("src/main.ts")}`), console.log("");
|
|
154
107
|
}
|
|
155
|
-
//# sourceMappingURL=new-command.js.map
|