@vibe-lang/runtime 0.2.5
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/package.json +46 -0
- package/src/ast/index.ts +375 -0
- package/src/ast.ts +2 -0
- package/src/debug/advanced-features.ts +482 -0
- package/src/debug/bun-inspector.ts +424 -0
- package/src/debug/handoff-manager.ts +283 -0
- package/src/debug/index.ts +150 -0
- package/src/debug/runner.ts +365 -0
- package/src/debug/server.ts +565 -0
- package/src/debug/stack-merger.ts +267 -0
- package/src/debug/state.ts +581 -0
- package/src/debug/test/advanced-features.test.ts +300 -0
- package/src/debug/test/e2e.test.ts +218 -0
- package/src/debug/test/handoff-manager.test.ts +256 -0
- package/src/debug/test/runner.test.ts +256 -0
- package/src/debug/test/stack-merger.test.ts +163 -0
- package/src/debug/test/state.test.ts +400 -0
- package/src/debug/test/ts-debug-integration.test.ts +374 -0
- package/src/debug/test/ts-import-tracker.test.ts +125 -0
- package/src/debug/test/ts-source-map.test.ts +169 -0
- package/src/debug/ts-import-tracker.ts +151 -0
- package/src/debug/ts-source-map.ts +171 -0
- package/src/errors/index.ts +124 -0
- package/src/index.ts +358 -0
- package/src/lexer/index.ts +348 -0
- package/src/lexer.ts +2 -0
- package/src/parser/index.ts +792 -0
- package/src/parser/parse.ts +45 -0
- package/src/parser/test/async.test.ts +248 -0
- package/src/parser/test/destructuring.test.ts +167 -0
- package/src/parser/test/do-expression.test.ts +486 -0
- package/src/parser/test/errors/do-expression.test.ts +95 -0
- package/src/parser/test/errors/error-locations.test.ts +230 -0
- package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
- package/src/parser/test/errors/missing-tokens.test.ts +126 -0
- package/src/parser/test/errors/model-declaration.test.ts +185 -0
- package/src/parser/test/errors/nested-blocks.test.ts +226 -0
- package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
- package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
- package/src/parser/test/import-export.test.ts +143 -0
- package/src/parser/test/literals.test.ts +404 -0
- package/src/parser/test/model-declaration.test.ts +161 -0
- package/src/parser/test/nested-blocks.test.ts +402 -0
- package/src/parser/test/parser.test.ts +743 -0
- package/src/parser/test/private.test.ts +136 -0
- package/src/parser/test/template-literal.test.ts +127 -0
- package/src/parser/test/tool-declaration.test.ts +302 -0
- package/src/parser/test/ts-block.test.ts +252 -0
- package/src/parser/test/type-annotations.test.ts +254 -0
- package/src/parser/visitor/helpers.ts +330 -0
- package/src/parser/visitor.ts +794 -0
- package/src/parser.ts +2 -0
- package/src/runtime/ai/cache-chunking.test.ts +69 -0
- package/src/runtime/ai/cache-chunking.ts +73 -0
- package/src/runtime/ai/client.ts +109 -0
- package/src/runtime/ai/context.ts +168 -0
- package/src/runtime/ai/formatters.ts +316 -0
- package/src/runtime/ai/index.ts +38 -0
- package/src/runtime/ai/language-ref.ts +38 -0
- package/src/runtime/ai/providers/anthropic.ts +253 -0
- package/src/runtime/ai/providers/google.ts +201 -0
- package/src/runtime/ai/providers/openai.ts +156 -0
- package/src/runtime/ai/retry.ts +100 -0
- package/src/runtime/ai/return-tools.ts +301 -0
- package/src/runtime/ai/test/client.test.ts +83 -0
- package/src/runtime/ai/test/formatters.test.ts +485 -0
- package/src/runtime/ai/test/retry.test.ts +137 -0
- package/src/runtime/ai/test/return-tools.test.ts +450 -0
- package/src/runtime/ai/test/tool-loop.test.ts +319 -0
- package/src/runtime/ai/test/tool-schema.test.ts +241 -0
- package/src/runtime/ai/tool-loop.ts +203 -0
- package/src/runtime/ai/tool-schema.ts +151 -0
- package/src/runtime/ai/types.ts +113 -0
- package/src/runtime/ai-logger.ts +255 -0
- package/src/runtime/ai-provider.ts +347 -0
- package/src/runtime/async/dependencies.ts +276 -0
- package/src/runtime/async/executor.ts +293 -0
- package/src/runtime/async/index.ts +43 -0
- package/src/runtime/async/scheduling.ts +163 -0
- package/src/runtime/async/test/dependencies.test.ts +284 -0
- package/src/runtime/async/test/executor.test.ts +388 -0
- package/src/runtime/context.ts +357 -0
- package/src/runtime/exec/ai.ts +139 -0
- package/src/runtime/exec/expressions.ts +475 -0
- package/src/runtime/exec/frames.ts +26 -0
- package/src/runtime/exec/functions.ts +305 -0
- package/src/runtime/exec/interpolation.ts +312 -0
- package/src/runtime/exec/statements.ts +604 -0
- package/src/runtime/exec/tools.ts +129 -0
- package/src/runtime/exec/typescript.ts +215 -0
- package/src/runtime/exec/variables.ts +279 -0
- package/src/runtime/index.ts +975 -0
- package/src/runtime/modules.ts +452 -0
- package/src/runtime/serialize.ts +103 -0
- package/src/runtime/state.ts +489 -0
- package/src/runtime/stdlib/core.ts +45 -0
- package/src/runtime/stdlib/directory.test.ts +156 -0
- package/src/runtime/stdlib/edit.test.ts +154 -0
- package/src/runtime/stdlib/fastEdit.test.ts +201 -0
- package/src/runtime/stdlib/glob.test.ts +106 -0
- package/src/runtime/stdlib/grep.test.ts +144 -0
- package/src/runtime/stdlib/index.ts +16 -0
- package/src/runtime/stdlib/readFile.test.ts +123 -0
- package/src/runtime/stdlib/tools/index.ts +707 -0
- package/src/runtime/stdlib/writeFile.test.ts +157 -0
- package/src/runtime/step.ts +969 -0
- package/src/runtime/test/ai-context.test.ts +1086 -0
- package/src/runtime/test/ai-result-object.test.ts +419 -0
- package/src/runtime/test/ai-tool-flow.test.ts +859 -0
- package/src/runtime/test/async-execution-order.test.ts +618 -0
- package/src/runtime/test/async-execution.test.ts +344 -0
- package/src/runtime/test/async-nested.test.ts +660 -0
- package/src/runtime/test/async-parallel-timing.test.ts +546 -0
- package/src/runtime/test/basic1.test.ts +154 -0
- package/src/runtime/test/binary-operators.test.ts +431 -0
- package/src/runtime/test/break-statement.test.ts +257 -0
- package/src/runtime/test/context-modes.test.ts +650 -0
- package/src/runtime/test/context.test.ts +466 -0
- package/src/runtime/test/core-functions.test.ts +228 -0
- package/src/runtime/test/e2e.test.ts +88 -0
- package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
- package/src/runtime/test/error-locations/main-error.vibe +4 -0
- package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
- package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
- package/src/runtime/test/for-in.test.ts +312 -0
- package/src/runtime/test/helpers.ts +69 -0
- package/src/runtime/test/imports.test.ts +334 -0
- package/src/runtime/test/json-expressions.test.ts +232 -0
- package/src/runtime/test/literals.test.ts +372 -0
- package/src/runtime/test/logical-indexing.test.ts +478 -0
- package/src/runtime/test/member-methods.test.ts +324 -0
- package/src/runtime/test/model-config.test.ts +338 -0
- package/src/runtime/test/null-handling.test.ts +342 -0
- package/src/runtime/test/private-visibility.test.ts +332 -0
- package/src/runtime/test/runtime-state.test.ts +514 -0
- package/src/runtime/test/scoping.test.ts +370 -0
- package/src/runtime/test/string-interpolation.test.ts +354 -0
- package/src/runtime/test/template-literal.test.ts +181 -0
- package/src/runtime/test/tool-execution.test.ts +467 -0
- package/src/runtime/test/tool-schema-generation.test.ts +477 -0
- package/src/runtime/test/tostring.test.ts +210 -0
- package/src/runtime/test/ts-block.test.ts +594 -0
- package/src/runtime/test/ts-error-location.test.ts +231 -0
- package/src/runtime/test/types.test.ts +732 -0
- package/src/runtime/test/verbose-logger.test.ts +710 -0
- package/src/runtime/test/vibe-expression.test.ts +54 -0
- package/src/runtime/test/vibe-value-errors.test.ts +541 -0
- package/src/runtime/test/while.test.ts +232 -0
- package/src/runtime/tools/builtin.ts +30 -0
- package/src/runtime/tools/directory-tools.ts +70 -0
- package/src/runtime/tools/file-tools.ts +228 -0
- package/src/runtime/tools/index.ts +5 -0
- package/src/runtime/tools/registry.ts +48 -0
- package/src/runtime/tools/search-tools.ts +134 -0
- package/src/runtime/tools/security.ts +36 -0
- package/src/runtime/tools/system-tools.ts +312 -0
- package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
- package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
- package/src/runtime/tools/test/registry.test.ts +713 -0
- package/src/runtime/tools/test/security.test.ts +86 -0
- package/src/runtime/tools/test/system-tools.test.ts +679 -0
- package/src/runtime/tools/test/ts-schema.test.ts +357 -0
- package/src/runtime/tools/ts-schema.ts +341 -0
- package/src/runtime/tools/types.ts +89 -0
- package/src/runtime/tools/utility-tools.ts +198 -0
- package/src/runtime/ts-eval.ts +126 -0
- package/src/runtime/types.ts +797 -0
- package/src/runtime/validation.ts +160 -0
- package/src/runtime/verbose-logger.ts +459 -0
- package/src/runtime.ts +2 -0
- package/src/semantic/analyzer-context.ts +62 -0
- package/src/semantic/analyzer-validators.ts +575 -0
- package/src/semantic/analyzer-visitors.ts +534 -0
- package/src/semantic/analyzer.ts +83 -0
- package/src/semantic/index.ts +11 -0
- package/src/semantic/symbol-table.ts +58 -0
- package/src/semantic/test/async-validation.test.ts +301 -0
- package/src/semantic/test/compress-validation.test.ts +179 -0
- package/src/semantic/test/const-reassignment.test.ts +111 -0
- package/src/semantic/test/control-flow.test.ts +346 -0
- package/src/semantic/test/destructuring.test.ts +185 -0
- package/src/semantic/test/duplicate-declarations.test.ts +168 -0
- package/src/semantic/test/export-validation.test.ts +111 -0
- package/src/semantic/test/fixtures/math.ts +31 -0
- package/src/semantic/test/imports.test.ts +148 -0
- package/src/semantic/test/json-type.test.ts +68 -0
- package/src/semantic/test/literals.test.ts +127 -0
- package/src/semantic/test/model-validation.test.ts +179 -0
- package/src/semantic/test/prompt-validation.test.ts +343 -0
- package/src/semantic/test/scoping.test.ts +312 -0
- package/src/semantic/test/tool-validation.test.ts +306 -0
- package/src/semantic/test/ts-type-checking.test.ts +563 -0
- package/src/semantic/test/type-constraints.test.ts +111 -0
- package/src/semantic/test/type-inference.test.ts +87 -0
- package/src/semantic/test/type-validation.test.ts +552 -0
- package/src/semantic/test/undefined-variables.test.ts +163 -0
- package/src/semantic/ts-block-checker.ts +204 -0
- package/src/semantic/ts-signatures.ts +194 -0
- package/src/semantic/ts-types.ts +170 -0
- package/src/semantic/types.ts +58 -0
- package/tests/fixtures/conditional-logic.vibe +14 -0
- package/tests/fixtures/function-call.vibe +16 -0
- package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
- package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
- package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
- package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
- package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
- package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
- package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
- package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
- package/tests/fixtures/imports/nested-import/main.vibe +3 -0
- package/tests/fixtures/imports/nested-import/utils.ts +3 -0
- package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
- package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
- package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
- package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
- package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
- package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
- package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
- package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
- package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
- package/tests/fixtures/imports/ts-import/main.vibe +4 -0
- package/tests/fixtures/imports/ts-import/math.ts +9 -0
- package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/data.ts +10 -0
- package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
- package/tests/fixtures/multiple-ai-calls.vibe +10 -0
- package/tests/fixtures/simple-greeting.vibe +6 -0
- package/tests/fixtures/template-literals.vibe +11 -0
- package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
- package/tests/integration/basic-ai/basic-ai.vibe +12 -0
- package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
- package/tests/integration/bug-fix/buggy-code.ts +22 -0
- package/tests/integration/bug-fix/fix-bug.vibe +21 -0
- package/tests/integration/compress/compress.integration.test.ts +206 -0
- package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
- package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
- package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
- package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
- package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
- package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
- package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
- package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug State - Functional debug state management
|
|
3
|
+
* Pure functions for managing debug state alongside RuntimeState
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
Breakpoint,
|
|
8
|
+
SourceLocation,
|
|
9
|
+
StackFrame,
|
|
10
|
+
Variable,
|
|
11
|
+
Scope,
|
|
12
|
+
ContextEntry,
|
|
13
|
+
ToolCallRecord,
|
|
14
|
+
StopReason,
|
|
15
|
+
StepMode,
|
|
16
|
+
DebugState,
|
|
17
|
+
} from '@vibe-lang/debug-core';
|
|
18
|
+
|
|
19
|
+
import type { RuntimeState } from '../runtime/types';
|
|
20
|
+
|
|
21
|
+
// Extended debug state with runtime reference tracking
|
|
22
|
+
export interface VibeDebugState extends DebugState {
|
|
23
|
+
breakpoints: Map<string, Breakpoint[]>; // file -> breakpoints
|
|
24
|
+
nextBreakpointId: number;
|
|
25
|
+
variableReferences: Map<number, VariableReference>; // For expandable variables
|
|
26
|
+
nextVariableRef: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Reference to a variable that can be expanded
|
|
30
|
+
export interface VariableReference {
|
|
31
|
+
type: 'object' | 'array' | 'vibeValue' | 'scope';
|
|
32
|
+
value: unknown;
|
|
33
|
+
frameId?: number;
|
|
34
|
+
scopeType?: 'local' | 'global' | 'context';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create initial debug state
|
|
39
|
+
*/
|
|
40
|
+
export function createDebugState(options?: {
|
|
41
|
+
stopOnEntry?: boolean;
|
|
42
|
+
}): VibeDebugState {
|
|
43
|
+
return {
|
|
44
|
+
running: false,
|
|
45
|
+
paused: options?.stopOnEntry ?? false,
|
|
46
|
+
pausedAt: null,
|
|
47
|
+
stopReason: options?.stopOnEntry ? 'entry' : null,
|
|
48
|
+
stepMode: 'none',
|
|
49
|
+
breakpoints: new Map(),
|
|
50
|
+
nextBreakpointId: 1,
|
|
51
|
+
variableReferences: new Map(),
|
|
52
|
+
nextVariableRef: 1,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Set breakpoints for a file
|
|
58
|
+
* Returns the new debug state and verified breakpoints
|
|
59
|
+
*/
|
|
60
|
+
export function setBreakpoints(
|
|
61
|
+
debugState: VibeDebugState,
|
|
62
|
+
file: string,
|
|
63
|
+
lines: number[],
|
|
64
|
+
conditions?: (string | undefined)[]
|
|
65
|
+
): { debugState: VibeDebugState; breakpoints: Breakpoint[] } {
|
|
66
|
+
const breakpoints: Breakpoint[] = lines.map((line, i) => ({
|
|
67
|
+
id: debugState.nextBreakpointId + i,
|
|
68
|
+
file,
|
|
69
|
+
line,
|
|
70
|
+
verified: true, // We assume all breakpoints are valid for now
|
|
71
|
+
condition: conditions?.[i],
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
const newBreakpoints = new Map(debugState.breakpoints);
|
|
75
|
+
newBreakpoints.set(normalizeFilePath(file), breakpoints);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
debugState: {
|
|
79
|
+
...debugState,
|
|
80
|
+
breakpoints: newBreakpoints,
|
|
81
|
+
nextBreakpointId: debugState.nextBreakpointId + lines.length,
|
|
82
|
+
},
|
|
83
|
+
breakpoints,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Clear all breakpoints for a file
|
|
89
|
+
*/
|
|
90
|
+
export function clearBreakpoints(
|
|
91
|
+
debugState: VibeDebugState,
|
|
92
|
+
file: string
|
|
93
|
+
): VibeDebugState {
|
|
94
|
+
const newBreakpoints = new Map(debugState.breakpoints);
|
|
95
|
+
newBreakpoints.delete(normalizeFilePath(file));
|
|
96
|
+
return { ...debugState, breakpoints: newBreakpoints };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if execution should pause at current location
|
|
101
|
+
*/
|
|
102
|
+
export function shouldPauseAtLocation(
|
|
103
|
+
debugState: VibeDebugState,
|
|
104
|
+
runtimeState: RuntimeState,
|
|
105
|
+
location: SourceLocation
|
|
106
|
+
): { shouldPause: boolean; reason: StopReason | null } {
|
|
107
|
+
// Check breakpoints
|
|
108
|
+
const fileBreakpoints = debugState.breakpoints.get(normalizeFilePath(location.file));
|
|
109
|
+
if (fileBreakpoints) {
|
|
110
|
+
const hitBreakpoint = fileBreakpoints.find(bp => bp.line === location.line);
|
|
111
|
+
if (hitBreakpoint) {
|
|
112
|
+
// Check condition if present
|
|
113
|
+
if (hitBreakpoint.condition) {
|
|
114
|
+
// TODO: Evaluate condition expression
|
|
115
|
+
// For now, always break on conditional breakpoints
|
|
116
|
+
}
|
|
117
|
+
return { shouldPause: true, reason: 'breakpoint' };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Check step mode
|
|
122
|
+
if (debugState.stepMode !== 'none') {
|
|
123
|
+
return { shouldPause: true, reason: 'step' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { shouldPause: false, reason: null };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Pause execution
|
|
131
|
+
*/
|
|
132
|
+
export function pauseExecution(
|
|
133
|
+
debugState: VibeDebugState,
|
|
134
|
+
location: SourceLocation,
|
|
135
|
+
reason: StopReason
|
|
136
|
+
): VibeDebugState {
|
|
137
|
+
return {
|
|
138
|
+
...debugState,
|
|
139
|
+
running: false,
|
|
140
|
+
paused: true,
|
|
141
|
+
pausedAt: location,
|
|
142
|
+
stopReason: reason,
|
|
143
|
+
stepMode: 'none',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Resume execution (continue)
|
|
149
|
+
*/
|
|
150
|
+
export function resumeExecution(debugState: VibeDebugState): VibeDebugState {
|
|
151
|
+
return {
|
|
152
|
+
...debugState,
|
|
153
|
+
running: true,
|
|
154
|
+
paused: false,
|
|
155
|
+
pausedAt: null,
|
|
156
|
+
stopReason: null,
|
|
157
|
+
stepMode: 'none',
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Set step mode
|
|
163
|
+
*/
|
|
164
|
+
export function setStepMode(
|
|
165
|
+
debugState: VibeDebugState,
|
|
166
|
+
mode: StepMode
|
|
167
|
+
): VibeDebugState {
|
|
168
|
+
return {
|
|
169
|
+
...debugState,
|
|
170
|
+
running: true,
|
|
171
|
+
paused: false,
|
|
172
|
+
stepMode: mode,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get current source location from runtime state
|
|
178
|
+
*/
|
|
179
|
+
export function getCurrentLocation(runtimeState: RuntimeState): SourceLocation | null {
|
|
180
|
+
// Get location from current instruction or statement
|
|
181
|
+
const instruction = runtimeState.instructionStack[0];
|
|
182
|
+
if (instruction?.location) {
|
|
183
|
+
return {
|
|
184
|
+
file: instruction.location.file ?? runtimeState.rootDir ?? '',
|
|
185
|
+
line: instruction.location.line,
|
|
186
|
+
column: instruction.location.column,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Fallback to current frame's location
|
|
191
|
+
const frame = runtimeState.callStack[runtimeState.callStack.length - 1];
|
|
192
|
+
if (frame?.currentLocation) {
|
|
193
|
+
return {
|
|
194
|
+
file: frame.currentLocation.file ?? runtimeState.rootDir ?? '',
|
|
195
|
+
line: frame.currentLocation.line,
|
|
196
|
+
column: frame.currentLocation.column,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get stack trace from runtime state
|
|
205
|
+
*/
|
|
206
|
+
export function getStackTrace(runtimeState: RuntimeState): {
|
|
207
|
+
stackFrames: StackFrame[];
|
|
208
|
+
totalFrames: number;
|
|
209
|
+
} {
|
|
210
|
+
const stackFrames: StackFrame[] = runtimeState.callStack.map((frame, index) => ({
|
|
211
|
+
id: index,
|
|
212
|
+
name: frame.functionName ?? '<main>',
|
|
213
|
+
source: {
|
|
214
|
+
file: frame.currentLocation?.file ?? '',
|
|
215
|
+
line: frame.currentLocation?.line ?? 1,
|
|
216
|
+
column: frame.currentLocation?.column ?? 1,
|
|
217
|
+
},
|
|
218
|
+
isVibeCode: true, // For now, all frames are Vibe code
|
|
219
|
+
})).reverse(); // Most recent frame first
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
stackFrames,
|
|
223
|
+
totalFrames: stackFrames.length,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get scopes for a stack frame
|
|
229
|
+
*/
|
|
230
|
+
export function getScopes(
|
|
231
|
+
debugState: VibeDebugState,
|
|
232
|
+
runtimeState: RuntimeState,
|
|
233
|
+
frameId: number
|
|
234
|
+
): { debugState: VibeDebugState; scopes: Scope[] } {
|
|
235
|
+
const scopes: Scope[] = [];
|
|
236
|
+
let newDebugState = debugState;
|
|
237
|
+
|
|
238
|
+
// Local scope
|
|
239
|
+
const localRef = newDebugState.nextVariableRef++;
|
|
240
|
+
newDebugState = {
|
|
241
|
+
...newDebugState,
|
|
242
|
+
variableReferences: new Map(newDebugState.variableReferences).set(localRef, {
|
|
243
|
+
type: 'scope',
|
|
244
|
+
value: null,
|
|
245
|
+
frameId,
|
|
246
|
+
scopeType: 'local',
|
|
247
|
+
}),
|
|
248
|
+
};
|
|
249
|
+
scopes.push({
|
|
250
|
+
name: 'Local',
|
|
251
|
+
type: 'local',
|
|
252
|
+
variablesReference: localRef,
|
|
253
|
+
expensive: false,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Global scope (if not at top level)
|
|
257
|
+
if (frameId < runtimeState.callStack.length - 1) {
|
|
258
|
+
const globalRef = newDebugState.nextVariableRef++;
|
|
259
|
+
newDebugState = {
|
|
260
|
+
...newDebugState,
|
|
261
|
+
variableReferences: new Map(newDebugState.variableReferences).set(globalRef, {
|
|
262
|
+
type: 'scope',
|
|
263
|
+
value: null,
|
|
264
|
+
frameId: 0,
|
|
265
|
+
scopeType: 'global',
|
|
266
|
+
}),
|
|
267
|
+
};
|
|
268
|
+
scopes.push({
|
|
269
|
+
name: 'Global',
|
|
270
|
+
type: 'global',
|
|
271
|
+
variablesReference: globalRef,
|
|
272
|
+
expensive: false,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Context scope (AI context)
|
|
277
|
+
const contextRef = newDebugState.nextVariableRef++;
|
|
278
|
+
newDebugState = {
|
|
279
|
+
...newDebugState,
|
|
280
|
+
variableReferences: new Map(newDebugState.variableReferences).set(contextRef, {
|
|
281
|
+
type: 'scope',
|
|
282
|
+
value: null,
|
|
283
|
+
frameId,
|
|
284
|
+
scopeType: 'context',
|
|
285
|
+
}),
|
|
286
|
+
};
|
|
287
|
+
scopes.push({
|
|
288
|
+
name: 'AI Context',
|
|
289
|
+
type: 'context',
|
|
290
|
+
variablesReference: contextRef,
|
|
291
|
+
expensive: true, // Context can be large
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
return { debugState: newDebugState, scopes };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get variables for a reference
|
|
299
|
+
*/
|
|
300
|
+
export function getVariables(
|
|
301
|
+
debugState: VibeDebugState,
|
|
302
|
+
runtimeState: RuntimeState,
|
|
303
|
+
variablesReference: number
|
|
304
|
+
): { debugState: VibeDebugState; variables: Variable[] } {
|
|
305
|
+
const ref = debugState.variableReferences.get(variablesReference);
|
|
306
|
+
if (!ref) {
|
|
307
|
+
return { debugState, variables: [] };
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let newDebugState = debugState;
|
|
311
|
+
const variables: Variable[] = [];
|
|
312
|
+
|
|
313
|
+
if (ref.type === 'scope') {
|
|
314
|
+
// Get variables from a scope
|
|
315
|
+
const frame = runtimeState.callStack[runtimeState.callStack.length - 1 - (ref.frameId ?? 0)];
|
|
316
|
+
if (!frame) {
|
|
317
|
+
return { debugState, variables: [] };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (ref.scopeType === 'local' || ref.scopeType === 'global') {
|
|
321
|
+
// Get local/global variables
|
|
322
|
+
// Pass the entire VibeValue so createVariable can detect .err and .toolCalls
|
|
323
|
+
for (const [name, variable] of Object.entries(frame.locals)) {
|
|
324
|
+
const { debugState: ds, variable: v } = createVariable(newDebugState, name, variable, variable.typeAnnotation);
|
|
325
|
+
newDebugState = ds;
|
|
326
|
+
variables.push(v);
|
|
327
|
+
}
|
|
328
|
+
} else if (ref.scopeType === 'context') {
|
|
329
|
+
// Get context entries
|
|
330
|
+
const contextEntries = runtimeState.localContext ?? [];
|
|
331
|
+
for (const entry of contextEntries) {
|
|
332
|
+
variables.push({
|
|
333
|
+
name: entry.name ?? 'context',
|
|
334
|
+
value: String(entry.value).slice(0, 100),
|
|
335
|
+
type: 'context',
|
|
336
|
+
variablesReference: 0,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
} else if (ref.type === 'object' || ref.type === 'array') {
|
|
341
|
+
// Expand object or array
|
|
342
|
+
const value = ref.value;
|
|
343
|
+
if (Array.isArray(value)) {
|
|
344
|
+
value.forEach((item, index) => {
|
|
345
|
+
const { debugState: ds, variable: v } = createVariable(newDebugState, `[${index}]`, item);
|
|
346
|
+
newDebugState = ds;
|
|
347
|
+
variables.push(v);
|
|
348
|
+
});
|
|
349
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
350
|
+
for (const [key, val] of Object.entries(value)) {
|
|
351
|
+
const { debugState: ds, variable: v } = createVariable(newDebugState, key, val);
|
|
352
|
+
newDebugState = ds;
|
|
353
|
+
variables.push(v);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} else if (ref.type === 'vibeValue') {
|
|
357
|
+
// Expand VibeValue (show .value, .err, .toolCalls)
|
|
358
|
+
const vibeValue = ref.value as any;
|
|
359
|
+
if (vibeValue) {
|
|
360
|
+
variables.push({
|
|
361
|
+
name: 'value',
|
|
362
|
+
value: formatValue(vibeValue.value),
|
|
363
|
+
type: typeof vibeValue.value,
|
|
364
|
+
variablesReference: 0,
|
|
365
|
+
});
|
|
366
|
+
if (vibeValue.err && vibeValue.errDetails) {
|
|
367
|
+
const errMsg = vibeValue.errDetails.message ?? 'unknown error';
|
|
368
|
+
variables.push({
|
|
369
|
+
name: 'err',
|
|
370
|
+
value: 'true',
|
|
371
|
+
type: 'boolean',
|
|
372
|
+
variablesReference: 0,
|
|
373
|
+
});
|
|
374
|
+
variables.push({
|
|
375
|
+
name: 'errDetails',
|
|
376
|
+
value: errMsg,
|
|
377
|
+
type: 'error',
|
|
378
|
+
variablesReference: 0,
|
|
379
|
+
hasError: true,
|
|
380
|
+
errorMessage: errMsg,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
if (vibeValue.toolCalls && vibeValue.toolCalls.length > 0) {
|
|
384
|
+
const toolCallsRef = newDebugState.nextVariableRef++;
|
|
385
|
+
newDebugState = {
|
|
386
|
+
...newDebugState,
|
|
387
|
+
variableReferences: new Map(newDebugState.variableReferences).set(toolCallsRef, {
|
|
388
|
+
type: 'array',
|
|
389
|
+
value: vibeValue.toolCalls,
|
|
390
|
+
}),
|
|
391
|
+
};
|
|
392
|
+
variables.push({
|
|
393
|
+
name: 'toolCalls',
|
|
394
|
+
value: `Array(${vibeValue.toolCalls.length})`,
|
|
395
|
+
type: 'array',
|
|
396
|
+
variablesReference: toolCallsRef,
|
|
397
|
+
hasToolCalls: true,
|
|
398
|
+
toolCallCount: vibeValue.toolCalls.length,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return { debugState: newDebugState, variables };
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Create a variable from a value
|
|
409
|
+
*/
|
|
410
|
+
function createVariable(
|
|
411
|
+
debugState: VibeDebugState,
|
|
412
|
+
name: string,
|
|
413
|
+
value: unknown,
|
|
414
|
+
typeAnnotation?: string | null
|
|
415
|
+
): { debugState: VibeDebugState; variable: Variable } {
|
|
416
|
+
let variablesReference = 0;
|
|
417
|
+
let newDebugState = debugState;
|
|
418
|
+
let displayType = typeAnnotation ?? typeof value;
|
|
419
|
+
let hasError = false;
|
|
420
|
+
let errorMessage: string | undefined;
|
|
421
|
+
let hasToolCalls = false;
|
|
422
|
+
let toolCallCount: number | undefined;
|
|
423
|
+
let isPrivate = false;
|
|
424
|
+
|
|
425
|
+
// Check if it's a VibeValue
|
|
426
|
+
if (isVibeValue(value)) {
|
|
427
|
+
const vibeValue = value as any;
|
|
428
|
+
variablesReference = newDebugState.nextVariableRef++;
|
|
429
|
+
newDebugState = {
|
|
430
|
+
...newDebugState,
|
|
431
|
+
variableReferences: new Map(newDebugState.variableReferences).set(variablesReference, {
|
|
432
|
+
type: 'vibeValue',
|
|
433
|
+
value: vibeValue,
|
|
434
|
+
}),
|
|
435
|
+
};
|
|
436
|
+
displayType = 'VibeValue';
|
|
437
|
+
hasError = !!vibeValue.err;
|
|
438
|
+
// Extract error message from errDetails object (err is now boolean)
|
|
439
|
+
errorMessage = vibeValue.errDetails?.message ? String(vibeValue.errDetails.message) : undefined;
|
|
440
|
+
hasToolCalls = vibeValue.toolCalls && vibeValue.toolCalls.length > 0;
|
|
441
|
+
toolCallCount = vibeValue.toolCalls?.length;
|
|
442
|
+
isPrivate = vibeValue.isPrivate === true;
|
|
443
|
+
} else if (Array.isArray(value)) {
|
|
444
|
+
variablesReference = newDebugState.nextVariableRef++;
|
|
445
|
+
newDebugState = {
|
|
446
|
+
...newDebugState,
|
|
447
|
+
variableReferences: new Map(newDebugState.variableReferences).set(variablesReference, {
|
|
448
|
+
type: 'array',
|
|
449
|
+
value,
|
|
450
|
+
}),
|
|
451
|
+
};
|
|
452
|
+
displayType = 'array';
|
|
453
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
454
|
+
variablesReference = newDebugState.nextVariableRef++;
|
|
455
|
+
newDebugState = {
|
|
456
|
+
...newDebugState,
|
|
457
|
+
variableReferences: new Map(newDebugState.variableReferences).set(variablesReference, {
|
|
458
|
+
type: 'object',
|
|
459
|
+
value,
|
|
460
|
+
}),
|
|
461
|
+
};
|
|
462
|
+
displayType = 'object';
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Add [private] suffix to display name if variable is private
|
|
466
|
+
const displayName = isPrivate ? `${name} [private]` : name;
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
debugState: newDebugState,
|
|
470
|
+
variable: {
|
|
471
|
+
name: displayName,
|
|
472
|
+
value: formatValue(value),
|
|
473
|
+
type: displayType,
|
|
474
|
+
variablesReference,
|
|
475
|
+
hasError,
|
|
476
|
+
errorMessage,
|
|
477
|
+
hasToolCalls,
|
|
478
|
+
toolCallCount,
|
|
479
|
+
...(isPrivate ? { isPrivate: true } : {}),
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Format a value for display
|
|
486
|
+
*/
|
|
487
|
+
function formatValue(value: unknown): string {
|
|
488
|
+
if (value === null) return 'null';
|
|
489
|
+
if (value === undefined) return 'undefined';
|
|
490
|
+
if (typeof value === 'string') return `"${value.slice(0, 100)}${value.length > 100 ? '...' : ''}"`;
|
|
491
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
492
|
+
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
493
|
+
if (isVibeValue(value)) {
|
|
494
|
+
const v = value as any;
|
|
495
|
+
if (v.err) return `VibeValue(error: ${v.errDetails?.message ?? 'unknown error'})`;
|
|
496
|
+
return `VibeValue(${formatValue(v.value)})`;
|
|
497
|
+
}
|
|
498
|
+
if (typeof value === 'object') return `{...}`;
|
|
499
|
+
return String(value);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Check if a value is a VibeValue
|
|
504
|
+
*/
|
|
505
|
+
function isVibeValue(value: unknown): boolean {
|
|
506
|
+
return (
|
|
507
|
+
typeof value === 'object' &&
|
|
508
|
+
value !== null &&
|
|
509
|
+
'value' in value &&
|
|
510
|
+
('err' in value || 'toolCalls' in value || 'typeAnnotation' in value)
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Normalize file path for comparison
|
|
516
|
+
*/
|
|
517
|
+
function normalizeFilePath(path: string): string {
|
|
518
|
+
return path.replace(/\\/g, '/').toLowerCase();
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Get tool calls from a VibeValue
|
|
523
|
+
*/
|
|
524
|
+
export function getToolCalls(
|
|
525
|
+
debugState: VibeDebugState,
|
|
526
|
+
variablesReference: number
|
|
527
|
+
): ToolCallRecord[] {
|
|
528
|
+
const ref = debugState.variableReferences.get(variablesReference);
|
|
529
|
+
if (!ref || ref.type !== 'vibeValue') {
|
|
530
|
+
return [];
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const vibeValue = ref.value as any;
|
|
534
|
+
if (!vibeValue?.toolCalls) {
|
|
535
|
+
return [];
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return vibeValue.toolCalls.map((tc: any) => {
|
|
539
|
+
// Support both old format (error) and new format (err/errDetails)
|
|
540
|
+
const hasError = tc.err ?? (tc.error != null);
|
|
541
|
+
const errorMessage = tc.errDetails?.message ?? tc.error ?? null;
|
|
542
|
+
return {
|
|
543
|
+
toolName: tc.name ?? tc.toolName ?? 'unknown',
|
|
544
|
+
args: tc.args ?? tc.arguments ?? {},
|
|
545
|
+
result: tc.result,
|
|
546
|
+
err: hasError,
|
|
547
|
+
errDetails: hasError ? { message: errorMessage } : null,
|
|
548
|
+
duration: tc.duration ?? 0,
|
|
549
|
+
};
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Get AI context entries
|
|
555
|
+
*/
|
|
556
|
+
export function getContextEntries(
|
|
557
|
+
runtimeState: RuntimeState,
|
|
558
|
+
contextType: 'default' | 'local'
|
|
559
|
+
): ContextEntry[] {
|
|
560
|
+
const entries: ContextEntry[] = [];
|
|
561
|
+
|
|
562
|
+
if (contextType === 'local') {
|
|
563
|
+
// Get local context
|
|
564
|
+
for (const entry of runtimeState.localContext ?? []) {
|
|
565
|
+
entries.push({
|
|
566
|
+
role: 'user',
|
|
567
|
+
content: `${entry.name}: ${entry.value}`,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
} else {
|
|
571
|
+
// Get default context
|
|
572
|
+
for (const entry of runtimeState.defaultContext ?? []) {
|
|
573
|
+
entries.push({
|
|
574
|
+
role: entry.role as 'user' | 'assistant' | 'system' | 'tool',
|
|
575
|
+
content: String(entry.content),
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return entries;
|
|
581
|
+
}
|