@xano/xanoscript-language-server 11.10.1 → 11.12.0
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/.claude/settings.local.json +28 -13
- package/package.json +1 -1
- package/parser/addon_parser.js +2 -1
- package/parser/agent_parser.js +2 -1
- package/parser/agent_trigger_parser.js +2 -1
- package/parser/api_group_parser.js +2 -1
- package/parser/base_parser.js +11 -0
- package/parser/branch_parser.js +2 -1
- package/parser/function_parser.js +1 -0
- package/parser/function_parser.spec.js +14 -0
- package/parser/functions/db/dbDelFn.spec.js +5 -0
- package/parser/functions/schema/schemaParseAttributeFn.js +2 -10
- package/parser/functions/schema/schemaParseAttributeFn.spec.js +4 -2
- package/parser/mcp_server_parser.js +2 -1
- package/parser/mcp_server_trigger_parser.js +2 -1
- package/parser/middleware_parser.js +2 -1
- package/parser/query_parser.js +1 -0
- package/parser/query_parser.spec.js +14 -0
- package/parser/realtime_channel_parser.js +2 -1
- package/parser/realtime_trigger_parser.js +2 -1
- package/parser/run_parser.js +4 -2
- package/parser/table_parser.js +2 -1
- package/parser/table_trigger_parser.js +2 -1
- package/parser/task_parser.js +2 -1
- package/parser/task_parser.spec.js +11 -0
- package/parser/tool_parser.js +2 -1
- package/parser/workflow_test_parser.js +2 -1
- package/parser/workspace_parser.js +2 -1
- package/parser/workspace_trigger_parser.js +2 -1
- package/.claude/memory/feedback_no_git.md +0 -11
|
@@ -2,20 +2,35 @@
|
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
4
|
"Bash(npm test:*)",
|
|
5
|
-
"Bash(
|
|
6
|
-
"Bash(
|
|
7
|
-
"Bash(
|
|
5
|
+
"Bash(npm run lint)",
|
|
6
|
+
"Bash(npm run test:*)",
|
|
7
|
+
"Bash(npx eslint:*)",
|
|
8
|
+
"Bash(node:*)",
|
|
9
|
+
"Bash(npm install)",
|
|
8
10
|
"Bash(grep:*)",
|
|
11
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server log --all --pretty=format:\"%h %s\")",
|
|
12
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server log --all -S \"password\\\\|secret\\\\|api_key\\\\|token\" --oneline)",
|
|
13
|
+
"Bash(xargs file:*)",
|
|
9
14
|
"Bash(find:*)",
|
|
10
|
-
"
|
|
11
|
-
"Bash(git
|
|
12
|
-
"Bash(
|
|
13
|
-
"Bash(
|
|
14
|
-
"Bash(
|
|
15
|
-
"Bash(
|
|
16
|
-
"Bash(
|
|
17
|
-
"Bash(
|
|
18
|
-
"Bash(
|
|
19
|
-
|
|
15
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server log -p --all -S \"webhook\\\\|Bearer\\\\|discord\\\\|slack\\\\|xano_insiders\" -- \"*.xs\" \"*.js\")",
|
|
16
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server ls-files:*)",
|
|
17
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server status)",
|
|
18
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server diff --stat)",
|
|
19
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server log --oneline -5)",
|
|
20
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server add README.md LICENSE package.json lexer/tests/query/valid_sources/basic_query.xs parser/functions/stream/streamFromRequestFn.js parser/functions/stream/streamFromRequestFn.spec.js parser/tests/function/valid_sources/discord_poll_send_to_slack.xs parser/tests/query/valid_sources/all_basics.xs)",
|
|
21
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server commit -m \"$\\(cat <<''EOF''\nPrepare package for public npm release as @xano/xanoscript-language-server\n\n- Rename package to @xano/xanoscript-language-server\n- Add MIT LICENSE file\n- Add npm metadata \\(description, repository, author, license, bugs, homepage\\)\n- Remove private flag to allow publishing\n- Sanitize test files: replace internal URLs, IDs, and env var names with placeholders\n- Simplify README maintainer section\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
|
22
|
+
"Bash(git -C /Users/justinalbrecht/git/xs-language-server log -1 --oneline)",
|
|
23
|
+
"Bash(git add:*)",
|
|
24
|
+
"Bash(git commit:*)",
|
|
25
|
+
"Bash(git push)",
|
|
26
|
+
"Bash(npm whoami:*)",
|
|
27
|
+
"Bash(npm view:*)",
|
|
28
|
+
"Bash(npm version:*)",
|
|
29
|
+
"Bash(npm publish:*)",
|
|
30
|
+
"Bash(wc:*)",
|
|
31
|
+
"Bash(git push:*)"
|
|
32
|
+
],
|
|
33
|
+
"deny": [],
|
|
34
|
+
"ask": []
|
|
20
35
|
}
|
|
21
36
|
}
|
package/package.json
CHANGED
package/parser/addon_parser.js
CHANGED
|
@@ -26,10 +26,11 @@ export function addonDeclaration($) {
|
|
|
26
26
|
// Allow leading comments and newlines before the addon declaration
|
|
27
27
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
28
28
|
const parent = $.CONSUME(AddonToken);
|
|
29
|
-
$.OR([
|
|
29
|
+
const nameToken = $.OR([
|
|
30
30
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
31
31
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
32
32
|
]);
|
|
33
|
+
$.validateDeclarationName(nameToken, "addon");
|
|
33
34
|
$.CONSUME(LCurly); // "{"
|
|
34
35
|
$.MANY(() => {
|
|
35
36
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
package/parser/agent_parser.js
CHANGED
|
@@ -21,10 +21,11 @@ export function agentDeclaration($) {
|
|
|
21
21
|
// Allow leading comments and newlines before the agent declaration
|
|
22
22
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
23
23
|
const parent = $.CONSUME(AgentToken); // agent
|
|
24
|
-
$.OR([
|
|
24
|
+
const nameToken = $.OR([
|
|
25
25
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
26
26
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
27
27
|
]);
|
|
28
|
+
$.validateDeclarationName(nameToken, "agent");
|
|
28
29
|
$.CONSUME(LCurly); // "{"
|
|
29
30
|
$.MANY(() => {
|
|
30
31
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -26,10 +26,11 @@ export function agentTriggerDeclaration($) {
|
|
|
26
26
|
// Allow leading comments and newlines before the agent_trigger declaration
|
|
27
27
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
28
28
|
const parent = $.CONSUME(AgentTriggerToken); // agent_trigger
|
|
29
|
-
$.OR([
|
|
29
|
+
const nameToken = $.OR([
|
|
30
30
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
31
31
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
32
32
|
]);
|
|
33
|
+
$.validateDeclarationName(nameToken, "agent_trigger");
|
|
33
34
|
$.CONSUME(LCurly); // "{"
|
|
34
35
|
$.MANY(() => {
|
|
35
36
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -27,10 +27,11 @@ export function apiGroupDeclaration($) {
|
|
|
27
27
|
// Allow leading comments and newlines before the api_group declaration
|
|
28
28
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
29
29
|
$.CONSUME(ApiGroupToken); // api_group
|
|
30
|
-
$.OR([
|
|
30
|
+
const nameToken = $.OR([
|
|
31
31
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
32
32
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
33
33
|
]);
|
|
34
|
+
$.validateDeclarationName(nameToken, "api_group");
|
|
34
35
|
$.CONSUME(LCurly); // "{"
|
|
35
36
|
$.MANY(() => {
|
|
36
37
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken));
|
package/parser/base_parser.js
CHANGED
|
@@ -270,6 +270,17 @@ export class XanoBaseParser extends CstParser {
|
|
|
270
270
|
this.SAVE_ERROR(new MismatchedTokenException(message, token));
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Validate that a declaration name token is not an empty string
|
|
275
|
+
* @param {import('chevrotain').IToken} nameToken
|
|
276
|
+
* @param {string} typeName the declaration type (e.g. "query", "function")
|
|
277
|
+
*/
|
|
278
|
+
validateDeclarationName(nameToken, typeName) {
|
|
279
|
+
if (nameToken?.image === '""') {
|
|
280
|
+
this.addInvalidValueError(nameToken, `${typeName} name must not be empty`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
273
284
|
/**
|
|
274
285
|
* Setup all the required rules for the parser but without creating duplicates
|
|
275
286
|
*
|
package/parser/branch_parser.js
CHANGED
|
@@ -9,10 +9,11 @@ export function branchDeclaration($) {
|
|
|
9
9
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
10
10
|
|
|
11
11
|
const parent = $.CONSUME(BranchToken); // branch
|
|
12
|
-
$.OR([
|
|
12
|
+
const nameToken = $.OR([
|
|
13
13
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
14
14
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
15
|
]);
|
|
16
|
+
$.validateDeclarationName(nameToken, "branch");
|
|
16
17
|
|
|
17
18
|
const middlewareSchema = {
|
|
18
19
|
pre: [{ name: "[string]" }],
|
|
@@ -16,6 +16,20 @@ describe("function_parser", () => {
|
|
|
16
16
|
expect(parser.errors).to.be.empty;
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
it("should raise an error when a function name is empty", () => {
|
|
20
|
+
const parser = xanoscriptParser(`function "" {
|
|
21
|
+
input {
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
stack {
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
response = null
|
|
28
|
+
}`);
|
|
29
|
+
expect(parser.errors).to.not.be.empty;
|
|
30
|
+
expect(parser.errors[0].message).to.include("must not be empty");
|
|
31
|
+
});
|
|
32
|
+
|
|
19
33
|
it("should raise an error when a function name starts with /", () => {
|
|
20
34
|
const parser = xanoscriptParser(`function "/foo" {
|
|
21
35
|
input {
|
|
@@ -46,6 +46,11 @@ describe("dbDelFn", () => {
|
|
|
46
46
|
expect(parser.errors).to.be.empty;
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
it("dbDelFn rejects comma separated attributes", () => {
|
|
50
|
+
const parser = parse(`del account {field_name = "id", field_value = "a"}`);
|
|
51
|
+
expect(parser.errors).to.not.be.empty;
|
|
52
|
+
});
|
|
53
|
+
|
|
49
54
|
it("dbDelFn requires a field_name", () => {
|
|
50
55
|
const parser = parse(`del user {
|
|
51
56
|
field_value = $input.email
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { get, isPlainObject, keys, some } from "lodash-es";
|
|
2
2
|
import { ExclamationToken } from "../../../lexer/cast.js";
|
|
3
|
-
import {
|
|
4
|
-
CommaToken,
|
|
5
|
-
EqualToken,
|
|
6
|
-
LCurly,
|
|
7
|
-
RCurly,
|
|
8
|
-
} from "../../../lexer/control.js";
|
|
3
|
+
import { EqualToken, LCurly, RCurly } from "../../../lexer/control.js";
|
|
9
4
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
10
5
|
import { Identifier, NewlineToken } from "../../../lexer/tokens.js";
|
|
11
6
|
import {
|
|
@@ -156,10 +151,7 @@ function _schemaParseAttributeFn($) {
|
|
|
156
151
|
$.CONSUME1(NewlineToken);
|
|
157
152
|
});
|
|
158
153
|
|
|
159
|
-
|
|
160
|
-
needSeparator = false;
|
|
161
|
-
$.CONSUME1(CommaToken);
|
|
162
|
-
});
|
|
154
|
+
lastToken = objectKeyToken;
|
|
163
155
|
});
|
|
164
156
|
$.CONSUME(RCurly); // "}"
|
|
165
157
|
|
|
@@ -127,15 +127,17 @@ describe("schemaParseAttributeFn", () => {
|
|
|
127
127
|
expect(parser.errors).to.be.empty;
|
|
128
128
|
|
|
129
129
|
parse(`value = {
|
|
130
|
-
something = 123.2
|
|
130
|
+
something = 123.2
|
|
131
131
|
other_thing = 44
|
|
132
132
|
}`).schemaParseAttributeFn_flat();
|
|
133
133
|
expect(parser.errors).to.be.empty;
|
|
134
|
+
});
|
|
134
135
|
|
|
136
|
+
it("schemaParseAttributeFn rejects comma separated attributes", () => {
|
|
135
137
|
parse(
|
|
136
138
|
`value = { something = 123.2, other_thing = 44 }`,
|
|
137
139
|
).schemaParseAttributeFn_flat();
|
|
138
|
-
expect(parser.errors).to.be.empty;
|
|
140
|
+
expect(parser.errors).to.not.be.empty;
|
|
139
141
|
});
|
|
140
142
|
|
|
141
143
|
it("schemaParseAttributeFn immutable restricts to valid token", () => {
|
|
@@ -24,10 +24,11 @@ export function mcpServerDeclaration($) {
|
|
|
24
24
|
// Allow leading comments and newlines before the mcp_server declaration
|
|
25
25
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
26
26
|
const parent = $.CONSUME(McpServerToken); // mcp_server
|
|
27
|
-
$.OR([
|
|
27
|
+
const nameToken = $.OR([
|
|
28
28
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
29
29
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
30
30
|
]);
|
|
31
|
+
$.validateDeclarationName(nameToken, "mcp_server");
|
|
31
32
|
$.CONSUME(LCurly); // "{"
|
|
32
33
|
$.MANY(() => {
|
|
33
34
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -25,10 +25,11 @@ export function mcpServerTriggerDeclaration($) {
|
|
|
25
25
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
26
26
|
|
|
27
27
|
const parent = $.CONSUME(McpServerTriggerToken); // mcp_server_trigger
|
|
28
|
-
$.OR([
|
|
28
|
+
const nameToken = $.OR([
|
|
29
29
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
30
30
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
31
31
|
]);
|
|
32
|
+
$.validateDeclarationName(nameToken, "mcp_server_trigger");
|
|
32
33
|
$.CONSUME(LCurly); // "{"
|
|
33
34
|
$.MANY(() => {
|
|
34
35
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -28,10 +28,11 @@ export function middlewareDeclaration($) {
|
|
|
28
28
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
29
29
|
|
|
30
30
|
const parent = $.CONSUME(MiddlewareToken);
|
|
31
|
-
$.OR([
|
|
31
|
+
const nameToken = $.OR([
|
|
32
32
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
33
33
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
34
34
|
]);
|
|
35
|
+
$.validateDeclarationName(nameToken, "middleware");
|
|
35
36
|
$.CONSUME(LCurly); // "{"
|
|
36
37
|
$.MANY(() => {
|
|
37
38
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
package/parser/query_parser.js
CHANGED
|
@@ -43,6 +43,7 @@ export function queryDeclaration($) {
|
|
|
43
43
|
{ ALT: () => $.CONSUME(Identifier) }, // foo
|
|
44
44
|
]);
|
|
45
45
|
|
|
46
|
+
$.validateDeclarationName(nameToken, "query");
|
|
46
47
|
if (nameToken?.image && getVarName(nameToken).startsWith("/")) {
|
|
47
48
|
$.addInvalidValueError(nameToken, "query name must not start with '/'");
|
|
48
49
|
}
|
|
@@ -16,6 +16,20 @@ describe("query_parser", () => {
|
|
|
16
16
|
expect(parser.errors).to.be.empty;
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
it("should raise an error when a query name is empty", () => {
|
|
20
|
+
const parser = xanoscriptParser(`query "" verb=GET {
|
|
21
|
+
input {
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
stack {
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
response = null
|
|
28
|
+
}`);
|
|
29
|
+
expect(parser.errors).to.not.be.empty;
|
|
30
|
+
expect(parser.errors[0].message).to.include("must not be empty");
|
|
31
|
+
});
|
|
32
|
+
|
|
19
33
|
it("should raise an error when a query starts with /", () => {
|
|
20
34
|
const parser = xanoscriptParser(`query "/foo" verb=GET {
|
|
21
35
|
input {
|
|
@@ -9,10 +9,11 @@ export function realtimeChannelDeclaration($) {
|
|
|
9
9
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
10
10
|
|
|
11
11
|
const parent = $.CONSUME(RealtimeChannelToken); // realtime_channel
|
|
12
|
-
$.OR([
|
|
12
|
+
const nameToken = $.OR([
|
|
13
13
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
14
14
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
15
|
]);
|
|
16
|
+
$.validateDeclarationName(nameToken, "realtime_channel");
|
|
16
17
|
|
|
17
18
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
18
19
|
ARGS: [
|
|
@@ -25,10 +25,11 @@ export function realtimeTriggerDeclaration($) {
|
|
|
25
25
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
26
26
|
|
|
27
27
|
const parent = $.CONSUME(RealtimeTriggerToken); // realtime_trigger
|
|
28
|
-
$.OR([
|
|
28
|
+
const nameToken = $.OR([
|
|
29
29
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
30
30
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
31
31
|
]);
|
|
32
|
+
$.validateDeclarationName(nameToken, "realtime_trigger");
|
|
32
33
|
$.CONSUME(LCurly); // "{"
|
|
33
34
|
$.MANY(() => {
|
|
34
35
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
package/parser/run_parser.js
CHANGED
|
@@ -25,10 +25,11 @@ export function runJobClause($) {
|
|
|
25
25
|
return () => {
|
|
26
26
|
const parent = $.CONSUME(JobToken); // "job"
|
|
27
27
|
|
|
28
|
-
$.OR([
|
|
28
|
+
const nameToken = $.OR([
|
|
29
29
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
30
30
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
31
31
|
]);
|
|
32
|
+
$.validateDeclarationName(nameToken, "job");
|
|
32
33
|
|
|
33
34
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
34
35
|
ARGS: [
|
|
@@ -49,10 +50,11 @@ export function runServiceClause($) {
|
|
|
49
50
|
return () => {
|
|
50
51
|
const parent = $.CONSUME(ServiceToken); // "service"
|
|
51
52
|
|
|
52
|
-
$.OR([
|
|
53
|
+
const nameToken = $.OR([
|
|
53
54
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
54
55
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
55
56
|
]);
|
|
57
|
+
$.validateDeclarationName(nameToken, "service");
|
|
56
58
|
|
|
57
59
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
58
60
|
ARGS: [
|
package/parser/table_parser.js
CHANGED
|
@@ -25,7 +25,7 @@ export function tableDeclaration($) {
|
|
|
25
25
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
26
26
|
|
|
27
27
|
$.CONSUME(TableToken); // "table"
|
|
28
|
-
$.OR1([
|
|
28
|
+
const nameToken = $.OR1([
|
|
29
29
|
{
|
|
30
30
|
ALT: () =>
|
|
31
31
|
$.CONSUME(StringLiteral, {
|
|
@@ -39,6 +39,7 @@ export function tableDeclaration($) {
|
|
|
39
39
|
}),
|
|
40
40
|
},
|
|
41
41
|
]);
|
|
42
|
+
$.validateDeclarationName(nameToken, "table");
|
|
42
43
|
|
|
43
44
|
let hasSchema = false;
|
|
44
45
|
let hasView = false;
|
|
@@ -30,10 +30,11 @@ export function tableTriggerDeclaration($) {
|
|
|
30
30
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
31
31
|
|
|
32
32
|
const parent = $.CONSUME(TableTriggerToken); // table_trigger
|
|
33
|
-
$.OR([
|
|
33
|
+
const nameToken = $.OR([
|
|
34
34
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
35
35
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
36
36
|
]);
|
|
37
|
+
$.validateDeclarationName(nameToken, "table_trigger");
|
|
37
38
|
$.CONSUME(LCurly); // "{"
|
|
38
39
|
$.MANY(() => {
|
|
39
40
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
package/parser/task_parser.js
CHANGED
|
@@ -25,10 +25,11 @@ export function taskDeclaration($) {
|
|
|
25
25
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
26
26
|
|
|
27
27
|
$.CONSUME(TaskToken);
|
|
28
|
-
$.OR([
|
|
28
|
+
const nameToken = $.OR([
|
|
29
29
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
30
30
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
31
31
|
]);
|
|
32
|
+
$.validateDeclarationName(nameToken, "task");
|
|
32
33
|
$.CONSUME(LCurly); // "{"
|
|
33
34
|
$.MANY(() => {
|
|
34
35
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -13,6 +13,17 @@ describe("task_parser", () => {
|
|
|
13
13
|
expect(parser.errors).to.be.empty;
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
it("should raise an error when a task name is empty", () => {
|
|
17
|
+
const parser = xanoscriptParser(`task "" {
|
|
18
|
+
stack {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
schedule = []
|
|
22
|
+
}`);
|
|
23
|
+
expect(parser.errors).to.not.be.empty;
|
|
24
|
+
expect(parser.errors[0].message).to.include("must not be empty");
|
|
25
|
+
});
|
|
26
|
+
|
|
16
27
|
it("should parse an active task", () => {
|
|
17
28
|
const parser = xanoscriptParser(`task task_for_listing {
|
|
18
29
|
active = true
|
package/parser/tool_parser.js
CHANGED
|
@@ -21,10 +21,11 @@ export function toolDeclaration($) {
|
|
|
21
21
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
22
22
|
|
|
23
23
|
const parent = $.CONSUME(ToolToken);
|
|
24
|
-
$.OR([
|
|
24
|
+
const nameToken = $.OR([
|
|
25
25
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
26
26
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
27
27
|
]);
|
|
28
|
+
$.validateDeclarationName(nameToken, "tool");
|
|
28
29
|
$.CONSUME(LCurly); // "{"
|
|
29
30
|
$.MANY(() => {
|
|
30
31
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -16,10 +16,11 @@ export function workflowTestDeclaration($) {
|
|
|
16
16
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
17
17
|
|
|
18
18
|
const parent = $.CONSUME(WorkflowTestToken);
|
|
19
|
-
$.OR([
|
|
19
|
+
const nameToken = $.OR([
|
|
20
20
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
21
21
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
22
22
|
]);
|
|
23
|
+
$.validateDeclarationName(nameToken, "workflow_test");
|
|
23
24
|
$.CONSUME(LCurly); // "{"
|
|
24
25
|
$.MANY(() => {
|
|
25
26
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -9,10 +9,11 @@ export function workspaceDeclaration($) {
|
|
|
9
9
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
10
10
|
|
|
11
11
|
const parent = $.CONSUME(WorkspaceToken); // workspace
|
|
12
|
-
$.OR([
|
|
12
|
+
const nameToken = $.OR([
|
|
13
13
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
14
14
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
15
|
]);
|
|
16
|
+
$.validateDeclarationName(nameToken, "workspace");
|
|
16
17
|
|
|
17
18
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
18
19
|
ARGS: [
|
|
@@ -23,10 +23,11 @@ export function workspaceTriggerDeclaration($) {
|
|
|
23
23
|
$.SUBRULE($.optionalCommentBlockFn);
|
|
24
24
|
|
|
25
25
|
const parent = $.CONSUME(WorkspaceTriggerToken); // workspace_trigger
|
|
26
|
-
$.OR([
|
|
26
|
+
const nameToken = $.OR([
|
|
27
27
|
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
28
28
|
{ ALT: () => $.CONSUME(Identifier) },
|
|
29
29
|
]);
|
|
30
|
+
$.validateDeclarationName(nameToken, "workspace_trigger");
|
|
30
31
|
$.CONSUME(LCurly); // "{"
|
|
31
32
|
$.MANY(() => {
|
|
32
33
|
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: no-git-interactions
|
|
3
|
-
description: User does not want Claude to interact with git (no commits, no staging, no git commands)
|
|
4
|
-
type: feedback
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Do not interact with git — no commits, no staging, no git commands. Focus purely on implementation and testing.
|
|
8
|
-
|
|
9
|
-
**Why:** User manages their own git workflow.
|
|
10
|
-
|
|
11
|
-
**How to apply:** Skip all git-related steps in plans. When dispatching subagents, explicitly tell them not to run any git commands. Remove commit steps from task instructions.
|