@archon-claw/cli 0.5.0 → 0.6.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.
Files changed (28) hide show
  1. package/dist/public/assets/{chat-input-D-F2IIDK.js → chat-input-BNct1ILJ.js} +34 -34
  2. package/dist/public/assets/{embed-XPDwGdtM.js → embed-D4R7hpA_.js} +1 -1
  3. package/dist/public/assets/{main-DDb5hJ5F.js → main-C4meEBxF.js} +2 -2
  4. package/dist/public/embed.html +3 -3
  5. package/dist/public/index.html +3 -3
  6. package/dist/server.d.ts +5 -1
  7. package/dist/server.js +57 -12
  8. package/package.json +5 -3
  9. package/dist/scaffold.d.ts +0 -7
  10. package/dist/scaffold.js +0 -115
  11. package/dist/templates/agent/model.json +0 -6
  12. package/dist/templates/agent/system-prompt.md +0 -9
  13. package/dist/templates/agent/tool-impls/greeting.impl.js +0 -9
  14. package/dist/templates/agent/tools/greeting.json +0 -14
  15. package/dist/templates/workspace/.claude/skills/create-agent/SKILL.md +0 -90
  16. package/dist/templates/workspace/.claude/skills/create-dataset/SKILL.md +0 -57
  17. package/dist/templates/workspace/.claude/skills/create-eval-case/SKILL.md +0 -159
  18. package/dist/templates/workspace/.claude/skills/create-eval-judge/SKILL.md +0 -128
  19. package/dist/templates/workspace/.claude/skills/create-mcp-config/SKILL.md +0 -151
  20. package/dist/templates/workspace/.claude/skills/create-model-config/SKILL.md +0 -45
  21. package/dist/templates/workspace/.claude/skills/create-skill/SKILL.md +0 -63
  22. package/dist/templates/workspace/.claude/skills/create-system-prompt/SKILL.md +0 -168
  23. package/dist/templates/workspace/.claude/skills/create-tool/SKILL.md +0 -56
  24. package/dist/templates/workspace/.claude/skills/create-tool-impl/SKILL.md +0 -83
  25. package/dist/templates/workspace/.claude/skills/create-tool-test/SKILL.md +0 -117
  26. package/dist/templates/workspace/.claude/skills/create-tool-ui/SKILL.md +0 -218
  27. package/dist/templates/workspace/README.md +0 -13
  28. package/dist/templates/workspace/package.json +0 -19
