@garrix82/reactgenie-dsl 1.0.0 → 1.0.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 (105) hide show
  1. package/.env +10 -0
  2. package/.env.example +17 -0
  3. package/.github/workflows/publish.yml +20 -0
  4. package/README.md +5 -1
  5. package/package.json +1 -5
  6. package/dist/__test__/dsl-descriptor.test.d.ts +0 -1
  7. package/dist/__test__/dsl-descriptor.test.js +0 -27
  8. package/dist/__test__/dsl-descriptor.test.js.map +0 -1
  9. package/dist/__test__/example_descriptor.d.ts +0 -125
  10. package/dist/__test__/example_descriptor.js +0 -607
  11. package/dist/__test__/example_descriptor.js.map +0 -1
  12. package/dist/__test__/food_descriptor.state.json +0 -1
  13. package/dist/__test__/food_descriptor.test.d.ts +0 -74
  14. package/dist/__test__/food_descriptor.test.js +0 -205
  15. package/dist/__test__/food_descriptor.test.js.map +0 -1
  16. package/dist/__test__/nl-interpreter-provider-selection.test.d.ts +0 -1
  17. package/dist/__test__/nl-interpreter-provider-selection.test.js +0 -73
  18. package/dist/__test__/nl-interpreter-provider-selection.test.js.map +0 -1
  19. package/dist/__test__/nl-interpreter.test.d.ts +0 -1
  20. package/dist/__test__/nl-interpreter.test.js +0 -86
  21. package/dist/__test__/nl-interpreter.test.js.map +0 -1
  22. package/dist/decorators/__test__/decorators.test.d.ts +0 -1
  23. package/dist/decorators/__test__/decorators.test.js +0 -182
  24. package/dist/decorators/__test__/decorators.test.js.map +0 -1
  25. package/dist/decorators/__test__/inheritance-descriptor.test.d.ts +0 -1
  26. package/dist/decorators/__test__/inheritance-descriptor.test.js +0 -107
  27. package/dist/decorators/__test__/inheritance-descriptor.test.js.map +0 -1
  28. package/dist/dsl/__test__/dsl-interpreter.test.d.ts +0 -1
  29. package/dist/dsl/__test__/dsl-interpreter.test.js +0 -334
  30. package/dist/dsl/__test__/dsl-interpreter.test.js.map +0 -1
  31. package/dist/dsl/__test__/parser.gen.test.d.ts +0 -1
  32. package/dist/dsl/__test__/parser.gen.test.js +0 -283
  33. package/dist/dsl/__test__/parser.gen.test.js.map +0 -1
  34. package/dist/nl/__test__/context-aware-prompt.test.d.ts +0 -1
  35. package/dist/nl/__test__/context-aware-prompt.test.js +0 -247
  36. package/dist/nl/__test__/context-aware-prompt.test.js.map +0 -1
  37. package/dist/nl/__test__/context-selector.test.d.ts +0 -1
  38. package/dist/nl/__test__/context-selector.test.js +0 -20
  39. package/dist/nl/__test__/context-selector.test.js.map +0 -1
  40. package/dist/nl/__test__/nl-parser-groq-transport.test.d.ts +0 -1
  41. package/dist/nl/__test__/nl-parser-groq-transport.test.js +0 -87
  42. package/dist/nl/__test__/nl-parser-groq-transport.test.js.map +0 -1
  43. package/dist/nl/__test__/nl-parser-openai-parity.test.d.ts +0 -1
  44. package/dist/nl/__test__/nl-parser-openai-parity.test.js +0 -206
  45. package/dist/nl/__test__/nl-parser-openai-parity.test.js.map +0 -1
  46. package/dist/nl/__test__/nl-parser-openai-sampling.test.d.ts +0 -1
  47. package/dist/nl/__test__/nl-parser-openai-sampling.test.js +0 -44
  48. package/dist/nl/__test__/nl-parser-openai-sampling.test.js.map +0 -1
  49. package/dist/nl/__test__/nl-parser-openai-transport.test.d.ts +0 -1
  50. package/dist/nl/__test__/nl-parser-openai-transport.test.js +0 -55
  51. package/dist/nl/__test__/nl-parser-openai-transport.test.js.map +0 -1
  52. package/dist/nl/__test__/nl-parser-utils.test.d.ts +0 -1
  53. package/dist/nl/__test__/nl-parser-utils.test.js +0 -70
  54. package/dist/nl/__test__/nl-parser-utils.test.js.map +0 -1
  55. package/dist/nl/__test__/nl-parser.test.d.ts +0 -1
  56. package/dist/nl/__test__/nl-parser.test.js +0 -64
  57. package/dist/nl/__test__/nl-parser.test.js.map +0 -1
  58. package/dist/nl/__test__/parameter-tuning.test.d.ts +0 -1
  59. package/dist/nl/__test__/parameter-tuning.test.js +0 -95
  60. package/dist/nl/__test__/parameter-tuning.test.js.map +0 -1
  61. package/dist/nl/__test__/semantic-parsing-experiment.test.d.ts +0 -1
  62. package/dist/nl/__test__/semantic-parsing-experiment.test.js +0 -178
  63. package/dist/nl/__test__/semantic-parsing-experiment.test.js.map +0 -1
  64. package/dist/nl/llm-monitoring.test.d.ts +0 -5
  65. package/dist/nl/llm-monitoring.test.js +0 -101
  66. package/dist/nl/llm-monitoring.test.js.map +0 -1
  67. package/lib/__test__/dsl-descriptor.test.ts +0 -27
  68. package/lib/__test__/example_descriptor.ts +0 -762
  69. package/lib/__test__/food_descriptor.state.json +0 -1
  70. package/lib/__test__/food_descriptor.test.ts +0 -331
  71. package/lib/__test__/nl-interpreter-provider-selection.test.ts +0 -126
  72. package/lib/__test__/nl-interpreter.test.ts +0 -129
  73. package/lib/decorators/__test__/decorators.test.ts +0 -177
  74. package/lib/decorators/__test__/inheritance-descriptor.test.ts +0 -92
  75. package/lib/decorators/decorators.ts +0 -754
  76. package/lib/decorators/index.ts +0 -2
  77. package/lib/decorators/store.ts +0 -47
  78. package/lib/dsl/__test__/dsl-interpreter.test.ts +0 -453
  79. package/lib/dsl/__test__/parser.gen.test.ts +0 -296
  80. package/lib/dsl/dsl-interpreter.ts +0 -974
  81. package/lib/dsl/index.ts +0 -1
  82. package/lib/dsl/parser.gen.js +0 -1479
  83. package/lib/dsl/parser.pegjs +0 -130
  84. package/lib/dsl-descriptor.ts +0 -241
  85. package/lib/index.ts +0 -5
  86. package/lib/nl/__test__/context-aware-prompt.test.ts +0 -372
  87. package/lib/nl/__test__/context-selector.test.ts +0 -27
  88. package/lib/nl/__test__/nl-parser-groq-transport.test.ts +0 -139
  89. package/lib/nl/__test__/nl-parser-openai-parity.test.ts +0 -381
  90. package/lib/nl/__test__/nl-parser-openai-sampling.test.ts +0 -73
  91. package/lib/nl/__test__/nl-parser-openai-transport.test.ts +0 -79
  92. package/lib/nl/__test__/nl-parser-utils.test.ts +0 -98
  93. package/lib/nl/__test__/nl-parser.test.ts +0 -119
  94. package/lib/nl/__test__/parameter-tuning.test.ts +0 -137
  95. package/lib/nl/__test__/semantic-parsing-experiment.test.ts +0 -260
  96. package/lib/nl/context-selector.ts +0 -123
  97. package/lib/nl/index.ts +0 -19
  98. package/lib/nl/llm-monitoring.test.ts +0 -136
  99. package/lib/nl/llm-monitoring.ts +0 -339
  100. package/lib/nl/nl-parser-groq.ts +0 -510
  101. package/lib/nl/nl-parser-utils.ts +0 -310
  102. package/lib/nl/nl-parser.ts +0 -616
  103. package/lib/nl/prompt-gen.ts +0 -607
  104. package/lib/nl/prompt-res.ts +0 -207
  105. package/lib/nl-interpreter.ts +0 -262
