@dot-agent/compiler 0.10.2 → 0.12.0-beta.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/LICENSE +202 -0
- package/README.md +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.mjs +1 -1
- package/dist/index.cjs +59 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -24
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +24 -24
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +59 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{namespace-0cuKn3-s.cjs → namespace-CLx06F20.cjs} +3 -3
- package/dist/namespace-CLx06F20.cjs.map +1 -0
- package/dist/namespace-DsoVSANe.d.cts.map +1 -1
- package/dist/namespace-DsoVSANe.d.mts.map +1 -1
- package/dist/{namespace-CjeG5-7u.mjs → namespace-oeoFrzmu.mjs} +2 -2
- package/dist/namespace-oeoFrzmu.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/namespace-0cuKn3-s.cjs.map +0 -1
- package/dist/namespace-CjeG5-7u.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -2,15 +2,15 @@ import { A as PackOptions, C as Capability, D as LangId, E as Integrity, F as St
|
|
|
2
2
|
import { Node, Tree } from "web-tree-sitter";
|
|
3
3
|
import JSZip from "jszip";
|
|
4
4
|
//#region src/parser.d.ts
|
|
5
|
-
declare function initBehaviorParser(): Promise<void>;
|
|
5
|
+
export declare function initBehaviorParser(): Promise<void>;
|
|
6
6
|
interface ParseResult<T> {
|
|
7
7
|
ok: T | null;
|
|
8
8
|
diagnostics: ParseDiagnostic[];
|
|
9
9
|
}
|
|
10
|
-
declare function parseBehaviorFile(text: string): ParseResult<BehaviorFile>;
|
|
11
|
-
declare function parseDescriptionFile(text: string): ParseResult<DescriptionFile>;
|
|
12
|
-
declare function getBehaviorScxml(text: string): string;
|
|
13
|
-
declare function initParsers(): Promise<void>;
|
|
10
|
+
export declare function parseBehaviorFile(text: string): ParseResult<BehaviorFile>;
|
|
11
|
+
export declare function parseDescriptionFile(text: string): ParseResult<DescriptionFile>;
|
|
12
|
+
export declare function getBehaviorScxml(text: string): string;
|
|
13
|
+
export declare function initParsers(): Promise<void>;
|
|
14
14
|
/**
|
|
15
15
|
* Parse source text and return a tree-sitter Tree.
|
|
16
16
|
*
|
|
@@ -18,12 +18,12 @@ declare function initParsers(): Promise<void>;
|
|
|
18
18
|
* @param text - source text to parse
|
|
19
19
|
* @param previousTree - optional previous tree for incremental parsing (LSP use)
|
|
20
20
|
*/
|
|
21
|
-
declare function parse(langId: LangId, text: string, previousTree?: Tree): Promise<Tree>;
|
|
21
|
+
export declare function parse(langId: LangId, text: string, previousTree?: Tree): Promise<Tree>;
|
|
22
22
|
/** Parse without initializing if parsers are already ready. Returns null if not initialized. */
|
|
23
|
-
declare function parseSync(langId: LangId, text: string, previousTree?: Tree): Tree | null;
|
|
24
|
-
declare function nodesOfType(tree: Tree, type: string): Node[];
|
|
25
|
-
declare function nodeAtOffset(tree: Tree, offset: number): Node | null;
|
|
26
|
-
declare function nodeToRange(node: Node): {
|
|
23
|
+
export declare function parseSync(langId: LangId, text: string, previousTree?: Tree): Tree | null;
|
|
24
|
+
export declare function nodesOfType(tree: Tree, type: string): Node[];
|
|
25
|
+
export declare function nodeAtOffset(tree: Tree, offset: number): Node | null;
|
|
26
|
+
export declare function nodeToRange(node: Node): {
|
|
27
27
|
start: {
|
|
28
28
|
line: number;
|
|
29
29
|
character: number;
|
|
@@ -33,34 +33,34 @@ declare function nodeToRange(node: Node): {
|
|
|
33
33
|
character: number;
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
|
-
declare function positionToOffset(text: string, line: number, character: number): number;
|
|
37
|
-
declare function getContextNode(tree: Tree, offset: number): Node;
|
|
36
|
+
export declare function positionToOffset(text: string, line: number, character: number): number;
|
|
37
|
+
export declare function getContextNode(tree: Tree, offset: number): Node;
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region src/linter.d.ts
|
|
40
|
-
declare function lintDescription(text: string, file?: string): Promise<LintMessage[]>;
|
|
41
|
-
declare function lintBehavior(text: string, file?: string, docPath?: string, consolidated?: boolean, externalStates?: Set<string>, mergedText?: string): Promise<LintMessage[]>;
|
|
42
|
-
declare function createLinter(): Promise<{
|
|
40
|
+
export declare function lintDescription(text: string, file?: string): Promise<LintMessage[]>;
|
|
41
|
+
export declare function lintBehavior(text: string, file?: string, docPath?: string, consolidated?: boolean, externalStates?: Set<string>, mergedText?: string): Promise<LintMessage[]>;
|
|
42
|
+
export declare function createLinter(): Promise<{
|
|
43
43
|
lintDescription: typeof lintDescription;
|
|
44
44
|
lintBehavior: typeof lintBehavior;
|
|
45
45
|
}>;
|
|
46
46
|
//#endregion
|
|
47
47
|
//#region src/zip.d.ts
|
|
48
|
-
declare function readZip(filePath: string): Promise<JSZip>;
|
|
49
|
-
declare function validateZipBomb(filePath: string): Promise<boolean>;
|
|
50
|
-
declare function validateMagicBytes(filePath: string): Promise<boolean>;
|
|
51
|
-
declare function writeZip(zip: JSZip, outPath: string): Promise<void>;
|
|
48
|
+
export declare function readZip(filePath: string): Promise<JSZip>;
|
|
49
|
+
export declare function validateZipBomb(filePath: string): Promise<boolean>;
|
|
50
|
+
export declare function validateMagicBytes(filePath: string): Promise<boolean>;
|
|
51
|
+
export declare function writeZip(zip: JSZip, outPath: string): Promise<void>;
|
|
52
52
|
//#endregion
|
|
53
53
|
//#region src/pack.d.ts
|
|
54
54
|
interface ConsolidateResult {
|
|
55
55
|
mergedText: string;
|
|
56
56
|
mergeSources: string[];
|
|
57
57
|
}
|
|
58
|
-
declare function consolidate(agentRoot: string, entryFile: string): Promise<ConsolidateResult>;
|
|
59
|
-
declare function collectFiles(dir: string, descriptionFile: string, mergedBehaviorText: string, mergeSources: string[], personaFile?: string): Promise<Map<string, string>>;
|
|
60
|
-
declare function pack(options?: PackOptions): Promise<PackResult>;
|
|
58
|
+
export declare function consolidate(agentRoot: string, entryFile: string): Promise<ConsolidateResult>;
|
|
59
|
+
export declare function collectFiles(dir: string, descriptionFile: string, mergedBehaviorText: string, mergeSources: string[], personaFile?: string): Promise<Map<string, string>>;
|
|
60
|
+
export declare function pack(options?: PackOptions): Promise<PackResult>;
|
|
61
61
|
//#endregion
|
|
62
62
|
//#region src/bundle.d.ts
|
|
63
|
-
declare function bundleFromDir(dir: string): Promise<AgentBundle>;
|
|
63
|
+
export declare function bundleFromDir(dir: string): Promise<AgentBundle>;
|
|
64
64
|
//#endregion
|
|
65
|
-
export { type AboutMe, type AgentBundle, type AgentDecl, type AgentFiles, type AnnotatedRef, type BehaviorFile, type BuildAboutmeOptions, CONTENT_NAMESPACES, type Capability, type ContentNamespace, type DescriptionFile, type IdParts, type Integrity, type LangId, type LintMessage, type OntologyRef, type PackOptions, type PackResult, type PropertyDecl, type PropertyType, type StateDef, type Statement, type TriggerDecl, type TypeDefinition, aboutmeToJson, buildAboutme, buildId,
|
|
65
|
+
export { type AboutMe, type AgentBundle, type AgentDecl, type AgentFiles, type AnnotatedRef, type BehaviorFile, type BuildAboutmeOptions, CONTENT_NAMESPACES, type Capability, type ContentNamespace, type DescriptionFile, type IdParts, type Integrity, type LangId, type LintMessage, type OntologyRef, type PackOptions, type PackResult, type PropertyDecl, type PropertyType, type StateDef, type Statement, type TriggerDecl, type TypeDefinition, aboutmeToJson, buildAboutme, buildId, classifyContentPath, createZip, extractDigest, extractFiles, extractName, isInContentNamespace, parseAboutme, parseId };
|
|
66
66
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/parser.ts","../src/linter.ts","../src/zip.ts","../src/pack.ts","../src/bundle.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/parser.ts","../src/linter.ts","../src/zip.ts","../src/pack.ts","../src/bundle.ts"],"mappings":";;;;wBAmBsB,sBAAsB;UAM3B,YAAY;EAC3B,IAAI;EACJ,aAAa;;wBAGC,kBAAkB,eAAe,YAAY;wBAI7C,qBAAqB,eAAe,YAAY;wBAIhD,iBAAiB;wBAIX,eAAe;;;;;;;;wBAmBf,MACpB,QAAQ,QACR,cACA,eAAe,OACd,QAAQ;;wBAOK,UAAU,QAAQ,QAAQ,cAAc,eAAe,OAAO;wBAQ9D,YAAY,MAAM,MAAM,eAAe;wBAKvC,aAAa,MAAM,MAAM,iBAAiB;wBAK1C,YAAY,MAAM;EAChC;IAAS;IAAc;;EACvB;IAAO;IAAc;;;wBAQP,iBAAiB,cAAc,cAAc;wBAS7C,eAAe,MAAM,MAAM,iBAAiB;;;wBCxCtC,gBAAgB,cAAc,gBAA6B,QAAQ;wBAqKnE,aACpB,cACA,eACA,kBACA,wBACA,iBAAiB,aACjB,sBACC,QAAQ;wBAuXW,gBAAY;;;;;;wBC9lBZ,QAAQ,mBAAmB,QAAQ;wBAKnC,gBAAgB,mBAAmB;wBAOnC,mBAAmB,mBAAmB;wBAMtC,SAAS,KAAK,OAAO,kBAAkB;;;UCmInD;EACR;EACA;;wBAGoB,YAAY,mBAAmB,oBAAoB,QAAQ;wBAqN3D,aACpB,aACA,yBACA,4BACA,wBACA,uBACC,QAAQ;wBAkFW,KAAK,UAAS,cAAmB,QAAQ;;;wBCnczC,cAAc,cAAc,QAAQ"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as COMPILER_VERSION, a as extractFiles, c as buildId, d as isValidVersion, f as parseId, g as parseAboutme, h as buildAboutme, i as createZip, l as extractDigest, m as aboutmeToJson, n as classifyContentPath, o as validateMagicBytes$1, p as slugify, r as isInContentNamespace, s as validateZipBomb$1, t as CONTENT_NAMESPACES, u as extractName } from "./namespace-
|
|
1
|
+
import { _ as COMPILER_VERSION, a as extractFiles, c as buildId, d as isValidVersion, f as parseId, g as parseAboutme, h as buildAboutme, i as createZip, l as extractDigest, m as aboutmeToJson, n as classifyContentPath, o as validateMagicBytes$1, p as slugify, r as isInContentNamespace, s as validateZipBomb$1, t as CONTENT_NAMESPACES, u as extractName } from "./namespace-oeoFrzmu.mjs";
|
|
2
2
|
import { createRequire } from "module";
|
|
3
3
|
import { Language, Parser } from "web-tree-sitter";
|
|
4
4
|
import { get_graph, init, parse_behavior, parse_description } from "@dot-agent/parser-dsl";
|
|
@@ -257,7 +257,8 @@ function collectMergedStates(tree, docDir, states, visited = /* @__PURE__ */ new
|
|
|
257
257
|
for (const mergeNode of nodesOfType(tree, "merge_decl")) {
|
|
258
258
|
const pathNode = mergeNode.childForFieldName("path");
|
|
259
259
|
if (!pathNode) continue;
|
|
260
|
-
const
|
|
260
|
+
const filename = pathNode.text.replace(/^"|"$/g, "");
|
|
261
|
+
const absPath = resolve(docDir, filename);
|
|
261
262
|
if (visited.has(absPath)) continue;
|
|
262
263
|
visited.add(absPath);
|
|
263
264
|
let mergedText;
|
|
@@ -287,6 +288,8 @@ async function lintBehavior(text, file = "agent.behavior", docPath, consolidated
|
|
|
287
288
|
const stateName = nameNode?.text ?? "?";
|
|
288
289
|
const hasInteract = stateNode.descendantsOfType("interact_stmt").length > 0;
|
|
289
290
|
const hasGoal = stateNode.descendantsOfType("goal_stmt").length > 0;
|
|
291
|
+
const hasGuide = stateNode.descendantsOfType("guide_stmt").length > 0;
|
|
292
|
+
const hasTeach = stateNode.descendantsOfType("teach_stmt").length > 0;
|
|
290
293
|
const intentHandlers = stateNode.descendantsOfType("intent_handler");
|
|
291
294
|
if (hasInteract && !hasGoal) {
|
|
292
295
|
const { line, col } = nodePosition(nameNode ?? stateNode);
|
|
@@ -299,17 +302,54 @@ async function lintBehavior(text, file = "agent.behavior", docPath, consolidated
|
|
|
299
302
|
message: `'interact' without 'goal'. Add 'goal "..."' before 'interact'.`
|
|
300
303
|
});
|
|
301
304
|
}
|
|
302
|
-
|
|
305
|
+
const presentOrientationNames = [
|
|
306
|
+
hasGoal && "goal",
|
|
307
|
+
hasGuide && "guide",
|
|
308
|
+
hasTeach && "teach"
|
|
309
|
+
].filter((n) => n !== false);
|
|
310
|
+
if (presentOrientationNames.length > 0 && !hasInteract) {
|
|
303
311
|
const { line, col } = nodePosition(nameNode ?? stateNode);
|
|
312
|
+
const list = presentOrientationNames.map((n) => `'${n}'`).join(", ");
|
|
313
|
+
const isPlural = presentOrientationNames.length > 1;
|
|
304
314
|
messages.push({
|
|
305
315
|
file,
|
|
306
316
|
line,
|
|
307
317
|
col,
|
|
308
318
|
severity: "warning",
|
|
309
319
|
code: "W012",
|
|
310
|
-
message:
|
|
320
|
+
message: `${list} ${isPlural ? "are" : "is"} only valid in an oriented state. Add 'interact' or remove ${isPlural ? "them" : "it"}.`
|
|
311
321
|
});
|
|
312
322
|
}
|
|
323
|
+
const bodyStmts = (stateNode.childForFieldName("body")?.children ?? []).filter((n) => n !== null);
|
|
324
|
+
const firstTransitionIndex = bodyStmts.findIndex((n) => n.type === "transition_stmt");
|
|
325
|
+
const interactsBeforeFirstTransition = bodyStmts.filter((n, i) => n.type === "interact_stmt" && (firstTransitionIndex === -1 || i < firstTransitionIndex));
|
|
326
|
+
if (interactsBeforeFirstTransition.length > 1) for (const dup of interactsBeforeFirstTransition.slice(1)) {
|
|
327
|
+
const { line, col } = nodePosition(dup);
|
|
328
|
+
messages.push({
|
|
329
|
+
file,
|
|
330
|
+
line,
|
|
331
|
+
col,
|
|
332
|
+
severity: "warning",
|
|
333
|
+
code: "W017",
|
|
334
|
+
message: `Duplicate 'interact' in state '${stateName}' before any transition. Only one 'interact' is allowed per state before a 'transition to' — a second one, still reachable in the same entry batch, emits a second 'request_interact' effect with no dedupe at the host layer.`
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const leavingIndex = bodyStmts.findIndex((n) => n.type === "transition_stmt" && n.childForFieldName("state")?.text !== stateName);
|
|
338
|
+
if (leavingIndex !== -1) {
|
|
339
|
+
const target = bodyStmts[leavingIndex].childForFieldName("state")?.text ?? "?";
|
|
340
|
+
for (const stmt of bodyStmts.slice(leavingIndex + 1)) {
|
|
341
|
+
if (stmt.type === "intent_handler" || stmt.type === "offtopic_handler" || stmt.type === "comment") continue;
|
|
342
|
+
const { line, col } = nodePosition(stmt);
|
|
343
|
+
messages.push({
|
|
344
|
+
file,
|
|
345
|
+
line,
|
|
346
|
+
col,
|
|
347
|
+
severity: "warning",
|
|
348
|
+
code: "W018",
|
|
349
|
+
message: `Unreachable: state '${stateName}' leaves for '${target}' on entry before this statement runs. Everything after a state-level 'transition to' is skipped, like code after a return — move it before the transition or remove it.`
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
313
353
|
if (hasInteract && intentHandlers.length === 0) {
|
|
314
354
|
const { line, col } = nodePosition(nameNode ?? stateNode);
|
|
315
355
|
messages.push({
|
|
@@ -585,11 +625,13 @@ async function readZip(filePath) {
|
|
|
585
625
|
}
|
|
586
626
|
async function validateZipBomb(filePath) {
|
|
587
627
|
const data = await readFile(filePath);
|
|
588
|
-
|
|
628
|
+
const zip = await JSZip.loadAsync(data);
|
|
629
|
+
validateZipBomb$1(zip, data.length);
|
|
589
630
|
return true;
|
|
590
631
|
}
|
|
591
632
|
async function validateMagicBytes(filePath) {
|
|
592
|
-
|
|
633
|
+
const data = await readFile(filePath);
|
|
634
|
+
validateMagicBytes$1(data);
|
|
593
635
|
return true;
|
|
594
636
|
}
|
|
595
637
|
async function writeZip(zip, outPath) {
|
|
@@ -731,7 +773,8 @@ async function resolveVersionInteractive(explicit) {
|
|
|
731
773
|
function isExternalPath(agentRoot, declaredPath) {
|
|
732
774
|
if (isAbsolute(declaredPath)) return true;
|
|
733
775
|
const normRoot = normalize(resolve(agentRoot));
|
|
734
|
-
|
|
776
|
+
const resolved = resolve(normRoot, declaredPath);
|
|
777
|
+
return relative(normRoot, resolved).startsWith("..");
|
|
735
778
|
}
|
|
736
779
|
async function discoverDescriptionFile(dir, explicit) {
|
|
737
780
|
if (explicit) try {
|
|
@@ -813,7 +856,6 @@ function collectFileRefs(stmts, out) {
|
|
|
813
856
|
case "conditional_stmt":
|
|
814
857
|
collectFileRefs(s.then, out);
|
|
815
858
|
if (s.else) collectFileRefs(s.else, out);
|
|
816
|
-
break;
|
|
817
859
|
}
|
|
818
860
|
}
|
|
819
861
|
function normalizeRefPath(text) {
|
|
@@ -865,9 +907,9 @@ async function findOrphanContentFiles(dir, mergedBehaviorText) {
|
|
|
865
907
|
file: bundlePath,
|
|
866
908
|
line: 1,
|
|
867
909
|
col: 1,
|
|
868
|
-
severity: "
|
|
869
|
-
code: "
|
|
870
|
-
message: `'${kind}' reference '${text}' resolves outside guides/
|
|
910
|
+
severity: "error",
|
|
911
|
+
code: "E022",
|
|
912
|
+
message: `'${kind}' reference '${text}' resolves to '${bundlePath}', which is outside guides/ and knowledge/ — those are the only two directories the runtime can serve content from; move '${bundlePath}' under guides/ or knowledge/ and update the '${kind}' statement to reference it there`
|
|
871
913
|
});
|
|
872
914
|
}
|
|
873
915
|
return [...[...await listContentFiles(dir, "guides"), ...await listContentFiles(dir, "knowledge")].filter((path) => !referenced.has(path)).map((path) => ({
|
|
@@ -939,11 +981,15 @@ async function pack(options = {}) {
|
|
|
939
981
|
const version = await resolveVersionInteractive(options.version);
|
|
940
982
|
const commit = await resolveCommit(options.commit);
|
|
941
983
|
const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? void 0);
|
|
942
|
-
const
|
|
984
|
+
const contentMessages = await findOrphanContentFiles(dir, mergedText);
|
|
985
|
+
const contentErrors = contentMessages.filter((m) => m.severity === "error");
|
|
986
|
+
if (contentErrors.length > 0) throw new Error(`Lint failed:\n${contentErrors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join("\n")}`);
|
|
987
|
+
const warnings = [...lintWarnings, ...contentMessages.filter((m) => m.severity === "warning")];
|
|
943
988
|
const contentForHash = Array.from(allFiles.values()).join("");
|
|
944
989
|
const sha256 = createHash("sha256").update(contentForHash).digest("hex");
|
|
990
|
+
const namespace = df.agent.domain ?? "unknown";
|
|
945
991
|
const id = buildId({
|
|
946
|
-
namespace
|
|
992
|
+
namespace,
|
|
947
993
|
name: slugify(df.agent.name),
|
|
948
994
|
version,
|
|
949
995
|
digest: version ? commit : void 0
|