agency-lang 0.0.16 → 0.0.18

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.
@@ -1,9 +1,10 @@
1
- import { InterpolationSegment, Literal, NumberLiteral, PromptLiteral, StringLiteral, TextSegment, VariableNameLiteral } from "../types.js";
1
+ import { InterpolationSegment, Literal, MultiLineStringLiteral, NumberLiteral, PromptLiteral, StringLiteral, TextSegment, VariableNameLiteral } from "../types.js";
2
2
  import { Parser } from "tarsec";
3
3
  export declare const textSegmentParser: Parser<TextSegment>;
4
4
  export declare const interpolationSegmentParser: Parser<InterpolationSegment>;
5
5
  export declare const promptParser: Parser<PromptLiteral>;
6
6
  export declare const numberParser: Parser<NumberLiteral>;
7
7
  export declare const stringParser: Parser<StringLiteral>;
8
+ export declare const multiLineStringParser: Parser<MultiLineStringLiteral>;
8
9
  export declare const variableNameParser: Parser<VariableNameLiteral>;
9
10
  export declare const literalParser: Parser<Literal>;
@@ -1,13 +1,14 @@
1
1
  import { backtick, varNameChar } from "./utils.js";
2
- import { capture, char, digit, letter, many, many1Till, many1WithJoin, manyTill, manyWithJoin, map, or, seq, seqC, set, } from "tarsec";
2
+ import { capture, char, digit, letter, many, many1Till, many1WithJoin, manyTillOneOf, manyTillStr, manyWithJoin, map, or, seq, seqC, set, str, } from "tarsec";
3
3
  export const textSegmentParser = map(many1Till(or(backtick, char("$"))), (text) => ({
4
4
  type: "text",
5
5
  value: text,
6
6
  }));
7
- export const interpolationSegmentParser = seqC(set("type", "interpolation"), char("$"), char("{"), capture(many1Till(char("}")), "variableName"), char("}"));
7
+ export const interpolationSegmentParser = seqC(set("type", "interpolation"), char("$"), char("{"), capture(manyTillStr("}"), "variableName"), char("}"));
8
8
  export const promptParser = seqC(set("type", "prompt"), backtick, capture(many(or(textSegmentParser, interpolationSegmentParser)), "segments"), backtick);
9
9
  export const numberParser = seqC(set("type", "number"), capture(many1WithJoin(or(char("-"), char("."), digit)), "value"));
