keystone-cli 2.0.0 → 2.1.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 +43 -4
- package/package.json +4 -1
- package/src/cli.ts +1 -0
- package/src/commands/event.ts +9 -0
- package/src/commands/run.ts +17 -0
- package/src/db/dynamic-state-manager.ts +12 -9
- package/src/db/memory-db.test.ts +19 -1
- package/src/db/memory-db.ts +101 -22
- package/src/db/workflow-db.ts +181 -9
- package/src/expression/evaluator.ts +4 -1
- package/src/parser/config-schema.ts +6 -0
- package/src/parser/schema.ts +1 -0
- package/src/runner/__test__/llm-test-setup.ts +43 -11
- package/src/runner/durable-timers.test.ts +1 -1
- package/src/runner/executors/dynamic-executor.ts +125 -88
- package/src/runner/executors/engine-executor.ts +10 -39
- package/src/runner/executors/file-executor.ts +67 -0
- package/src/runner/executors/foreach-executor.ts +170 -17
- package/src/runner/executors/human-executor.ts +18 -0
- package/src/runner/executors/llm/stream-handler.ts +103 -0
- package/src/runner/executors/llm/tool-manager.ts +360 -0
- package/src/runner/executors/llm-executor.ts +288 -555
- package/src/runner/executors/memory-executor.ts +41 -34
- package/src/runner/executors/shell-executor.ts +96 -52
- package/src/runner/executors/subworkflow-executor.ts +16 -0
- package/src/runner/executors/types.ts +3 -1
- package/src/runner/executors/verification_fixes.test.ts +46 -0
- package/src/runner/join-scheduling.test.ts +2 -1
- package/src/runner/llm-adapter.integration.test.ts +10 -5
- package/src/runner/llm-adapter.ts +57 -18
- package/src/runner/llm-clarification.test.ts +4 -1
- package/src/runner/llm-executor.test.ts +21 -7
- package/src/runner/mcp-client.ts +36 -2
- package/src/runner/mcp-server.ts +65 -36
- package/src/runner/recovery-security.test.ts +5 -2
- package/src/runner/reflexion.test.ts +6 -3
- package/src/runner/services/context-builder.ts +13 -4
- package/src/runner/services/workflow-validator.ts +2 -1
- package/src/runner/standard-tools-ast.test.ts +4 -2
- package/src/runner/standard-tools-execution.test.ts +14 -1
- package/src/runner/standard-tools-integration.test.ts +6 -0
- package/src/runner/standard-tools.ts +13 -10
- package/src/runner/step-executor.ts +2 -2
- package/src/runner/tool-integration.test.ts +4 -1
- package/src/runner/workflow-runner.test.ts +23 -12
- package/src/runner/workflow-runner.ts +172 -79
- package/src/runner/workflow-state.ts +181 -111
- package/src/ui/dashboard.tsx +17 -3
- package/src/utils/config-loader.ts +4 -0
- package/src/utils/constants.ts +4 -0
- package/src/utils/context-injector.test.ts +27 -27
- package/src/utils/context-injector.ts +68 -26
- package/src/utils/process-sandbox.ts +138 -148
- package/src/utils/redactor.ts +39 -9
- package/src/utils/resource-loader.ts +24 -19
- package/src/utils/sandbox.ts +6 -0
- package/src/utils/stream-utils.ts +58 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { bundleAssets } from './assets.macro.ts' with { type: 'macro' };
|
|
4
5
|
|
|
@@ -129,30 +130,34 @@ export class ResourceLoader {
|
|
|
129
130
|
return false;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Returns the manifest of embedded assets.
|
|
135
|
+
*/
|
|
136
|
+
static getEmbeddedAssets(): Record<string, string> {
|
|
137
|
+
return { ...EMBEDDED_ASSETS };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private static getProjectRelativePath(targetPath: string): string | null {
|
|
133
141
|
const cwd = process.cwd();
|
|
134
142
|
const keystoneDir = join(cwd, '.keystone');
|
|
135
143
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
// Use path.resolve to handle potential .. and normalization
|
|
145
|
+
const absTarget = join(cwd, targetPath); // assume relative to cwd if not absolute, checking resolve
|
|
146
|
+
// Actually, join/resolve logic:
|
|
147
|
+
// If targetPath is absolute, resolve returns it. If relative, joins with cwd.
|
|
148
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
149
|
+
const resolvedKeystone = path.resolve(keystoneDir);
|
|
150
|
+
|
|
151
|
+
// Check if target is inside keystone dir
|
|
152
|
+
// We use relative() to check containment
|
|
153
|
+
const rel = path.relative(resolvedKeystone, resolvedTarget);
|
|
154
|
+
|
|
155
|
+
// If rel starts with '..', it is outside. If strictly inside, it won't start with ..
|
|
156
|
+
// Also internal paths shouldn't be absolute (on windows relative might return absolute if different drive)
|
|
157
|
+
if (!rel.startsWith('..') && !path.isAbsolute(rel)) {
|
|
158
|
+
return rel;
|
|
147
159
|
}
|
|
148
160
|
|
|
149
161
|
return null;
|
|
150
162
|
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Get all embedded assets for debugging/manifest
|
|
154
|
-
*/
|
|
155
|
-
static getEmbeddedAssets(): Record<string, string> {
|
|
156
|
-
return EMBEDDED_ASSETS;
|
|
157
|
-
}
|
|
158
163
|
}
|
package/src/utils/sandbox.ts
CHANGED
|
@@ -109,6 +109,12 @@ export class SafeSandbox {
|
|
|
109
109
|
options: SandboxOptions = {}
|
|
110
110
|
): Promise<unknown> {
|
|
111
111
|
// Show warning once per process
|
|
112
|
+
if (process.env.NODE_ENV === 'production') {
|
|
113
|
+
throw new Error(
|
|
114
|
+
'Security Error: Insecure VM fallback is disabled in production environment. Use process isolation.'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
112
118
|
if (!SafeSandbox.warned) {
|
|
113
119
|
SafeSandbox.logger.warn(
|
|
114
120
|
'\n⚠️ SECURITY WARNING: Using Bun/Node.js built-in VM for script execution.\n' +
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
2
|
+
|
|
3
|
+
export const TRUNCATED_SUFFIX = '\n... [truncated]';
|
|
4
|
+
|
|
5
|
+
export interface OutputLimiter {
|
|
6
|
+
append(chunk: Buffer | string): void;
|
|
7
|
+
finalize(): string;
|
|
8
|
+
readonly truncated: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a limiter that accumulates output up to a maximum number of bytes.
|
|
13
|
+
* Handles multi-byte character boundaries correctly using StringDecoder.
|
|
14
|
+
*/
|
|
15
|
+
export function createOutputLimiter(maxBytes: number): OutputLimiter {
|
|
16
|
+
let bytes = 0;
|
|
17
|
+
let text = '';
|
|
18
|
+
let truncated = false;
|
|
19
|
+
// Use StringDecoder to correctly handle multi-byte characters split across chunks
|
|
20
|
+
const decoder = new StringDecoder('utf8');
|
|
21
|
+
|
|
22
|
+
const append = (chunk: Buffer | string) => {
|
|
23
|
+
if (truncated || maxBytes <= 0) {
|
|
24
|
+
truncated = true;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
28
|
+
const remaining = maxBytes - bytes;
|
|
29
|
+
if (remaining <= 0) {
|
|
30
|
+
truncated = true;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (buffer.length <= remaining) {
|
|
34
|
+
text += decoder.write(buffer);
|
|
35
|
+
bytes += buffer.length;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Truncate logic: decode up to allowable bytes
|
|
39
|
+
const sub = buffer.subarray(0, remaining);
|
|
40
|
+
text += decoder.write(sub);
|
|
41
|
+
bytes = maxBytes;
|
|
42
|
+
truncated = true;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const finalize = () => {
|
|
46
|
+
// Flush any remaining bytes in the decoder
|
|
47
|
+
text += decoder.end();
|
|
48
|
+
return truncated ? `${text}${TRUNCATED_SUFFIX}` : text;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
append,
|
|
53
|
+
finalize,
|
|
54
|
+
get truncated() {
|
|
55
|
+
return truncated;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|