@dot-agent/language-server 0.2.0 → 0.3.1
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/.github/workflows/publish.yml +28 -0
- package/AGENTS.md +2 -2
- package/README.md +1 -1
- package/features/diagnostics.js +21 -33
- package/package.json +10 -4
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout repository
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Setup Node.js
|
|
19
|
+
uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: '24.x'
|
|
22
|
+
registry-url: 'https://registry.npmjs.org'
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: npm ci
|
|
26
|
+
|
|
27
|
+
- name: Publish package to npm
|
|
28
|
+
run: npm publish
|
package/AGENTS.md
CHANGED
|
@@ -20,7 +20,7 @@ All structural analysis is performed on **tree-sitter ASTs** (not regex). `parse
|
|
|
20
20
|
| `parser.js` | Tree-sitter engine — WASM initialization, per-document AST cache, and shared traversal helpers |
|
|
21
21
|
| `features/hover.js` | Hover documentation for all DSL keywords (static lookup, no tree traversal) |
|
|
22
22
|
| `features/completions.js` | Context-aware completions using `getContextNode` and `nodesOfType` for name lookups |
|
|
23
|
-
| `features/diagnostics.js` | Linting — dangling transitions, dead-end interact (AST),
|
|
23
|
+
| `features/diagnostics.js` | Linting — dangling transitions, dead-end interact (AST), undeclared types (AST) |
|
|
24
24
|
| `features/definition.js` | Go-to-definition via `state_decl` / `type_decl` node lookup |
|
|
25
25
|
| `features/references.js` | Find all references via `transition_stmt`, `intent_trigger`, `type_ref` traversal |
|
|
26
26
|
| `features/rename.js` | Rename symbol — same traversal as references, produces `TextEdit[]` |
|
|
@@ -153,4 +153,4 @@ The Apache 2.0 header:
|
|
|
153
153
|
| Agent grammar (canonical) | [tree-sitter-agent/grammar.js](https://github.com/daniloborges/tree-sitter-agent/blob/main/grammar.js) |
|
|
154
154
|
| Flow grammar (canonical) | [tree-sitter-agent/flow/grammar.js](https://github.com/daniloborges/tree-sitter-agent/blob/main/flow/grammar.js) |
|
|
155
155
|
| VS Code extension | [vscode-dot-agent](https://github.com/daniloborges/vscode-dot-agent) |
|
|
156
|
-
| WASM execution engine | [dot-agent-kernel](https://github.com/
|
|
156
|
+
| WASM execution engine | [dot-agent-kernel](https://github.com/dot-agent-spec/kernel-dsl) |
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A standalone [Language Server Protocol (LSP)](https://microsoft.github.io/langua
|
|
|
8
8
|
|---|---|---|
|
|
9
9
|
| **Hover** | Keyword documentation | Keyword documentation |
|
|
10
10
|
| **Completion** | Manifest keywords, custom types | Keywords, state names, memory domains (`context.`, `session.`, …) |
|
|
11
|
-
| **Diagnostics** |
|
|
11
|
+
| **Diagnostics** | Strict block lint, undeclared types | Dangling `transition` targets, dead-end `interact` |
|
|
12
12
|
| **Go-to-Definition** | Type name → `type` declaration | `transition to stateName` → `state` declaration |
|
|
13
13
|
| **Find References** | All uses of a type | All `transition` references to a state |
|
|
14
14
|
| **Rename** | Type and its references | State and all `transition` references |
|
package/features/diagnostics.js
CHANGED
|
@@ -19,11 +19,6 @@
|
|
|
19
19
|
const { DiagnosticSeverity } = require('vscode-languageserver');
|
|
20
20
|
const { nodesOfType, nodeToRange } = require('../parser');
|
|
21
21
|
|
|
22
|
-
const DEPRECATED_AGENT_KW = new Set([
|
|
23
|
-
'do', 'server', 'endpoint', 'author', 'version', 'requirements', 'step',
|
|
24
|
-
'softwareVersion', 'applicationCategory', 'character', 'publishingPrinciples',
|
|
25
|
-
]);
|
|
26
|
-
|
|
27
22
|
const STRICT_BLOCK_TYPES = {
|
|
28
23
|
input_block: 'input',
|
|
29
24
|
output_block: 'output',
|
|
@@ -34,26 +29,6 @@ const STRICT_BLOCK_TYPES = {
|
|
|
34
29
|
function diagnoseAgent(tree, text) {
|
|
35
30
|
const diagnostics = [];
|
|
36
31
|
|
|
37
|
-
// ── Deprecated keywords: line scan (no tree-sitter benefit here) ──────────
|
|
38
|
-
const lines = text.split('\n');
|
|
39
|
-
for (let i = 0; i < lines.length; i++) {
|
|
40
|
-
const raw = lines[i];
|
|
41
|
-
const stripped = raw.split('//')[0].trim();
|
|
42
|
-
if (!stripped) continue;
|
|
43
|
-
const wordM = stripped.match(/^([a-zA-Z0-9_.-]+)\b/);
|
|
44
|
-
if (!wordM) continue;
|
|
45
|
-
const word = wordM[1];
|
|
46
|
-
if (DEPRECATED_AGENT_KW.has(word)) {
|
|
47
|
-
const col = raw.indexOf(word);
|
|
48
|
-
diagnostics.push({
|
|
49
|
-
range: { start: { line: i, character: col }, end: { line: i, character: col + word.length } },
|
|
50
|
-
message: `The keyword '${word}' is deprecated or invalid in the current .agent specification.`,
|
|
51
|
-
severity: DiagnosticSeverity.Error,
|
|
52
|
-
source: 'agent-dsl',
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
32
|
// ── Strict block validation ───────────────────────────────────────────────
|
|
58
33
|
const declaredTypes = new Set(
|
|
59
34
|
nodesOfType(tree, 'type_decl')
|
|
@@ -99,6 +74,7 @@ function diagnoseFlow(tree) {
|
|
|
99
74
|
const diagnostics = [];
|
|
100
75
|
|
|
101
76
|
// ── Rule 1: Dangling transitions ──────────────────────────────────────────
|
|
77
|
+
// Collect all defined state names (from both oriented_state_body and setup_state_body)
|
|
102
78
|
const definedStates = new Set(
|
|
103
79
|
nodesOfType(tree, 'state_decl')
|
|
104
80
|
.map(n => n.childForFieldName('name')?.text)
|
|
@@ -125,26 +101,38 @@ function diagnoseFlow(tree) {
|
|
|
125
101
|
checkTransitionTarget(n.childForFieldName('state'));
|
|
126
102
|
}
|
|
127
103
|
for (const n of nodesOfType(tree, 'intent_trigger')) {
|
|
128
|
-
// inline form: on intent "..."
|
|
104
|
+
// inline form: on intent "..." transition to <state>
|
|
105
|
+
checkTransitionTarget(n.childForFieldName('state'));
|
|
106
|
+
}
|
|
107
|
+
for (const n of nodesOfType(tree, 'fallback_stmt')) {
|
|
108
|
+
// inline form: on fallback transition to <state>
|
|
109
|
+
checkTransitionTarget(n.childForFieldName('state'));
|
|
110
|
+
}
|
|
111
|
+
for (const n of nodesOfType(tree, 'offtopic_stmt')) {
|
|
112
|
+
// inline form: on offtopic transition to <state>
|
|
129
113
|
checkTransitionTarget(n.childForFieldName('state'));
|
|
130
114
|
}
|
|
131
115
|
|
|
132
|
-
// ── Rule 2: Dead-end interact
|
|
116
|
+
// ── Rule 2: Dead-end interact (now redundant but kept for safety) ────────────
|
|
117
|
+
// With the new grammar, oriented_state_body requires repeat1(handlers),
|
|
118
|
+
// so dead-end interact is structurally impossible. But kept for edge cases.
|
|
133
119
|
for (const interactNode of nodesOfType(tree, 'interact_stmt')) {
|
|
134
120
|
let ancestor = interactNode.parent;
|
|
135
|
-
while (ancestor && ancestor.type !== 'state_decl') {
|
|
121
|
+
while (ancestor && ancestor.type !== 'oriented_state_body' && ancestor.type !== 'state_decl') {
|
|
136
122
|
ancestor = ancestor.parent;
|
|
137
123
|
}
|
|
138
124
|
if (!ancestor) continue;
|
|
139
125
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
126
|
+
// With new grammar: oriented_state_body always has handlers after interact (repeat1)
|
|
127
|
+
// So this check should never trigger, but kept for robustness
|
|
128
|
+
const hasHandlers = ancestor.descendantsOfType('intent_trigger').length +
|
|
129
|
+
ancestor.descendantsOfType('fallback_stmt').length +
|
|
130
|
+
ancestor.descendantsOfType('offtopic_stmt').length > 0;
|
|
143
131
|
|
|
144
|
-
if (!
|
|
132
|
+
if (!hasHandlers) {
|
|
145
133
|
diagnostics.push({
|
|
146
134
|
range: nodeToRange(interactNode),
|
|
147
|
-
message: "This state calls interact but has no
|
|
135
|
+
message: "This state calls interact but has no handlers (on intent/fallback/offtopic). This will trap the agent.",
|
|
148
136
|
severity: DiagnosticSeverity.Warning,
|
|
149
137
|
source: 'behavior-dsl',
|
|
150
138
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dot-agent/language-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "LSP server for .agent DSL files",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Danilo Borges <contato@daniloborg.es>",
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/dot-agent-spec/language-server/issues"
|
|
14
14
|
},
|
|
15
|
-
"keywords": [
|
|
15
|
+
"keywords": [
|
|
16
|
+
"lsp",
|
|
17
|
+
"language-server",
|
|
18
|
+
"agent",
|
|
19
|
+
"dsl",
|
|
20
|
+
"flow"
|
|
21
|
+
],
|
|
16
22
|
"main": "server.js",
|
|
17
23
|
"engines": {
|
|
18
24
|
"node": ">=18"
|
|
@@ -21,10 +27,10 @@
|
|
|
21
27
|
"start": "node server.js --stdio"
|
|
22
28
|
},
|
|
23
29
|
"dependencies": {
|
|
30
|
+
"@dot-agent/tree-sitter": "^0.3.2",
|
|
24
31
|
"vscode-languageserver": "^9.0.1",
|
|
25
32
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
26
|
-
"web-tree-sitter": "^0.25.
|
|
27
|
-
"@dot-agent/tree-sitter": "^0.2.0"
|
|
33
|
+
"web-tree-sitter": "^0.25.10"
|
|
28
34
|
},
|
|
29
35
|
"publishConfig": {
|
|
30
36
|
"access": "public"
|