10
- export const stringParser = seqC(set("type", "string"), char('"'), capture(manyTill(char('"')), "value"), char('"'));
10
+ export const stringParser = seqC(set("type", "string"), char('"'), capture(manyTillOneOf(['"', "\n"]), "value"), char('"'));
11
+ export const multiLineStringParser = seqC(set("type", "multiLineString"), str('"""'), capture(manyTillStr('"""'), "value"), str('"""'));
11
12
  export const variableNameParser = seq([
12
13
  set("type", "variableName"),
13
14
  capture(letter, "init"),
@@ -18,4 +19,4 @@ export const variableNameParser = seq([
18
19
  value: `${captures.init}${captures.value}`,
19
20
  };
20
21
  });
21
- export const literalParser = or(promptParser, numberParser, stringParser, variableNameParser);
22
+ export const literalParser = or(promptParser, numberParser, multiLineStringParser, stringParser, variableNameParser);
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { textSegmentParser, interpolationSegmentParser, promptParser, numberParser, stringParser, variableNameParser, literalParser, } from "./literals.js";
2
+ import { textSegmentParser, interpolationSegmentParser, promptParser, numberParser, stringParser, multiLineStringParser, variableNameParser, literalParser, } from "./literals.js";
3
3
  describe("literals parsers", () => {
4
4
  describe("textSegmentParser", () => {
5
5
  const testCases = [
@@ -112,7 +112,16 @@ describe("literals parsers", () => {
112
112
  { input: "${foo", expected: { success: false } },
113
113
  { input: "$foo}", expected: { success: false } },
114
114
  { input: "{foo}", expected: { success: false } },
115
- { input: "${}", expected: { success: false } },
115
+ {
116
+ input: "${}",
117
+ expected: {
118
+ success: true,
119
+ result: {
120
+ type: "interpolation",
121
+ variableName: "",
122
+ },
123
+ },
124
+ },
116
125
  { input: "", expected: { success: false } },
117
126
  { input: "foo", expected: { success: false } },
118
127
  ];
@@ -391,13 +400,6 @@ describe("literals parsers", () => {
391
400
  result: { type: "string", value: "tab\there" },
392
401
  },
393
402
  },
394
- {
395
- input: '"newline\nhere"',
396
- expected: {
397
- success: true,
398
- result: { type: "string", value: "newline\nhere" },
399
- },
400
- },
401
403
  {
402
404
  input: '"special!@#$%^&*()"',
403
405
  expected: {
@@ -425,6 +427,13 @@ describe("literals parsers", () => {
425
427
  { input: "'hello'", expected: { success: false } },
426
428
  { input: "", expected: { success: false } },
427
429
  { input: "hello", expected: { success: false } },
430
+ /// use """ for multi-line strings
431
+ {
432
+ input: '"newline\nhere"',
433
+ expected: {
434
+ success: false,
435
+ },
436
+ },
428
437
  ];
429
438
  testCases.forEach(({ input, expected }) => {
430
439
  if (expected.success) {
@@ -444,6 +453,170 @@ describe("literals parsers", () => {
444
453
  }
445
454
  });
446
455
  });
456
+ describe("multiLineStringParser", () => {
457
+ const testCases = [
458
+ // Happy path - simple strings
459
+ {
460
+ input: '"""hello"""',
461
+ expected: {
462
+ success: true,
463
+ result: { type: "multiLineString", value: "hello" },
464
+ },
465
+ },
466
+ {
467
+ input: '"""world"""',
468
+ expected: {
469
+ success: true,
470
+ result: { type: "multiLineString", value: "world" },
471
+ },
472
+ },
473
+ // Empty multi-line string
474
+ {
475
+ input: '""""""',
476
+ expected: {
477
+ success: true,
478
+ result: { type: "multiLineString", value: "" },
479
+ },
480
+ },
481
+ // Multi-line strings with actual newlines
482
+ {
483
+ input: '"""line1\nline2"""',
484
+ expected: {
485
+ success: true,
486
+ result: { type: "multiLineString", value: "line1\nline2" },
487
+ },
488
+ },
489
+ {
490
+ input: '"""line1\nline2\nline3"""',
491
+ expected: {
492
+ success: true,
493
+ result: { type: "multiLineString", value: "line1\nline2\nline3" },
494
+ },
495
+ },
496
+ {
497
+ input: '"""\nstarts with newline"""',
498
+ expected: {
499
+ success: true,
500
+ result: { type: "multiLineString", value: "\nstarts with newline" },
501
+ },
502
+ },
503
+ {
504
+ input: '"""ends with newline\n"""',
505
+ expected: {
506
+ success: true,
507
+ result: { type: "multiLineString", value: "ends with newline\n" },
508
+ },
509
+ },
510
+ // Strings with special characters
511
+ {
512
+ input: '"""Hello, World!"""',
513
+ expected: {
514
+ success: true,
515
+ result: { type: "multiLineString", value: "Hello, World!" },
516
+ },
517
+ },
518
+ {
519
+ input: '"""123"""',
520
+ expected: {
521
+ success: true,
522
+ result: { type: "multiLineString", value: "123" },
523
+ },
524
+ },
525
+ {
526
+ input: '""" spaces and tabs\t\t"""',
527
+ expected: {
528
+ success: true,
529
+ result: { type: "multiLineString", value: " spaces and tabs\t\t" },
530
+ },
531
+ },
532
+ {
533
+ input: '"""special!@#$%^&*()"""',
534
+ expected: {
535
+ success: true,
536
+ result: { type: "multiLineString", value: "special!@#$%^&*()" },
537
+ },
538
+ },
539
+ // Strings containing single and double quotes
540
+ {
541
+ input: '"""single\'quotes\'here"""',
542
+ expected: {
543
+ success: true,
544
+ result: { type: "multiLineString", value: "single'quotes'here" },
545
+ },
546
+ },
547
+ {
548
+ input: '"""double"quotes"here"""',
549
+ expected: {
550
+ success: true,
551
+ result: { type: "multiLineString", value: 'double"quotes"here' },
552
+ },
553
+ },
554
+ {
555
+ input: '"""mixed"and\'quotes"""',
556
+ expected: {
557
+ success: true,
558
+ result: { type: "multiLineString", value: `mixed"and'quotes` },
559
+ },
560
+ },
561
+ // Strings containing backticks and interpolation-like syntax
562
+ {
563
+ input: '"""`backtick`"""',
564
+ expected: {
565
+ success: true,
566
+ result: { type: "multiLineString", value: "`backtick`" },
567
+ },
568
+ },
569
+ {
570
+ input: '"""${notInterpolation}"""',
571
+ expected: {
572
+ success: true,
573
+ result: { type: "multiLineString", value: "${notInterpolation}" },
574
+ },
575
+ },
576
+ // Multiple consecutive newlines
577
+ {
578
+ input: '"""line1\n\n\nline2"""',
579
+ expected: {
580
+ success: true,
581
+ result: { type: "multiLineString", value: "line1\n\n\nline2" },
582
+ },
583
+ },
584
+ // Mixed whitespace
585
+ {
586
+ input: '""" \n\t\n """',
587
+ expected: {
588
+ success: true,
589
+ result: { type: "multiLineString", value: " \n\t\n " },
590
+ },
591
+ },
592
+ // Failure cases
593
+ { input: '"""hello', expected: { success: false } },
594
+ { input: 'hello"""', expected: { success: false } },
595
+ { input: '""hello"""', expected: { success: false } },
596
+ { input: '"""hello""', expected: { success: false } },
597
+ { input: '"hello"', expected: { success: false } },
598
+ { input: "'hello'", expected: { success: false } },
599
+ { input: "", expected: { success: false } },
600
+ { input: "hello", expected: { success: false } },
601
+ ];
602
+ testCases.forEach(({ input, expected }) => {
603
+ if (expected.success) {
604
+ it(`should parse ${JSON.stringify(input)} successfully`, () => {
605
+ const result = multiLineStringParser(input);
606
+ expect(result.success).toBe(true);
607
+ if (result.success) {
608
+ expect(result.result).toEqual(expected.result);
609
+ }
610
+ });
611
+ }
612
+ else {
613
+ it(`should fail to parse ${JSON.stringify(input)}`, () => {
614
+ const result = multiLineStringParser(input);
615
+ expect(result.success).toBe(false);
616
+ });
617
+ }
618
+ });
619
+ });
447
620
  describe("variableNameParser", () => {
448
621
  const testCases = [
449
622
  // Happy path
@@ -1,4 +1,4 @@
1
- export declare const template = "graph.node(\"{{{name}}}\", async (state) => {\n {{#hasParam}}\n const {{{paramName}}} = state.data;\n {{/hasParam}}\n {{{body}}}\n});\n";
1
+ export declare const template = "graph.node(\"{{{name}}}\", async (state): Promise<any> => {\n {{#hasParam}}\n const {{{paramName}}} = state.data;\n {{/hasParam}}\n {{{body}}}\n});\n";
2
2
  export type TemplateType = {
3
3
  name: string | boolean | number;
4
4
  hasParam: boolean;
@@ -2,7 +2,7 @@
2
2
  // Source: lib/templates/backends/graphGenerator/graphNode.mustache
3
3
  // Any manual changes will be lost.
4
4
  import { apply } from "typestache";
5
- export const template = `graph.node("{{{name}}}", async (state) => {
5
+ export const template = `graph.node("{{{name}}}", async (state): Promise<any> => {
6
6
  {{#hasParam}}
7
7
  const {{{paramName}}} = state.data;
8
8
  {{/hasParam}}
@@ -1,6 +1,7 @@
1
- export declare const template = "export async function {{{nodeName:string}}}(data:any): Promise<any> {\n const result = await graph.run(\"{{{nodeName:string}}}\", { messages: [], data });\n return result.data;\n}\n";
1
+ export declare const template = "export async function {{{nodeName:string}}}(data:any): Promise<{{{returnType:string}}}> {\n const result = await graph.run(\"{{{nodeName:string}}}\", { messages: [], data });\n return result.data;\n}\n";
2
2
  export type TemplateType = {
3
3
  nodeName: string;
4
+ returnType: string;
4
5
  };
5
6
  declare const render: (args: TemplateType) => string;
6
7
  export default render;
@@ -2,7 +2,7 @@
2
2
  // Source: lib/templates/backends/graphGenerator/runNodeFunction.mustache
3
3
  // Any manual changes will be lost.
4
4
  import { apply } from "typestache";
5
- export const template = `export async function {{{nodeName:string}}}(data:any): Promise<any> {
5
+ export const template = `export async function {{{nodeName:string}}}(data:any): Promise<{{{returnType:string}}}> {
6
6
  const result = await graph.run("{{{nodeName:string}}}", { messages: [], data });
7
7
  return result.data;
8
8
  }
@@ -1,7 +1,8 @@
1
- export declare const template = "async function {{{functionName:string}}}({{{args}}}) {\n {{{functionBody}}}\n}";
1
+ export declare const template = "async function {{{functionName:string}}}({{{args}}}) : Promise<{{{returnType}}}> {\n {{{functionBody}}}\n}";
2
2
  export type TemplateType = {
3
3
  functionName: string;
4
4
  args: string | boolean | number;
5
+ returnType: string | boolean | number;
5
6
  functionBody: string | boolean | number;
6
7
  };
7
8
  declare const render: (args: TemplateType) => string;
@@ -2,7 +2,7 @@
2
2
  // Source: lib/templates/backends/typescriptGenerator/functionDefinition.mustache
3
3
  // Any manual changes will be lost.
4
4
  import { apply } from "typestache";
5
- export const template = `async function {{{functionName:string}}}({{{args}}}) {
5
+ export const template = `async function {{{functionName:string}}}({{{args}}}) : Promise<{{{returnType}}}> {
6
6
  {{{functionBody}}}
7
7
  }`;
8
8
  const render = (args) => {
@@ -11,7 +11,7 @@ export type FunctionDefinition = {
11
11
  functionName: string;
12
12
  parameters: FunctionParameter[];
13
13
  body: AgencyNode[];
14
- returnType?: VariableType;
14
+ returnType?: VariableType | null;
15
15
  docString?: DocString;
16
16
  };
17
17
  export type FunctionCall = {
@@ -1,4 +1,4 @@
1
- import { AgencyNode, FunctionCall } from "../types.js";
1
+ import { AgencyNode, FunctionCall, VariableType } from "../types.js";
2
2
  import { AccessExpression } from "./access.js";
3
3
  import { Literal } from "./literals.js";
4
4
  export type GraphNodeDefinition = {
@@ -6,6 +6,7 @@ export type GraphNodeDefinition = {
6
6
  nodeName: string;
7
7
  parameters: string[];
8
8
  body: AgencyNode[];
9
+ returnType?: VariableType | null;
9
10
  };
10
11
  export type NodeCall = {
11
12
  type: "nodeCall";
@@ -1,4 +1,4 @@
1
- export type Literal = NumberLiteral | StringLiteral | VariableNameLiteral | PromptLiteral;
1
+ export type Literal = NumberLiteral | MultiLineStringLiteral | StringLiteral | VariableNameLiteral | PromptLiteral;
2
2
  export type NumberLiteral = {
3
3
  type: "number";
4
4
  value: string;
@@ -7,6 +7,10 @@ export type StringLiteral = {
7
7
  type: "string";
8
8
  value: string;
9
9
  };
10
+ export type MultiLineStringLiteral = {
11
+ type: "multiLineString";
12
+ value: string;
13
+ };
10
14
  export type VariableNameLiteral = {
11
15
  type: "variableName";
12
16
  value: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agency-lang",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "The Agency language",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -55,4 +55,4 @@
55
55
  "typescript": "^5.9.3",
56
56
  "vitest": "^4.0.16"
57
57
  }
58
- }
58
+ }