@dot-agent/compiler 0.10.1 → 0.12.0-alpha.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/dist/index.d.mts CHANGED
@@ -1,16 +1,16 @@
1
- import { A as PropertyType, C as LangId, D as PackResult, E as PackOptions, M as Statement, N as TriggerDecl, O as ParseDiagnostic, P as TypeDefinition, S as Integrity, T as OntologyRef, _ as BehaviorFile, a as buildId, b as DescriptionFile, c as parseId, d as parseAboutme, f as AboutMe, g as AnnotatedRef, h as AgentFiles, j as StateDef, k as PropertyDecl, l as aboutmeToJson, m as AgentDecl, n as extractFiles, o as extractDigest, p as AgentBundle, s as extractName, t as createZip, u as buildAboutme, v as BuildAboutmeOptions, w as LintMessage, x as IdParts, y as Capability } from "./zip-core-BCiH0sUt.mjs";
1
+ import { A as PackOptions, C as Capability, D as LangId, E as Integrity, F as StateDef, I as Statement, L as TriggerDecl, M as ParseDiagnostic, N as PropertyDecl, O as LintMessage, P as PropertyType, R as TypeDefinition, S as BuildAboutmeOptions, T as IdParts, _ as AgentBundle, a as createZip, b as AnnotatedRef, d as extractName, f as parseId, g as AboutMe, h as parseAboutme, i as isInContentNamespace, j as PackResult, k as OntologyRef, l as buildId, m as buildAboutme, n as ContentNamespace, o as extractFiles, p as aboutmeToJson, r as classifyContentPath, t as CONTENT_NAMESPACES, u as extractDigest, v as AgentDecl, w as DescriptionFile, x as BehaviorFile, y as AgentFiles } from "./namespace-DsoVSANe.mjs";
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, type Capability, 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, bundleFromDir, collectFiles, consolidate, createLinter, createZip, extractDigest, extractFiles, extractName, getBehaviorScxml, getContextNode, initBehaviorParser, initParsers, lintBehavior, lintDescription, nodeAtOffset, nodeToRange, nodesOfType, pack, parse, parseAboutme, parseBehaviorFile, parseDescriptionFile, parseId, parseSync, positionToOffset, readZip, validateMagicBytes, validateZipBomb, writeZip };
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
@@ -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":";;;;iBAyBsB,sBAAsB;UAM3B,YAAY;EAC3B,IAAI;EACJ,aAAa;;iBAGC,kBAAkB,eAAe,YAAY;iBAI7C,qBAAqB,eAAe,YAAY;iBAIhD,iBAAiB;iBAIX,eAAe;;;;;;;;iBAmBf,MACpB,QAAQ,QACR,cACA,eAAe,OACd,QAAQ;;iBAOK,UAAU,QAAQ,QAAQ,cAAc,eAAe,OAAO;iBAQ9D,YAAY,MAAM,MAAM,eAAe;iBAKvC,aAAa,MAAM,MAAM,iBAAiB;iBAK1C,YAAY,MAAM;EAChC;IAAS;IAAc;;EACvB;IAAO;IAAc;;;iBAQP,iBAAiB,cAAc,cAAc;iBAS7C,eAAe,MAAM,MAAM,iBAAiB;;;iBCtCtC,gBAAgB,cAAc,gBAA6B,QAAQ;iBAqKnE,aACpB,cACA,eACA,kBACA,wBACA,iBAAiB,aACjB,sBACC,QAAQ;iBAgUW,gBAAY;;;;;;iBCniBZ,QAAQ,mBAAmB,QAAQ;iBAKnC,gBAAgB,mBAAmB;iBAOnC,mBAAmB,mBAAmB;iBAMtC,SAAS,KAAK,OAAO,kBAAkB;;;UC4HnD;EACR;EACA;;iBAGoB,YAAY,mBAAmB,oBAAoB,QAAQ;iBA6K3D,aACpB,aACA,yBACA,4BACA,wBACA,uBACC,QAAQ;iBA2EW,KAAK,UAAS,cAAmB,QAAQ;;;iBCpZzC,cAAc,cAAc,QAAQ"}
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 { a as buildId, c as isValidVersion, d as aboutmeToJson, f as buildAboutme, i as validateZipBomb$1, l as parseId, m as COMPILER_VERSION, n as extractFiles, o as extractDigest, p as parseAboutme, r as validateMagicBytes$1, s as extractName, t as createZip, u as slugify } from "./zip-core-Dw_OgIjV.mjs";
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-B8prujsD.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 absPath = resolve(docDir, pathNode.text.replace(/^"|"$/g, ""));
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
- if (hasGoal && !hasInteract) {
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: `'goal' is only valid in an oriented state. Add 'interact' or remove 'goal'.`
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
- validateZipBomb$1(await JSZip.loadAsync(data), data.length);
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
- validateMagicBytes$1(await readFile(filePath));
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
- return relative(normRoot, resolve(normRoot, declaredPath)).startsWith("..");
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,11 +856,10 @@ 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
- function namespaceOf(kind) {
820
- return kind === "guide" ? "guides" : "knowledge";
861
+ function normalizeRefPath(text) {
862
+ return text.replace(/\\/g, "/").replace(/^\.\//, "");
821
863
  }
822
864
  async function collectBehaviorFileRefs(mergedBehaviorText) {
823
865
  await initBehaviorParser();
@@ -851,15 +893,33 @@ async function listContentFiles(dir, ns) {
851
893
  async function findOrphanContentFiles(dir, mergedBehaviorText) {
852
894
  const refs = await collectBehaviorFileRefs(mergedBehaviorText);
853
895
  const referenced = /* @__PURE__ */ new Set();
854
- for (const { kind, text } of refs.values()) referenced.add(`${namespaceOf(kind)}/${text}`);
855
- return [...await listContentFiles(dir, "guides"), ...await listContentFiles(dir, "knowledge")].filter((path) => !referenced.has(path)).map((path) => ({
896
+ const messages = [];
897
+ for (const { kind, text } of refs.values()) {
898
+ const bundlePath = normalizeRefPath(text);
899
+ referenced.add(bundlePath);
900
+ if (isExternalPath(dir, bundlePath) || isInContentNamespace(bundlePath)) continue;
901
+ try {
902
+ await stat(join(dir, bundlePath));
903
+ } catch {
904
+ continue;
905
+ }
906
+ messages.push({
907
+ file: bundlePath,
908
+ line: 1,
909
+ col: 1,
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`
913
+ });
914
+ }
915
+ return [...[...await listContentFiles(dir, "guides"), ...await listContentFiles(dir, "knowledge")].filter((path) => !referenced.has(path)).map((path) => ({
856
916
  file: path,
857
917
  line: 1,
858
918
  col: 1,
859
919
  severity: "warning",
860
920
  code: "W015",
861
921
  message: `'${path}' is not referenced by any guide or teach statement — it will not be included in the bundle`
862
- }));
922
+ })), ...messages];
863
923
  }
864
924
  async function collectFiles(dir, descriptionFile, mergedBehaviorText, mergeSources, personaFile) {
865
925
  const files = /* @__PURE__ */ new Map();
@@ -879,16 +939,16 @@ async function collectFiles(dir, descriptionFile, mergedBehaviorText, mergeSourc
879
939
  }
880
940
  const refs = await collectBehaviorFileRefs(mergedBehaviorText);
881
941
  for (const { kind, text } of refs.values()) {
882
- if (isExternalPath(dir, text)) throw new Error(`E014: '${kind}' path '${text}' is absolute or escapes the agent root`);
883
- const ns = namespaceOf(kind);
884
- const nsPath = `${ns}/${text}`;
942
+ const bundlePath = normalizeRefPath(text);
943
+ if (isExternalPath(dir, bundlePath)) throw new Error(`E014: '${kind}' path '${text}' is absolute or escapes the agent root`);
885
944
  let content;
886
- for (const candidate of [join(dir, ns, text), join(dir, text)]) try {
887
- content = await readFile(candidate, "utf-8");
888
- break;
889
- } catch {}
890
- if (content === void 0) throw new Error(`E018: '${kind}' file '${text}' referenced in agent.behavior not found in ${dir} — looked for '${nsPath}' and '${text}'`);
891
- files.set(nsPath, content);
945
+ try {
946
+ content = await readFile(join(dir, bundlePath), "utf-8");
947
+ } catch {
948
+ throw new Error(`E018: '${kind}' file '${text}' referenced in agent.behavior not found in ${dir} — looked for '${bundlePath}' relative to the agent root`);
949
+ }
950
+ if (files.has(bundlePath)) throw new Error(`E020: '${kind}' reference '${text}' resolves to '${bundlePath}', which collides with a reserved bundle path (the description file, agent.behavior, a merged behaviors/ file, or the persona) — reference a different path`);
951
+ files.set(bundlePath, content);
892
952
  }
893
953
  return files;
894
954
  }
@@ -921,11 +981,15 @@ async function pack(options = {}) {
921
981
  const version = await resolveVersionInteractive(options.version);
922
982
  const commit = await resolveCommit(options.commit);
923
983
  const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? void 0);
924
- const warnings = [...lintWarnings, ...await findOrphanContentFiles(dir, mergedText)];
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")];
925
988
  const contentForHash = Array.from(allFiles.values()).join("");
926
989
  const sha256 = createHash("sha256").update(contentForHash).digest("hex");
990
+ const namespace = df.agent.domain ?? "unknown";
927
991
  const id = buildId({
928
- namespace: df.agent.domain ?? "unknown",
992
+ namespace,
929
993
  name: slugify(df.agent.name),
930
994
  version,
931
995
  digest: version ? commit : void 0
@@ -963,8 +1027,8 @@ async function pack(options = {}) {
963
1027
  behavior: "agent.behavior",
964
1028
  ...df.persona ? { persona: df.persona } : {},
965
1029
  behaviors: Array.from(allFiles.keys()).filter((f) => f.startsWith("behaviors/")),
966
- guides: Array.from(allFiles.keys()).filter((f) => f.startsWith("guides/")),
967
- knowledge: Array.from(allFiles.keys()).filter((f) => f.startsWith("knowledge/"))
1030
+ guides: Array.from(allFiles.keys()).filter((f) => classifyContentPath(f) === "guides"),
1031
+ knowledge: Array.from(allFiles.keys()).filter((f) => classifyContentPath(f) === "knowledge")
968
1032
  };
969
1033
  agentFolder.file("files.json", JSON.stringify(filesJson, null, 2));
970
1034
  for (const [path, content] of allFiles) zip.file(path, content);
@@ -1036,11 +1100,11 @@ async function bundleFromDir(dir) {
1036
1100
  description: descriptionText,
1037
1101
  behavior: allFiles.get("agent.behavior") ?? mergedText,
1038
1102
  persona: df.persona ? allFiles.get(df.persona) : void 0,
1039
- guides: Array.from(allFiles.entries()).filter(([p]) => p.startsWith("guides/")).map(([path, content]) => ({
1103
+ guides: Array.from(allFiles.entries()).filter(([p]) => classifyContentPath(p) === "guides").map(([path, content]) => ({
1040
1104
  path,
1041
1105
  content
1042
1106
  })),
1043
- knowledge: Array.from(allFiles.entries()).filter(([p]) => p.startsWith("knowledge/")).map(([path, content]) => ({
1107
+ knowledge: Array.from(allFiles.entries()).filter(([p]) => classifyContentPath(p) === "knowledge").map(([path, content]) => ({
1044
1108
  path,
1045
1109
  content
1046
1110
  })),
@@ -1052,6 +1116,6 @@ async function bundleFromDir(dir) {
1052
1116
  };
1053
1117
  }
1054
1118
  //#endregion
1055
- export { aboutmeToJson, buildAboutme, buildId, bundleFromDir, collectFiles, consolidate, createLinter, createZip, extractDigest, extractFiles, extractName, getBehaviorScxml, getContextNode, initBehaviorParser, initParsers, lintBehavior, lintDescription, nodeAtOffset, nodeToRange, nodesOfType, pack, parse, parseAboutme, parseBehaviorFile, parseDescriptionFile, parseId, parseSync, positionToOffset, readZip, validateMagicBytes, validateZipBomb, writeZip };
1119
+ export { CONTENT_NAMESPACES, aboutmeToJson, buildAboutme, buildId, bundleFromDir, classifyContentPath, collectFiles, consolidate, createLinter, createZip, extractDigest, extractFiles, extractName, getBehaviorScxml, getContextNode, initBehaviorParser, initParsers, isInContentNamespace, lintBehavior, lintDescription, nodeAtOffset, nodeToRange, nodesOfType, pack, parse, parseAboutme, parseBehaviorFile, parseDescriptionFile, parseId, parseSync, positionToOffset, readZip, validateMagicBytes, validateZipBomb, writeZip };
1056
1120
 
1057
1121
  //# sourceMappingURL=index.mjs.map