From d71a4baa2697f70bb62c315e67827ecc1ef19e9f Mon Sep 17 00:00:00 2001 From: Dominic Nguyen Date: Wed, 22 Jul 2026 09:10:52 -0700 Subject: [PATCH 1/3] Preserve quoted grammar object keys - Track quoted-key syntax while parsing object properties. - Re-emit quoted keys when writing formatted grammars. - Cover quoted key parsing and formatting regressions. --- ts/packages/actionGrammar/README.AUTOGEN.md | 21 ++++++++++++------- .../actionGrammar/src/grammarRuleParser.ts | 7 +++++-- .../actionGrammar/src/grammarRuleWriter.ts | 7 +++++-- .../test/grammarRuleParser.spec.ts | 4 ++++ .../test/grammarRuleWriter.spec.ts | 10 +++++++++ 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/ts/packages/actionGrammar/README.AUTOGEN.md b/ts/packages/actionGrammar/README.AUTOGEN.md index d8ab51d2d0..cbd88edf2c 100644 --- a/ts/packages/actionGrammar/README.AUTOGEN.md +++ b/ts/packages/actionGrammar/README.AUTOGEN.md @@ -3,7 +3,7 @@ - + # @typeagent/action-grammar — AI-generated documentation @@ -12,13 +12,13 @@ ## Overview -The `@typeagent/action-grammar` package is a TypeScript library that provides the grammar engine for the TypeAgent framework. It enables the parsing, compilation, and matching of natural language input against grammar rules defined in `.agr` files. These rules allow the conversion of user input, such as natural language commands, into structured JSON action objects that can be processed by agents. +The `@typeagent/action-grammar` package is a TypeScript library that serves as the grammar engine for the TypeAgent framework. It provides tools for parsing, compiling, and matching natural language input against grammar rules defined in `.agr` files. These rules enable the conversion of user utterances into structured JSON action objects, which can be processed by other components in the TypeAgent ecosystem. -This package is a core component of the TypeAgent ecosystem and is used by several other packages, including `@typeagent/core`, `@typeagent/action-grammar-compiler`, and `agent-cli`. +This package is a foundational dependency for many other TypeAgent packages, including `@typeagent/core`, `@typeagent/action-grammar-compiler`, and `agent-cli`. It supports both rule-based and machine learning-assisted approaches to grammar generation and matching. ## What it does -The primary purpose of this package is to process natural language input and match it against predefined grammar rules to generate structured actions. These actions are represented as JSON objects, which can be consumed by other components in the TypeAgent ecosystem. For example: +The primary function of this package is to interpret natural language input and match it against predefined grammar rules to produce structured actions. These actions are represented as JSON objects, such as: ```json { @@ -34,8 +34,8 @@ The primary purpose of this package is to process natural language input and mat 1. **Grammar Parsing**: - - Parses `.agr` files, which are written in a custom domain-specific language (DSL) for defining natural language grammar rules. - - The DSL supports constructs such as literals, wildcards, alternation, optionals, repetition, rule references, imports, and entity declarations. + - Parses `.agr` files written in a custom DSL for defining natural language grammar rules. + - The DSL supports constructs like literals, wildcards, alternation, optionals, repetition, rule references, imports, and entity declarations. - The `parseGrammarRules` function converts `.agr` files into an Abstract Syntax Tree (AST). 2. **Grammar Compilation**: @@ -58,8 +58,12 @@ The primary purpose of this package is to process natural language input and mat - Supports runtime loading and caching of grammar rules, enabling dynamic updates to the grammar. 6. **Grammar Generation**: + - Includes tools for generating grammar rules from schemas and examples using large language models (LLMs) like Claude. +7. **Collision Analysis**: + - Provides utilities for detecting and resolving overlaps between grammar rules. + ## Setup To use the `@typeagent/action-grammar` package, follow these steps: @@ -170,6 +174,7 @@ External: `@anthropic-ai/claude-agent-sdk`, `debug`, `dotenv`, `regexp.escape` ### Used by +- [@typeagent/action-browser](../../tools/actionBrowser/README.md) - [@typeagent/action-grammar-compiler](../../packages/actionGrammarCompiler/README.md) - [@typeagent/core](../../packages/typeagent-core/README.md) - [agent-cache](../../packages/cache/README.md) @@ -179,7 +184,7 @@ External: `@anthropic-ai/claude-agent-sdk`, `debug`, `dotenv`, `regexp.escape` - [default-agent-provider](../../packages/defaultAgentProvider/README.md) - grammar-tools-cli - grammar-tools-core -- [snips-bench](../../examples/snipsBench/README.md) +- _…and 1 more workspace consumers._ ### Files of interest @@ -197,6 +202,6 @@ External: `@anthropic-ai/claude-agent-sdk`, `debug`, `dotenv`, `regexp.escape` --- -_Auto-generated against commit `defc71271dc68db47e0d376be7aa9f755da0ac91` on `2026-07-14T08:47:00.044Z` by `docs-generate.yml`. Links validated at that commit; the working tree may have drifted by up to 24h. Re-run `pnpm --filter @typeagent/action-grammar docs:verify-links` to spot-check._ +_Auto-generated against commit `7073fc7afbe92c1ed8df57f71835ffa337f9bb08` on `2026-07-22T08:35:04.479Z` by `docs-generate.yml`. Links validated at that commit; the working tree may have drifted by up to 24h. Re-run `pnpm --filter @typeagent/action-grammar docs:verify-links` to spot-check._ diff --git a/ts/packages/actionGrammar/src/grammarRuleParser.ts b/ts/packages/actionGrammar/src/grammarRuleParser.ts index a9cfd36ff4..385237d0c4 100644 --- a/ts/packages/actionGrammar/src/grammarRuleParser.ts +++ b/ts/packages/actionGrammar/src/grammarRuleParser.ts @@ -266,8 +266,9 @@ export type ValueNode = | VariableValueNode | ValueExprNode; -// Parser-time value node types: compiled base types augmented with comment fields. -// The compiler strips these before storing into GrammarRule (see grammarCompiler.ts). +// Parser-time value node types: compiled base types augmented with source-formatting +// metadata. The compiler strips these before storing into GrammarRule (see +// grammarCompiler.ts). // // leadingComments: comments before the value (e.g. after ":" or "["). // trailingComments: comments after the value but before the trailing "," or "]"/"}" delimiter. @@ -289,6 +290,7 @@ type VariableValueNode = CompiledVariableValueNode & { export type ObjectProperty = { type: "property"; key: string; + keyQuoted?: true | undefined; value: ValueNode | null; // null = shorthand: { x } means { x: x } leadingComments?: Comment[] | undefined; trailingComments?: Comment[] | undefined; @@ -1004,6 +1006,7 @@ class GrammarRuleParser implements ValueExprParserContext { obj.push({ type: "property", key: id, + ...(isStringLiteral ? { keyQuoted: true as const } : {}), value: v, leadingComments: pendingLeading, }); diff --git a/ts/packages/actionGrammar/src/grammarRuleWriter.ts b/ts/packages/actionGrammar/src/grammarRuleWriter.ts index aeb592af8c..be89a5ec8a 100644 --- a/ts/packages/actionGrammar/src/grammarRuleWriter.ts +++ b/ts/packages/actionGrammar/src/grammarRuleWriter.ts @@ -78,7 +78,7 @@ export type GrammarWriterOptions = { // This applies at two levels: // a. Between distinct Expr elements (variables, rule refs, groups, // and multi-word string tokens treated as units). -// b. Within a single multi-word string token: individual words are +// b. Within a single multi-word string token, individual words are // also wrapped at the same continuation column when needed. // // IR NODE TYPES: @@ -1088,7 +1088,10 @@ function writeValueNode( } else if (elem.value === null) { result.write(elem.key); } else { - result.write(`${elem.key}: `); + const key = elem.keyQuoted + ? JSON.stringify(elem.key) + : elem.key; + result.write(`${key}: `); writeValueNode( result, elem.value, diff --git a/ts/packages/actionGrammar/test/grammarRuleParser.spec.ts b/ts/packages/actionGrammar/test/grammarRuleParser.spec.ts index f4dc089989..f1ae971ada 100644 --- a/ts/packages/actionGrammar/test/grammarRuleParser.spec.ts +++ b/ts/packages/actionGrammar/test/grammarRuleParser.spec.ts @@ -416,11 +416,13 @@ describe("Grammar Rule Parser", () => { { type: "property", key: "type", + keyQuoted: true, value: { type: "literal", value: "greeting" }, }, { type: "property", key: "count", + keyQuoted: true, value: { type: "literal", value: 1 }, }, ], @@ -438,11 +440,13 @@ describe("Grammar Rule Parser", () => { { type: "property", key: "type", + keyQuoted: true, value: { type: "literal", value: "greeting" }, }, { type: "property", key: "count", + keyQuoted: true, value: { type: "literal", value: 1 }, }, ], diff --git a/ts/packages/actionGrammar/test/grammarRuleWriter.spec.ts b/ts/packages/actionGrammar/test/grammarRuleWriter.spec.ts index 0d68b55673..c1df411d27 100644 --- a/ts/packages/actionGrammar/test/grammarRuleWriter.spec.ts +++ b/ts/packages/actionGrammar/test/grammarRuleWriter.spec.ts @@ -311,6 +311,16 @@ describe("Grammar Rule Writer", () => { it("with object value", () => { validateRoundTrip(` = hello -> { b: true, n: 12, s: "string" };`); }); + it("preserves quoted object property names", () => { + const grammar = + ` = hello -> ` + + `{ "display-name": 1, "title": 2, role: 3 };`; + + expect(writeGrammarRules(parseGrammarRules("test", grammar))).toBe( + `${grammar}\n`, + ); + validateRoundTrip(grammar); + }); it("with object spread value", () => { validateRoundTrip( ` = hello $(x:) -> { ...x, extra: 1 };\n = world -> { a: 2 };`, From f257ffefdbeabe9b86880138b83adb2ec285479a Mon Sep 17 00:00:00 2001 From: typeagent-bot Date: Wed, 22 Jul 2026 16:17:59 +0000 Subject: [PATCH 2/3] docs: regenerate README.AUTOGEN.md, command reference, and action browser --- ts/packages/actionGrammar/README.AUTOGEN.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ts/packages/actionGrammar/README.AUTOGEN.md b/ts/packages/actionGrammar/README.AUTOGEN.md index cbd88edf2c..77a3776017 100644 --- a/ts/packages/actionGrammar/README.AUTOGEN.md +++ b/ts/packages/actionGrammar/README.AUTOGEN.md @@ -3,7 +3,7 @@ - + # @typeagent/action-grammar — AI-generated documentation @@ -12,13 +12,13 @@ ## Overview -The `@typeagent/action-grammar` package is a TypeScript library that serves as the grammar engine for the TypeAgent framework. It provides tools for parsing, compiling, and matching natural language input against grammar rules defined in `.agr` files. These rules enable the conversion of user utterances into structured JSON action objects, which can be processed by other components in the TypeAgent ecosystem. +The `@typeagent/action-grammar` package is a TypeScript library that provides a grammar engine for the TypeAgent framework. It enables the parsing, compilation, and matching of natural language input against grammar rules defined in `.agr` files. These rules allow user utterances to be converted into structured JSON action objects, which can then be processed by other components in the TypeAgent ecosystem. -This package is a foundational dependency for many other TypeAgent packages, including `@typeagent/core`, `@typeagent/action-grammar-compiler`, and `agent-cli`. It supports both rule-based and machine learning-assisted approaches to grammar generation and matching. +This package is a core dependency for several other TypeAgent packages, such as `@typeagent/core`, `@typeagent/action-grammar-compiler`, and `agent-cli`. It supports both rule-based and machine learning-assisted approaches to grammar generation and matching, making it a versatile tool for natural language understanding. ## What it does -The primary function of this package is to interpret natural language input and match it against predefined grammar rules to produce structured actions. These actions are represented as JSON objects, such as: +The primary purpose of `@typeagent/action-grammar` is to process natural language input and match it against predefined grammar rules to generate structured actions. These actions are represented as JSON objects, such as: ```json { @@ -34,8 +34,8 @@ The primary function of this package is to interpret natural language input and 1. **Grammar Parsing**: - - Parses `.agr` files written in a custom DSL for defining natural language grammar rules. - - The DSL supports constructs like literals, wildcards, alternation, optionals, repetition, rule references, imports, and entity declarations. + - Parses `.agr` files written in a custom domain-specific language (DSL) for defining natural language grammar rules. + - The DSL supports constructs such as literals, wildcards, alternation, optionals, repetition, rule references, imports, and entity declarations. - The `parseGrammarRules` function converts `.agr` files into an Abstract Syntax Tree (AST). 2. **Grammar Compilation**: @@ -202,6 +202,6 @@ External: `@anthropic-ai/claude-agent-sdk`, `debug`, `dotenv`, `regexp.escape` --- -_Auto-generated against commit `7073fc7afbe92c1ed8df57f71835ffa337f9bb08` on `2026-07-22T08:35:04.479Z` by `docs-generate.yml`. Links validated at that commit; the working tree may have drifted by up to 24h. Re-run `pnpm --filter @typeagent/action-grammar docs:verify-links` to spot-check._ +_Auto-generated against commit `d71a4baa2697f70bb62c315e67827ecc1ef19e9f` on `2026-07-22T16:16:20.408Z` by `docs-generate.yml`. Links validated at that commit; the working tree may have drifted by up to 24h. Re-run `pnpm --filter @typeagent/action-grammar docs:verify-links` to spot-check._ From 19c6767abac371cc5cf23d76d68dc336d92122fa Mon Sep 17 00:00:00 2001 From: Dominic Nguyen Date: Wed, 22 Jul 2026 09:40:29 -0700 Subject: [PATCH 3/3] Re-run macOS CI