@agent-native/core 0.37.0 → 0.37.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/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +72 -10
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +1 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/extensions/SkillReference.js +1 -1
- package/dist/client/composer/extensions/SkillReference.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +2 -2
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/resources/store.js +4 -4
- package/dist/resources/store.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +92 -56
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agents-bundle.d.ts +6 -4
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +20 -12
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/templates/default/AGENTS.md +10 -8
- package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
- package/dist/vite/agents-bundle-plugin.js +16 -6
- package/dist/vite/agents-bundle-plugin.js.map +1 -1
- package/docs/content/workspace.md +3 -3
- package/package.json +1 -1
- package/src/templates/default/AGENTS.md +10 -8
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agents bundle — loads AGENTS.md and .agents/skills/ from the template.
|
|
3
|
+
* The legacy singular .agent/skills/ directory is also accepted as an alias.
|
|
3
4
|
*
|
|
4
5
|
* This is the single source of truth the framework's agent uses to mirror what
|
|
5
6
|
* Claude Code / Codex / any other agent would see when running locally in the
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* framework's Vite plugin. This is the ONLY path that works on edge
|
|
13
14
|
* runtimes (Cloudflare Workers) where `readFileSync` doesn't exist.
|
|
14
15
|
* 2. Filesystem fallback — `process.cwd()/AGENTS.md` +
|
|
15
|
-
* `process.cwd()/.agents/skills
|
|
16
|
+
* `process.cwd()/.agents/skills/` (or legacy `.agent/skills/`). Only reliable in local dev and Node
|
|
16
17
|
* production (`agent-native start`); not on Netlify/Vercel/CF at runtime.
|
|
17
18
|
* 3. Empty bundle — everything silently returns empty strings.
|
|
18
19
|
*
|
|
@@ -100,9 +101,10 @@ export declare function loadAgentsBundle(): Promise<AgentsBundle>;
|
|
|
100
101
|
/**
|
|
101
102
|
* Generate the `<skills>` block to inject into the system prompt.
|
|
102
103
|
*
|
|
103
|
-
* Skills are folders at `.agents/skills/<name>/`
|
|
104
|
-
*
|
|
105
|
-
* images, scripts). This
|
|
104
|
+
* Skills are folders at `.agents/skills/<name>/` (or legacy
|
|
105
|
+
* `.agent/skills/<name>/`) containing a `SKILL.md` entry file plus any number
|
|
106
|
+
* of supporting files (additional markdown, examples, images, scripts). This
|
|
107
|
+
* block lists what's available and how to read them.
|
|
106
108
|
*
|
|
107
109
|
* In dev mode the agent has bash access and reads skills via `cat` — exactly
|
|
108
110
|
* like running `claude` locally in the repo. In production mode the agent has
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-bundle.d.ts","sourceRoot":"","sources":["../../src/server/agents-bundle.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents-bundle.d.ts","sourceRoot":"","sources":["../../src/server/agents-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA+CzE;AAUD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uDAAuD;IACvD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AA6DD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,eAAe,GAAE,qBAAqB,GAAG,IAAW,GACnD,YAAY,CA4Cd;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC,CA2C9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAsBtE;AAED,0CAA0C;AAC1C,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agents bundle — loads AGENTS.md and .agents/skills/ from the template.
|
|
3
|
+
* The legacy singular .agent/skills/ directory is also accepted as an alias.
|
|
3
4
|
*
|
|
4
5
|
* This is the single source of truth the framework's agent uses to mirror what
|
|
5
6
|
* Claude Code / Codex / any other agent would see when running locally in the
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* framework's Vite plugin. This is the ONLY path that works on edge
|
|
13
14
|
* runtimes (Cloudflare Workers) where `readFileSync` doesn't exist.
|
|
14
15
|
* 2. Filesystem fallback — `process.cwd()/AGENTS.md` +
|
|
15
|
-
* `process.cwd()/.agents/skills
|
|
16
|
+
* `process.cwd()/.agents/skills/` (or legacy `.agent/skills/`). Only reliable in local dev and Node
|
|
16
17
|
* production (`agent-native start`); not on Netlify/Vercel/CF at runtime.
|
|
17
18
|
* 3. Empty bundle — everything silently returns empty strings.
|
|
18
19
|
*
|
|
@@ -80,6 +81,10 @@ export function parseSkillFrontmatter(content) {
|
|
|
80
81
|
}
|
|
81
82
|
import fs from "node:fs";
|
|
82
83
|
import path from "node:path";
|
|
84
|
+
const TEMPLATE_SKILLS_DIRS = [
|
|
85
|
+
path.join(".agents", "skills"),
|
|
86
|
+
path.join(".agent", "skills"),
|
|
87
|
+
];
|
|
83
88
|
/**
|
|
84
89
|
* Read one skills directory into a `Record<string, Skill>`. Extracted so
|
|
85
90
|
* both the template and workspace-core paths can reuse it. `dirPrefix` is
|
|
@@ -168,13 +173,15 @@ export function readAgentsBundleFromFs(cwd, workspaceSource = null) {
|
|
|
168
173
|
}
|
|
169
174
|
// Merge skills: template first (so its entries are authoritative), then
|
|
170
175
|
// workspace-core with skipExistingNames=true so same-named skills don't
|
|
171
|
-
// overwrite the template's.
|
|
176
|
+
// overwrite the template's. `.agents/skills` is canonical; `.agent/skills`
|
|
177
|
+
// is accepted as a legacy alias and does not override canonical skills.
|
|
172
178
|
const skills = {};
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
179
|
+
for (const [index, relSkillsDir] of TEMPLATE_SKILLS_DIRS.entries()) {
|
|
180
|
+
try {
|
|
181
|
+
readSkillsDir(path.join(cwd, relSkillsDir), cwd, skills, index > 0);
|
|
182
|
+
}
|
|
183
|
+
catch { }
|
|
176
184
|
}
|
|
177
|
-
catch { }
|
|
178
185
|
if (workspaceSource?.skillsDir) {
|
|
179
186
|
try {
|
|
180
187
|
readSkillsDir(workspaceSource.skillsDir, workspaceSource.rootDir, skills, true);
|
|
@@ -238,9 +245,10 @@ export async function loadAgentsBundle() {
|
|
|
238
245
|
/**
|
|
239
246
|
* Generate the `<skills>` block to inject into the system prompt.
|
|
240
247
|
*
|
|
241
|
-
* Skills are folders at `.agents/skills/<name>/`
|
|
242
|
-
*
|
|
243
|
-
* images, scripts). This
|
|
248
|
+
* Skills are folders at `.agents/skills/<name>/` (or legacy
|
|
249
|
+
* `.agent/skills/<name>/`) containing a `SKILL.md` entry file plus any number
|
|
250
|
+
* of supporting files (additional markdown, examples, images, scripts). This
|
|
251
|
+
* block lists what's available and how to read them.
|
|
244
252
|
*
|
|
245
253
|
* In dev mode the agent has bash access and reads skills via `cat` — exactly
|
|
246
254
|
* like running `claude` locally in the repo. In production mode the agent has
|
|
@@ -258,11 +266,11 @@ export function generateSkillsPromptBlock(bundle) {
|
|
|
258
266
|
return `- \`${s.meta.name}\` at \`${s.dir}/\` — ${s.meta.description || "(no description)"}${extras}`;
|
|
259
267
|
});
|
|
260
268
|
return `<skills>
|
|
261
|
-
The following skills live in the repo at \`.agents/skills/<name
|
|
269
|
+
The following skills live in the repo, usually at \`.agents/skills/<name>/\` (legacy \`.agent/skills/<name>/\` is also supported). Each skill is a folder containing a \`SKILL.md\` entry file and sometimes supporting files. Read a skill BEFORE starting a task it applies to.
|
|
262
270
|
|
|
263
271
|
To read a skill in dev mode (when you have bash access):
|
|
264
|
-
\`bash(command="cat
|
|
265
|
-
\`bash(command="ls
|
|
272
|
+
\`bash(command="cat <skill-dir>/SKILL.md")\`
|
|
273
|
+
\`bash(command="ls <skill-dir>/")\` to see all files in the folder
|
|
266
274
|
|
|
267
275
|
Available skills:
|
|
268
276
|
${lines.join("\n")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-bundle.js","sourceRoot":"","sources":["../../src/server/agents-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA8CH,MAAM,KAAK,GAAiB,EAAE,QAAQ,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAEhF,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;QACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEhC,MAAM,QAAQ,GAAG,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;QACrD,MAAM,SAAS,GAAG,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;QAEtD,IAAI,KAAa,CAAC;QAClB,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC1B,kEAAkE;YAClE,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACf,CAAC,EAAE,CAAC;oBACJ,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,MAAM;gBAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;gBACrC,CAAC,EAAE,CAAC;YACN,CAAC;YACD,4BAA4B;YAC5B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;gBAAE,KAAK,CAAC,GAAG,EAAE,CAAC;YACvE,KAAK,GAAG,QAAQ;gBACd,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACzC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,OAAO,CAAC;QAClB,CAAC;QAED,IAAI,GAAG,KAAK,MAAM,IAAI,KAAK;YAAE,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;aAC5C,IAAI,GAAG,KAAK,aAAa,IAAI,KAAK;YAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;IACtE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B;;;;;;GAMG;AACH,SAAS,aAAa,CACpB,SAAiB,EACjB,eAAuB,EACvB,GAA0B,EAC1B,iBAA0B;IAE1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO;IACtC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;YAAE,SAAS;QAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;gBAAE,SAAS;YAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;YACrC,IAAI,iBAAiB,IAAI,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS,CAAC,gBAAgB;YAE9D,MAAM,UAAU,GAAa,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,MAAc,EAAE,EAAE;oBAC9C,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;wBAChE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;wBACtC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;wBACpD,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC;4BAC1C,IAAI,CAAC;gCACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gCAC9B,IAAI,IAAI,CAAC,WAAW,EAAE;oCAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;4BACzC,CAAC;4BAAC,MAAM,CAAC,CAAA,CAAC;wBACZ,CAAC;6BAAM,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;4BAC/C,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACvB,CAAC;oBACH,CAAC;gBACH,CAAC,CAAC;gBACF,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,UAAU,CAAC,IAAI,EAAE,CAAC;YAElB,GAAG,CAAC,IAAI,CAAC,GAAG;gBACV,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE;gBACnD,OAAO;gBACP,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;gBACpE,UAAU;aACX,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAW,EACX,kBAAgD,IAAI;IAEpD,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,eAAe,EAAE,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChD,iBAAiB,GAAG,EAAE,CAAC,YAAY,CACjC,eAAe,CAAC,YAAY,EAC5B,OAAO,CACR,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,wEAAwE;IACxE,wEAAwE;IACxE,4BAA4B;IAC5B,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtD,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,IAAI,eAAe,EAAE,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,aAAa,CACX,eAAe,CAAC,SAAS,EACzB,eAAe,CAAC,OAAO,EACvB,MAAM,EACN,IAAI,CACL,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,yEAAyE;IACzE,2EAA2E;IAC3E,sEAAsE;IACtE,uCAAuC;IACvC,IAAI,CAAC;QACH,qEAAqE;QACrE,oDAAoD;QACpD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClD,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,CAAC,OAAuB,CAAC;YACrC,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;IAED,yEAAyE;IACzE,wEAAwE;IACxE,IAAI,CAAC;QACH,IAAI,eAAe,GAAiC,IAAI,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,EAAE,uBAAuB,EAAE,GAC/B,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAG,MAAM,uBAAuB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACxD,IAAI,EAAE,EAAE,CAAC;gBACP,eAAe,GAAG;oBAChB,SAAS,EAAE,EAAE,CAAC,SAAS;oBACvB,YAAY,EAAE,EAAE,CAAC,YAAY;oBAC7B,OAAO,EAAE,EAAE,CAAC,UAAU;iBACvB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;QACD,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,KAAK,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAoB;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9B,MAAM,MAAM,GACV,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,oBAAoB,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAChD,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,kBAAkB,GAAG,MAAM,EAAE,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,OAAO;;;;;;;;EAQP,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;UACR,CAAC;AACX,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,wBAAwB;IACtC,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Agents bundle — loads AGENTS.md and .agents/skills/ from the template.\n *\n * This is the single source of truth the framework's agent uses to mirror what\n * Claude Code / Codex / any other agent would see when running locally in the\n * repo. The filesystem is the canonical source; this module is just a loader\n * that works both in dev (direct fs read) and production (content bundled at\n * build time via the `virtual:agents-bundle` Vite plugin).\n *\n * Resolution order inside `loadAgentsBundle()`:\n * 1. Virtual module (`virtual:agents-bundle`) — inlined at build time by the\n * framework's Vite plugin. This is the ONLY path that works on edge\n * runtimes (Cloudflare Workers) where `readFileSync` doesn't exist.\n * 2. Filesystem fallback — `process.cwd()/AGENTS.md` +\n * `process.cwd()/.agents/skills/`. Only reliable in local dev and Node\n * production (`agent-native start`); not on Netlify/Vercel/CF at runtime.\n * 3. Empty bundle — everything silently returns empty strings.\n *\n * Result is cached in module scope so it's only computed once per cold start.\n */\n\nexport interface SkillMeta {\n name: string;\n description: string;\n}\n\nexport interface Skill {\n meta: SkillMeta;\n /** Contents of SKILL.md (the entry file of the skill). */\n content: string;\n /**\n * Filesystem path to the skill directory, relative to the template root\n * (e.g. `.agents/skills/create-deck`). The agent can read any file here via\n * bash in dev — skills are folders, not single files, and may contain\n * supporting assets, scripts, or additional markdown.\n */\n dir: string;\n /**\n * Files inside the skill directory (relative to the skill dir), excluding\n * `SKILL.md`. Lets the agent know what else is available without a separate\n * `ls` call. Empty array if the skill is single-file.\n */\n extraFiles: string[];\n}\n\nexport interface AgentsBundle {\n /** Contents of the template's AGENTS.md (empty string if missing). */\n agentsMd: string;\n /**\n * Contents of the workspace core's AGENTS.md, if the app is inside an\n * enterprise monorepo with a `workspaceCore` configured. Empty string\n * otherwise. Sits between the framework system prompt and the template's\n * AGENTS.md in the instruction stack.\n */\n workspaceAgentsMd?: string;\n /**\n * Map from skill name → skill content. Contains skills merged from the\n * workspace core layer (if present) and the template layer. On name\n * collision, the template's version wins so apps can override a shared\n * enterprise skill by dropping a same-named file under\n * `.agents/skills/<name>/`.\n */\n skills: Record<string, Skill>;\n}\n\nconst EMPTY: AgentsBundle = { agentsMd: \"\", workspaceAgentsMd: \"\", skills: {} };\n\nlet cached: AgentsBundle | null = null;\n\n/**\n * Parse the YAML frontmatter at the top of a skill file.\n * Only pulls out `name` and `description` — deliberately simple, no YAML lib.\n * Handles:\n * - Inline: `description: Some text`\n * - Folded scalar: `description: >-\\n multi\\n line` → \"multi line\"\n * - Literal scalar: `description: |\\n multi\\n line` → \"multi\\nline\"\n */\nexport function parseSkillFrontmatter(content: string): Partial<SkillMeta> {\n const match = content.match(/^---\\r?\\n([\\s\\S]+?)\\r?\\n---/);\n if (!match) return {};\n const lines = match[1].split(/\\r?\\n/);\n const result: Partial<SkillMeta> = {};\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const keyMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\\s*(.*)$/);\n if (!keyMatch) continue;\n const [, key, valueRaw] = keyMatch;\n const trimmed = valueRaw.trim();\n\n const isFolded = trimmed === \">\" || trimmed === \">-\";\n const isLiteral = trimmed === \"|\" || trimmed === \"|-\";\n\n let value: string;\n if (isFolded || isLiteral) {\n // Collect subsequent indented lines (at least one leading space).\n const block: string[] = [];\n let j = i + 1;\n while (j < lines.length) {\n const next = lines[j];\n if (next.length === 0) {\n block.push(\"\");\n j++;\n continue;\n }\n if (!/^\\s/.test(next)) break;\n block.push(next.replace(/^\\s+/, \"\"));\n j++;\n }\n // Trim trailing blank lines\n while (block.length > 0 && block[block.length - 1] === \"\") block.pop();\n value = isFolded\n ? block.filter((l) => l !== \"\").join(\" \")\n : block.join(\"\\n\");\n i = j - 1;\n } else {\n value = trimmed;\n }\n\n if (key === \"name\" && value) result.name = value;\n else if (key === \"description\" && value) result.description = value;\n }\n\n return result;\n}\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Paths to a workspace-core's agent resources, for merging into a template's\n * bundle. All fields optional — pass null for any missing piece.\n */\nexport interface WorkspaceAgentsSource {\n /** Absolute path to the workspace core's skills/ directory. */\n skillsDir: string | null;\n /** Absolute path to the workspace core's AGENTS.md. */\n agentsMdPath: string | null;\n /** Root dir (used to compute `dir` paths for workspace-core skills). */\n rootDir: string;\n}\n\n/**\n * Read one skills directory into a `Record<string, Skill>`. Extracted so\n * both the template and workspace-core paths can reuse it. `dirPrefix` is\n * the display path that will be reported to the agent (e.g.\n * `.agents/skills/<name>` for templates, or\n * `<workspace-shared-package>/.agents/skills/<name>` for the workspace layer).\n */\nfunction readSkillsDir(\n skillsDir: string,\n rootForRelative: string,\n out: Record<string, Skill>,\n skipExistingNames: boolean,\n): void {\n if (!fs.existsSync(skillsDir)) return;\n const entries = fs.readdirSync(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const skillDirAbs = path.join(skillsDir, entry.name);\n const skillFile = path.join(skillDirAbs, \"SKILL.md\");\n try {\n const realSkillFile = fs.realpathSync(skillFile);\n if (!fs.existsSync(realSkillFile)) continue;\n const content = fs.readFileSync(realSkillFile, \"utf-8\");\n const meta = parseSkillFrontmatter(content);\n const name = meta.name ?? entry.name;\n if (skipExistingNames && out[name]) continue; // Template wins\n\n const extraFiles: string[] = [];\n try {\n const walk = (subdir: string, prefix: string) => {\n for (const e of fs.readdirSync(subdir, { withFileTypes: true })) {\n const abs = path.join(subdir, e.name);\n const rel = prefix ? `${prefix}/${e.name}` : e.name;\n if (e.isDirectory() || e.isSymbolicLink()) {\n try {\n const stat = fs.statSync(abs);\n if (stat.isDirectory()) walk(abs, rel);\n } catch {}\n } else if (e.isFile() && e.name !== \"SKILL.md\") {\n extraFiles.push(rel);\n }\n }\n };\n walk(skillDirAbs, \"\");\n } catch {}\n extraFiles.sort();\n\n out[name] = {\n meta: { name, description: meta.description ?? \"\" },\n content,\n dir: path.relative(rootForRelative, skillDirAbs).replace(/\\\\/g, \"/\"),\n extraFiles,\n };\n } catch {\n // Skip unreadable skills\n }\n }\n}\n\n/**\n * Read AGENTS.md + all skills directly from the filesystem rooted at `cwd`.\n * Optionally also reads a workspace-core's AGENTS.md and skills directory\n * and merges them in (template wins on name collisions). Used by both the\n * Vite plugin (at build time) and the runtime fallback (in dev / Node prod).\n *\n * Synchronous — the Vite plugin's load hook calls it inline during the build.\n */\nexport function readAgentsBundleFromFs(\n cwd: string,\n workspaceSource: WorkspaceAgentsSource | null = null,\n): AgentsBundle {\n let agentsMd = \"\";\n try {\n const agentsMdPath = path.join(cwd, \"AGENTS.md\");\n if (fs.existsSync(agentsMdPath)) {\n agentsMd = fs.readFileSync(agentsMdPath, \"utf-8\");\n }\n } catch {}\n\n let workspaceAgentsMd = \"\";\n if (workspaceSource?.agentsMdPath) {\n try {\n if (fs.existsSync(workspaceSource.agentsMdPath)) {\n workspaceAgentsMd = fs.readFileSync(\n workspaceSource.agentsMdPath,\n \"utf-8\",\n );\n }\n } catch {}\n }\n\n // Merge skills: template first (so its entries are authoritative), then\n // workspace-core with skipExistingNames=true so same-named skills don't\n // overwrite the template's.\n const skills: Record<string, Skill> = {};\n try {\n const skillsDir = path.join(cwd, \".agents\", \"skills\");\n readSkillsDir(skillsDir, cwd, skills, false);\n } catch {}\n\n if (workspaceSource?.skillsDir) {\n try {\n readSkillsDir(\n workspaceSource.skillsDir,\n workspaceSource.rootDir,\n skills,\n true,\n );\n } catch {}\n }\n\n return { agentsMd, workspaceAgentsMd, skills };\n}\n\n/**\n * Load the agents bundle. Returns a cached result on subsequent calls.\n * Tries the virtual module first (works everywhere, including edge), then\n * falls back to filesystem reads from `process.cwd()` — which, when a\n * workspace core is present, also merges in the workspace core's skills\n * and AGENTS.md.\n */\nexport async function loadAgentsBundle(): Promise<AgentsBundle> {\n if (cached) return cached;\n\n // 1. Try the Vite-emitted virtual module. This is the path that works on\n // every deployment target because the content is inlined at build time.\n // The Vite plugin itself is responsible for merging workspace-core\n // content into the bundle it emits.\n try {\n // @ts-expect-error — virtual module is resolved at build time by our\n // Vite plugin; nothing exists at this path on disk.\n const mod = await import(\"virtual:agents-bundle\");\n if (mod && mod.default) {\n cached = mod.default as AgentsBundle;\n return cached;\n }\n } catch {\n // Virtual module not available — fall through to filesystem.\n }\n\n // 2. Filesystem fallback — works in dev / Node prod. If a workspace core\n // is present in the ancestor chain, merge its skills + AGENTS.md in.\n try {\n let workspaceSource: WorkspaceAgentsSource | null = null;\n try {\n const { getWorkspaceCoreExports } =\n await import(\"../deploy/workspace-core.js\");\n const ws = await getWorkspaceCoreExports(process.cwd());\n if (ws) {\n workspaceSource = {\n skillsDir: ws.skillsDir,\n agentsMdPath: ws.agentsMdPath,\n rootDir: ws.packageDir,\n };\n }\n } catch {\n // workspace-core discovery isn't available (e.g. edge runtime).\n }\n cached = readAgentsBundleFromFs(process.cwd(), workspaceSource);\n return cached;\n } catch {\n cached = EMPTY;\n return cached;\n }\n}\n\n/**\n * Generate the `<skills>` block to inject into the system prompt.\n *\n * Skills are folders at `.agents/skills/<name>/` containing a `SKILL.md` entry\n * file plus any number of supporting files (additional markdown, examples,\n * images, scripts). This block lists what's available and how to read them.\n *\n * In dev mode the agent has bash access and reads skills via `cat` — exactly\n * like running `claude` locally in the repo. In production mode the agent has\n * no bash; templates that need skill content at runtime should inline the\n * critical parts directly in `AGENTS.md`.\n */\nexport function generateSkillsPromptBlock(bundle: AgentsBundle): string {\n const entries = Object.values(bundle.skills);\n if (entries.length === 0) return \"\";\n\n const lines = entries.map((s) => {\n const extras =\n s.extraFiles.length > 0\n ? ` (also contains: ${s.extraFiles.join(\", \")})`\n : \"\";\n return `- \\`${s.meta.name}\\` at \\`${s.dir}/\\` — ${s.meta.description || \"(no description)\"}${extras}`;\n });\n\n return `<skills>\nThe following skills live in the repo at \\`.agents/skills/<name>/\\`. Each skill is a folder containing a \\`SKILL.md\\` entry file and sometimes supporting files. Read a skill BEFORE starting a task it applies to.\n\nTo read a skill in dev mode (when you have bash access):\n \\`bash(command=\"cat .agents/skills/<name>/SKILL.md\")\\`\n \\`bash(command=\"ls .agents/skills/<name>/\")\\` to see all files in the folder\n\nAvailable skills:\n${lines.join(\"\\n\")}\n</skills>`;\n}\n\n/** For tests — reset the module cache. */\nexport function __resetAgentsBundleCache(): void {\n cached = null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agents-bundle.js","sourceRoot":"","sources":["../../src/server/agents-bundle.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agents bundle — loads AGENTS.md and .agents/skills/ from the template.\n * The legacy singular .agent/skills/ directory is also accepted as an alias.\n *\n * This is the single source of truth the framework's agent uses to mirror what\n * Claude Code / Codex / any other agent would see when running locally in the\n * repo. The filesystem is the canonical source; this module is just a loader\n * that works both in dev (direct fs read) and production (content bundled at\n * build time via the `virtual:agents-bundle` Vite plugin).\n *\n * Resolution order inside `loadAgentsBundle()`:\n * 1. Virtual module (`virtual:agents-bundle`) — inlined at build time by the\n * framework's Vite plugin. This is the ONLY path that works on edge\n * runtimes (Cloudflare Workers) where `readFileSync` doesn't exist.\n * 2. Filesystem fallback — `process.cwd()/AGENTS.md` +\n * `process.cwd()/.agents/skills/` (or legacy `.agent/skills/`). Only reliable in local dev and Node\n * production (`agent-native start`); not on Netlify/Vercel/CF at runtime.\n * 3. Empty bundle — everything silently returns empty strings.\n *\n * Result is cached in module scope so it's only computed once per cold start.\n */\n\nexport interface SkillMeta {\n name: string;\n description: string;\n}\n\nexport interface Skill {\n meta: SkillMeta;\n /** Contents of SKILL.md (the entry file of the skill). */\n content: string;\n /**\n * Filesystem path to the skill directory, relative to the template root\n * (e.g. `.agents/skills/create-deck`). The agent can read any file here via\n * bash in dev — skills are folders, not single files, and may contain\n * supporting assets, scripts, or additional markdown.\n */\n dir: string;\n /**\n * Files inside the skill directory (relative to the skill dir), excluding\n * `SKILL.md`. Lets the agent know what else is available without a separate\n * `ls` call. Empty array if the skill is single-file.\n */\n extraFiles: string[];\n}\n\nexport interface AgentsBundle {\n /** Contents of the template's AGENTS.md (empty string if missing). */\n agentsMd: string;\n /**\n * Contents of the workspace core's AGENTS.md, if the app is inside an\n * enterprise monorepo with a `workspaceCore` configured. Empty string\n * otherwise. Sits between the framework system prompt and the template's\n * AGENTS.md in the instruction stack.\n */\n workspaceAgentsMd?: string;\n /**\n * Map from skill name → skill content. Contains skills merged from the\n * workspace core layer (if present) and the template layer. On name\n * collision, the template's version wins so apps can override a shared\n * enterprise skill by dropping a same-named file under\n * `.agents/skills/<name>/`.\n */\n skills: Record<string, Skill>;\n}\n\nconst EMPTY: AgentsBundle = { agentsMd: \"\", workspaceAgentsMd: \"\", skills: {} };\n\nlet cached: AgentsBundle | null = null;\n\n/**\n * Parse the YAML frontmatter at the top of a skill file.\n * Only pulls out `name` and `description` — deliberately simple, no YAML lib.\n * Handles:\n * - Inline: `description: Some text`\n * - Folded scalar: `description: >-\\n multi\\n line` → \"multi line\"\n * - Literal scalar: `description: |\\n multi\\n line` → \"multi\\nline\"\n */\nexport function parseSkillFrontmatter(content: string): Partial<SkillMeta> {\n const match = content.match(/^---\\r?\\n([\\s\\S]+?)\\r?\\n---/);\n if (!match) return {};\n const lines = match[1].split(/\\r?\\n/);\n const result: Partial<SkillMeta> = {};\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const keyMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\\s*(.*)$/);\n if (!keyMatch) continue;\n const [, key, valueRaw] = keyMatch;\n const trimmed = valueRaw.trim();\n\n const isFolded = trimmed === \">\" || trimmed === \">-\";\n const isLiteral = trimmed === \"|\" || trimmed === \"|-\";\n\n let value: string;\n if (isFolded || isLiteral) {\n // Collect subsequent indented lines (at least one leading space).\n const block: string[] = [];\n let j = i + 1;\n while (j < lines.length) {\n const next = lines[j];\n if (next.length === 0) {\n block.push(\"\");\n j++;\n continue;\n }\n if (!/^\\s/.test(next)) break;\n block.push(next.replace(/^\\s+/, \"\"));\n j++;\n }\n // Trim trailing blank lines\n while (block.length > 0 && block[block.length - 1] === \"\") block.pop();\n value = isFolded\n ? block.filter((l) => l !== \"\").join(\" \")\n : block.join(\"\\n\");\n i = j - 1;\n } else {\n value = trimmed;\n }\n\n if (key === \"name\" && value) result.name = value;\n else if (key === \"description\" && value) result.description = value;\n }\n\n return result;\n}\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst TEMPLATE_SKILLS_DIRS = [\n path.join(\".agents\", \"skills\"),\n path.join(\".agent\", \"skills\"),\n] as const;\n\n/**\n * Paths to a workspace-core's agent resources, for merging into a template's\n * bundle. All fields optional — pass null for any missing piece.\n */\nexport interface WorkspaceAgentsSource {\n /** Absolute path to the workspace core's skills/ directory. */\n skillsDir: string | null;\n /** Absolute path to the workspace core's AGENTS.md. */\n agentsMdPath: string | null;\n /** Root dir (used to compute `dir` paths for workspace-core skills). */\n rootDir: string;\n}\n\n/**\n * Read one skills directory into a `Record<string, Skill>`. Extracted so\n * both the template and workspace-core paths can reuse it. `dirPrefix` is\n * the display path that will be reported to the agent (e.g.\n * `.agents/skills/<name>` for templates, or\n * `<workspace-shared-package>/.agents/skills/<name>` for the workspace layer).\n */\nfunction readSkillsDir(\n skillsDir: string,\n rootForRelative: string,\n out: Record<string, Skill>,\n skipExistingNames: boolean,\n): void {\n if (!fs.existsSync(skillsDir)) return;\n const entries = fs.readdirSync(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const skillDirAbs = path.join(skillsDir, entry.name);\n const skillFile = path.join(skillDirAbs, \"SKILL.md\");\n try {\n const realSkillFile = fs.realpathSync(skillFile);\n if (!fs.existsSync(realSkillFile)) continue;\n const content = fs.readFileSync(realSkillFile, \"utf-8\");\n const meta = parseSkillFrontmatter(content);\n const name = meta.name ?? entry.name;\n if (skipExistingNames && out[name]) continue; // Template wins\n\n const extraFiles: string[] = [];\n try {\n const walk = (subdir: string, prefix: string) => {\n for (const e of fs.readdirSync(subdir, { withFileTypes: true })) {\n const abs = path.join(subdir, e.name);\n const rel = prefix ? `${prefix}/${e.name}` : e.name;\n if (e.isDirectory() || e.isSymbolicLink()) {\n try {\n const stat = fs.statSync(abs);\n if (stat.isDirectory()) walk(abs, rel);\n } catch {}\n } else if (e.isFile() && e.name !== \"SKILL.md\") {\n extraFiles.push(rel);\n }\n }\n };\n walk(skillDirAbs, \"\");\n } catch {}\n extraFiles.sort();\n\n out[name] = {\n meta: { name, description: meta.description ?? \"\" },\n content,\n dir: path.relative(rootForRelative, skillDirAbs).replace(/\\\\/g, \"/\"),\n extraFiles,\n };\n } catch {\n // Skip unreadable skills\n }\n }\n}\n\n/**\n * Read AGENTS.md + all skills directly from the filesystem rooted at `cwd`.\n * Optionally also reads a workspace-core's AGENTS.md and skills directory\n * and merges them in (template wins on name collisions). Used by both the\n * Vite plugin (at build time) and the runtime fallback (in dev / Node prod).\n *\n * Synchronous — the Vite plugin's load hook calls it inline during the build.\n */\nexport function readAgentsBundleFromFs(\n cwd: string,\n workspaceSource: WorkspaceAgentsSource | null = null,\n): AgentsBundle {\n let agentsMd = \"\";\n try {\n const agentsMdPath = path.join(cwd, \"AGENTS.md\");\n if (fs.existsSync(agentsMdPath)) {\n agentsMd = fs.readFileSync(agentsMdPath, \"utf-8\");\n }\n } catch {}\n\n let workspaceAgentsMd = \"\";\n if (workspaceSource?.agentsMdPath) {\n try {\n if (fs.existsSync(workspaceSource.agentsMdPath)) {\n workspaceAgentsMd = fs.readFileSync(\n workspaceSource.agentsMdPath,\n \"utf-8\",\n );\n }\n } catch {}\n }\n\n // Merge skills: template first (so its entries are authoritative), then\n // workspace-core with skipExistingNames=true so same-named skills don't\n // overwrite the template's. `.agents/skills` is canonical; `.agent/skills`\n // is accepted as a legacy alias and does not override canonical skills.\n const skills: Record<string, Skill> = {};\n for (const [index, relSkillsDir] of TEMPLATE_SKILLS_DIRS.entries()) {\n try {\n readSkillsDir(path.join(cwd, relSkillsDir), cwd, skills, index > 0);\n } catch {}\n }\n\n if (workspaceSource?.skillsDir) {\n try {\n readSkillsDir(\n workspaceSource.skillsDir,\n workspaceSource.rootDir,\n skills,\n true,\n );\n } catch {}\n }\n\n return { agentsMd, workspaceAgentsMd, skills };\n}\n\n/**\n * Load the agents bundle. Returns a cached result on subsequent calls.\n * Tries the virtual module first (works everywhere, including edge), then\n * falls back to filesystem reads from `process.cwd()` — which, when a\n * workspace core is present, also merges in the workspace core's skills\n * and AGENTS.md.\n */\nexport async function loadAgentsBundle(): Promise<AgentsBundle> {\n if (cached) return cached;\n\n // 1. Try the Vite-emitted virtual module. This is the path that works on\n // every deployment target because the content is inlined at build time.\n // The Vite plugin itself is responsible for merging workspace-core\n // content into the bundle it emits.\n try {\n // @ts-expect-error — virtual module is resolved at build time by our\n // Vite plugin; nothing exists at this path on disk.\n const mod = await import(\"virtual:agents-bundle\");\n if (mod && mod.default) {\n cached = mod.default as AgentsBundle;\n return cached;\n }\n } catch {\n // Virtual module not available — fall through to filesystem.\n }\n\n // 2. Filesystem fallback — works in dev / Node prod. If a workspace core\n // is present in the ancestor chain, merge its skills + AGENTS.md in.\n try {\n let workspaceSource: WorkspaceAgentsSource | null = null;\n try {\n const { getWorkspaceCoreExports } =\n await import(\"../deploy/workspace-core.js\");\n const ws = await getWorkspaceCoreExports(process.cwd());\n if (ws) {\n workspaceSource = {\n skillsDir: ws.skillsDir,\n agentsMdPath: ws.agentsMdPath,\n rootDir: ws.packageDir,\n };\n }\n } catch {\n // workspace-core discovery isn't available (e.g. edge runtime).\n }\n cached = readAgentsBundleFromFs(process.cwd(), workspaceSource);\n return cached;\n } catch {\n cached = EMPTY;\n return cached;\n }\n}\n\n/**\n * Generate the `<skills>` block to inject into the system prompt.\n *\n * Skills are folders at `.agents/skills/<name>/` (or legacy\n * `.agent/skills/<name>/`) containing a `SKILL.md` entry file plus any number\n * of supporting files (additional markdown, examples, images, scripts). This\n * block lists what's available and how to read them.\n *\n * In dev mode the agent has bash access and reads skills via `cat` — exactly\n * like running `claude` locally in the repo. In production mode the agent has\n * no bash; templates that need skill content at runtime should inline the\n * critical parts directly in `AGENTS.md`.\n */\nexport function generateSkillsPromptBlock(bundle: AgentsBundle): string {\n const entries = Object.values(bundle.skills);\n if (entries.length === 0) return \"\";\n\n const lines = entries.map((s) => {\n const extras =\n s.extraFiles.length > 0\n ? ` (also contains: ${s.extraFiles.join(\", \")})`\n : \"\";\n return `- \\`${s.meta.name}\\` at \\`${s.dir}/\\` — ${s.meta.description || \"(no description)\"}${extras}`;\n });\n\n return `<skills>\nThe following skills live in the repo, usually at \\`.agents/skills/<name>/\\` (legacy \\`.agent/skills/<name>/\\` is also supported). Each skill is a folder containing a \\`SKILL.md\\` entry file and sometimes supporting files. Read a skill BEFORE starting a task it applies to.\n\nTo read a skill in dev mode (when you have bash access):\n \\`bash(command=\"cat <skill-dir>/SKILL.md\")\\`\n \\`bash(command=\"ls <skill-dir>/\")\\` to see all files in the folder\n\nAvailable skills:\n${lines.join(\"\\n\")}\n</skills>`;\n}\n\n/** For tests — reset the module cache. */\nexport function __resetAgentsBundleCache(): void {\n cached = null;\n}\n"]}
|
|
@@ -37,14 +37,16 @@ Resources are SQL-backed persistent files for notes, learnings, and context.
|
|
|
37
37
|
1. **`AGENTS.md`** -- inherited workspace defaults, app/team instructions, and user-specific context.
|
|
38
38
|
2. **`LEARNINGS.md`** -- user preferences, corrections, and patterns. Read personal and shared scopes.
|
|
39
39
|
|
|
40
|
-
**Update `LEARNINGS.md` when you learn something important.**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
40
|
+
**Update `LEARNINGS.md` when you learn something important.** Built-in app
|
|
41
|
+
chat agents use the `resources` tool with the `action` argument. External CLI
|
|
42
|
+
agents can use the equivalent `pnpm action resource-*` commands.
|
|
43
|
+
|
|
44
|
+
| Built-in agent tool call | CLI equivalent | Purpose |
|
|
45
|
+
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------- |
|
|
46
|
+
| `resources` with `action: "read"`, `path`, optional `scope` | `pnpm action resource-read --path <path> [--scope personal\|shared]` | Read a resource |
|
|
47
|
+
| `resources` with `action: "write"`, `path`, `content`, optional `scope` | `pnpm action resource-write --path <path> --content <text> [--scope personal\|shared]` | Write/update a resource |
|
|
48
|
+
| `resources` with `action: "list"`, optional `prefix`/`scope` | `pnpm action resource-list [--prefix <path>] [--scope personal\|shared\|all]` | List resources |
|
|
49
|
+
| `resources` with `action: "delete"`, `path`, optional `scope` | `pnpm action resource-delete --path <path> [--scope personal\|shared]` | Delete a resource |
|
|
48
50
|
|
|
49
51
|
## Application State
|
|
50
52
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-bundle-plugin.d.ts","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents-bundle-plugin.d.ts","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AA4CnC,wBAAgB,kBAAkB,IAAI,MAAM,CAiG3C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vite plugin that resolves `virtual:agents-bundle` to a statically-inlined
|
|
3
3
|
* ES module containing the template's AGENTS.md + .agents/skills/ content.
|
|
4
|
+
* The legacy singular .agent/skills/ directory is also watched as an alias.
|
|
4
5
|
*
|
|
5
6
|
* This is how the framework's agent gets its instructions and skills into the
|
|
6
7
|
* system prompt on EVERY deployment target — Node, Netlify Functions, Vercel
|
|
@@ -17,6 +18,10 @@ import { readAgentsBundleFromFs, } from "../server/agents-bundle.js";
|
|
|
17
18
|
import { getWorkspaceCoreExports } from "../deploy/workspace-core.js";
|
|
18
19
|
const VIRTUAL_ID = "virtual:agents-bundle";
|
|
19
20
|
const RESOLVED_ID = "\0" + VIRTUAL_ID;
|
|
21
|
+
const TEMPLATE_SKILLS_DIRS = [
|
|
22
|
+
path.join(".agents", "skills"),
|
|
23
|
+
path.join(".agent", "skills"),
|
|
24
|
+
];
|
|
20
25
|
async function emitBundleModule(projectRoot) {
|
|
21
26
|
// If the project is inside an enterprise monorepo with a workspace core,
|
|
22
27
|
// merge in its AGENTS.md + skills. Template skills override workspace
|
|
@@ -90,9 +95,12 @@ export function agentsBundlePlugin() {
|
|
|
90
95
|
if (!rel.startsWith("..")) {
|
|
91
96
|
if (rel === "AGENTS.md")
|
|
92
97
|
return true;
|
|
93
|
-
if (rel.
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
if (rel.endsWith("SKILL.md")) {
|
|
99
|
+
for (const skillsDir of TEMPLATE_SKILLS_DIRS) {
|
|
100
|
+
if (rel.startsWith(skillsDir + path.sep))
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
96
104
|
}
|
|
97
105
|
// Workspace-core files
|
|
98
106
|
if (workspaceAgentsMdPath && file === workspaceAgentsMdPath) {
|
|
@@ -117,11 +125,13 @@ export function agentsBundlePlugin() {
|
|
|
117
125
|
// Explicitly add template + workspace-core paths to the watcher so
|
|
118
126
|
// edits outside the normal Vite watch set still trigger invalidation.
|
|
119
127
|
const agentsMdPath = path.join(projectRoot, "AGENTS.md");
|
|
120
|
-
const
|
|
128
|
+
const skillsDirs = TEMPLATE_SKILLS_DIRS.map((rel) => path.join(projectRoot, rel));
|
|
121
129
|
if (fs.existsSync(agentsMdPath))
|
|
122
130
|
watcher.add(agentsMdPath);
|
|
123
|
-
|
|
124
|
-
|
|
131
|
+
for (const skillsDir of skillsDirs) {
|
|
132
|
+
if (fs.existsSync(skillsDir))
|
|
133
|
+
watcher.add(skillsDir);
|
|
134
|
+
}
|
|
125
135
|
if (workspaceAgentsMdPath && fs.existsSync(workspaceAgentsMdPath)) {
|
|
126
136
|
watcher.add(workspaceAgentsMdPath);
|
|
127
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-bundle-plugin.js","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents-bundle-plugin.js","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Vite plugin that resolves `virtual:agents-bundle` to a statically-inlined\n * ES module containing the template's AGENTS.md + .agents/skills/ content.\n * The legacy singular .agent/skills/ directory is also watched as an alias.\n *\n * This is how the framework's agent gets its instructions and skills into the\n * system prompt on EVERY deployment target — Node, Netlify Functions, Vercel\n * serverless, and Cloudflare Workers. The content is baked into the server\n * bundle at build time, so nothing needs to exist on the runtime filesystem.\n *\n * In dev mode, the plugin re-reads from disk on each import and triggers HMR\n * when any AGENTS.md or SKILL.md file changes, so edits show up instantly\n * without restarting the server.\n */\nimport path from \"path\";\nimport fs from \"fs\";\nimport type { Plugin } from \"vite\";\nimport {\n readAgentsBundleFromFs,\n type WorkspaceAgentsSource,\n} from \"../server/agents-bundle.js\";\nimport { getWorkspaceCoreExports } from \"../deploy/workspace-core.js\";\n\nconst VIRTUAL_ID = \"virtual:agents-bundle\";\nconst RESOLVED_ID = \"\\0\" + VIRTUAL_ID;\nconst TEMPLATE_SKILLS_DIRS = [\n path.join(\".agents\", \"skills\"),\n path.join(\".agent\", \"skills\"),\n] as const;\n\nasync function emitBundleModule(projectRoot: string): Promise<string> {\n // If the project is inside an enterprise monorepo with a workspace core,\n // merge in its AGENTS.md + skills. Template skills override workspace\n // core skills on name collision.\n let workspaceSource: WorkspaceAgentsSource | null = null;\n try {\n const ws = await getWorkspaceCoreExports(projectRoot);\n if (ws) {\n workspaceSource = {\n skillsDir: ws.skillsDir,\n agentsMdPath: ws.agentsMdPath,\n rootDir: ws.packageDir,\n };\n }\n } catch {\n // fall back to template-only\n }\n\n const bundle = readAgentsBundleFromFs(projectRoot, workspaceSource);\n // Serialize as JSON and wrap in `export default` — this produces a valid\n // ES module that any bundler (Rollup, esbuild, Rolldown) can statically\n // analyze and tree-shake if nothing imports it.\n return `// AUTO-GENERATED by @agent-native/core/vite/agents-bundle-plugin\n// Contains the inlined AGENTS.md + .agents/skills/ content from the template,\n// merged with any workspace AGENTS.md + .agents/skills/ when present.\nconst bundle = ${JSON.stringify(bundle)};\nexport default bundle;\n`;\n}\n\nexport function agentsBundlePlugin(): Plugin {\n let projectRoot = \"\";\n\n return {\n name: \"agent-native-agents-bundle\",\n\n configResolved(config) {\n projectRoot = config.root;\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ID) return RESOLVED_ID;\n return null;\n },\n\n async load(id) {\n if (id !== RESOLVED_ID) return null;\n if (!projectRoot) projectRoot = process.cwd();\n return await emitBundleModule(projectRoot);\n },\n\n async configureServer(server) {\n // Watch AGENTS.md + any SKILL.md changes and invalidate the virtual\n // module so the next request picks up fresh content. Also watches\n // the workspace core's AGENTS.md + skills directory (if present)\n // so edits to the enterprise mid-layer propagate to every app.\n const watcher = server.watcher;\n\n // Resolve the workspace core up front so we can tell which files\n // outside projectRoot should trigger invalidation.\n let workspaceAgentsMdPath: string | null = null;\n let workspaceSkillsDir: string | null = null;\n try {\n const ws = await getWorkspaceCoreExports(projectRoot);\n if (ws) {\n workspaceAgentsMdPath = ws.agentsMdPath;\n workspaceSkillsDir = ws.skillsDir;\n }\n } catch {\n // ignore\n }\n\n const shouldInvalidate = (file: string): boolean => {\n const rel = path.relative(projectRoot, file);\n if (!rel.startsWith(\"..\")) {\n if (rel === \"AGENTS.md\") return true;\n if (rel.endsWith(\"SKILL.md\")) {\n for (const skillsDir of TEMPLATE_SKILLS_DIRS) {\n if (rel.startsWith(skillsDir + path.sep)) return true;\n }\n }\n }\n // Workspace-core files\n if (workspaceAgentsMdPath && file === workspaceAgentsMdPath) {\n return true;\n }\n if (\n workspaceSkillsDir &&\n file.startsWith(workspaceSkillsDir + path.sep) &&\n file.endsWith(\"SKILL.md\")\n ) {\n return true;\n }\n return false;\n };\n\n const invalidate = (file: string) => {\n if (!shouldInvalidate(file)) return;\n const mod = server.moduleGraph.getModuleById(RESOLVED_ID);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\" });\n }\n };\n\n // Explicitly add template + workspace-core paths to the watcher so\n // edits outside the normal Vite watch set still trigger invalidation.\n const agentsMdPath = path.join(projectRoot, \"AGENTS.md\");\n const skillsDirs = TEMPLATE_SKILLS_DIRS.map((rel) =>\n path.join(projectRoot, rel),\n );\n if (fs.existsSync(agentsMdPath)) watcher.add(agentsMdPath);\n for (const skillsDir of skillsDirs) {\n if (fs.existsSync(skillsDir)) watcher.add(skillsDir);\n }\n if (workspaceAgentsMdPath && fs.existsSync(workspaceAgentsMdPath)) {\n watcher.add(workspaceAgentsMdPath);\n }\n if (workspaceSkillsDir && fs.existsSync(workspaceSkillsDir)) {\n watcher.add(workspaceSkillsDir);\n }\n\n watcher.on(\"change\", invalidate);\n watcher.on(\"add\", invalidate);\n watcher.on(\"unlink\", invalidate);\n },\n };\n}\n"]}
|
|
@@ -139,7 +139,7 @@ Change how the agent behaves, in 60 seconds.
|
|
|
139
139
|
|
|
140
140
|
## How the Agent Uses Resources {#how-the-agent-uses-resources}
|
|
141
141
|
|
|
142
|
-
The
|
|
142
|
+
The built-in app agent manages resources with the unified `resources` tool: use `action: "list"`, `"read"`, `"effective"`, `"write"`, `"promote"`, or `"delete"`. External CLI/code agents can use the equivalent `pnpm action resource-*` commands.
|
|
143
143
|
|
|
144
144
|
At the start of every conversation, the agent automatically reads:
|
|
145
145
|
|
|
@@ -182,7 +182,7 @@ Both normal chat and integration-triggered agent runs load these instruction res
|
|
|
182
182
|
|
|
183
183
|
### Reference Resources {#reference-resources}
|
|
184
184
|
|
|
185
|
-
Put reusable company context under `context/`: personas, positioning, messaging, product facts, customer proof points, brand guidelines, competitive notes, and similar material. The agent sees an index of workspace and shared reference resources and reads the relevant file with `
|
|
185
|
+
Put reusable company context under `context/`: personas, positioning, messaging, product facts, customer proof points, brand guidelines, competitive notes, and similar material. The agent sees an index of workspace and shared reference resources and reads the relevant file with the `resources` tool (`action: "read"`) when a task may depend on it. Use `resources` with `action: "effective"` and `path: "context/brand.md"` when you need to see whether a workspace default is overridden by an organization/app or personal resource.
|
|
186
186
|
|
|
187
187
|
Examples:
|
|
188
188
|
|
|
@@ -440,7 +440,7 @@ What shows up depends on the mode:
|
|
|
440
440
|
|
|
441
441
|
## / Slash Commands {#slash-commands}
|
|
442
442
|
|
|
443
|
-
Type `/` at the start of a line to invoke a skill. A dropdown shows available skills with their names and descriptions. Selecting a skill adds it as an inline chip, and its content is included as context when the message is sent.
|
|
443
|
+
Type `/` at the start of a line to invoke a skill. A dropdown shows available skills with their names and descriptions. Selecting a skill adds it as an inline chip, and its content is included as context when the message is sent when the backend can resolve it; otherwise the agent receives the exact skill path and reads it with the appropriate resource or file tool.
|
|
444
444
|
|
|
445
445
|
What shows up depends on the mode:
|
|
446
446
|
|
package/package.json
CHANGED
|
@@ -37,14 +37,16 @@ Resources are SQL-backed persistent files for notes, learnings, and context.
|
|
|
37
37
|
1. **`AGENTS.md`** -- inherited workspace defaults, app/team instructions, and user-specific context.
|
|
38
38
|
2. **`LEARNINGS.md`** -- user preferences, corrections, and patterns. Read personal and shared scopes.
|
|
39
39
|
|
|
40
|
-
**Update `LEARNINGS.md` when you learn something important.**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
40
|
+
**Update `LEARNINGS.md` when you learn something important.** Built-in app
|
|
41
|
+
chat agents use the `resources` tool with the `action` argument. External CLI
|
|
42
|
+
agents can use the equivalent `pnpm action resource-*` commands.
|
|
43
|
+
|
|
44
|
+
| Built-in agent tool call | CLI equivalent | Purpose |
|
|
45
|
+
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------- |
|
|
46
|
+
| `resources` with `action: "read"`, `path`, optional `scope` | `pnpm action resource-read --path <path> [--scope personal\|shared]` | Read a resource |
|
|
47
|
+
| `resources` with `action: "write"`, `path`, `content`, optional `scope` | `pnpm action resource-write --path <path> --content <text> [--scope personal\|shared]` | Write/update a resource |
|
|
48
|
+
| `resources` with `action: "list"`, optional `prefix`/`scope` | `pnpm action resource-list [--prefix <path>] [--scope personal\|shared\|all]` | List resources |
|
|
49
|
+
| `resources` with `action: "delete"`, `path`, optional `scope` | `pnpm action resource-delete --path <path> [--scope personal\|shared]` | Delete a resource |
|
|
48
50
|
|
|
49
51
|
## Application State
|
|
50
52
|
|