@@ -1,207 +0,0 @@
1
- import { ExampleParse } from "./prompt-gen";
2
-
3
- export const pre_section_separator = "\n";
4
- export const post_section_separator = "\n\n\n";
5
-
6
- export const class_prequel = "// Here are all the functions";
7
-
8
- export const array_definition =
9
- "extension Array<Type> {\n" +
10
- " // Find items with matching fields in an array\n" +
11
- " Array<Type> matching(field: Field, value: Type);\n" +
12
- "\n" +
13
- " // Find items with field in an array that contains a specific value\n" +
14
- " Array<Type> contains(field: Field, value: Type);\n" +
15
- "\n" +
16
- " // Find items with exact fields in an array\n" +
17
- " Array<Type> equals(field: Field, value: Type);\n" +
18
- "\n" +
19
- " // Find items with the field above from (if provided) and below to (if provided).\n" +
20
- " Array<Type> between(field: Field, from?: Type, to?: Type);\n" +
21
- "\n" +
22
- " // Sort an array based on a specific field in ascending or descending order\n" +
23
- " Array<Type> sort(field: Field, ascending: bool);\n" +
24
- "\n" +
25
- " // Get length of an array\n" +
26
- " int length();\n" +
27
- "}";
28
-
29
- export const class_separator = "\n\n";
30
-
31
- export const example_prequel = "// Here are all the examples that we have";
32
-
33
- export function example_pair(example: ExampleParse) {
34
- return (
35
- `user: ${example.user_utterance}\n` + `parsed: ${example.example_parsed}`
36
- );
37
- }
38
-
39
- export const example_separator = "\n\n";
40
-
41
- export const accessor_parameter_rules =
42
- "// Accessor parameter rules\n" +
43
- "// For matching, contains, equals, between, and sort, the field parameter MUST be a dotted accessor, never a quoted string.\n" +
44
- '// ✅ CORRECT: Probe.getAllProbes().contains(field: .customerName, value: "Freshmarket")\n' +
45
- '// ❌ WRONG: Probe.getAllProbes().contains(field: "customerName", value: "Freshmarket")\n' +
46
- "// Use nested dotted accessors for nested fields, for example .dateTime.day.\n";
47
-
48
- export function example_parses(examples: ExampleParse[]) {
49
- return examples
50
- .map((example) => example_pair(example))
51
- .join(example_separator);
52
- }
53
-
54
- export const user_interaction_prequel = "// New user interaction";
55
-
56
- export function user_interaction_prompt(user_utterance: string) {
57
- return `user: ${user_utterance}\n` + `parsed:`;
58
- }
59
-
60
- export function agent_response_prompt(
61
- user_utterance: string,
62
- parsed: string,
63
- result: string
64
- ) {
65
- return (
66
- `user: ${user_utterance}\n` +
67
- `parsed: ${parsed}\n` +
68
- `response_context: ${result}\n` +
69
- `Generate STRICT JSON with keys: minimalText, fullText, type, shouldSpeak.\n` +
70
- `Rules: minimalText MUST be exactly one or two words, easy to speak, and no DSL/code.\n` +
71
- `Rules: minimalText should sound task/equipment-work professional (lab persona), low emotion, low cognitive load.\n` +
72
- `Rules: minimalText examples: "Completed", "In progress", "Check sample", "Retry task".\n` +
73
- `Rules: fullText should be informative but concise (<=240 chars).\n` +
74
- `Rules: type must be one of info|error|success|warning.\n` +
75
- `Rules: shouldSpeak must be true only when spoken feedback helps the user.\n` +
76
- `agent_response_json:`
77
- );
78
- }
79
-
80
- export const parse_issues = `
81
- // Here are the issues that need to be noticed
82
- // 1. Use "Array[index]" instead of index related functions. For example, "hotels[0]" instead of "hotels.first()"
83
- // 2. Use "setProperty(value) instead of "property = value". For example, "hotel.setName(123)" instead of "hotel.name = 123"
84
- // 3. Use ";" between multiple function calls. For example, "hotel.setName(123); hotel.setDesc(123)"`
85
-
86
- const exampleDeveloperClasses = `
87
- // Here are all the function that we have
88
- extension Array<Type> {
89
- // find items with matching field in an array
90
- Array<Type> matching(field: Field, value: Type);
91
-
92
- // find items with field in an array that contains a specific value
93
- Array<Type> contains(field: Field, value: Type);
94
-
95
- // find items with exact field in an array
96
- Array<Type> equals(field: Field, value: Type);
97
-
98
- // find items with field between two values in an array
99
- Array<Type> between(field: Field, from: Type, to: Type);
100
-
101
- // sort an array based on a specific field in ascending or descending order
102
- Array<Type> sort(field: Field, ascending: bool);
103
- }
104
-
105
- class Counter {
106
- string name;
107
- string type;
108
- int count;
109
- static float Version;
110
- static Counter GetCounter(name: string);
111
- void increment();
112
- void decrement();
113
- static Counter[] All();
114
- static Counter Current();
115
- }
116
-
117
-
118
- // Here are all the examples that we have
119
- user: increment
120
- parsed: Counter.Current().increment()
121
-
122
- user: what is the count
123
- parsed: Counter.Current().count
124
-
125
- user: what is the count of potato
126
- parsed: Counter.GetCounter(name: "potato").count
127
-
128
- user: increment potato counter
129
- parsed: Counter.GetCounter(name: "potato").increment()
130
-
131
- user: show me all vegetables counters
132
- parsed: Counter.All().matching(field: .type, value: "vegetable")
133
- `
134
-
135
- export function parseCodePrompt(appBasicPrompt: string): string {
136
- return `
137
- Below are the developer class definitions, methods, and their descriptions as the comments of an example app.
138
- After that, code parses from another app using ReactGenieDSL will be given.
139
- A code parse is a voice command the user gives to be parsed into code that completes the requested action.
140
-
141
- BEGIN
142
- \`
143
- ${exampleDeveloperClasses}
144
- \`
145
- END
146
-
147
- Note that all function calls have to have explicit parameter names in ReactGenieDSL.
148
-
149
- For example:
150
- \`
151
- parsed: Counter.All().matching(.type, "vegetable")
152
- \`
153
- Is INCORRECT.
154
-
155
- This is correct:
156
- \`
157
- parsed: Counter.All().matching(field: .type, value: "vegetable")
158
- \`
159
-
160
- And here is the developer classes and (optionally) code parses for this app in ReactGenieDSL:\n
161
- BEGIN
162
- \`
163
- ${appBasicPrompt}
164
- \`
165
- END
166
-
167
- For code translation using \`ReactGenieDSL\`, follow these guidelines:
168
-
169
- 1. Formatting: Directly output code without code blocks. Use semicolons for separating multiple statements.
170
- 2. Follow declarations: Only use existing functions, do not introduce new functions.
171
- 3. Retrieval Over Answers: Translate user queries into code for information retrieval, not direct answers.
172
- 4. Contextual 'Current': Use 'Current' for items the user is directly interacting with or viewing.
173
- 5. Indexing: Use bracket notation for array indexing, supporting negative indices for last element.
174
- 6. No Math Operations: Replace direct math operations with method calls (e.g., 1.plus(1)).
175
- 7. Simplified Array Operations: Avoid map/lambda expressions; apply functions directly to array elements.
176
- 8. No Default Constructors: Use 'Create' methods for object creation; otherwise, selection from existing options.
177
- 9. Static vs. Non-Static Methods: Use static methods for direct class calls; retrieve instances for non-static methods.
178
- 10. Optional Parameters: Optional parameters are noted by \`?\` after their type, they can be omitted in function calls.
179
- 11. Use Setters: Avoid assignments; utilize function calls (set[Something]) for selections or changes.
180
- 12. Property Access: When accessing nested properties, ensure to navigate through all necessary parent properties.
181
-
182
- **CRITICAL - Array Parameter Syntax:**
183
- 13. When passing array values to function parameters, you MUST wrap them in square brackets [...] even if the expression already returns an array.
184
-
185
- ✅ CORRECT: Order.current().addFoods(foods: [Order.all().matching(field: .restaurant, value: Restaurant.all()[0]).foods()])
186
- ❌ WRONG: Order.current().addFoods(foods: Order.all().matching(field: .restaurant, value: Restaurant.all()[0]).foods())
187
-
188
- ✅ CORRECT: someFunction(items: [array.matching(field: .name, value: "test")])
189
- ❌ WRONG: someFunction(items: array.matching(field: .name, value: "test"))
190
-
191
- Even though the expression returns an array type, the DSL syntax requires explicit brackets for array parameters.
192
-
193
- **CRITICAL - Accessor Parameter Syntax:**
194
- 14. For matching, contains, equals, between, and sort, the \`field\` parameter MUST be a dotted accessor, never a quoted string literal.
195
-
196
- ✅ CORRECT: Probe.getAllProbes().contains(field: .customerName, value: "Freshmarket")
197
- ❌ WRONG: Probe.getAllProbes().contains(field: "customerName", value: "Freshmarket")
198
-
199
- ✅ CORRECT: Probe.getAllProbes().sort(field: .receivedAt, ascending: false)
200
- ❌ WRONG: Probe.getAllProbes().sort(field: "receivedAt", ascending: false)
201
-
202
- For nested fields, keep the full dotted path, for example \`.dateTime.day\`.
203
-
204
- New user interaction (think carefully)
205
-
206
- `;
207
- }
@@ -1,262 +0,0 @@
1
- import { PromptGen, SamplingParams } from "./nl";
2
- import { ClassDescriptor, GenieObject } from "./dsl-descriptor";
3
- import { NlParser, NlParserGroq } from "./nl";
4
- import { DslInterpreter } from "./dsl";
5
- import {
6
- AgentResponsePayload,
7
- ContextAwareDescriptorPromptGen,
8
- ExampleParse,
9
- PromptInteractionRecorder,
10
- PromptRuntimeContextSetter,
11
- RuntimeUiContext,
12
- } from "./nl/prompt-gen";
13
-
14
- export type NlParserProvider = "groq" | "openai";
15
-
16
- export interface NlInterpreterProviderSettings {
17
- baseUrl?: string;
18
- model?: string;
19
- samplingParams?: SamplingParams;
20
- statefulValidationRetry?: boolean;
21
- }
22
-
23
- export interface NlInterpreterParserConfig {
24
- provider?: NlParserProvider;
25
- groq?: NlInterpreterProviderSettings;
26
- openai?: NlInterpreterProviderSettings;
27
- }
28
-
29
- export interface NlInterpreterMonitoringConfig {
30
- langsmithApiKey?: string;
31
- langsmithProject?: string;
32
- langsmithEndpoint?: string;
33
- }
34
-
35
- export interface NlInterpreterOptions {
36
- parser?: NlInterpreterParserConfig;
37
- monitoring?: NlInterpreterMonitoringConfig;
38
- }
39
-
40
- const DEFAULT_GROQ_BASE_URL = "https://api.groq.com/openai/v1";
41
- const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
42
- const PROVIDER_ENV_KEY = "GENIE_PARSER_PROVIDER";
43
-
44
- function normalizeBaseUrl(baseUrl: string): string {
45
- return baseUrl.trim().replace(/\/+$/, "");
46
- }
47
-
48
- function stripChatCompletionsSuffix(baseUrl: string): string {
49
- if (!baseUrl.endsWith("/chat/completions")) {
50
- return baseUrl;
51
- }
52
- return baseUrl.slice(0, -"/chat/completions".length);
53
- }
54
-
55
- function isDirectOpenAIBaseUrl(baseUrl: string): boolean {
56
- try {
57
- const url = new URL(baseUrl);
58
- return url.hostname === "api.openai.com";
59
- } catch {
60
- return false;
61
- }
62
- }
63
-
64
- function normalizeProviderBaseUrl(
65
- provider: NlParserProvider,
66
- baseUrl?: string
67
- ): string {
68
- const fallbackBaseUrl =
69
- provider === "openai" ? DEFAULT_OPENAI_BASE_URL : DEFAULT_GROQ_BASE_URL;
70
-
71
- if (!baseUrl || baseUrl.trim().length === 0) {
72
- return fallbackBaseUrl;
73
- }
74
-
75
- const normalizedBaseUrl = stripChatCompletionsSuffix(normalizeBaseUrl(baseUrl));
76
-
77
- if (
78
- normalizedBaseUrl.endsWith("/openai/v1") ||
79
- normalizedBaseUrl.endsWith("/v1")
80
- ) {
81
- return normalizedBaseUrl;
82
- }
83
-
84
- if (provider === "openai" && isDirectOpenAIBaseUrl(normalizedBaseUrl)) {
85
- return `${normalizedBaseUrl}/v1`;
86
- }
87
-
88
- return `${normalizedBaseUrl}/openai/v1`;
89
- }
90
-
91
- function resolveParserProvider(
92
- parserConfig?: NlInterpreterParserConfig
93
- ): NlParserProvider {
94
- if (parserConfig?.provider === "openai" || parserConfig?.provider === "groq") {
95
- return parserConfig.provider;
96
- }
97
-
98
- const envProvider = process.env[PROVIDER_ENV_KEY]?.trim().toLowerCase();
99
- if (envProvider === "openai" || envProvider === "groq") {
100
- return envProvider;
101
- }
102
-
103
- return "groq";
104
- }
105
-
106
- function requireOpenAIModel(model?: string): string {
107
- const trimmed = model?.trim();
108
- if (!trimmed) {
109
- throw new Error(
110
- "OpenAI parser requires parser.openai.model / semanticModel / SEMANTIC_MODEL configuration."
111
- );
112
- }
113
- return trimmed;
114
- }
115
-
116
- export class NlInterpreter {
117
- public nlParser: NlParser | NlParserGroq;
118
- public dslInterpreter: DslInterpreter;
119
- private dslValidator: DslInterpreter;
120
-
121
- constructor(
122
- private descriptions: ClassDescriptor<GenieObject>[],
123
- private apiKey: string,
124
- private prompt?: PromptGen,
125
- private examples?: ExampleParse[],
126
- private extraPrompt?: string,
127
- private options: NlInterpreterOptions = {}
128
- ) {
129
- if (this.prompt === undefined) {
130
- console.assert(this.examples !== undefined);
131
- this.prompt = new ContextAwareDescriptorPromptGen(
132
- this.descriptions,
133
- this.examples!,
134
- extraPrompt
135
- );
136
- }
137
-
138
- const parserConfig = this.options.parser;
139
- const monitoringConfig = this.options.monitoring;
140
- const provider = resolveParserProvider(parserConfig);
141
-
142
- this.dslInterpreter = new DslInterpreter([...descriptions]);
143
- this.dslValidator = new DslInterpreter([...descriptions], true);
144
-
145
- const validateCommand = async (command: string) => {
146
- await this.dslValidator.interpret(command);
147
- };
148
-
149
- if (provider === "openai") {
150
- const openAIConfig = parserConfig?.openai;
151
- this.nlParser = new NlParser(
152
- this.prompt,
153
- apiKey,
154
- normalizeProviderBaseUrl("openai", openAIConfig?.baseUrl),
155
- requireOpenAIModel(openAIConfig?.model),
156
- openAIConfig?.samplingParams,
157
- monitoringConfig?.langsmithApiKey,
158
- monitoringConfig?.langsmithProject,
159
- monitoringConfig?.langsmithEndpoint,
160
- validateCommand,
161
- {
162
- statefulValidationRetry: !!openAIConfig?.statefulValidationRetry,
163
- }
164
- );
165
- } else {
166
- const groqConfig = parserConfig?.groq;
167
- const resolvedGroqModel =
168
- groqConfig?.model ||
169
- process.env.SEMANTIC_MODEL ||
170
- "llama-3.3-70b-versatile";
171
- this.nlParser = new NlParserGroq(
172
- this.prompt,
173
- apiKey,
174
- resolvedGroqModel,
175
- groqConfig?.samplingParams,
176
- normalizeProviderBaseUrl("groq", groqConfig?.baseUrl),
177
- monitoringConfig?.langsmithApiKey,
178
- monitoringConfig?.langsmithProject,
179
- monitoringConfig?.langsmithEndpoint,
180
- validateCommand
181
- );
182
- }
183
- }
184
-
185
- private recordInteraction(record: {
186
- utterance: string;
187
- parsed?: string | null;
188
- success: boolean;
189
- resultSummary?: string;
190
- }) {
191
- const recorder = this.prompt as unknown as PromptInteractionRecorder;
192
- if (typeof recorder?.recordInteraction === "function") {
193
- recorder.recordInteraction(record);
194
- }
195
- }
196
-
197
- public recordTurn(record: {
198
- utterance: string;
199
- parsed?: string | null;
200
- success: boolean;
201
- resultSummary?: string;
202
- }): void {
203
- this.recordInteraction(record);
204
- }
205
-
206
- setRuntimeContext(context: RuntimeUiContext | null): void {
207
- const runtimeContextSetter = this.prompt as unknown as PromptRuntimeContextSetter;
208
- if (typeof runtimeContextSetter?.setRuntimeContext === "function") {
209
- runtimeContextSetter.setRuntimeContext(context);
210
- }
211
- }
212
-
213
- async interpret(nl: string): Promise<GenieObject | null> {
214
- let command: string | null = null;
215
- try {
216
- command = await this.nlParser.parse(nl);
217
- } catch (error) {
218
- this.recordInteraction({
219
- utterance: nl,
220
- success: false,
221
- resultSummary: `parse_error:${error instanceof Error ? error.message : String(error)}`,
222
- });
223
- throw error;
224
- }
225
-
226
- if (command === null) {
227
- this.recordInteraction({
228
- utterance: nl,
229
- success: false,
230
- resultSummary: "parse_empty",
231
- });
232
- return null;
233
- }
234
-
235
- try {
236
- const result = await this.dslInterpreter.interpret(command);
237
- this.recordInteraction({
238
- utterance: nl,
239
- parsed: command,
240
- success: true,
241
- resultSummary: "execute_ok",
242
- });
243
- return result;
244
- } catch (error) {
245
- this.recordInteraction({
246
- utterance: nl,
247
- parsed: command,
248
- success: false,
249
- resultSummary: `execute_error:${error instanceof Error ? error.message : String(error)}`,
250
- });
251
- throw error;
252
- }
253
- }
254
-
255
- async respond(
256
- nl: string,
257
- parsed: string,
258
- result: string
259
- ): Promise<AgentResponsePayload | null> {
260
- return await this.nlParser.respond(nl, parsed, result);
261
- }
262
- }