agency-lang 0.0.92 → 0.0.93
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/lib/backends/agencyGenerator.d.ts +3 -0
- package/dist/lib/backends/agencyGenerator.js +76 -35
- package/dist/lib/backends/agencyGenerator.test.js +130 -0
- package/dist/lib/backends/typescriptBuilder.d.ts +11 -2
- package/dist/lib/backends/typescriptBuilder.integration.test.js +50 -0
- package/dist/lib/backends/typescriptBuilder.js +277 -97
- package/dist/lib/backends/typescriptGenerator/typeToString.js +2 -0
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.d.ts +9 -1
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.js +31 -20
- package/dist/lib/cli/bundle.test.js +32 -20
- package/dist/lib/cli/commands.js +8 -7
- package/dist/lib/cli/debug.js +16 -2
- package/dist/lib/cli/doc.js +96 -32
- package/dist/lib/cli/doc.test.js +106 -0
- package/dist/lib/cli/events.d.ts +1 -0
- package/dist/lib/cli/events.js +15 -0
- package/dist/lib/cli/events.test.js +95 -0
- package/dist/lib/cli/watch.d.ts +4 -0
- package/dist/lib/cli/watch.js +101 -0
- package/dist/lib/cli/watch.test.d.ts +1 -0
- package/dist/lib/cli/watch.test.js +120 -0
- package/dist/lib/config.d.ts +12 -0
- package/dist/lib/debugger/driver.js +9 -1
- package/dist/lib/debugger/driver.test.js +37 -28
- package/dist/lib/debugger/testHelpers.d.ts +1 -0
- package/dist/lib/debugger/testHelpers.js +1 -0
- package/dist/lib/debugger/trace.test.js +40 -5
- package/dist/lib/debugger/types.d.ts +3 -0
- package/dist/lib/debugger/ui.d.ts +5 -0
- package/dist/lib/debugger/ui.js +443 -32
- package/dist/lib/debugger/uiState.d.ts +1 -1
- package/dist/lib/debugger/uiState.js +2 -2
- package/dist/lib/ir/builders.d.ts +1 -0
- package/dist/lib/ir/builders.js +3 -0
- package/dist/lib/ir/prettyPrint.js +3 -1
- package/dist/lib/parsers/access.test.js +133 -0
- package/dist/lib/parsers/assignment.test.js +23 -0
- package/dist/lib/parsers/binop.test.js +230 -3
- package/dist/lib/parsers/expression.test.js +32 -0
- package/dist/lib/parsers/function.test.js +99 -0
- package/dist/lib/parsers/literals.test.js +5 -4
- package/dist/lib/parsers/multiLineComment.test.js +31 -3
- package/dist/lib/parsers/parsers.d.ts +5 -0
- package/dist/lib/parsers/parsers.js +140 -25
- package/dist/lib/parsers/returnStatement.test.js +5 -3
- package/dist/lib/parsers/typeHints.test.js +53 -2
- package/dist/lib/preprocessors/typescriptPreprocessor.core.test.js +212 -1
- package/dist/lib/preprocessors/typescriptPreprocessor.d.ts +1 -1
- package/dist/lib/preprocessors/typescriptPreprocessor.js +55 -35
- package/dist/lib/runtime/__tests__/testHelpers.d.ts +8 -0
- package/dist/lib/runtime/__tests__/testHelpers.js +46 -0
- package/dist/lib/runtime/checkpoint.test.js +2 -22
- package/dist/lib/runtime/classReviver.js +10 -4
- package/dist/lib/runtime/debugger.js +11 -5
- package/dist/lib/runtime/debugger.test.js +13 -31
- package/dist/lib/runtime/errors.d.ts +4 -0
- package/dist/lib/runtime/errors.js +15 -0
- package/dist/lib/runtime/errors.test.js +35 -1
- package/dist/lib/runtime/hooks.d.ts +3 -2
- package/dist/lib/runtime/hooks.js +9 -1
- package/dist/lib/runtime/index.d.ts +10 -6
- package/dist/lib/runtime/index.js +7 -5
- package/dist/lib/runtime/interrupts.d.ts +4 -8
- package/dist/lib/runtime/interrupts.js +37 -59
- package/dist/lib/runtime/isDebugger.test.js +4 -3
- package/dist/lib/runtime/node.d.ts +2 -1
- package/dist/lib/runtime/node.js +38 -10
- package/dist/lib/runtime/prompt.js +91 -65
- package/dist/lib/runtime/result.d.ts +4 -2
- package/dist/lib/runtime/result.js +8 -7
- package/dist/lib/runtime/result.test.js +5 -3
- package/dist/lib/runtime/revivers/baseReviver.d.ts +7 -0
- package/dist/lib/runtime/revivers/baseReviver.js +1 -0
- package/dist/lib/runtime/revivers/dateReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/dateReviver.js +21 -0
- package/dist/lib/runtime/revivers/errorReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/errorReviver.js +37 -0
- package/dist/lib/runtime/revivers/index.d.ts +2 -0
- package/dist/lib/runtime/revivers/index.js +44 -0
- package/dist/lib/runtime/revivers/mapReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/mapReviver.js +17 -0
- package/dist/lib/runtime/revivers/regExpReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/regExpReviver.js +17 -0
- package/dist/lib/runtime/revivers/setReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/setReviver.js +17 -0
- package/dist/lib/runtime/revivers/urlReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/urlReviver.js +17 -0
- package/dist/lib/runtime/rewind.js +3 -2
- package/dist/lib/runtime/runner.d.ts +1 -1
- package/dist/lib/runtime/runner.js +23 -11
- package/dist/lib/runtime/runner.test.js +3 -22
- package/dist/lib/runtime/schema.d.ts +9 -0
- package/dist/lib/runtime/schema.js +37 -0
- package/dist/lib/runtime/schema.test.d.ts +1 -0
- package/dist/lib/runtime/schema.test.js +82 -0
- package/dist/lib/runtime/state/checkpointStore.d.ts +3 -1
- package/dist/lib/runtime/state/checkpointStore.js +18 -10
- package/dist/lib/runtime/state/checkpointStore.test.js +1 -17
- package/dist/lib/runtime/state/context.d.ts +22 -3
- package/dist/lib/runtime/state/context.js +80 -3
- package/dist/lib/runtime/state/context.test.js +39 -0
- package/dist/lib/runtime/state/globalStore.js +2 -1
- package/dist/lib/runtime/state/stateStack.d.ts +2 -2
- package/dist/lib/runtime/state/stateStack.js +7 -7
- package/dist/lib/runtime/state/stateStack.test.js +2 -2
- package/dist/lib/runtime/streaming.js +54 -35
- package/dist/lib/runtime/trace/eventLog.d.ts +79 -0
- package/dist/lib/runtime/trace/eventLog.js +296 -0
- package/dist/lib/runtime/trace/eventLog.test.d.ts +1 -0
- package/dist/lib/runtime/trace/eventLog.test.js +944 -0
- package/dist/lib/runtime/trace/sinks.d.ts +18 -0
- package/dist/lib/runtime/trace/sinks.js +49 -0
- package/dist/lib/runtime/trace/sinks.test.d.ts +1 -0
- package/dist/lib/runtime/trace/sinks.test.js +79 -0
- package/dist/lib/runtime/trace/traceReader.test.js +57 -24
- package/dist/lib/runtime/trace/traceWriter.d.ts +19 -3
- package/dist/lib/runtime/trace/traceWriter.js +83 -12
- package/dist/lib/runtime/trace/traceWriter.test.js +73 -12
- package/dist/lib/runtime/trace/types.d.ts +15 -0
- package/dist/lib/runtime/utils.js +3 -2
- package/dist/lib/templates/backends/typescriptGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.js +2 -1
- package/dist/lib/typeChecker/checker.js +2 -2
- package/dist/lib/typeChecker/inference.js +1 -1
- package/dist/lib/types/access.d.ts +5 -0
- package/dist/lib/types/binop.d.ts +1 -1
- package/dist/lib/types/binop.js +12 -1
- package/dist/lib/types/function.d.ts +7 -1
- package/dist/lib/types/function.js +14 -1
- package/dist/lib/types/graphNode.d.ts +5 -2
- package/dist/lib/types/returnStatement.d.ts +1 -1
- package/dist/lib/types/schemaExpression.d.ts +6 -0
- package/dist/lib/types/schemaExpression.js +1 -0
- package/dist/lib/types/typeHints.d.ts +2 -0
- package/dist/lib/types.d.ts +7 -4
- package/dist/lib/types.js +1 -1
- package/dist/lib/utils/node.js +19 -2
- package/dist/lib/version.d.ts +1 -1
- package/dist/lib/version.js +1 -1
- package/dist/scripts/agency.js +29 -5
- package/package.json +4 -6
- package/stdlib/agent.js +6 -2
- package/stdlib/array.agency +1 -3
- package/stdlib/array.js +17 -29
- package/stdlib/consensus.js +129 -8
- package/stdlib/firstValid.js +132 -9
- package/stdlib/fs.js +6 -2
- package/stdlib/http.js +739 -0
- package/stdlib/index.js +2 -5
- package/stdlib/lib/syntax.js +75 -0
- package/stdlib/lib/ui.js +393 -0
- package/stdlib/math.js +6 -2
- package/stdlib/object.js +82 -94
- package/stdlib/path.js +6 -2
- package/stdlib/retry.js +144 -15
- package/stdlib/sample.js +128 -7
- package/stdlib/shell.js +6 -2
- package/stdlib/strategy.js +84 -92
- package/stdlib/system.js +6 -2
- package/stdlib/ui.agency +95 -0
- package/stdlib/ui.js +1716 -0
- package/stdlib/weather.js +6 -9
- package/dist/lib/agents/agency-agent/subagents/code.js +0 -628
- package/dist/lib/agents/agency-agent/subagents/plan.js +0 -445
- package/dist/lib/agents/agency-agent/subagents/task.js +0 -557
- package/dist/lib/templates/backends/typescriptGenerator/rewindCheckpoint.d.ts +0 -11
- package/dist/lib/templates/backends/typescriptGenerator/rewindCheckpoint.js +0 -32
- package/dist/lib/templates/backends/typescriptGenerator/traceSetup.d.ts +0 -7
- package/dist/lib/templates/backends/typescriptGenerator/traceSetup.js +0 -12
- package/dist/lib/types/sentinel.d.ts +0 -11
- package/stdlib/_utils.js +0 -51
- package/stdlib/lib/process.js +0 -29
- package/stdlib/lib/test.js +0 -3
- /package/dist/lib/{types/sentinel.js → cli/events.test.d.ts} +0 -0
|
@@ -82,6 +82,9 @@ export declare class AgencyGenerator {
|
|
|
82
82
|
protected processDebuggerStatement(node: DebuggerStatement): string;
|
|
83
83
|
protected processComment(node: AgencyComment): string;
|
|
84
84
|
protected processMultiLineComment(node: AgencyMultiLineComment): string;
|
|
85
|
+
protected formatDocComment(node: {
|
|
86
|
+
docComment?: AgencyMultiLineComment;
|
|
87
|
+
}): string;
|
|
85
88
|
protected processImportStatement(node: ImportStatement): string;
|
|
86
89
|
protected processImportNameType(node: ImportNameType): string;
|
|
87
90
|
protected processImportNodeStatement(node: ImportNodeStatement): string;
|
|
@@ -196,8 +196,10 @@ export class AgencyGenerator {
|
|
|
196
196
|
return this.processClassDefinition(node);
|
|
197
197
|
case "newExpression":
|
|
198
198
|
return this.processNewExpression(node);
|
|
199
|
+
case "schemaExpression":
|
|
200
|
+
return `schema(${variableTypeToString(node.typeArg, this.typeAliases)})`;
|
|
199
201
|
case "regex":
|
|
200
|
-
return
|
|
202
|
+
return `re/${node.pattern}/${node.flags}`;
|
|
201
203
|
default:
|
|
202
204
|
throw new Error(`Unhandled Agency node type: ${node.type}`);
|
|
203
205
|
}
|
|
@@ -205,6 +207,9 @@ export class AgencyGenerator {
|
|
|
205
207
|
needsParensLeft(child, parentOp) {
|
|
206
208
|
if (child.type !== "binOpExpression")
|
|
207
209
|
return false;
|
|
210
|
+
// For right-associative ops like **, (2 ** 3) ** 4 needs parens on the left
|
|
211
|
+
if (parentOp === "**")
|
|
212
|
+
return PRECEDENCE[child.operator] <= PRECEDENCE[parentOp];
|
|
208
213
|
return PRECEDENCE[child.operator] < PRECEDENCE[parentOp];
|
|
209
214
|
}
|
|
210
215
|
needsParensRight(child, parentOp) {
|
|
@@ -287,7 +292,8 @@ export class AgencyGenerator {
|
|
|
287
292
|
this.typeAliases[node.aliasName] = node.aliasedType;
|
|
288
293
|
const aliasedTypeStr = this.aliasedTypeToString(node.aliasedType);
|
|
289
294
|
const exportPrefix = node.exported ? "export " : "";
|
|
290
|
-
return this.
|
|
295
|
+
return (this.formatDocComment(node) +
|
|
296
|
+
this.indentStr(`${exportPrefix}type ${node.aliasName} = ${aliasedTypeStr}`));
|
|
291
297
|
}
|
|
292
298
|
// Assignment and literals
|
|
293
299
|
processAssignment(node) {
|
|
@@ -295,8 +301,9 @@ export class AgencyGenerator {
|
|
|
295
301
|
const chainStr = node.accessChain
|
|
296
302
|
?.map((ce) => this.processAccessChainElement(ce))
|
|
297
303
|
.join("") ?? "";
|
|
304
|
+
const bangSuffix = node.validated ? "!" : "";
|
|
298
305
|
const varName = node.typeHint
|
|
299
|
-
? `${node.variableName}${chainStr}: ${variableTypeToString(node.typeHint, this.typeAliases)}`
|
|
306
|
+
? `${node.variableName}${chainStr}: ${variableTypeToString(node.typeHint, this.typeAliases)}${bangSuffix}`
|
|
300
307
|
: `${node.variableName}${chainStr}`;
|
|
301
308
|
const sharedPrefix = node.shared ? "shared " : "";
|
|
302
309
|
const declPrefix = node.declKind ? `${node.declKind} ` : "";
|
|
@@ -365,19 +372,22 @@ export class AgencyGenerator {
|
|
|
365
372
|
: "";
|
|
366
373
|
if (p.typeHint) {
|
|
367
374
|
const typeStr = variableTypeToString(p.typeHint, this.typeAliases);
|
|
368
|
-
|
|
375
|
+
const bang = p.validated ? "!" : "";
|
|
376
|
+
return `${prefix}${p.name}: ${typeStr}${bang}${defaultSuffix}`;
|
|
369
377
|
}
|
|
370
378
|
else {
|
|
371
379
|
return `${prefix}${p.name}${defaultSuffix}`;
|
|
372
380
|
}
|
|
373
381
|
})
|
|
374
382
|
.join(", ");
|
|
383
|
+
const returnTypeBang = node.returnTypeValidated ? "!" : "";
|
|
375
384
|
const returnTypeStr = node.returnType
|
|
376
|
-
? ": " + variableTypeToString(node.returnType, this.typeAliases)
|
|
385
|
+
? ": " + variableTypeToString(node.returnType, this.typeAliases) + returnTypeBang
|
|
377
386
|
: "";
|
|
378
387
|
let safePrefix = node.safe ? "safe " : "";
|
|
379
388
|
const exportPrefix = node.exported ? "export " : "";
|
|
380
|
-
|
|
389
|
+
const keyword = node.callback ? "callback" : "def";
|
|
390
|
+
let result = this.indentStr(`${exportPrefix}${safePrefix}${keyword} ${functionName}(${params})${returnTypeStr} {\n`);
|
|
381
391
|
this.increaseIndent();
|
|
382
392
|
if (node.docString) {
|
|
383
393
|
const docLines = [`"""`, ...node.docString.value.split("\n"), `"""`];
|
|
@@ -395,7 +405,7 @@ export class AgencyGenerator {
|
|
|
395
405
|
result += bodyCode;
|
|
396
406
|
this.decreaseIndent();
|
|
397
407
|
result += this.indentStr(`}`);
|
|
398
|
-
return tags + result;
|
|
408
|
+
return this.formatDocComment(node) + tags + result;
|
|
399
409
|
}
|
|
400
410
|
processFunctionCall(node) {
|
|
401
411
|
const tags = this.formatAttachedTags(node);
|
|
@@ -588,6 +598,8 @@ export class AgencyGenerator {
|
|
|
588
598
|
return lines.join("");
|
|
589
599
|
}
|
|
590
600
|
processReturnStatement(node) {
|
|
601
|
+
if (!node.value)
|
|
602
|
+
return this.indentStr("return");
|
|
591
603
|
const valueCode = this.processNode(node.value).trim();
|
|
592
604
|
return this.indentStr(`return ${valueCode}`);
|
|
593
605
|
}
|
|
@@ -599,8 +611,16 @@ export class AgencyGenerator {
|
|
|
599
611
|
return this.indentStr(`//${node.content}`);
|
|
600
612
|
}
|
|
601
613
|
processMultiLineComment(node) {
|
|
614
|
+
if (node.isDoc) {
|
|
615
|
+
return this.indentStr(`/**${node.content}*/`);
|
|
616
|
+
}
|
|
602
617
|
return this.indentStr(`/*${node.content}*/`);
|
|
603
618
|
}
|
|
619
|
+
formatDocComment(node) {
|
|
620
|
+
if (!node.docComment)
|
|
621
|
+
return "";
|
|
622
|
+
return this.processMultiLineComment(node.docComment) + "\n";
|
|
623
|
+
}
|
|
604
624
|
processImportStatement(node) {
|
|
605
625
|
const importedNames = node.importedNames.map((name) => this.processImportNameType(name));
|
|
606
626
|
const modulePath = node.modulePath.startsWith("std::")
|
|
@@ -649,16 +669,26 @@ export class AgencyGenerator {
|
|
|
649
669
|
const tags = this.formatAttachedTags(node);
|
|
650
670
|
const { nodeName, body, parameters } = node;
|
|
651
671
|
const params = parameters
|
|
652
|
-
.map((p) =>
|
|
653
|
-
|
|
654
|
-
|
|
672
|
+
.map((p) => {
|
|
673
|
+
if (p.typeHint) {
|
|
674
|
+
const bang = p.validated ? "!" : "";
|
|
675
|
+
return `${p.name}: ${variableTypeToString(p.typeHint, this.typeAliases)}${bang}`;
|
|
676
|
+
}
|
|
677
|
+
return p.name;
|
|
678
|
+
})
|
|
655
679
|
.join(", ");
|
|
680
|
+
const returnTypeBang = node.returnTypeValidated ? "!" : "";
|
|
656
681
|
const returnTypeStr = node.returnType
|
|
657
|
-
? ": " + variableTypeToString(node.returnType, this.typeAliases)
|
|
682
|
+
? ": " + variableTypeToString(node.returnType, this.typeAliases) + returnTypeBang
|
|
658
683
|
: "";
|
|
659
684
|
const visibilityStr = this.visibilityToString(node.visibility);
|
|
660
685
|
let result = this.indentStr(`${visibilityStr}node ${nodeName}(${params})${returnTypeStr} {\n`);
|
|
661
686
|
this.increaseIndent();
|
|
687
|
+
if (node.docString) {
|
|
688
|
+
const docLines = [`"""`, ...node.docString.value.split("\n"), `"""`];
|
|
689
|
+
const docStr = docLines.map((line) => this.indentStr(line)).join("\n");
|
|
690
|
+
result += `${docStr}\n`;
|
|
691
|
+
}
|
|
662
692
|
const lines = [];
|
|
663
693
|
for (const stmt of body) {
|
|
664
694
|
lines.push(this.processNode(stmt));
|
|
@@ -670,7 +700,7 @@ export class AgencyGenerator {
|
|
|
670
700
|
result += bodyCode;
|
|
671
701
|
this.decreaseIndent();
|
|
672
702
|
result += this.indentStr(`}`);
|
|
673
|
-
return tags + result;
|
|
703
|
+
return this.formatDocComment(node) + tags + result;
|
|
674
704
|
}
|
|
675
705
|
processClassDefinition(node) {
|
|
676
706
|
const extendsStr = node.parentClass ? ` extends ${node.parentClass}` : "";
|
|
@@ -683,9 +713,13 @@ export class AgencyGenerator {
|
|
|
683
713
|
// Methods (constructor is auto-generated, not formatted)
|
|
684
714
|
for (const method of node.methods) {
|
|
685
715
|
const params = method.parameters
|
|
686
|
-
.map((p) =>
|
|
687
|
-
|
|
688
|
-
|
|
716
|
+
.map((p) => {
|
|
717
|
+
if (p.typeHint) {
|
|
718
|
+
const bang = p.validated ? "!" : "";
|
|
719
|
+
return `${p.name}: ${variableTypeToString(p.typeHint, this.typeAliases)}${bang}`;
|
|
720
|
+
}
|
|
721
|
+
return p.name;
|
|
722
|
+
})
|
|
689
723
|
.join(", ");
|
|
690
724
|
const returnTypeStr = `: ${variableTypeToString(method.returnType, this.typeAliases)}`;
|
|
691
725
|
result +=
|
|
@@ -747,8 +781,9 @@ export class AgencyGenerator {
|
|
|
747
781
|
.trimEnd() + "\n";
|
|
748
782
|
let handlerStr;
|
|
749
783
|
if (node.handler.kind === "inline") {
|
|
784
|
+
const handlerBang = node.handler.param.validated ? "!" : "";
|
|
750
785
|
const paramStr = node.handler.param.typeHint
|
|
751
|
-
? `${node.handler.param.name}: ${variableTypeToString(node.handler.param.typeHint, this.typeAliases)}`
|
|
786
|
+
? `${node.handler.param.name}: ${variableTypeToString(node.handler.param.typeHint, this.typeAliases)}${handlerBang}`
|
|
752
787
|
: node.handler.param.name;
|
|
753
788
|
this.increaseIndent();
|
|
754
789
|
const handlerBodyCodes = [];
|
|
@@ -771,26 +806,26 @@ export class AgencyGenerator {
|
|
|
771
806
|
return this.indentStr(`skill "${node.filepath}"`);
|
|
772
807
|
}
|
|
773
808
|
processBinOpExpression(node, assigned = false) {
|
|
774
|
-
// Collect a chain of the same operator (e.g. a |> b |> c)
|
|
775
809
|
const op = node.operator;
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
:
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
810
|
+
// Unary prefix operators: !x, typeof x, void x
|
|
811
|
+
if (op === "!" || op === "typeof" || op === "void") {
|
|
812
|
+
const operand = this.processNode(node.right).trim();
|
|
813
|
+
const sep = op === "!" ? "" : " ";
|
|
814
|
+
const result = `${op}${sep}${operand}`;
|
|
815
|
+
return assigned ? result : this.indentStr(result);
|
|
816
|
+
}
|
|
817
|
+
// Postfix operators: x++, x--
|
|
818
|
+
if (op === "++" || op === "--") {
|
|
819
|
+
const operand = this.processNode(node.left).trim();
|
|
820
|
+
const result = `${operand}${op}`;
|
|
821
|
+
return assigned ? result : this.indentStr(result);
|
|
822
|
+
}
|
|
823
|
+
const leftStr = this.processNode(node.left).trim();
|
|
824
|
+
const rightStr = this.processNode(node.right).trim();
|
|
825
|
+
const left = this.needsParensLeft(node.left, op) ? `(${leftStr})` : leftStr;
|
|
826
|
+
const right = this.needsParensRight(node.right, op) ? `(${rightStr})` : rightStr;
|
|
827
|
+
const result = `${left} ${op} ${right}`;
|
|
828
|
+
return assigned ? result : this.indentStr(result);
|
|
794
829
|
}
|
|
795
830
|
processAccessChainElement(node) {
|
|
796
831
|
const dot = node.optional ? "?." : ".";
|
|
@@ -801,6 +836,12 @@ export class AgencyGenerator {
|
|
|
801
836
|
const inner = this.processNode(node.index).trim();
|
|
802
837
|
return node.optional ? `?.[${inner}]` : `[${inner}]`;
|
|
803
838
|
}
|
|
839
|
+
case "slice": {
|
|
840
|
+
const start = node.start ? this.processNode(node.start).trim() : "";
|
|
841
|
+
const end = node.end ? this.processNode(node.end).trim() : "";
|
|
842
|
+
const inner = `${start}:${end}`;
|
|
843
|
+
return node.optional ? `?.[${inner}]` : `[${inner}]`;
|
|
844
|
+
}
|
|
804
845
|
case "methodCall":
|
|
805
846
|
return `${dot}${this.generateFunctionCallExpression(node.functionCall, "valueAccess")}`;
|
|
806
847
|
default:
|
|
@@ -239,4 +239,134 @@ describe("AgencyGenerator - Class Definitions", () => {
|
|
|
239
239
|
const output = formatAgency(input);
|
|
240
240
|
expect(output).toContain("new Counter(0)");
|
|
241
241
|
});
|
|
242
|
+
it("should format callback declarations with the callback keyword", () => {
|
|
243
|
+
const input = `callback onLLMCallEnd(data) {
|
|
244
|
+
log(data)
|
|
245
|
+
}`;
|
|
246
|
+
const output = formatAgency(input);
|
|
247
|
+
expect(output).toContain("callback onLLMCallEnd(data)");
|
|
248
|
+
expect(output).not.toContain("def onLLMCallEnd");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
describe("AgencyGenerator - Doc Comments", () => {
|
|
252
|
+
function formatAgency(input) {
|
|
253
|
+
const parseResult = parseAgency(input, {}, false);
|
|
254
|
+
expect(parseResult.success).toBe(true);
|
|
255
|
+
if (!parseResult.success)
|
|
256
|
+
return "";
|
|
257
|
+
const generator = new AgencyGenerator();
|
|
258
|
+
return generator.generate(parseResult.result).output.trim();
|
|
259
|
+
}
|
|
260
|
+
it("should preserve /** syntax for doc comments", () => {
|
|
261
|
+
const input = `/** This is a doc comment */\ndef foo() {\n print("hi")\n}`;
|
|
262
|
+
const output = formatAgency(input);
|
|
263
|
+
expect(output).toContain("/** This is a doc comment */");
|
|
264
|
+
});
|
|
265
|
+
it("should preserve /* syntax for regular multi-line comments", () => {
|
|
266
|
+
const input = `/* This is a regular comment */\ndef foo() {\n print("hi")\n}`;
|
|
267
|
+
const output = formatAgency(input);
|
|
268
|
+
expect(output).toContain("/* This is a regular comment */");
|
|
269
|
+
expect(output).not.toContain("/**");
|
|
270
|
+
});
|
|
271
|
+
it("should preserve multi-line doc comments", () => {
|
|
272
|
+
const input = `/**\nThis is a multi-line\ndoc comment\n*/\ndef foo() {\n print("hi")\n}`;
|
|
273
|
+
const output = formatAgency(input);
|
|
274
|
+
expect(output).toContain("/**");
|
|
275
|
+
expect(output).toContain("This is a multi-line");
|
|
276
|
+
});
|
|
277
|
+
it("should round-trip node docstrings", () => {
|
|
278
|
+
const input = `node main() {\n """Main entry point."""\n print("hello")\n}`;
|
|
279
|
+
const output = formatAgency(input);
|
|
280
|
+
expect(output).toContain('"""');
|
|
281
|
+
expect(output).toContain("Main entry point.");
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
describe("AgencyGenerator - bang (!) validated type annotations", () => {
|
|
285
|
+
function formatAgency(input) {
|
|
286
|
+
const parseResult = parseAgency(input, {}, false);
|
|
287
|
+
expect(parseResult.success).toBe(true);
|
|
288
|
+
if (!parseResult.success)
|
|
289
|
+
return "";
|
|
290
|
+
const generator = new AgencyGenerator();
|
|
291
|
+
return generator.generate(parseResult.result).output.trim();
|
|
292
|
+
}
|
|
293
|
+
it("should preserve ! on assignment type annotations", () => {
|
|
294
|
+
const input = `node main() {\n const x: number! = 42\n}`;
|
|
295
|
+
const output = formatAgency(input);
|
|
296
|
+
expect(output).toContain("const x: number! = 42");
|
|
297
|
+
});
|
|
298
|
+
it("should preserve ! on function parameter types", () => {
|
|
299
|
+
const input = `def process(data: number!) {\n print(data)\n}`;
|
|
300
|
+
const output = formatAgency(input);
|
|
301
|
+
expect(output).toContain("data: number!");
|
|
302
|
+
});
|
|
303
|
+
it("should preserve ! on function return types", () => {
|
|
304
|
+
const input = `def process(x: number): string! {\n return x\n}`;
|
|
305
|
+
const output = formatAgency(input);
|
|
306
|
+
expect(output).toContain("): string!");
|
|
307
|
+
});
|
|
308
|
+
it("should preserve ! on node return types", () => {
|
|
309
|
+
const input = `node main(): number! {\n return 42\n}`;
|
|
310
|
+
const output = formatAgency(input);
|
|
311
|
+
expect(output).toContain("(): number!");
|
|
312
|
+
});
|
|
313
|
+
it("should not add ! when not present", () => {
|
|
314
|
+
const input = `node main() {\n const x: number = 42\n}`;
|
|
315
|
+
const output = formatAgency(input);
|
|
316
|
+
expect(output).toContain("const x: number = 42");
|
|
317
|
+
expect(output).not.toContain("number!");
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
describe("AgencyGenerator - Result type formatting", () => {
|
|
321
|
+
function formatAgency(input) {
|
|
322
|
+
const parseResult = parseAgency(input, {}, false);
|
|
323
|
+
expect(parseResult.success).toBe(true);
|
|
324
|
+
if (!parseResult.success)
|
|
325
|
+
return "";
|
|
326
|
+
const generator = new AgencyGenerator();
|
|
327
|
+
return generator.generate(parseResult.result).output.trim();
|
|
328
|
+
}
|
|
329
|
+
it("should format Result<Foo> with single type param", () => {
|
|
330
|
+
const input = `def check(): Result<number> {\n return success(42)\n}`;
|
|
331
|
+
const output = formatAgency(input);
|
|
332
|
+
expect(output).toContain("Result<number>");
|
|
333
|
+
expect(output).not.toContain("Result<number,");
|
|
334
|
+
});
|
|
335
|
+
it("should format bare Result without type params", () => {
|
|
336
|
+
const input = `def check(): Result {\n return success(42)\n}`;
|
|
337
|
+
const output = formatAgency(input);
|
|
338
|
+
expect(output).toContain(": Result");
|
|
339
|
+
expect(output).not.toContain("Result<");
|
|
340
|
+
});
|
|
341
|
+
it("should format Result<Foo, Bar> with non-default failure type", () => {
|
|
342
|
+
const input = `def check(): Result<number, number> {\n return success(42)\n}`;
|
|
343
|
+
const output = formatAgency(input);
|
|
344
|
+
expect(output).toContain("Result<number, number>");
|
|
345
|
+
});
|
|
346
|
+
it("should normalize Result<Foo, string> to Result<Foo>", () => {
|
|
347
|
+
const input = `def check(): Result<number, string> {\n return success(42)\n}`;
|
|
348
|
+
const output = formatAgency(input);
|
|
349
|
+
expect(output).toContain("Result<number>");
|
|
350
|
+
expect(output).not.toContain("Result<number, string>");
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
describe("AgencyGenerator - schema(Type) expressions", () => {
|
|
354
|
+
function formatAgency(input) {
|
|
355
|
+
const parseResult = parseAgency(input, {}, false);
|
|
356
|
+
expect(parseResult.success).toBe(true);
|
|
357
|
+
if (!parseResult.success)
|
|
358
|
+
return "";
|
|
359
|
+
const generator = new AgencyGenerator();
|
|
360
|
+
return generator.generate(parseResult.result).output.trim();
|
|
361
|
+
}
|
|
362
|
+
it("should format schema(number)", () => {
|
|
363
|
+
const input = `node main() {\n const s = schema(number)\n}`;
|
|
364
|
+
const output = formatAgency(input);
|
|
365
|
+
expect(output).toContain("schema(number)");
|
|
366
|
+
});
|
|
367
|
+
it("should format schema(Result<number>)", () => {
|
|
368
|
+
const input = `node main() {\n const s = schema(Result<number>)\n}`;
|
|
369
|
+
const output = formatAgency(input);
|
|
370
|
+
expect(output).toContain("schema(Result<number>)");
|
|
371
|
+
});
|
|
242
372
|
});
|
|
@@ -24,7 +24,7 @@ export declare class TypeScriptBuilder {
|
|
|
24
24
|
/** Tracks the current substep nesting path. Empty when at the top level
|
|
25
25
|
* of a stepped body. Non-empty when inside a block (if/else, etc.) that
|
|
26
26
|
* has been broken into substeps. Used to generate unique variable names
|
|
27
|
-
* like
|
|
27
|
+
* like __substep_3.1 for nested blocks. */
|
|
28
28
|
private _subStepPath;
|
|
29
29
|
private _sourceMapBuilder;
|
|
30
30
|
private programInfo;
|
|
@@ -49,6 +49,11 @@ export declare class TypeScriptBuilder {
|
|
|
49
49
|
* emits a normal `lhs = rhs` assignment.
|
|
50
50
|
*/
|
|
51
51
|
private scopedAssign;
|
|
52
|
+
/**
|
|
53
|
+
* arr[1:3] = [10, 20] → arr.splice(start, end - start, ...value)
|
|
54
|
+
* arr[2:] = [10] → arr.splice(start, arr.length - start, ...value)
|
|
55
|
+
*/
|
|
56
|
+
private buildSliceAssignment;
|
|
52
57
|
private currentScopeKey;
|
|
53
58
|
/** Returns the name of the current scope (function, node, or block name, or empty string for global). */
|
|
54
59
|
private currentScopeName;
|
|
@@ -63,6 +68,7 @@ export declare class TypeScriptBuilder {
|
|
|
63
68
|
private isImpureImportedFunction;
|
|
64
69
|
private containsImpureCall;
|
|
65
70
|
private getScopeReturnType;
|
|
71
|
+
private getScopeReturnTypeValidated;
|
|
66
72
|
private agencyFileToDefaultImportName;
|
|
67
73
|
private needsParensLeft;
|
|
68
74
|
private needsParensRight;
|
|
@@ -105,6 +111,7 @@ export declare class TypeScriptBuilder {
|
|
|
105
111
|
private processPipeExpression;
|
|
106
112
|
private processTryExpression;
|
|
107
113
|
private processNewExpression;
|
|
114
|
+
private processSchemaExpression;
|
|
108
115
|
/**
|
|
109
116
|
* Check if a method name matches any method defined on any known Agency class.
|
|
110
117
|
* Used to decide whether to inject __state into method calls.
|
|
@@ -157,8 +164,11 @@ export declare class TypeScriptBuilder {
|
|
|
157
164
|
private processForkCall;
|
|
158
165
|
private generateNodeCallExpression;
|
|
159
166
|
private processGraphNode;
|
|
167
|
+
/** If the enclosing function/node has returnTypeValidated, wrap value in __validateType */
|
|
168
|
+
private maybeWrapReturnValidation;
|
|
160
169
|
private processReturnStatement;
|
|
161
170
|
private processAssignment;
|
|
171
|
+
private _processAssignmentInner;
|
|
162
172
|
private buildAccessChain;
|
|
163
173
|
private buildAssignmentLhs;
|
|
164
174
|
/**
|
|
@@ -167,7 +177,6 @@ export declare class TypeScriptBuilder {
|
|
|
167
177
|
* response format from type hints, and tools from config object.
|
|
168
178
|
*/
|
|
169
179
|
private processLlmCall;
|
|
170
|
-
private processSentinel;
|
|
171
180
|
private processDebuggerStatement;
|
|
172
181
|
private processMessageThread;
|
|
173
182
|
private processBlockPlain;
|
|
@@ -213,3 +213,53 @@ ${safeKeyword}def ${funcName}(id: string, shouldSave: boolean, items: string[]):
|
|
|
213
213
|
}
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
|
+
describe("schema(Type) expression", () => {
|
|
217
|
+
it("should compile schema(Type) for named type aliases", () => {
|
|
218
|
+
expect(() => generateWithBuilder(`
|
|
219
|
+
type Category = "bug" | "feature"
|
|
220
|
+
node main() {
|
|
221
|
+
const s = schema(Category)
|
|
222
|
+
}
|
|
223
|
+
`)).not.toThrow();
|
|
224
|
+
});
|
|
225
|
+
it("should compile schema(Type) for builtin types", () => {
|
|
226
|
+
expect(() => generateWithBuilder(`
|
|
227
|
+
node main() {
|
|
228
|
+
const s = schema(number)
|
|
229
|
+
}
|
|
230
|
+
`)).not.toThrow();
|
|
231
|
+
});
|
|
232
|
+
it("should compile schema(Result<number>)", () => {
|
|
233
|
+
expect(() => generateWithBuilder(`
|
|
234
|
+
node main() {
|
|
235
|
+
const s = schema(Result<number>)
|
|
236
|
+
}
|
|
237
|
+
`)).not.toThrow();
|
|
238
|
+
});
|
|
239
|
+
it("generated code contains new Schema(...)", () => {
|
|
240
|
+
const output = generateWithBuilder(`
|
|
241
|
+
type Category = "bug" | "feature"
|
|
242
|
+
node main() {
|
|
243
|
+
const s = schema(Category)
|
|
244
|
+
}
|
|
245
|
+
`);
|
|
246
|
+
expect(output).toContain("new Schema(");
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
import { mapTypeToValidationSchema } from "./typescriptGenerator/typeToZodSchema.js";
|
|
250
|
+
describe("mapTypeToValidationSchema", () => {
|
|
251
|
+
it("generates Result validation schema for bare Result", () => {
|
|
252
|
+
const schema = mapTypeToValidationSchema({ type: "resultType", successType: { type: "primitiveType", value: "any" }, failureType: { type: "primitiveType", value: "any" } }, {});
|
|
253
|
+
expect(schema).toContain("z.literal(true)");
|
|
254
|
+
expect(schema).toContain("z.literal(false)");
|
|
255
|
+
});
|
|
256
|
+
it("generates Result validation schema with typed success", () => {
|
|
257
|
+
const schema = mapTypeToValidationSchema({ type: "resultType", successType: { type: "primitiveType", value: "number" }, failureType: { type: "primitiveType", value: "string" } }, {});
|
|
258
|
+
expect(schema).toContain("z.number()");
|
|
259
|
+
expect(schema).toContain("z.literal(true)");
|
|
260
|
+
});
|
|
261
|
+
it("delegates non-Result types to mapTypeToZodSchema", () => {
|
|
262
|
+
const schema = mapTypeToValidationSchema({ type: "primitiveType", value: "number" }, {});
|
|
263
|
+
expect(schema).toBe("z.number()");
|
|
264
|
+
});
|
|
265
|
+
});
|