@@ -1 +1 @@
1
- import{u as t,r as n,i,j as e,b as d,C as l,X as x,d as u}from"./chat-input-D-F2IIDK.js";function m(){return e.jsxs("div",{className:"flex h-10 shrink-0 items-center justify-between border-b px-3",children:[e.jsx("span",{className:"text-sm font-semibold",children:"Archon Claw"}),e.jsx("button",{type:"button",className:"text-muted-foreground hover:bg-accent rounded p-1 transition-colors",onClick:()=>window.parent.postMessage({type:"archon-claw:request-close"},"*"),children:e.jsx(x,{className:"h-4 w-4"})})]})}function h(){const a=t(s=>s.setAgentId),o=t(s=>s.createSession),r=t(s=>s.activeSession());return n.useEffect(()=>{const c=new URLSearchParams(window.location.search).get("agentId");c&&a(c),i()},[a]),n.useEffect(()=>{r||o()},[r,o]),e.jsxs("div",{className:"flex h-dvh flex-col bg-background text-foreground",children:[e.jsx(m,{}),e.jsx(d,{}),e.jsx(l,{})]})}u.createRoot(document.getElementById("embed-root")).render(e.jsx(n.StrictMode,{children:e.jsx(h,{})}));
1
+ import{u as t,r as n,i,j as e,b as d,C as l,X as x,d as u}from"./chat-input-BNct1ILJ.js";function h(){return e.jsxs("div",{className:"flex h-10 shrink-0 items-center justify-between border-b px-3",children:[e.jsx("span",{className:"text-sm font-semibold",children:"Archon Claw"}),e.jsx("button",{type:"button",className:"text-muted-foreground hover:bg-accent rounded p-1 transition-colors",onClick:()=>window.parent.postMessage({type:"archon-claw:request-close"},"*"),children:e.jsx(x,{className:"h-4 w-4"})})]})}function m(){const a=t(s=>s.setAgentId),o=t(s=>s.createSession),r=t(s=>s.activeSession());return n.useEffect(()=>{const c=new URLSearchParams(window.location.search).get("agentId")??globalThis.__ARCHON_DEFAULT_AGENT__;c&&a(c),i()},[a]),n.useEffect(()=>{r||o()},[r,o]),e.jsxs("div",{className:"flex h-dvh flex-col bg-background text-foreground",children:[e.jsx(h,{}),e.jsx(d,{}),e.jsx(l,{})]})}u.createRoot(document.getElementById("embed-root")).render(e.jsx(n.StrictMode,{children:e.jsx(m,{})}));
@@ -1,4 +1,4 @@
1
- import{c as h,r as d,j as e,a as x,u as t,B as i,X as f,M as p,b,C as g,d as j}from"./chat-input-D-F2IIDK.js";/**
1
+ import{c as h,r as d,j as e,a as x,u as t,B as i,X as f,M as p,b,C as g,d as j}from"./chat-input-BNct1ILJ.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -13,4 +13,4 @@ import{c as h,r as d,j as e,a as x,u as t,B as i,X as f,M as p,b,C as g,d as j}f
13
13
  *
14
14
  * This source code is licensed under the ISC license.
15
15
  * See the LICENSE file in the root directory of this source tree.
16
- */const w=h("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);function N({content:o,children:a,side:n="top"}){const[l,r]=d.useState(!1),c={top:"bottom-full left-1/2 -translate-x-1/2 mb-2",bottom:"top-full left-1/2 -translate-x-1/2 mt-2",left:"right-full top-1/2 -translate-y-1/2 mr-2",right:"left-full top-1/2 -translate-y-1/2 ml-2"};return e.jsxs("div",{className:"relative inline-flex",onMouseEnter:()=>r(!0),onMouseLeave:()=>r(!1),children:[a,l&&e.jsx("div",{className:x("absolute z-50 whitespace-nowrap rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md border border-border animate-in fade-in-0",c[n]),children:o})]})}function k(){const o=t(s=>s.sessions),a=t(s=>s.activeLocalId),n=t(s=>s.sidebarOpen),l=t(s=>s.setSidebarOpen),r=t(s=>s.createSession),c=t(s=>s.switchSession),m=t(s=>s.deleteSession);return e.jsxs(e.Fragment,{children:[n&&e.jsx("div",{className:"fixed inset-0 z-40 bg-black/60 md:hidden",onClick:()=>l(!1)}),e.jsxs("aside",{className:x("fixed inset-y-0 left-0 z-50 flex w-60 flex-col border-r border-border bg-secondary transition-transform duration-200 md:relative md:translate-x-0",n?"translate-x-0":"-translate-x-full"),children:[e.jsxs("div",{className:"flex h-14 items-center justify-between border-b border-border px-4",children:[e.jsx("h1",{className:"text-sm font-semibold text-foreground",children:"Archon Claw"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(N,{content:"New chat",side:"bottom",children:e.jsx(i,{variant:"ghost",size:"icon",className:"h-8 w-8",onClick:r,children:e.jsx(v,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"ghost",size:"icon",className:"h-8 w-8 md:hidden",onClick:()=>l(!1),children:e.jsx(f,{className:"h-4 w-4"})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-2",children:[o.length===0&&e.jsx("p",{className:"px-2 py-4 text-center text-xs text-muted-foreground",children:"No conversations yet"}),o.map(s=>e.jsxs("div",{className:x("group flex items-center gap-2 rounded-lg px-3 py-2 text-sm cursor-pointer transition-colors",s.localId===a?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:bg-accent"),onClick:()=>c(s.localId),children:[e.jsx(p,{className:"h-4 w-4 shrink-0"}),e.jsx("span",{className:"flex-1 truncate",children:s.title}),e.jsx(i,{variant:"ghost",size:"icon",className:"h-6 w-6 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity",onClick:u=>{u.stopPropagation(),m(s.localId)},children:e.jsx(w,{className:"h-3.5 w-3.5 text-muted-foreground hover:text-destructive"})})]},s.localId))]})]})]})}function S(){const o=t(n=>n.setSidebarOpen),a=t(n=>n.activeSession());return e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsxs("div",{className:"flex h-14 items-center gap-3 border-b border-border px-4",children:[e.jsx(i,{variant:"ghost",size:"icon",className:"md:hidden",onClick:()=>o(!0),children:e.jsx(y,{className:"h-5 w-5"})}),e.jsx("h2",{className:"truncate text-sm font-medium text-foreground",children:(a==null?void 0:a.title)??""})]}),e.jsx(b,{}),e.jsx(g,{})]})}function I(){const o=t(r=>r.setAgentId),a=t(r=>r.loadSessions),[n,l]=d.useState(!1);return d.useEffect(()=>{const c=new URLSearchParams(window.location.search).get("agentId");c&&o(c),a().then(()=>l(!0)).catch(()=>l(!0))},[o,a]),n?e.jsxs("div",{className:"flex h-dvh overflow-hidden bg-background text-foreground",children:[e.jsx(k,{}),e.jsx("main",{className:"flex-1 overflow-hidden",children:e.jsx(S,{})})]}):null}j.createRoot(document.getElementById("root")).render(e.jsx(d.StrictMode,{children:e.jsx(I,{})}));
16
+ */const N=h("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);function w({content:o,children:a,side:n="top"}){const[l,r]=d.useState(!1),c={top:"bottom-full left-1/2 -translate-x-1/2 mb-2",bottom:"top-full left-1/2 -translate-x-1/2 mt-2",left:"right-full top-1/2 -translate-y-1/2 mr-2",right:"left-full top-1/2 -translate-y-1/2 ml-2"};return e.jsxs("div",{className:"relative inline-flex",onMouseEnter:()=>r(!0),onMouseLeave:()=>r(!1),children:[a,l&&e.jsx("div",{className:x("absolute z-50 whitespace-nowrap rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md border border-border animate-in fade-in-0",c[n]),children:o})]})}function k(){const o=t(s=>s.sessions),a=t(s=>s.activeLocalId),n=t(s=>s.sidebarOpen),l=t(s=>s.setSidebarOpen),r=t(s=>s.createSession),c=t(s=>s.switchSession),m=t(s=>s.deleteSession);return e.jsxs(e.Fragment,{children:[n&&e.jsx("div",{className:"fixed inset-0 z-40 bg-black/60 md:hidden",onClick:()=>l(!1)}),e.jsxs("aside",{className:x("fixed inset-y-0 left-0 z-50 flex w-60 flex-col border-r border-border bg-secondary transition-transform duration-200 md:relative md:translate-x-0",n?"translate-x-0":"-translate-x-full"),children:[e.jsxs("div",{className:"flex h-14 items-center justify-between border-b border-border px-4",children:[e.jsx("h1",{className:"text-sm font-semibold text-foreground",children:"Archon Claw"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(w,{content:"New chat",side:"bottom",children:e.jsx(i,{variant:"ghost",size:"icon",className:"h-8 w-8",onClick:r,children:e.jsx(v,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"ghost",size:"icon",className:"h-8 w-8 md:hidden",onClick:()=>l(!1),children:e.jsx(f,{className:"h-4 w-4"})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-2",children:[o.length===0&&e.jsx("p",{className:"px-2 py-4 text-center text-xs text-muted-foreground",children:"No conversations yet"}),o.map(s=>e.jsxs("div",{className:x("group flex items-center gap-2 rounded-lg px-3 py-2 text-sm cursor-pointer transition-colors",s.localId===a?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:bg-accent"),onClick:()=>c(s.localId),children:[e.jsx(p,{className:"h-4 w-4 shrink-0"}),e.jsx("span",{className:"flex-1 truncate",children:s.title}),e.jsx(i,{variant:"ghost",size:"icon",className:"h-6 w-6 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity",onClick:u=>{u.stopPropagation(),m(s.localId)},children:e.jsx(N,{className:"h-3.5 w-3.5 text-muted-foreground hover:text-destructive"})})]},s.localId))]})]})]})}function S(){const o=t(n=>n.setSidebarOpen),a=t(n=>n.activeSession());return e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsxs("div",{className:"flex h-14 items-center gap-3 border-b border-border px-4",children:[e.jsx(i,{variant:"ghost",size:"icon",className:"md:hidden",onClick:()=>o(!0),children:e.jsx(y,{className:"h-5 w-5"})}),e.jsx("h2",{className:"truncate text-sm font-medium text-foreground",children:(a==null?void 0:a.title)??""})]}),e.jsx(b,{}),e.jsx(g,{})]})}function C(){const o=t(r=>r.setAgentId),a=t(r=>r.loadSessions),[n,l]=d.useState(!1);return d.useEffect(()=>{const c=new URLSearchParams(window.location.search).get("agentId")??globalThis.__ARCHON_DEFAULT_AGENT__;c&&o(c),a().then(()=>l(!0)).catch(()=>l(!0))},[o,a]),n?e.jsxs("div",{className:"flex h-dvh overflow-hidden bg-background text-foreground",children:[e.jsx(k,{}),e.jsx("main",{className:"flex-1 overflow-hidden",children:e.jsx(S,{})})]}):null}j.createRoot(document.getElementById("root")).render(e.jsx(d.StrictMode,{children:e.jsx(C,{})}));
@@ -4,9 +4,9 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Archon Claw Embed</title>
7
- <script type="module" crossorigin src="/assets/embed-XPDwGdtM.js"></script>
8
- <link rel="modulepreload" crossorigin href="/assets/chat-input-D-F2IIDK.js">
9
- <link rel="stylesheet" crossorigin href="/assets/chat-input-qoFFWtdQ.css">
7
+ <script type="module" crossorigin src="./assets/embed-D4R7hpA_.js"></script>
8
+ <link rel="modulepreload" crossorigin href="./assets/chat-input-BNct1ILJ.js">
9
+ <link rel="stylesheet" crossorigin href="./assets/chat-input-qoFFWtdQ.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="embed-root"></div>
@@ -4,9 +4,9 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Archon Claw</title>
7
- <script type="module" crossorigin src="/assets/main-DDb5hJ5F.js"></script>
8
- <link rel="modulepreload" crossorigin href="/assets/chat-input-D-F2IIDK.js">
9
- <link rel="stylesheet" crossorigin href="/assets/chat-input-qoFFWtdQ.css">
7
+ <script type="module" crossorigin src="./assets/main-C4meEBxF.js"></script>
8
+ <link rel="modulepreload" crossorigin href="./assets/chat-input-BNct1ILJ.js">
9
+ <link rel="stylesheet" crossorigin href="./assets/chat-input-qoFFWtdQ.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/dist/server.d.ts CHANGED
@@ -6,5 +6,9 @@ export interface AgentEntry {
6
6
  sessions: SessionStore;
7
7
  }
8
8
  type AgentResolver = Map<string, AgentEntry> | (() => Map<string, AgentEntry>);
9
- export declare function createServer(agents: AgentResolver, port: number): http.Server;
9
+ export declare function normalizeBasePath(raw?: string): string;
10
+ export interface ServerOptions {
11
+ basePath?: string;
12
+ }
13
+ export declare function createServer(agents: AgentResolver, port: number, options?: ServerOptions): http.Server;
10
14
  export {};
package/dist/server.js CHANGED
@@ -33,25 +33,40 @@ function resolveStaticFile(pathname) {
33
33
  }
34
34
  return null;
35
35
  }
36
- function serveStatic(res, pathname) {
36
+ function serveStatic(res, pathname, injection) {
37
37
  // Serve embed.html directly (not SPA fallback)
38
38
  if (pathname === "/embed.html" || pathname === "/embed") {
39
39
  const embedPath = resolveStaticFile("embed.html");
40
- return embedPath ? serveFile(res, embedPath) : false;
40
+ return embedPath ? serveFile(res, embedPath, injection) : false;
41
41
  }
42
42
  const resolved = resolveStaticFile(pathname);
43
43
  if (resolved)
44
- return serveFile(res, resolved);
44
+ return serveFile(res, resolved, path.extname(resolved) === ".html" ? injection : undefined);
45
45
  // SPA fallback
46
46
  const indexPath = resolveStaticFile("index.html");
47
- return indexPath ? serveFile(res, indexPath) : false;
47
+ return indexPath ? serveFile(res, indexPath, injection) : false;
48
48
  }
49
- function serveFile(res, filePath) {
49
+ function serveFile(res, filePath, injection) {
50
50
  if (!fs.existsSync(filePath))
51
51
  return false;
52
52
  const ext = path.extname(filePath);
53
53
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
54
54
  const content = fs.readFileSync(filePath);
55
+ // Inject runtime config into HTML responses
56
+ if (ext === ".html" && injection) {
57
+ const vars = [];
58
+ if (injection.basePath)
59
+ vars.push(`window.__ARCHON_BASE_PATH__=${JSON.stringify(injection.basePath)}`);
60
+ if (injection.defaultAgent)
61
+ vars.push(`window.__ARCHON_DEFAULT_AGENT__=${JSON.stringify(injection.defaultAgent)}`);
62
+ if (vars.length > 0) {
63
+ let html = content.toString("utf-8");
64
+ html = html.replace("<head>", `<head><script>${vars.join(";")}</script>`);
65
+ res.writeHead(200, { "Content-Type": contentType });
66
+ res.end(html);
67
+ return true;
68
+ }
69
+ }
55
70
  res.writeHead(200, { "Content-Type": contentType });
56
71
  res.end(content);
57
72
  return true;
@@ -96,12 +111,30 @@ function readBody(req) {
96
111
  });
97
112
  });
98
113
  }
99
- export function createServer(agents, port) {
114
+ export function normalizeBasePath(raw) {
115
+ if (!raw || raw === "/")
116
+ return "";
117
+ let p = raw;
118
+ if (!p.startsWith("/"))
119
+ p = "/" + p;
120
+ if (p.endsWith("/"))
121
+ p = p.slice(0, -1);
122
+ return p;
123
+ }
124
+ export function createServer(agents, port, options) {
100
125
  const resolveAgents = typeof agents === "function" ? agents : () => agents;
126
+ const basePath = normalizeBasePath(options?.basePath ?? process.env.BASE_PATH);
101
127
  const server = http.createServer(async (req, res) => {
102
128
  const agentMap = resolveAgents();
103
129
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
104
130
  const method = req.method ?? "GET";
131
+ // Strip basePath prefix from incoming URL if present (segment-boundary match)
132
+ if (basePath && url.pathname.startsWith(basePath)) {
133
+ const rest = url.pathname.slice(basePath.length);
134
+ if (rest === "" || rest.startsWith("/")) {
135
+ url.pathname = rest || "/";
136
+ }
137
+ }
105
138
  // CORS preflight
106
139
  if (method === "OPTIONS") {
107
140
  setCors(res);
@@ -304,10 +337,13 @@ export function createServer(agents, port) {
304
337
  return;
305
338
  }
306
339
  if (agentIds.length === 1) {
307
- const target = `${url.pathname === "/embed" ? "/embed.html" : url.pathname}?agentId=${encodeURIComponent(agentIds[0])}`;
308
- res.writeHead(302, { Location: target });
309
- res.end();
310
- return;
340
+ // Serve page directly with default agent injected no redirect
341
+ const injection = { defaultAgent: agentIds[0] };
342
+ if (basePath)
343
+ injection.basePath = basePath;
344
+ const servePath = isEmbed ? "/embed.html" : "/";
345
+ if (serveStatic(res, servePath, injection))
346
+ return;
311
347
  }
312
348
  // Multiple agents
313
349
  if (isEmbed) {
@@ -318,15 +354,24 @@ export function createServer(agents, port) {
318
354
  // Selection page for standalone UI
319
355
  const items = agentIds.map((id) => {
320
356
  const entry = agentMap.get(id);
321
- return `<a href="/?agentId=${encodeURIComponent(id)}" style="display:block;padding:16px 20px;margin:8px 0;border:1px solid #e2e8f0;border-radius:8px;text-decoration:none;color:inherit;transition:background .15s"><strong>${id}</strong><br><span style="color:#64748b;font-size:14px">${entry.config.tools.length} tools · ${Object.keys(entry.config.skills).length} skills</span></a>`;
357
+ return `<a href="${basePath}/?agentId=${encodeURIComponent(id)}" style="display:block;padding:16px 20px;margin:8px 0;border:1px solid #e2e8f0;border-radius:8px;text-decoration:none;color:inherit;transition:background .15s"><strong>${id}</strong><br><span style="color:#64748b;font-size:14px">${entry.config.tools.length} tools · ${Object.keys(entry.config.skills).length} skills</span></a>`;
322
358
  }).join("");
323
359
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
324
360
  res.end(`<!DOCTYPE html><html><head><title>Select Agent</title></head><body style="font-family:system-ui,-apple-system,sans-serif;max-width:480px;margin:80px auto;padding:0 20px"><h2 style="margin-bottom:24px">Select an agent</h2>${items}</body></html>`);
325
361
  return;
326
362
  }
327
363
  }
364
+ // Build injection config for static HTML
365
+ const injection = {};
366
+ if (basePath)
367
+ injection.basePath = basePath;
368
+ // When only one agent, always inject default so frontend doesn't need agentId in URL
369
+ const agentIds = [...agentMap.keys()];
370
+ if (agentIds.length === 1)
371
+ injection.defaultAgent = agentIds[0];
372
+ const hasInjection = Object.keys(injection).length > 0;
328
373
  // Static files (SPA fallback)
329
- if (method === "GET" && serveStatic(res, url.pathname))
374
+ if (method === "GET" && serveStatic(res, url.pathname, hasInjection ? injection : undefined))
330
375
  return;
331
376
  // 404
332
377
  json(res, 404, { error: "Not found" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archon-claw/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "tsx": "^4.21.0",
22
22
  "typescript": "^5.9.3",
23
23
  "vitest": "^4.0.18",
24
- "@archon-claw/web": "0.1.1"
24
+ "@archon-claw/web": "0.2.0"
25
25
  },
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "^1.27.1",
@@ -36,7 +36,9 @@
36
36
  "zod": "^3.25.76"
37
37
  },
38
38
  "scripts": {
39
- "build": "tsc -p tsconfig.build.json && rm -rf dist/public && cp -r ../web/dist dist/public",
39
+ "clean": "rm -rf dist",
40
+ "build": "tsc -p tsconfig.build.json && cp -r ../web/dist dist/public",
41
+ "typecheck": "tsc --noEmit",
40
42
  "dev": "tsx src/cli.ts start examples/my-agent",
41
43
  "start": "node dist/cli.js",
42
44
  "test": "vitest run --exclude dist --exclude examples",
@@ -1,7 +0,0 @@
1
- export declare function scaffoldAgent(name: string, targetDir: string, opts?: {
2
- quiet?: boolean;
3
- }): Promise<void>;
4
- export declare function scaffoldWorkspace(targetDir: string, opts?: {
5
- install?: boolean;
6
- }): Promise<void>;
7
- export declare function exportSkills(targetDir: string): Promise<void>;
package/dist/scaffold.js DELETED
@@ -1,115 +0,0 @@
1
- import fs from "fs/promises";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- import { readFileSync } from "fs";
5
- import { execSync } from "child_process";
6
- import { skillsDir } from "@archon-claw/skills";
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const cliVersion = JSON.parse(readFileSync(path.resolve(__dirname, "../package.json"), "utf-8")).version;
9
- export async function scaffoldAgent(name, targetDir, opts = {}) {
10
- const dest = path.resolve(targetDir, name);
11
- // Check if destination already exists
12
- try {
13
- await fs.access(dest);
14
- throw new Error(`Directory already exists: ${dest}`);
15
- }
16
- catch (err) {
17
- if (err.code !== "ENOENT")
18
- throw err;
19
- }
20
- // Resolve template directory (works for both src/ and dist/)
21
- const templateDir = path.resolve(__dirname, "../templates/agent");
22
- try {
23
- await fs.access(templateDir);
24
- }
25
- catch {
26
- throw new Error(`Template directory not found: ${templateDir}`);
27
- }
28
- // Recursively copy template to destination
29
- await fs.cp(templateDir, dest, { recursive: true });
30
- if (!opts.quiet) {
31
- const files = await listFiles(dest, dest);
32
- console.log(`\nCreated agent "${name}" at ${dest}\n`);
33
- console.log("Files:");
34
- for (const file of files) {
35
- console.log(` ${file}`);
36
- }
37
- console.log(`\nNext steps:`);
38
- console.log(` cd ${dest}`);
39
- console.log(` archon-claw start .`);
40
- }
41
- }
42
- export async function scaffoldWorkspace(targetDir, opts = {}) {
43
- const dest = path.resolve(targetDir);
44
- const name = path.basename(dest);
45
- // Check if package.json already exists at the target
46
- const pkgPath = path.join(dest, "package.json");
47
- try {
48
- await fs.access(pkgPath);
49
- throw new Error(`package.json already exists in ${dest}`);
50
- }
51
- catch (err) {
52
- if (err.code !== "ENOENT")
53
- throw err;
54
- }
55
- await fs.mkdir(dest, { recursive: true });
56
- // Copy and render workspace template files (package.json, README.md, .gitignore)
57
- const templateDir = path.resolve(__dirname, "../templates/workspace");
58
- const vars = { name, cliVersion };
59
- const templateFiles = await listFiles(templateDir, templateDir);
60
- for (const relPath of templateFiles) {
61
- const src = path.join(templateDir, relPath);
62
- const destFile = path.join(dest, relPath);
63
- await fs.mkdir(path.dirname(destFile), { recursive: true });
64
- let content = await fs.readFile(src, "utf-8");
65
- content = content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? _);
66
- await fs.writeFile(destFile, content);
67
- }
68
- // Copy skills from @archon-claw/skills
69
- const destSkillsDir = path.join(dest, ".claude", "skills");
70
- await fs.mkdir(destSkillsDir, { recursive: true });
71
- await fs.cp(skillsDir, destSkillsDir, { recursive: true });
72
- // Create default agent
73
- await scaffoldAgent("my-agent", path.join(dest, "agents"), { quiet: true });
74
- const files = await listFiles(dest, dest);
75
- console.log(`\nInitialised workspace at ${dest}\n`);
76
- console.log("Files:");
77
- for (const file of files) {
78
- console.log(` ${file}`);
79
- }
80
- // Install dependencies
81
- if (opts.install) {
82
- console.log("\nInstalling dependencies...\n");
83
- execSync("npm install", { cwd: dest, stdio: "inherit" });
84
- }
85
- console.log(`\nNext steps:`);
86
- if (!opts.install) {
87
- console.log(` cd ${name}`);
88
- console.log(` npm install`);
89
- }
90
- console.log(` archon-claw dev agents/my-agent`);
91
- }
92
- export async function exportSkills(targetDir) {
93
- const dest = path.resolve(targetDir);
94
- await fs.mkdir(dest, { recursive: true });
95
- await fs.cp(skillsDir, dest, { recursive: true });
96
- const entries = await fs.readdir(dest);
97
- console.log(`\nExported ${entries.length} skills to ${dest}\n`);
98
- for (const entry of entries.sort()) {
99
- console.log(` ${entry}/SKILL.md`);
100
- }
101
- }
102
- async function listFiles(dir, root) {
103
- const entries = await fs.readdir(dir, { withFileTypes: true });
104
- const files = [];
105
- for (const entry of entries) {
106
- const full = path.join(dir, entry.name);
107
- if (entry.isDirectory()) {
108
- files.push(...(await listFiles(full, root)));
109
- }
110
- else {
111
- files.push(path.relative(root, full));
112
- }
113
- }
114
- return files.sort();
115
- }
@@ -1,6 +0,0 @@
1
- {
2
- "provider": "anthropic",
3
- "model": "claude-sonnet-4-20250514",
4
- "maxTokens": 4096,
5
- "temperature": 0.7
6
- }
@@ -1,9 +0,0 @@
1
- 你是一个专业的 AI 助手。
2
-
3
- ## 可用技能
4
-
5
- 当用户请求匹配某个技能时,使用 `skill_load` 工具加载该技能的完整指令,然后按照指令执行。
6
-
7
- {% for skill in skills %}
8
- - **{{ skill.name }}**:{{ skill.description }}
9
- {% endfor %}
@@ -1,9 +0,0 @@
1
- /**
2
- * Greeting tool implementation
3
- * @param {object} params
4
- * @param {string} params.name - The name of the person to greet
5
- * @returns {Promise<object>} Greeting message
6
- */
7
- export default async ({ name }) => {
8
- return { message: `Hello, ${name}!` };
9
- };
@@ -1,14 +0,0 @@
1
- {
2
- "name": "greeting",
3
- "description": "Generate a greeting message for the given name",
4
- "input_schema": {
5
- "type": "object",
6
- "properties": {
7
- "name": {
8
- "type": "string",
9
- "description": "The name of the person to greet"
10
- }
11
- },
12
- "required": ["name"]
13
- }
14
- }
@@ -1,90 +0,0 @@
1
- ---
2
- name: create-agent
3
- description: 创建完整的 agent 配置目录。当用户需要新建一个 AI Agent 时使用。
4
- argument-hint: "[agent_name]"
5
- ---
6
-
7
- 在 `agents/` 目录下创建一个完整的 agent 配置文件夹。
8
-
9
- ## 目录结构
10
-
11
- ```
12
- agents/<agent-name>/
13
- ├── system-prompt.md # 系统提示词(必填)
14
- ├── model.json # 模型配置(必填)
15
- ├── tools/ # 工具定义(必填,至少 1 个)
16
- │ └── <tool-name>.json
17
- ├── tool-impls/ # 工具实现(必填,与 tools/ 一一对应)
18
- │ └── <tool-name>.impl.js
19
- ├── datasets/ # 数据集(可选)
20
- │ └── <name>.json
21
- └── skills/ # 技能(可选)
22
- └── <skill-name>/
23
- └── SKILL.md
24
- ```
25
-
26
- ## 创建步骤
27
-
28
- 1. **创建 `system-prompt.md`** — 定义 agent 的角色和行为指令
29
- - 可使用 Liquid 模板语法引用 datasets 中的数据
30
- - 语法:`{% for item in dataset_name %}` / `{{ item.field }}`
31
- - 内容不能为空
32
-
33
- 2. **创建 `model.json`** — 模型配置
34
- - 必填:`provider`(`"anthropic"` 或 `"openai"`)、`model`(模型 ID)
35
- - 可选:`maxTokens`、`temperature`(0~2)、`apiKey`
36
- - 必须通过 `src/schemas/model.schema.json` 校验
37
-
38
- 3. **创建 `tools/` 目录** — 至少一个工具定义 JSON
39
- - 每个文件定义一个工具:`name`、`description`、`input_schema`
40
- - `name` 匹配 `^[a-z][a-z0-9_]*$`
41
- - 必须通过 `src/schemas/tool.schema.json` 校验
42
-
43
- 4. **创建 `tool-impls/` 目录** — 每个工具对应一个实现文件
44
- - 文件名格式:`<tool-name>.impl.js`
45
- - ES6 模块,export default async function
46
- - 必须与 tools/ 中的工具一一对应
47
-
48
- 5. **(可选)创建 `datasets/` 目录** — 数据集 JSON 文件
49
- - 必须是非空数组(字符串数组或对象数组)
50
- - 文件名去掉 `.json` 后作为 Liquid 模板变量名
51
-
52
- 6. **(可选)创建 `skills/` 目录** — agent 技能
53
- - 每个技能一个子目录,包含 `SKILL.md`
54
- - frontmatter 必须有 `name` 和 `description`
55
-
56
- ## 示例
57
-
58
- 创建一个名为 `my-assistant` 的 agent:
59
-
60
- ```
61
- agents/my-assistant/
62
- ├── system-prompt.md
63
- ├── model.json
64
- ├── tools/
65
- │ └── web_search.json
66
- ├── tool-impls/
67
- │ └── web_search.impl.js
68
- ├── datasets/
69
- │ └── rules.json
70
- └── skills/
71
- └── summarize/
72
- └── SKILL.md
73
- ```
74
-
75
- ## 验证
76
-
77
- 创建完成后运行验证确保配置正确:
78
-
79
- ```typescript
80
- import { validateDir } from "./src/validator/index.js";
81
- const result = await validateDir("agent-dir", "agents/<agent-name>");
82
- ```
83
-
84
- ## 注意
85
-
86
- - tools/ 和 tool-impls/ 必须一一对应(名称匹配)
87
- - system-prompt.md 中的 Liquid 模板变量名要与 datasets/ 中的文件名对应
88
- - 参考 `agents/my-agent/` 作为完整示例
89
-
90
- 请根据用户的需求创建 agent。$ARGUMENTS
@@ -1,57 +0,0 @@
1
- ---
2
- name: create-dataset
3
- description: 创建 dataset JSON 文件。当用户需要为 agent 添加数据集(few-shot 示例、规则列表等)时使用。
4
- ---
5
-
6
- 在 `agents/my-agent/datasets/` 目录下创建一个新的 dataset JSON 文件。
7
-
8
- ## 规范
9
-
10
- - 文件名语义化,如 `examples.json`、`rules.json`
11
- - 必须通过 `src/schemas/dataset.schema.json` 的校验
12
- - 必须是 JSON 数组,至少包含一个元素
13
-
14
- ## 支持的格式
15
-
16
- ### 字符串数组(规则、提示等)
17
-
18
- ```json
19
- [
20
- "回答使用中文",
21
- "代码示例使用 TypeScript"
22
- ]
23
- ```
24
-
25
- ### 对象数组(问答对、示例等)
26
-
27
- ```json
28
- [
29
- {
30
- "input": "什么是 TypeScript?",
31
- "output": "TypeScript 是 JavaScript 的超集,添加了静态类型系统。"
32
- }
33
- ]
34
- ```
35
-
36
- ## 在 system-prompt.md 中引用
37
-
38
- dataset 的文件名(去掉 .json)作为 Liquid 模板变量名:
39
-
40
- ```markdown
41
- {% for rule in rules %}
42
- - {{ rule }}
43
- {% endfor %}
44
-
45
- {% for item in examples %}
46
- 问:{{ item.input }}
47
- 答:{{ item.output }}
48
- {% endfor %}
49
- ```
50
-
51
- ## 注意
52
-
53
- - 数组不能为空(minItems: 1)
54
- - 文件名会作为模板变量名,建议用小写字母和下划线
55
- - 对象数组的字段名自由定义,但要和 system-prompt.md 模板对应
56
-
57
- 请根据用户需求创建 dataset 文件。$ARGUMENTS