@dot-agent/compiler 0.5.0-alpha.2 → 0.10.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/{chunk-P5LFGJ6P.js → chunk-AYXHOOUX.js} +14 -7
- package/dist/chunk-AYXHOOUX.js.map +1 -0
- package/dist/{core-b-7c6X6q.d.cts → core-D2X2Eohl.d.cts} +3 -3
- package/dist/{core-b-7c6X6q.d.ts → core-D2X2Eohl.d.ts} +3 -3
- package/dist/core.cjs +3 -5
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/index.cjs +139 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +131 -26
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/dist/chunk-P5LFGJ6P.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/generated-version.ts
|
|
2
|
-
var DSL_VERSION = "0.1
|
|
3
|
-
var COMPILER_VERSION = "0.
|
|
2
|
+
var DSL_VERSION = "0.1";
|
|
3
|
+
var COMPILER_VERSION = "0.10.0";
|
|
4
4
|
|
|
5
5
|
// src/manifest.ts
|
|
6
6
|
function parseAboutme(json) {
|
|
@@ -8,9 +8,7 @@ function parseAboutme(json) {
|
|
|
8
8
|
if (!json.id) throw new Error("Missing id in aboutme.json");
|
|
9
9
|
if (!json.name) throw new Error("Missing name in aboutme.json");
|
|
10
10
|
if (!json.description) throw new Error("Missing description in aboutme.json");
|
|
11
|
-
if (!json.version) throw new Error("Missing version in aboutme.json");
|
|
12
11
|
if (!json.domain) throw new Error("Missing domain in aboutme.json");
|
|
13
|
-
if (!json.persona) throw new Error("Missing persona in aboutme.json");
|
|
14
12
|
if (!json.compiler) throw new Error("Missing compiler in aboutme.json");
|
|
15
13
|
if (!Array.isArray(json.capabilities)) throw new Error("Missing capabilities array in aboutme.json");
|
|
16
14
|
if (!Array.isArray(json.requires)) throw new Error("Missing requires array in aboutme.json");
|
|
@@ -20,7 +18,7 @@ function parseAboutme(json) {
|
|
|
20
18
|
id: json.id,
|
|
21
19
|
name: json.name,
|
|
22
20
|
description: json.description,
|
|
23
|
-
version: json.version,
|
|
21
|
+
version: json.version ?? "",
|
|
24
22
|
domain: json.domain,
|
|
25
23
|
license: json.license ?? "",
|
|
26
24
|
persona: json.persona,
|
|
@@ -132,7 +130,14 @@ function buildId(parts) {
|
|
|
132
130
|
result += `:${version}`;
|
|
133
131
|
if (digest) result += `~${digest}`;
|
|
134
132
|
}
|
|
135
|
-
return result;
|
|
133
|
+
return result.toLowerCase();
|
|
134
|
+
}
|
|
135
|
+
function slugify(name) {
|
|
136
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
137
|
+
}
|
|
138
|
+
var VERSION_RE = /^v?\d+(\.\d+){0,2}(-[0-9A-Za-z.]+)?(\+[0-9A-Za-z.]+)?$/i;
|
|
139
|
+
function isValidVersion(version) {
|
|
140
|
+
return VERSION_RE.test(version);
|
|
136
141
|
}
|
|
137
142
|
function extractDigest(id) {
|
|
138
143
|
try {
|
|
@@ -196,6 +201,8 @@ export {
|
|
|
196
201
|
aboutmeToJson,
|
|
197
202
|
parseId,
|
|
198
203
|
buildId,
|
|
204
|
+
slugify,
|
|
205
|
+
isValidVersion,
|
|
199
206
|
extractDigest,
|
|
200
207
|
extractName,
|
|
201
208
|
validateMagicBytes,
|
|
@@ -203,4 +210,4 @@ export {
|
|
|
203
210
|
createZip,
|
|
204
211
|
extractFiles
|
|
205
212
|
};
|
|
206
|
-
//# sourceMappingURL=chunk-
|
|
213
|
+
//# sourceMappingURL=chunk-AYXHOOUX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/generated-version.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts"],"sourcesContent":["// Generated by scripts/embed-version.mjs from dsl/VERSION and package.json — do not edit by hand.\nexport const DSL_VERSION = '0.1'\nexport const COMPILER_VERSION = '0.10.0'\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport type { AboutMe, BuildAboutmeOptions } from './types.js'\nimport { DSL_VERSION } from './generated-version.js'\n\nexport function parseAboutme(json: any): AboutMe {\n if (!json.dslVersion) throw new Error('Missing dslVersion in aboutme.json')\n if (!json.id) throw new Error('Missing id in aboutme.json')\n if (!json.name) throw new Error('Missing name in aboutme.json')\n if (!json.description) throw new Error('Missing description in aboutme.json')\n if (!json.domain) throw new Error('Missing domain in aboutme.json')\n if (!json.compiler) throw new Error('Missing compiler in aboutme.json')\n if (!Array.isArray(json.capabilities)) throw new Error('Missing capabilities array in aboutme.json')\n if (!Array.isArray(json.requires)) throw new Error('Missing requires array in aboutme.json')\n if (!json.integrity) throw new Error('Missing integrity in aboutme.json')\n\n return {\n dslVersion: json.dslVersion,\n id: json.id,\n name: json.name,\n description: json.description,\n version: json.version ?? '',\n domain: json.domain,\n license: json.license ?? '',\n persona: json.persona,\n purpose: json.purpose ?? 'unknown',\n compiler: json.compiler,\n commit: json.commit,\n capabilities: json.capabilities,\n requires: json.requires,\n integrity: json.integrity,\n }\n}\n\nexport function buildAboutme(opts: BuildAboutmeOptions): AboutMe {\n return {\n dslVersion: `dot-agent/${DSL_VERSION}`,\n id: opts.id,\n name: opts.name,\n description: opts.description,\n version: opts.version,\n domain: opts.domain,\n license: opts.license ?? '',\n persona: opts.persona,\n purpose: opts.purpose ?? 'unknown',\n compiler: opts.compiler,\n commit: opts.commit,\n capabilities: opts.capabilities ?? [],\n requires: opts.requires ?? [],\n integrity: opts.integrity,\n }\n}\n\nexport function aboutmeToJson(aboutme: AboutMe): string {\n return JSON.stringify(aboutme, null, 2)\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { IdParts } from './types.js'\n\n// Code hosting platforms whose namespace format is platform/user rather than plain domain.\n// The list is maintained by the compiler and updated via CLI releases.\nexport const KNOWN_PLATFORMS = ['github.com', 'gitlab.com', 'codeberg.org', 'sr.ht'] as const\n\nfunction parseNamespaceName(identifier: string): { namespace: string; name: string } {\n // Email namespace: @ appears before any /\n const atIdx = identifier.indexOf('@')\n if (atIdx !== -1 && (identifier.indexOf('/') === -1 || atIdx < identifier.indexOf('/'))) {\n const slashIdx = identifier.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(`Invalid agent ID: email namespace requires a name after '/' (got '${identifier}')`)\n }\n return {\n namespace: identifier.slice(0, slashIdx),\n name: identifier.slice(slashIdx + 1),\n }\n }\n\n // Known code-hosting platforms: namespace is platform/user, name is the next segment.\n for (const platform of KNOWN_PLATFORMS) {\n if (identifier.startsWith(platform + '/')) {\n const afterPlatform = identifier.slice(platform.length + 1)\n const slashIdx = afterPlatform.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(\n `Invalid agent ID: '${platform}' namespace requires a user segment and a name (got '${identifier}')`,\n )\n }\n return {\n namespace: platform + '/' + afterPlatform.slice(0, slashIdx),\n name: afterPlatform.slice(slashIdx + 1),\n }\n }\n }\n\n // Domain or reserved keyword (e.g. 'unknown'): last '/' separates namespace from name.\n const lastSlash = identifier.lastIndexOf('/')\n if (lastSlash === -1) {\n throw new Error(`Invalid agent ID: missing '/' separator in '${identifier}'`)\n }\n return {\n namespace: identifier.slice(0, lastSlash),\n name: identifier.slice(lastSlash + 1),\n }\n}\n\nexport function parseId(id: string): IdParts {\n if (!id) throw new Error('Invalid agent ID: empty string')\n\n // Phase 1: split on the first ':' to isolate the identifier from version~digest.\n const colonIdx = id.indexOf(':')\n\n let identifier: string\n let version: string | undefined\n let digest: string | undefined\n\n if (colonIdx === -1) {\n // Form A: namespace/name\n identifier = id\n } else {\n identifier = id.slice(0, colonIdx)\n const rest = id.slice(colonIdx + 1)\n if (!rest) throw new Error(`Invalid agent ID: empty version after ':' in '${id}'`)\n\n // Phase 2: split version~digest\n const tildeIdx = rest.indexOf('~')\n if (tildeIdx === -1) {\n // Form B: namespace/name:version\n version = rest\n } else {\n // Form D: namespace/name:version~digest\n version = rest.slice(0, tildeIdx)\n digest = rest.slice(tildeIdx + 1)\n if (!version) throw new Error(`Invalid agent ID: empty version before '~' in '${id}'`)\n if (!digest) throw new Error(`Invalid agent ID: empty digest after '~' in '${id}'`)\n }\n }\n\n // Phase 3: extract namespace and name from the identifier\n const { namespace, name } = parseNamespaceName(identifier)\n\n if (!namespace) throw new Error(`Invalid agent ID: empty namespace in '${id}'`)\n if (!name) throw new Error(`Invalid agent ID: empty name in '${id}'`)\n\n return { namespace, name, version, digest }\n}\n\nexport function buildId(parts: IdParts): string {\n const { namespace, name, version, digest } = parts\n if (!namespace || !name) {\n throw new Error('Missing required ID parts: namespace and name')\n }\n if (digest && !version) {\n throw new Error('Invalid ID parts: digest requires version')\n }\n let result = `${namespace}/${name}`\n if (version) {\n result += `:${version}`\n if (digest) result += `~${digest}`\n }\n // Ids are always lowercase — domains, platform usernames (GitHub/GitLab/\n // Codeberg/Sourcehut) and email local-parts are all case-insensitive in\n // practice, so normalizing here is safe and gives every id a single shape.\n return result.toLowerCase()\n}\n\n// Turns a human display name (e.g. \"Fridge Assistant\", from `agent Fridge\n// Assistant` in the DSL — spaces/capitalization are deliberate there) into\n// the kebab-case slug used for an id's name segment.\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n// Accepts optional leading 'v' (id spec examples use it; monorepo tags after\n// their '@' split don't), 1-3 dot-separated numeric groups, and optional\n// -prerelease / +build suffixes — e.g. v1.0, 2.3.1, v1.0.0-alpha.1, 1.0+build.\nconst VERSION_RE = /^v?\\d+(\\.\\d+){0,2}(-[0-9A-Za-z.]+)?(\\+[0-9A-Za-z.]+)?$/i\n\nexport function isValidVersion(version: string): boolean {\n return VERSION_RE.test(version)\n}\n\nexport function extractDigest(id: string): string {\n try {\n return parseId(id).digest ?? ''\n } catch {\n return ''\n }\n}\n\nexport function extractName(id: string): string {\n try {\n return parseId(id).name\n } catch {\n return ''\n }\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport JSZip from 'jszip'\n\nexport const MAX_ZIP_SIZE = 500 * 1024 * 1024\nexport const MAX_COMPRESSION_RATIO = 100\n\nexport function validateMagicBytes(bytes: Uint8Array): void {\n if (!(bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04)) {\n throw new Error('Not a valid .agent file (invalid magic bytes)')\n }\n}\n\nexport function validateZipBomb(zip: JSZip, compressedSize: number): void {\n let totalUncompressed = 0\n zip.forEach((_path, file) => {\n if (!file.dir) totalUncompressed += (file as any)._data?.uncompressedSize || 0\n })\n if (totalUncompressed > MAX_ZIP_SIZE) {\n throw new Error(`Bundle exceeds 500MB uncompressed: ${totalUncompressed}`)\n }\n if (totalUncompressed / compressedSize > MAX_COMPRESSION_RATIO) {\n throw new Error(`Compression ratio exceeds 100x: ${(totalUncompressed / compressedSize).toFixed(1)}x`)\n }\n}\n\nexport function createZip(): JSZip {\n return new JSZip()\n}\n\nexport async function extractFiles(zip: JSZip, filter?: string[]): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n const promises: Promise<void>[] = []\n\n zip.forEach((relativePath, file) => {\n if (file.dir) return\n if (filter && !filter.some(f => relativePath.startsWith(f))) return\n promises.push(\n file.async('text').then(content => {\n files.set(relativePath, content)\n })\n )\n })\n\n await Promise.all(promises)\n return files\n}\n"],"mappings":";AACO,IAAM,cAAc;AACpB,IAAM,mBAAmB;;;ACSzB,SAAS,aAAa,MAAoB;AAC/C,MAAI,CAAC,KAAK,WAAY,OAAM,IAAI,MAAM,oCAAoC;AAC1E,MAAI,CAAC,KAAK,GAAI,OAAM,IAAI,MAAM,4BAA4B;AAC1D,MAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,8BAA8B;AAC9D,MAAI,CAAC,KAAK,YAAa,OAAM,IAAI,MAAM,qCAAqC;AAC5E,MAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,gCAAgC;AAClE,MAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,kCAAkC;AACtE,MAAI,CAAC,MAAM,QAAQ,KAAK,YAAY,EAAG,OAAM,IAAI,MAAM,4CAA4C;AACnG,MAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,EAAG,OAAM,IAAI,MAAM,wCAAwC;AAC3F,MAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,mCAAmC;AAExE,SAAO;AAAA,IACL,YAAY,KAAK;AAAA,IACjB,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,SAAS,KAAK,WAAW;AAAA,IACzB,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK;AAAA,IACd,SAAS,KAAK,WAAW;AAAA,IACzB,UAAU,KAAK;AAAA,IACf,QAAQ,KAAK;AAAA,IACb,cAAc,KAAK;AAAA,IACnB,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA,EAClB;AACF;AAEO,SAAS,aAAa,MAAoC;AAC/D,SAAO;AAAA,IACL,YAAY,aAAa,WAAW;AAAA,IACpC,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK;AAAA,IACd,SAAS,KAAK,WAAW;AAAA,IACzB,UAAU,KAAK;AAAA,IACf,QAAQ,KAAK;AAAA,IACb,cAAc,KAAK,gBAAgB,CAAC;AAAA,IACpC,UAAU,KAAK,YAAY,CAAC;AAAA,IAC5B,WAAW,KAAK;AAAA,EAClB;AACF;AAEO,SAAS,cAAc,SAA0B;AACtD,SAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AACxC;;;AC3CO,IAAM,kBAAkB,CAAC,cAAc,cAAc,gBAAgB,OAAO;AAEnF,SAAS,mBAAmB,YAAyD;AAEnF,QAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,MAAI,UAAU,OAAO,WAAW,QAAQ,GAAG,MAAM,MAAM,QAAQ,WAAW,QAAQ,GAAG,IAAI;AACvF,UAAM,WAAW,WAAW,QAAQ,GAAG;AACvC,QAAI,aAAa,IAAI;AACnB,YAAM,IAAI,MAAM,qEAAqE,UAAU,IAAI;AAAA,IACrG;AACA,WAAO;AAAA,MACL,WAAW,WAAW,MAAM,GAAG,QAAQ;AAAA,MACvC,MAAM,WAAW,MAAM,WAAW,CAAC;AAAA,IACrC;AAAA,EACF;AAGA,aAAW,YAAY,iBAAiB;AACtC,QAAI,WAAW,WAAW,WAAW,GAAG,GAAG;AACzC,YAAM,gBAAgB,WAAW,MAAM,SAAS,SAAS,CAAC;AAC1D,YAAM,WAAW,cAAc,QAAQ,GAAG;AAC1C,UAAI,aAAa,IAAI;AACnB,cAAM,IAAI;AAAA,UACR,sBAAsB,QAAQ,wDAAwD,UAAU;AAAA,QAClG;AAAA,MACF;AACA,aAAO;AAAA,QACL,WAAW,WAAW,MAAM,cAAc,MAAM,GAAG,QAAQ;AAAA,QAC3D,MAAM,cAAc,MAAM,WAAW,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,WAAW,YAAY,GAAG;AAC5C,MAAI,cAAc,IAAI;AACpB,UAAM,IAAI,MAAM,+CAA+C,UAAU,GAAG;AAAA,EAC9E;AACA,SAAO;AAAA,IACL,WAAW,WAAW,MAAM,GAAG,SAAS;AAAA,IACxC,MAAM,WAAW,MAAM,YAAY,CAAC;AAAA,EACtC;AACF;AAEO,SAAS,QAAQ,IAAqB;AAC3C,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,gCAAgC;AAGzD,QAAM,WAAW,GAAG,QAAQ,GAAG;AAE/B,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,aAAa,IAAI;AAEnB,iBAAa;AAAA,EACf,OAAO;AACL,iBAAa,GAAG,MAAM,GAAG,QAAQ;AACjC,UAAM,OAAO,GAAG,MAAM,WAAW,CAAC;AAClC,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,iDAAiD,EAAE,GAAG;AAGjF,UAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,QAAI,aAAa,IAAI;AAEnB,gBAAU;AAAA,IACZ,OAAO;AAEL,gBAAU,KAAK,MAAM,GAAG,QAAQ;AAChC,eAAS,KAAK,MAAM,WAAW,CAAC;AAChC,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,kDAAkD,EAAE,GAAG;AACrF,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,gDAAgD,EAAE,GAAG;AAAA,IACpF;AAAA,EACF;AAGA,QAAM,EAAE,WAAW,KAAK,IAAI,mBAAmB,UAAU;AAEzD,MAAI,CAAC,UAAW,OAAM,IAAI,MAAM,yCAAyC,EAAE,GAAG;AAC9E,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oCAAoC,EAAE,GAAG;AAEpE,SAAO,EAAE,WAAW,MAAM,SAAS,OAAO;AAC5C;AAEO,SAAS,QAAQ,OAAwB;AAC9C,QAAM,EAAE,WAAW,MAAM,SAAS,OAAO,IAAI;AAC7C,MAAI,CAAC,aAAa,CAAC,MAAM;AACvB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AACA,MAAI,UAAU,CAAC,SAAS;AACtB,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,MAAI,SAAS,GAAG,SAAS,IAAI,IAAI;AACjC,MAAI,SAAS;AACX,cAAU,IAAI,OAAO;AACrB,QAAI,OAAQ,WAAU,IAAI,MAAM;AAAA,EAClC;AAIA,SAAO,OAAO,YAAY;AAC5B;AAKO,SAAS,QAAQ,MAAsB;AAC5C,SAAO,KACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAKA,IAAM,aAAa;AAEZ,SAAS,eAAe,SAA0B;AACvD,SAAO,WAAW,KAAK,OAAO;AAChC;AAEO,SAAS,cAAc,IAAoB;AAChD,MAAI;AACF,WAAO,QAAQ,EAAE,EAAE,UAAU;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YAAY,IAAoB;AAC9C,MAAI;AACF,WAAO,QAAQ,EAAE,EAAE;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC7IA,OAAO,WAAW;AAEX,IAAM,eAAe,MAAM,OAAO;AAClC,IAAM,wBAAwB;AAE9B,SAAS,mBAAmB,OAAyB;AAC1D,MAAI,EAAE,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,KAAQ,MAAM,CAAC,MAAM,IAAO;AACvF,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AACF;AAEO,SAAS,gBAAgB,KAAY,gBAA8B;AACxE,MAAI,oBAAoB;AACxB,MAAI,QAAQ,CAAC,OAAO,SAAS;AAC3B,QAAI,CAAC,KAAK,IAAK,sBAAsB,KAAa,OAAO,oBAAoB;AAAA,EAC/E,CAAC;AACD,MAAI,oBAAoB,cAAc;AACpC,UAAM,IAAI,MAAM,sCAAsC,iBAAiB,EAAE;AAAA,EAC3E;AACA,MAAI,oBAAoB,iBAAiB,uBAAuB;AAC9D,UAAM,IAAI,MAAM,oCAAoC,oBAAoB,gBAAgB,QAAQ,CAAC,CAAC,GAAG;AAAA,EACvG;AACF;AAEO,SAAS,YAAmB;AACjC,SAAO,IAAI,MAAM;AACnB;AAEA,eAAsB,aAAa,KAAY,QAAiD;AAC9F,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,WAA4B,CAAC;AAEnC,MAAI,QAAQ,CAAC,cAAc,SAAS;AAClC,QAAI,KAAK,IAAK;AACd,QAAI,UAAU,CAAC,OAAO,KAAK,OAAK,aAAa,WAAW,CAAC,CAAC,EAAG;AAC7D,aAAS;AAAA,MACP,KAAK,MAAM,MAAM,EAAE,KAAK,aAAW;AACjC,cAAM,IAAI,cAAc,OAAO;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,IAAI,QAAQ;AAC1B,SAAO;AACT;","names":[]}
|
|
@@ -45,7 +45,7 @@ interface AboutMe {
|
|
|
45
45
|
version: string;
|
|
46
46
|
domain: string;
|
|
47
47
|
license: string;
|
|
48
|
-
persona
|
|
48
|
+
persona?: string;
|
|
49
49
|
purpose: string;
|
|
50
50
|
compiler: string;
|
|
51
51
|
commit?: string;
|
|
@@ -56,7 +56,7 @@ interface AboutMe {
|
|
|
56
56
|
interface AgentFiles {
|
|
57
57
|
description: string;
|
|
58
58
|
behavior: string;
|
|
59
|
-
|
|
59
|
+
persona?: string;
|
|
60
60
|
guides: Array<{
|
|
61
61
|
path: string;
|
|
62
62
|
content: string;
|
|
@@ -94,7 +94,7 @@ interface BuildAboutmeOptions {
|
|
|
94
94
|
version: string;
|
|
95
95
|
domain: string;
|
|
96
96
|
license?: string;
|
|
97
|
-
persona
|
|
97
|
+
persona?: string;
|
|
98
98
|
purpose?: string;
|
|
99
99
|
compiler: string;
|
|
100
100
|
commit?: string;
|
|
@@ -45,7 +45,7 @@ interface AboutMe {
|
|
|
45
45
|
version: string;
|
|
46
46
|
domain: string;
|
|
47
47
|
license: string;
|
|
48
|
-
persona
|
|
48
|
+
persona?: string;
|
|
49
49
|
purpose: string;
|
|
50
50
|
compiler: string;
|
|
51
51
|
commit?: string;
|
|
@@ -56,7 +56,7 @@ interface AboutMe {
|
|
|
56
56
|
interface AgentFiles {
|
|
57
57
|
description: string;
|
|
58
58
|
behavior: string;
|
|
59
|
-
|
|
59
|
+
persona?: string;
|
|
60
60
|
guides: Array<{
|
|
61
61
|
path: string;
|
|
62
62
|
content: string;
|
|
@@ -94,7 +94,7 @@ interface BuildAboutmeOptions {
|
|
|
94
94
|
version: string;
|
|
95
95
|
domain: string;
|
|
96
96
|
license?: string;
|
|
97
|
-
persona
|
|
97
|
+
persona?: string;
|
|
98
98
|
purpose?: string;
|
|
99
99
|
compiler: string;
|
|
100
100
|
commit?: string;
|
package/dist/core.cjs
CHANGED
|
@@ -45,7 +45,7 @@ __export(core_exports, {
|
|
|
45
45
|
module.exports = __toCommonJS(core_exports);
|
|
46
46
|
|
|
47
47
|
// src/generated-version.ts
|
|
48
|
-
var DSL_VERSION = "0.1
|
|
48
|
+
var DSL_VERSION = "0.1";
|
|
49
49
|
|
|
50
50
|
// src/manifest.ts
|
|
51
51
|
function parseAboutme(json) {
|
|
@@ -53,9 +53,7 @@ function parseAboutme(json) {
|
|
|
53
53
|
if (!json.id) throw new Error("Missing id in aboutme.json");
|
|
54
54
|
if (!json.name) throw new Error("Missing name in aboutme.json");
|
|
55
55
|
if (!json.description) throw new Error("Missing description in aboutme.json");
|
|
56
|
-
if (!json.version) throw new Error("Missing version in aboutme.json");
|
|
57
56
|
if (!json.domain) throw new Error("Missing domain in aboutme.json");
|
|
58
|
-
if (!json.persona) throw new Error("Missing persona in aboutme.json");
|
|
59
57
|
if (!json.compiler) throw new Error("Missing compiler in aboutme.json");
|
|
60
58
|
if (!Array.isArray(json.capabilities)) throw new Error("Missing capabilities array in aboutme.json");
|
|
61
59
|
if (!Array.isArray(json.requires)) throw new Error("Missing requires array in aboutme.json");
|
|
@@ -65,7 +63,7 @@ function parseAboutme(json) {
|
|
|
65
63
|
id: json.id,
|
|
66
64
|
name: json.name,
|
|
67
65
|
description: json.description,
|
|
68
|
-
version: json.version,
|
|
66
|
+
version: json.version ?? "",
|
|
69
67
|
domain: json.domain,
|
|
70
68
|
license: json.license ?? "",
|
|
71
69
|
persona: json.persona,
|
|
@@ -177,7 +175,7 @@ function buildId(parts) {
|
|
|
177
175
|
result += `:${version}`;
|
|
178
176
|
if (digest) result += `~${digest}`;
|
|
179
177
|
}
|
|
180
|
-
return result;
|
|
178
|
+
return result.toLowerCase();
|
|
181
179
|
}
|
|
182
180
|
function extractDigest(id) {
|
|
183
181
|
try {
|
package/dist/core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core.ts","../src/generated-version.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts"],"sourcesContent":["// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Browser-safe sub-path export — no Node.js dependencies.\n// Import via: import { ... } from '@dot-agent/compiler/core'\n\nexport { parseAboutme, buildAboutme, aboutmeToJson } from './manifest.js'\nexport { parseId, buildId, extractDigest, extractName } from './id.js'\nexport { createZip, extractFiles, validateMagicBytes, validateZipBomb } from './zip-core.js'\n\nexport type {\n AboutMe,\n AgentBundle,\n AgentFiles,\n Capability,\n AnnotatedRef,\n DescriptionFile,\n Integrity,\n BuildAboutmeOptions,\n IdParts,\n LintMessage,\n} from './types.js'\n","// Generated by scripts/embed-version.mjs from dsl/VERSION and package.json — do not edit by hand.\nexport const DSL_VERSION = '0.1-alpha'\nexport const COMPILER_VERSION = '0.5.0-alpha.2'\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport type { AboutMe, BuildAboutmeOptions } from './types.js'\nimport { DSL_VERSION } from './generated-version.js'\n\nexport function parseAboutme(json: any): AboutMe {\n if (!json.dslVersion) throw new Error('Missing dslVersion in aboutme.json')\n if (!json.id) throw new Error('Missing id in aboutme.json')\n if (!json.name) throw new Error('Missing name in aboutme.json')\n if (!json.description) throw new Error('Missing description in aboutme.json')\n if (!json.version) throw new Error('Missing version in aboutme.json')\n if (!json.domain) throw new Error('Missing domain in aboutme.json')\n if (!json.persona) throw new Error('Missing persona in aboutme.json')\n if (!json.compiler) throw new Error('Missing compiler in aboutme.json')\n if (!Array.isArray(json.capabilities)) throw new Error('Missing capabilities array in aboutme.json')\n if (!Array.isArray(json.requires)) throw new Error('Missing requires array in aboutme.json')\n if (!json.integrity) throw new Error('Missing integrity in aboutme.json')\n\n return {\n dslVersion: json.dslVersion,\n id: json.id,\n name: json.name,\n description: json.description,\n version: json.version,\n domain: json.domain,\n license: json.license ?? '',\n persona: json.persona,\n purpose: json.purpose ?? 'unknown',\n compiler: json.compiler,\n commit: json.commit,\n capabilities: json.capabilities,\n requires: json.requires,\n integrity: json.integrity,\n }\n}\n\nexport function buildAboutme(opts: BuildAboutmeOptions): AboutMe {\n return {\n dslVersion: `dot-agent/${DSL_VERSION}`,\n id: opts.id,\n name: opts.name,\n description: opts.description,\n version: opts.version,\n domain: opts.domain,\n license: opts.license ?? '',\n persona: opts.persona,\n purpose: opts.purpose ?? 'unknown',\n compiler: opts.compiler,\n commit: opts.commit,\n capabilities: opts.capabilities ?? [],\n requires: opts.requires ?? [],\n integrity: opts.integrity,\n }\n}\n\nexport function aboutmeToJson(aboutme: AboutMe): string {\n return JSON.stringify(aboutme, null, 2)\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { IdParts } from './types.js'\n\n// Code hosting platforms whose namespace format is platform/user rather than plain domain.\n// The list is maintained by the compiler and updated via CLI releases.\nexport const KNOWN_PLATFORMS = ['github.com', 'gitlab.com', 'codeberg.org', 'sr.ht'] as const\n\nfunction parseNamespaceName(identifier: string): { namespace: string; name: string } {\n // Email namespace: @ appears before any /\n const atIdx = identifier.indexOf('@')\n if (atIdx !== -1 && (identifier.indexOf('/') === -1 || atIdx < identifier.indexOf('/'))) {\n const slashIdx = identifier.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(`Invalid agent ID: email namespace requires a name after '/' (got '${identifier}')`)\n }\n return {\n namespace: identifier.slice(0, slashIdx),\n name: identifier.slice(slashIdx + 1),\n }\n }\n\n // Known code-hosting platforms: namespace is platform/user, name is the next segment.\n for (const platform of KNOWN_PLATFORMS) {\n if (identifier.startsWith(platform + '/')) {\n const afterPlatform = identifier.slice(platform.length + 1)\n const slashIdx = afterPlatform.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(\n `Invalid agent ID: '${platform}' namespace requires a user segment and a name (got '${identifier}')`,\n )\n }\n return {\n namespace: platform + '/' + afterPlatform.slice(0, slashIdx),\n name: afterPlatform.slice(slashIdx + 1),\n }\n }\n }\n\n // Domain or reserved keyword (e.g. 'unknown'): last '/' separates namespace from name.\n const lastSlash = identifier.lastIndexOf('/')\n if (lastSlash === -1) {\n throw new Error(`Invalid agent ID: missing '/' separator in '${identifier}'`)\n }\n return {\n namespace: identifier.slice(0, lastSlash),\n name: identifier.slice(lastSlash + 1),\n }\n}\n\nexport function parseId(id: string): IdParts {\n if (!id) throw new Error('Invalid agent ID: empty string')\n\n // Phase 1: split on the first ':' to isolate the identifier from version~digest.\n const colonIdx = id.indexOf(':')\n\n let identifier: string\n let version: string | undefined\n let digest: string | undefined\n\n if (colonIdx === -1) {\n // Form A: namespace/name\n identifier = id\n } else {\n identifier = id.slice(0, colonIdx)\n const rest = id.slice(colonIdx + 1)\n if (!rest) throw new Error(`Invalid agent ID: empty version after ':' in '${id}'`)\n\n // Phase 2: split version~digest\n const tildeIdx = rest.indexOf('~')\n if (tildeIdx === -1) {\n // Form B: namespace/name:version\n version = rest\n } else {\n // Form D: namespace/name:version~digest\n version = rest.slice(0, tildeIdx)\n digest = rest.slice(tildeIdx + 1)\n if (!version) throw new Error(`Invalid agent ID: empty version before '~' in '${id}'`)\n if (!digest) throw new Error(`Invalid agent ID: empty digest after '~' in '${id}'`)\n }\n }\n\n // Phase 3: extract namespace and name from the identifier\n const { namespace, name } = parseNamespaceName(identifier)\n\n if (!namespace) throw new Error(`Invalid agent ID: empty namespace in '${id}'`)\n if (!name) throw new Error(`Invalid agent ID: empty name in '${id}'`)\n\n return { namespace, name, version, digest }\n}\n\nexport function buildId(parts: IdParts): string {\n const { namespace, name, version, digest } = parts\n if (!namespace || !name) {\n throw new Error('Missing required ID parts: namespace and name')\n }\n if (digest && !version) {\n throw new Error('Invalid ID parts: digest requires version')\n }\n let result = `${namespace}/${name}`\n if (version) {\n result += `:${version}`\n if (digest) result += `~${digest}`\n }\n return result\n}\n\nexport function extractDigest(id: string): string {\n try {\n return parseId(id).digest ?? ''\n } catch {\n return ''\n }\n}\n\nexport function extractName(id: string): string {\n try {\n return parseId(id).name\n } catch {\n return ''\n }\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport JSZip from 'jszip'\n\nexport const MAX_ZIP_SIZE = 500 * 1024 * 1024\nexport const MAX_COMPRESSION_RATIO = 100\n\nexport function validateMagicBytes(bytes: Uint8Array): void {\n if (!(bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04)) {\n throw new Error('Not a valid .agent file (invalid magic bytes)')\n }\n}\n\nexport function validateZipBomb(zip: JSZip, compressedSize: number): void {\n let totalUncompressed = 0\n zip.forEach((_path, file) => {\n if (!file.dir) totalUncompressed += (file as any)._data?.uncompressedSize || 0\n })\n if (totalUncompressed > MAX_ZIP_SIZE) {\n throw new Error(`Bundle exceeds 500MB uncompressed: ${totalUncompressed}`)\n }\n if (totalUncompressed / compressedSize > MAX_COMPRESSION_RATIO) {\n throw new Error(`Compression ratio exceeds 100x: ${(totalUncompressed / compressedSize).toFixed(1)}x`)\n }\n}\n\nexport function createZip(): JSZip {\n return new JSZip()\n}\n\nexport async function extractFiles(zip: JSZip, filter?: string[]): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n const promises: Promise<void>[] = []\n\n zip.forEach((relativePath, file) => {\n if (file.dir) return\n if (filter && !filter.some(f => relativePath.startsWith(f))) return\n promises.push(\n file.async('text').then(content => {\n files.set(relativePath, content)\n })\n )\n })\n\n await Promise.all(promises)\n return files\n}\n"],"mappings":"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","names":["JSZip"]}
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/generated-version.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts"],"sourcesContent":["// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Browser-safe sub-path export — no Node.js dependencies.\n// Import via: import { ... } from '@dot-agent/compiler/core'\n\nexport { parseAboutme, buildAboutme, aboutmeToJson } from './manifest.js'\nexport { parseId, buildId, extractDigest, extractName } from './id.js'\nexport { createZip, extractFiles, validateMagicBytes, validateZipBomb } from './zip-core.js'\n\nexport type {\n AboutMe,\n AgentBundle,\n AgentFiles,\n Capability,\n AnnotatedRef,\n DescriptionFile,\n Integrity,\n BuildAboutmeOptions,\n IdParts,\n LintMessage,\n} from './types.js'\n","// Generated by scripts/embed-version.mjs from dsl/VERSION and package.json — do not edit by hand.\nexport const DSL_VERSION = '0.1'\nexport const COMPILER_VERSION = '0.10.0'\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport type { AboutMe, BuildAboutmeOptions } from './types.js'\nimport { DSL_VERSION } from './generated-version.js'\n\nexport function parseAboutme(json: any): AboutMe {\n if (!json.dslVersion) throw new Error('Missing dslVersion in aboutme.json')\n if (!json.id) throw new Error('Missing id in aboutme.json')\n if (!json.name) throw new Error('Missing name in aboutme.json')\n if (!json.description) throw new Error('Missing description in aboutme.json')\n if (!json.domain) throw new Error('Missing domain in aboutme.json')\n if (!json.compiler) throw new Error('Missing compiler in aboutme.json')\n if (!Array.isArray(json.capabilities)) throw new Error('Missing capabilities array in aboutme.json')\n if (!Array.isArray(json.requires)) throw new Error('Missing requires array in aboutme.json')\n if (!json.integrity) throw new Error('Missing integrity in aboutme.json')\n\n return {\n dslVersion: json.dslVersion,\n id: json.id,\n name: json.name,\n description: json.description,\n version: json.version ?? '',\n domain: json.domain,\n license: json.license ?? '',\n persona: json.persona,\n purpose: json.purpose ?? 'unknown',\n compiler: json.compiler,\n commit: json.commit,\n capabilities: json.capabilities,\n requires: json.requires,\n integrity: json.integrity,\n }\n}\n\nexport function buildAboutme(opts: BuildAboutmeOptions): AboutMe {\n return {\n dslVersion: `dot-agent/${DSL_VERSION}`,\n id: opts.id,\n name: opts.name,\n description: opts.description,\n version: opts.version,\n domain: opts.domain,\n license: opts.license ?? '',\n persona: opts.persona,\n purpose: opts.purpose ?? 'unknown',\n compiler: opts.compiler,\n commit: opts.commit,\n capabilities: opts.capabilities ?? [],\n requires: opts.requires ?? [],\n integrity: opts.integrity,\n }\n}\n\nexport function aboutmeToJson(aboutme: AboutMe): string {\n return JSON.stringify(aboutme, null, 2)\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { IdParts } from './types.js'\n\n// Code hosting platforms whose namespace format is platform/user rather than plain domain.\n// The list is maintained by the compiler and updated via CLI releases.\nexport const KNOWN_PLATFORMS = ['github.com', 'gitlab.com', 'codeberg.org', 'sr.ht'] as const\n\nfunction parseNamespaceName(identifier: string): { namespace: string; name: string } {\n // Email namespace: @ appears before any /\n const atIdx = identifier.indexOf('@')\n if (atIdx !== -1 && (identifier.indexOf('/') === -1 || atIdx < identifier.indexOf('/'))) {\n const slashIdx = identifier.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(`Invalid agent ID: email namespace requires a name after '/' (got '${identifier}')`)\n }\n return {\n namespace: identifier.slice(0, slashIdx),\n name: identifier.slice(slashIdx + 1),\n }\n }\n\n // Known code-hosting platforms: namespace is platform/user, name is the next segment.\n for (const platform of KNOWN_PLATFORMS) {\n if (identifier.startsWith(platform + '/')) {\n const afterPlatform = identifier.slice(platform.length + 1)\n const slashIdx = afterPlatform.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(\n `Invalid agent ID: '${platform}' namespace requires a user segment and a name (got '${identifier}')`,\n )\n }\n return {\n namespace: platform + '/' + afterPlatform.slice(0, slashIdx),\n name: afterPlatform.slice(slashIdx + 1),\n }\n }\n }\n\n // Domain or reserved keyword (e.g. 'unknown'): last '/' separates namespace from name.\n const lastSlash = identifier.lastIndexOf('/')\n if (lastSlash === -1) {\n throw new Error(`Invalid agent ID: missing '/' separator in '${identifier}'`)\n }\n return {\n namespace: identifier.slice(0, lastSlash),\n name: identifier.slice(lastSlash + 1),\n }\n}\n\nexport function parseId(id: string): IdParts {\n if (!id) throw new Error('Invalid agent ID: empty string')\n\n // Phase 1: split on the first ':' to isolate the identifier from version~digest.\n const colonIdx = id.indexOf(':')\n\n let identifier: string\n let version: string | undefined\n let digest: string | undefined\n\n if (colonIdx === -1) {\n // Form A: namespace/name\n identifier = id\n } else {\n identifier = id.slice(0, colonIdx)\n const rest = id.slice(colonIdx + 1)\n if (!rest) throw new Error(`Invalid agent ID: empty version after ':' in '${id}'`)\n\n // Phase 2: split version~digest\n const tildeIdx = rest.indexOf('~')\n if (tildeIdx === -1) {\n // Form B: namespace/name:version\n version = rest\n } else {\n // Form D: namespace/name:version~digest\n version = rest.slice(0, tildeIdx)\n digest = rest.slice(tildeIdx + 1)\n if (!version) throw new Error(`Invalid agent ID: empty version before '~' in '${id}'`)\n if (!digest) throw new Error(`Invalid agent ID: empty digest after '~' in '${id}'`)\n }\n }\n\n // Phase 3: extract namespace and name from the identifier\n const { namespace, name } = parseNamespaceName(identifier)\n\n if (!namespace) throw new Error(`Invalid agent ID: empty namespace in '${id}'`)\n if (!name) throw new Error(`Invalid agent ID: empty name in '${id}'`)\n\n return { namespace, name, version, digest }\n}\n\nexport function buildId(parts: IdParts): string {\n const { namespace, name, version, digest } = parts\n if (!namespace || !name) {\n throw new Error('Missing required ID parts: namespace and name')\n }\n if (digest && !version) {\n throw new Error('Invalid ID parts: digest requires version')\n }\n let result = `${namespace}/${name}`\n if (version) {\n result += `:${version}`\n if (digest) result += `~${digest}`\n }\n // Ids are always lowercase — domains, platform usernames (GitHub/GitLab/\n // Codeberg/Sourcehut) and email local-parts are all case-insensitive in\n // practice, so normalizing here is safe and gives every id a single shape.\n return result.toLowerCase()\n}\n\n// Turns a human display name (e.g. \"Fridge Assistant\", from `agent Fridge\n// Assistant` in the DSL — spaces/capitalization are deliberate there) into\n// the kebab-case slug used for an id's name segment.\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n// Accepts optional leading 'v' (id spec examples use it; monorepo tags after\n// their '@' split don't), 1-3 dot-separated numeric groups, and optional\n// -prerelease / +build suffixes — e.g. v1.0, 2.3.1, v1.0.0-alpha.1, 1.0+build.\nconst VERSION_RE = /^v?\\d+(\\.\\d+){0,2}(-[0-9A-Za-z.]+)?(\\+[0-9A-Za-z.]+)?$/i\n\nexport function isValidVersion(version: string): boolean {\n return VERSION_RE.test(version)\n}\n\nexport function extractDigest(id: string): string {\n try {\n return parseId(id).digest ?? ''\n } catch {\n return ''\n }\n}\n\nexport function extractName(id: string): string {\n try {\n return parseId(id).name\n } catch {\n return ''\n }\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport JSZip from 'jszip'\n\nexport const MAX_ZIP_SIZE = 500 * 1024 * 1024\nexport const MAX_COMPRESSION_RATIO = 100\n\nexport function validateMagicBytes(bytes: Uint8Array): void {\n if (!(bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04)) {\n throw new Error('Not a valid .agent file (invalid magic bytes)')\n }\n}\n\nexport function validateZipBomb(zip: JSZip, compressedSize: number): void {\n let totalUncompressed = 0\n zip.forEach((_path, file) => {\n if (!file.dir) totalUncompressed += (file as any)._data?.uncompressedSize || 0\n })\n if (totalUncompressed > MAX_ZIP_SIZE) {\n throw new Error(`Bundle exceeds 500MB uncompressed: ${totalUncompressed}`)\n }\n if (totalUncompressed / compressedSize > MAX_COMPRESSION_RATIO) {\n throw new Error(`Compression ratio exceeds 100x: ${(totalUncompressed / compressedSize).toFixed(1)}x`)\n }\n}\n\nexport function createZip(): JSZip {\n return new JSZip()\n}\n\nexport async function extractFiles(zip: JSZip, filter?: string[]): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n const promises: Promise<void>[] = []\n\n zip.forEach((relativePath, file) => {\n if (file.dir) return\n if (filter && !filter.some(f => relativePath.startsWith(f))) return\n promises.push(\n file.async('text').then(content => {\n files.set(relativePath, content)\n })\n )\n })\n\n await Promise.all(promises)\n return files\n}\n"],"mappings":"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","names":["JSZip"]}
|
package/dist/core.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { d as AboutMe, A as AgentBundle, e as AgentFiles, B as BuildAboutmeOptions, C as Capability, I as IdParts, f as Integrity, a as LintMessage, g as aboutmeToJson, h as buildAboutme, i as buildId, j as createZip, k as extractDigest, l as extractFiles, m as extractName, p as parseAboutme, n as parseId, v as validateMagicBytes, o as validateZipBomb } from './core-
|
|
1
|
+
export { d as AboutMe, A as AgentBundle, e as AgentFiles, B as BuildAboutmeOptions, C as Capability, I as IdParts, f as Integrity, a as LintMessage, g as aboutmeToJson, h as buildAboutme, i as buildId, j as createZip, k as extractDigest, l as extractFiles, m as extractName, p as parseAboutme, n as parseId, v as validateMagicBytes, o as validateZipBomb } from './core-D2X2Eohl.cjs';
|
|
2
2
|
export { AnnotatedRef, DescriptionFile } from '@dot-agent/parser-dsl';
|
|
3
3
|
import 'jszip';
|
package/dist/core.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { d as AboutMe, A as AgentBundle, e as AgentFiles, B as BuildAboutmeOptions, C as Capability, I as IdParts, f as Integrity, a as LintMessage, g as aboutmeToJson, h as buildAboutme, i as buildId, j as createZip, k as extractDigest, l as extractFiles, m as extractName, p as parseAboutme, n as parseId, v as validateMagicBytes, o as validateZipBomb } from './core-
|
|
1
|
+
export { d as AboutMe, A as AgentBundle, e as AgentFiles, B as BuildAboutmeOptions, C as Capability, I as IdParts, f as Integrity, a as LintMessage, g as aboutmeToJson, h as buildAboutme, i as buildId, j as createZip, k as extractDigest, l as extractFiles, m as extractName, p as parseAboutme, n as parseId, v as validateMagicBytes, o as validateZipBomb } from './core-D2X2Eohl.js';
|
|
2
2
|
export { AnnotatedRef, DescriptionFile } from '@dot-agent/parser-dsl';
|
|
3
3
|
import 'jszip';
|
package/dist/core.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -677,8 +677,8 @@ async function createLinter() {
|
|
|
677
677
|
}
|
|
678
678
|
|
|
679
679
|
// src/generated-version.ts
|
|
680
|
-
var DSL_VERSION = "0.1
|
|
681
|
-
var COMPILER_VERSION = "0.
|
|
680
|
+
var DSL_VERSION = "0.1";
|
|
681
|
+
var COMPILER_VERSION = "0.10.0";
|
|
682
682
|
|
|
683
683
|
// src/manifest.ts
|
|
684
684
|
function parseAboutme(json) {
|
|
@@ -686,9 +686,7 @@ function parseAboutme(json) {
|
|
|
686
686
|
if (!json.id) throw new Error("Missing id in aboutme.json");
|
|
687
687
|
if (!json.name) throw new Error("Missing name in aboutme.json");
|
|
688
688
|
if (!json.description) throw new Error("Missing description in aboutme.json");
|
|
689
|
-
if (!json.version) throw new Error("Missing version in aboutme.json");
|
|
690
689
|
if (!json.domain) throw new Error("Missing domain in aboutme.json");
|
|
691
|
-
if (!json.persona) throw new Error("Missing persona in aboutme.json");
|
|
692
690
|
if (!json.compiler) throw new Error("Missing compiler in aboutme.json");
|
|
693
691
|
if (!Array.isArray(json.capabilities)) throw new Error("Missing capabilities array in aboutme.json");
|
|
694
692
|
if (!Array.isArray(json.requires)) throw new Error("Missing requires array in aboutme.json");
|
|
@@ -698,7 +696,7 @@ function parseAboutme(json) {
|
|
|
698
696
|
id: json.id,
|
|
699
697
|
name: json.name,
|
|
700
698
|
description: json.description,
|
|
701
|
-
version: json.version,
|
|
699
|
+
version: json.version ?? "",
|
|
702
700
|
domain: json.domain,
|
|
703
701
|
license: json.license ?? "",
|
|
704
702
|
persona: json.persona,
|
|
@@ -810,7 +808,14 @@ function buildId(parts) {
|
|
|
810
808
|
result += `:${version}`;
|
|
811
809
|
if (digest) result += `~${digest}`;
|
|
812
810
|
}
|
|
813
|
-
return result;
|
|
811
|
+
return result.toLowerCase();
|
|
812
|
+
}
|
|
813
|
+
function slugify(name) {
|
|
814
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
815
|
+
}
|
|
816
|
+
var VERSION_RE = /^v?\d+(\.\d+){0,2}(-[0-9A-Za-z.]+)?(\+[0-9A-Za-z.]+)?$/i;
|
|
817
|
+
function isValidVersion(version) {
|
|
818
|
+
return VERSION_RE.test(version);
|
|
814
819
|
}
|
|
815
820
|
function extractDigest(id) {
|
|
816
821
|
try {
|
|
@@ -954,13 +959,6 @@ function buildTypesJson(df) {
|
|
|
954
959
|
}
|
|
955
960
|
|
|
956
961
|
// src/pack.ts
|
|
957
|
-
function gitDescribeTags() {
|
|
958
|
-
try {
|
|
959
|
-
return (0, import_child_process.execSync)("git describe --tags --abbrev=0", { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
960
|
-
} catch {
|
|
961
|
-
return null;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
962
|
function gitRevParseShort() {
|
|
965
963
|
try {
|
|
966
964
|
return (0, import_child_process.execSync)("git rev-parse --short HEAD", { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
@@ -968,14 +966,65 @@ function gitRevParseShort() {
|
|
|
968
966
|
return null;
|
|
969
967
|
}
|
|
970
968
|
}
|
|
971
|
-
async function resolveVersion(explicit) {
|
|
972
|
-
if (explicit) return explicit;
|
|
973
|
-
return gitDescribeTags() ?? "v1.0.0";
|
|
974
|
-
}
|
|
975
969
|
async function resolveCommit(explicit) {
|
|
976
970
|
if (explicit) return explicit;
|
|
977
971
|
return gitRevParseShort() ?? void 0;
|
|
978
972
|
}
|
|
973
|
+
function recentTagCandidates(limit = 5) {
|
|
974
|
+
let tags;
|
|
975
|
+
try {
|
|
976
|
+
tags = (0, import_child_process.execSync)("git tag --sort=-creatordate", { stdio: "pipe", encoding: "utf-8" }).trim().split("\n").filter(Boolean);
|
|
977
|
+
} catch {
|
|
978
|
+
return [];
|
|
979
|
+
}
|
|
980
|
+
return tags.slice(0, limit).map((tag) => {
|
|
981
|
+
const atIdx = tag.lastIndexOf("@");
|
|
982
|
+
const version = atIdx === -1 ? tag : tag.slice(atIdx + 1);
|
|
983
|
+
const label = atIdx === -1 ? tag : `${version} (tag: ${tag})`;
|
|
984
|
+
return { version, label };
|
|
985
|
+
}).filter((c) => isValidVersion(c.version));
|
|
986
|
+
}
|
|
987
|
+
var CUSTOM_VERSION = "__dot-agent-custom-version__";
|
|
988
|
+
var BARE_VERSION = "__dot-agent-bare-version__";
|
|
989
|
+
async function resolveVersionInteractive(explicit) {
|
|
990
|
+
if (explicit) {
|
|
991
|
+
if (!isValidVersion(explicit)) {
|
|
992
|
+
throw new Error(`E019: Invalid version format '${explicit}' \u2014 expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]`);
|
|
993
|
+
}
|
|
994
|
+
return explicit;
|
|
995
|
+
}
|
|
996
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
997
|
+
process.stderr.write("[dot-agent] no TTY and no --version \u2014 packing without a version\n");
|
|
998
|
+
return void 0;
|
|
999
|
+
}
|
|
1000
|
+
const candidates = recentTagCandidates();
|
|
1001
|
+
const clack = await import("@clack/prompts");
|
|
1002
|
+
const choice = await clack.select({
|
|
1003
|
+
message: "Choose a version for this package",
|
|
1004
|
+
options: [
|
|
1005
|
+
...candidates.map((c) => ({ value: c.version, label: c.label })),
|
|
1006
|
+
{ value: CUSTOM_VERSION, label: "Type a custom version\u2026" },
|
|
1007
|
+
{ value: BARE_VERSION, label: "None (bare \u2014 no version)" }
|
|
1008
|
+
]
|
|
1009
|
+
});
|
|
1010
|
+
if (clack.isCancel(choice)) {
|
|
1011
|
+
clack.cancel("Pack cancelled.");
|
|
1012
|
+
process.exit(1);
|
|
1013
|
+
}
|
|
1014
|
+
if (choice === BARE_VERSION) return void 0;
|
|
1015
|
+
if (choice === CUSTOM_VERSION) {
|
|
1016
|
+
const typed = await clack.text({
|
|
1017
|
+
message: "Version",
|
|
1018
|
+
validate: (v) => v && isValidVersion(v) ? void 0 : "Invalid version format \u2014 expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]"
|
|
1019
|
+
});
|
|
1020
|
+
if (clack.isCancel(typed)) {
|
|
1021
|
+
clack.cancel("Pack cancelled.");
|
|
1022
|
+
process.exit(1);
|
|
1023
|
+
}
|
|
1024
|
+
return typed;
|
|
1025
|
+
}
|
|
1026
|
+
return choice;
|
|
1027
|
+
}
|
|
979
1028
|
function isExternalPath(agentRoot, declaredPath) {
|
|
980
1029
|
if ((0, import_path2.isAbsolute)(declaredPath)) return true;
|
|
981
1030
|
const normRoot = (0, import_path2.normalize)((0, import_path2.resolve)(agentRoot));
|
|
@@ -1050,7 +1099,35 @@ async function consolidate(agentRoot, entryFile) {
|
|
|
1050
1099
|
mergeSources: order
|
|
1051
1100
|
};
|
|
1052
1101
|
}
|
|
1053
|
-
|
|
1102
|
+
var FILE_REF_RE = /\.(txt|md)$/i;
|
|
1103
|
+
function collectFileRefs(stmts, out) {
|
|
1104
|
+
for (const s of stmts) {
|
|
1105
|
+
switch (s.type) {
|
|
1106
|
+
case "guide_stmt":
|
|
1107
|
+
if (FILE_REF_RE.test(s.text)) out.set(`guide:${s.text}`, { kind: "guide", text: s.text });
|
|
1108
|
+
break;
|
|
1109
|
+
case "teach_stmt":
|
|
1110
|
+
if (FILE_REF_RE.test(s.text)) out.set(`teach:${s.text}`, { kind: "teach", text: s.text });
|
|
1111
|
+
break;
|
|
1112
|
+
case "interact_stmt":
|
|
1113
|
+
collectFileRefs(s.handlers, out);
|
|
1114
|
+
break;
|
|
1115
|
+
case "intent_handler":
|
|
1116
|
+
if (Array.isArray(s.body)) collectFileRefs(s.body, out);
|
|
1117
|
+
break;
|
|
1118
|
+
case "offtopic_handler":
|
|
1119
|
+
case "after_stmt":
|
|
1120
|
+
case "parallel_stmt":
|
|
1121
|
+
collectFileRefs(s.body, out);
|
|
1122
|
+
break;
|
|
1123
|
+
case "conditional_stmt":
|
|
1124
|
+
collectFileRefs(s.then, out);
|
|
1125
|
+
if (s.else) collectFileRefs(s.else, out);
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
async function collectFiles(dir, descriptionFile, mergedBehaviorText, mergeSources, personaFile) {
|
|
1054
1131
|
const files = /* @__PURE__ */ new Map();
|
|
1055
1132
|
async function walk(subdir, prefix = "") {
|
|
1056
1133
|
try {
|
|
@@ -1075,17 +1152,47 @@ async function collectFiles(dir, descriptionFile, mergedBehaviorText, mergeSourc
|
|
|
1075
1152
|
for (const relPath of mergeSources) {
|
|
1076
1153
|
files.set(`behaviors/${relPath}`, await (0, import_promises2.readFile)((0, import_path2.join)(dir, relPath), "utf-8"));
|
|
1077
1154
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1155
|
+
if (personaFile) {
|
|
1156
|
+
if (isExternalPath(dir, personaFile)) {
|
|
1157
|
+
throw new Error(`E014: persona path '${personaFile}' in '${descriptionFile}' is absolute or escapes the agent root`);
|
|
1158
|
+
}
|
|
1159
|
+
let personaText;
|
|
1160
|
+
try {
|
|
1161
|
+
personaText = await (0, import_promises2.readFile)((0, import_path2.join)(dir, personaFile), "utf-8");
|
|
1162
|
+
} catch {
|
|
1163
|
+
throw new Error(`E_DESC: persona file '${personaFile}' declared in '${descriptionFile}' not found`);
|
|
1164
|
+
}
|
|
1165
|
+
files.set(personaFile, personaText);
|
|
1081
1166
|
}
|
|
1082
1167
|
await walk((0, import_path2.join)(dir, "guides"), "guides");
|
|
1083
1168
|
await walk((0, import_path2.join)(dir, "knowledge"), "knowledge");
|
|
1169
|
+
await initBehaviorParser();
|
|
1170
|
+
const behaviorAst = parseBehaviorFile(mergedBehaviorText).ok;
|
|
1171
|
+
if (behaviorAst) {
|
|
1172
|
+
const refs = /* @__PURE__ */ new Map();
|
|
1173
|
+
for (const state of behaviorAst.states) collectFileRefs(state.body, refs);
|
|
1174
|
+
for (const trigger of behaviorAst.global_triggers) collectFileRefs(trigger.body, refs);
|
|
1175
|
+
for (const { kind, text } of refs.values()) {
|
|
1176
|
+
if (isExternalPath(dir, text)) {
|
|
1177
|
+
throw new Error(`E014: '${kind}' path '${text}' is absolute or escapes the agent root`);
|
|
1178
|
+
}
|
|
1179
|
+
let content;
|
|
1180
|
+
try {
|
|
1181
|
+
content = await (0, import_promises2.readFile)((0, import_path2.join)(dir, text), "utf-8");
|
|
1182
|
+
} catch {
|
|
1183
|
+
throw new Error(`E018: '${kind}' file '${text}' referenced in agent.behavior not found in ${dir}`);
|
|
1184
|
+
}
|
|
1185
|
+
files.set(`${kind === "guide" ? "guides" : "knowledge"}/${text}`, content);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1084
1188
|
return files;
|
|
1085
1189
|
}
|
|
1190
|
+
function withAgentExtension(path) {
|
|
1191
|
+
return path.endsWith(".agent") ? path : `${path}.agent`;
|
|
1192
|
+
}
|
|
1086
1193
|
async function pack(options = {}) {
|
|
1087
1194
|
const dir = options.dir ?? process.cwd();
|
|
1088
|
-
const outPath = options.out ?? (0, import_path2.join)(dir,
|
|
1195
|
+
const outPath = withAgentExtension(options.out ?? (0, import_path2.join)(dir, (0, import_path2.basename)(dir)));
|
|
1089
1196
|
const descriptionFileName = await discoverDescriptionFile(dir, options.description);
|
|
1090
1197
|
const descriptionText = await (0, import_promises2.readFile)((0, import_path2.join)(dir, descriptionFileName), "utf-8");
|
|
1091
1198
|
const descriptionMessages = await lintDescription(descriptionText, descriptionFileName);
|
|
@@ -1120,13 +1227,13 @@ ${descErrors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`)
|
|
|
1120
1227
|
${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join("\n")}`
|
|
1121
1228
|
);
|
|
1122
1229
|
}
|
|
1123
|
-
const version = await
|
|
1230
|
+
const version = await resolveVersionInteractive(options.version);
|
|
1124
1231
|
const commit = await resolveCommit(options.commit);
|
|
1125
|
-
const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources);
|
|
1232
|
+
const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? void 0);
|
|
1126
1233
|
const contentForHash = Array.from(allFiles.values()).join("");
|
|
1127
1234
|
const sha256 = (0, import_crypto.createHash)("sha256").update(contentForHash).digest("hex");
|
|
1128
1235
|
const namespace = df.agent.domain ?? "unknown";
|
|
1129
|
-
const id = buildId({ namespace, name: df.agent.name, version, digest: commit });
|
|
1236
|
+
const id = buildId({ namespace, name: slugify(df.agent.name), version, digest: version ? commit : void 0 });
|
|
1130
1237
|
const typesJson = buildTypesJson(df);
|
|
1131
1238
|
const integrity = {
|
|
1132
1239
|
sha256,
|
|
@@ -1137,10 +1244,10 @@ ${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).joi
|
|
|
1137
1244
|
id,
|
|
1138
1245
|
name: df.agent.name,
|
|
1139
1246
|
description: df.description ?? "",
|
|
1140
|
-
version,
|
|
1247
|
+
version: version ?? "",
|
|
1141
1248
|
domain: df.agent.domain ?? "",
|
|
1142
1249
|
license: df.agent.license ?? "",
|
|
1143
|
-
persona: df.persona ??
|
|
1250
|
+
persona: df.persona ?? void 0,
|
|
1144
1251
|
purpose: "unknown",
|
|
1145
1252
|
compiler: `dot-agent/${COMPILER_VERSION}`,
|
|
1146
1253
|
commit,
|
|
@@ -1158,6 +1265,7 @@ ${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).joi
|
|
|
1158
1265
|
const filesJson = {
|
|
1159
1266
|
description: descriptionFileName,
|
|
1160
1267
|
behavior: "agent.behavior",
|
|
1268
|
+
...df.persona ? { persona: df.persona } : {},
|
|
1161
1269
|
behaviors: Array.from(allFiles.keys()).filter((f) => f.startsWith("behaviors/")),
|
|
1162
1270
|
guides: Array.from(allFiles.keys()).filter((f) => f.startsWith("guides/") && !gitkeepPaths.has(f)),
|
|
1163
1271
|
knowledge: Array.from(allFiles.keys()).filter((f) => f.startsWith("knowledge/") && !gitkeepPaths.has(f))
|
|
@@ -1211,9 +1319,9 @@ ${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).joi
|
|
|
1211
1319
|
process.stderr.write(`\x1B[33m\u26A0\x1B[0m ${w.file}:${w.line}:${w.col} ${w.code} ${w.message}
|
|
1212
1320
|
`);
|
|
1213
1321
|
}
|
|
1214
|
-
const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources);
|
|
1322
|
+
const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? void 0);
|
|
1215
1323
|
const sha256 = (0, import_crypto2.createHash)("sha256").update(Array.from(allFiles.values()).join("")).digest("hex");
|
|
1216
|
-
const id = buildId({ namespace: df.agent.domain ?? "
|
|
1324
|
+
const id = buildId({ namespace: df.agent.domain ?? "unknown", name: slugify(df.agent.name), version: "dev" });
|
|
1217
1325
|
const aboutme = buildAboutme({
|
|
1218
1326
|
id,
|
|
1219
1327
|
name: df.agent.name,
|
|
@@ -1221,7 +1329,7 @@ ${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).joi
|
|
|
1221
1329
|
version: "dev",
|
|
1222
1330
|
domain: df.agent.domain ?? "",
|
|
1223
1331
|
license: df.agent.license ?? "",
|
|
1224
|
-
persona: df.persona ??
|
|
1332
|
+
persona: df.persona ?? void 0,
|
|
1225
1333
|
purpose: "development",
|
|
1226
1334
|
compiler: `dot-agent/${COMPILER_VERSION}`,
|
|
1227
1335
|
capabilities: df.capabilities.map((c) => ({ id: c.name, description: c.description ?? "" })),
|
|
@@ -1234,7 +1342,7 @@ ${errors.map((e) => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).joi
|
|
|
1234
1342
|
// mergedText — it has redundant `merge "..."` lines stripped (see
|
|
1235
1343
|
// collectFiles() for why they're dead weight once flattened).
|
|
1236
1344
|
behavior: allFiles.get("agent.behavior") ?? mergedText,
|
|
1237
|
-
|
|
1345
|
+
persona: df.persona ? allFiles.get(df.persona) : void 0,
|
|
1238
1346
|
guides: Array.from(allFiles.entries()).filter(([p]) => p.startsWith("guides/") && !GITKEEP.has(p)).map(([path, content]) => ({ path, content })),
|
|
1239
1347
|
knowledge: Array.from(allFiles.entries()).filter(([p]) => p.startsWith("knowledge/") && !GITKEEP.has(p)).map(([path, content]) => ({ path, content })),
|
|
1240
1348
|
behaviors: Array.from(allFiles.entries()).filter(([p]) => p.startsWith("behaviors/")).map(([path, content]) => ({ path, content }))
|