@rubytech/create-realagent 1.0.864 → 1.0.866

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 (27) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.d.ts +2 -0
  3. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.d.ts.map +1 -0
  4. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js +67 -0
  5. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js.map +1 -0
  6. package/payload/platform/plugins/admin/mcp/dist/index.js +44 -2
  7. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  8. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts +17 -0
  9. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -0
  10. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +62 -0
  11. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -0
  12. package/payload/platform/plugins/admin/mcp/package.json +4 -2
  13. package/payload/platform/plugins/admin/mcp/vitest.config.ts +9 -0
  14. package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +2 -0
  15. package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +2 -0
  16. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -0
  17. package/payload/platform/templates/specialists/agents/content-producer.md +17 -3
  18. package/payload/server/chunk-FHNFKJZN.js +2143 -0
  19. package/payload/server/chunk-ND23BDBM.js +11312 -0
  20. package/payload/server/chunk-TOLLHW7W.js +1155 -0
  21. package/payload/server/chunk-UXLZ5Z3Y.js +667 -0
  22. package/payload/server/client-pool-2IUOSYDF.js +34 -0
  23. package/payload/server/cloudflare-task-tracker-OCFIVXEJ.js +20 -0
  24. package/payload/server/maxy-edge.js +5 -6
  25. package/payload/server/public/assets/{admin-CCML_l4E.js → admin-CLp1xGlJ.js} +1 -1
  26. package/payload/server/public/index.html +1 -1
  27. package/payload/server/server.js +132 -155
@@ -0,0 +1,17 @@
1
+ export interface SkillOwner {
2
+ pluginName: string;
3
+ file: string;
4
+ }
5
+ export type SkillFindResult = {
6
+ status: "unique";
7
+ candidates: [SkillOwner];
8
+ } | {
9
+ status: "ambiguous";
10
+ candidates: SkillOwner[];
11
+ } | {
12
+ status: "not-found";
13
+ candidates: [];
14
+ };
15
+ export declare function findSkillOwners(platformRoot: string, skillName: string): SkillFindResult;
16
+ export declare function computePluginReadHint(platformRoot: string, pluginName: string, file: string): string | null;
17
+ //# sourceMappingURL=skill-resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-resolution.d.ts","sourceRoot":"","sources":["../src/skill-resolution.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAA;CAAE,GAC9C;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,UAAU,EAAE,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,EAAE,CAAA;CAAE,CAAC;AAI5C,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CA4BxF;AAKD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAQf"}
@@ -0,0 +1,62 @@
1
+ // Task 964 — deterministic plugin-skill resolution.
2
+ //
3
+ // `findSkillOwners` walks `<platformRoot>/plugins/*/skills/<skillName>/SKILL.md`
4
+ // once and returns every plugin that owns that skill. The `skill-find` MCP
5
+ // tool wraps this directly; `plugin-read`'s "not found" branch uses
6
+ // `computePluginReadHint` to surface the owning plugin when the agent
7
+ // guessed the wrong `pluginName` for a known skill.
8
+ //
9
+ // Pure filesystem read — no network, no subprocess. The walk is two-level
10
+ // (plugin dir → skill dir), never recursive, so deeper skill subtrees and
11
+ // sibling references/ directories are ignored.
12
+ import { existsSync, readdirSync, statSync } from "node:fs";
13
+ import { resolve } from "node:path";
14
+ const SKILL_FILE_PATH = /^skills\/([a-z0-9][a-z0-9-]*)\//;
15
+ export function findSkillOwners(platformRoot, skillName) {
16
+ const owners = [];
17
+ const pluginsDir = resolve(platformRoot, "plugins");
18
+ if (!existsSync(pluginsDir)) {
19
+ return { status: "not-found", candidates: [] };
20
+ }
21
+ let entries;
22
+ try {
23
+ entries = readdirSync(pluginsDir);
24
+ }
25
+ catch {
26
+ return { status: "not-found", candidates: [] };
27
+ }
28
+ for (const pluginName of entries) {
29
+ const skillFile = resolve(pluginsDir, pluginName, "skills", skillName, "SKILL.md");
30
+ if (!existsSync(skillFile))
31
+ continue;
32
+ try {
33
+ if (!statSync(skillFile).isFile())
34
+ continue;
35
+ }
36
+ catch {
37
+ continue;
38
+ }
39
+ owners.push({ pluginName, file: `skills/${skillName}/SKILL.md` });
40
+ }
41
+ if (owners.length === 0)
42
+ return { status: "not-found", candidates: [] };
43
+ if (owners.length === 1)
44
+ return { status: "unique", candidates: [owners[0]] };
45
+ return { status: "ambiguous", candidates: owners };
46
+ }
47
+ // Returns the plugin name that owns `skills/<n>/...` when exactly one
48
+ // sibling plugin holds it; null otherwise. Used by `plugin-read` to
49
+ // append `Did you mean pluginName="<owner>"?` on wrong-guess errors.
50
+ export function computePluginReadHint(platformRoot, pluginName, file) {
51
+ const match = file.match(SKILL_FILE_PATH);
52
+ if (!match)
53
+ return null;
54
+ const skillName = match[1];
55
+ const result = findSkillOwners(platformRoot, skillName);
56
+ if (result.status !== "unique")
57
+ return null;
58
+ if (result.candidates[0].pluginName === pluginName)
59
+ return null;
60
+ return result.candidates[0].pluginName;
61
+ }
62
+ //# sourceMappingURL=skill-resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-resolution.js","sourceRoot":"","sources":["../src/skill-resolution.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,iFAAiF;AACjF,2EAA2E;AAC3E,oEAAoE;AACpE,sEAAsE;AACtE,oDAAoD;AACpD,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,+CAA+C;AAC/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,MAAM,eAAe,GAAG,iCAAiC,CAAC;AAE1D,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,SAAiB;IACrE,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACjD,CAAC;IAED,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACjD,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACnF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS;QACrC,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE;gBAAE,SAAS;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,SAAS,WAAW,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACxE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,sEAAsE;AACtE,oEAAoE;AACpE,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,UAAkB,EAClB,IAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,eAAe,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAChE,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AACzC,CAAC"}
@@ -6,7 +6,8 @@
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "start": "node dist/index.js"
9
+ "start": "node dist/index.js",
10
+ "test": "vitest run"
10
11
  },
11
12
  "dependencies": {
12
13
  "@modelcontextprotocol/sdk": "^1.12.1",
@@ -16,6 +17,7 @@
16
17
  "devDependencies": {
17
18
  "@types/node": "^22.0.0",
18
19
  "@types/qrcode": "^1.5.6",
19
- "typescript": "^5.7.0"
20
+ "typescript": "^5.7.0",
21
+ "vitest": "^4.1.2"
20
22
  }
21
23
  }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["src/**/__tests__/**/*.test.ts"],
7
+ testTimeout: 10_000,
8
+ },
9
+ });
@@ -2,6 +2,8 @@
2
2
 
3
3
  Move an already-extracted static-site tree into the per-account static-publish surface (`<accountDir>/sites/<slug>/`) and emit exactly one canonical path slug for the operator to share. The operator pastes the slug after their own public-host root — the public hostname is whatever their tunnel terminates at, and is not knowable from inside this skill.
4
4
 
5
+ **Invoked from `specialists:content-producer`** when the brief carries a host-website / publish-site / put-online intent (Task 966). Admin's IDENTITY.md routes those intents to that specialist on turn 1; running this skill inline on the main admin runner exhausts the 10-turn budget on per-turn ToolSearch + plugin-read discovery before publish-site executes.
6
+
5
7
  ## When to Use
6
8
 
7
9
  Activate when **both** are true:
@@ -2,6 +2,8 @@
2
2
 
3
3
  Safely extract a zip archive the admin has uploaded, inventory its contents, and propose one concrete follow-up per entry class — refusing archives that attempt path traversal, symlink escape, or decompression-bomb pathologies.
4
4
 
5
+ **Invoked from `specialists:content-producer`** when the archive is a static-site zip and the brief carries a host-website / publish-site / put-online intent (Task 966) — the specialist chains directly into `publish-site` on the extracted tree. For graph-bound archives (LinkedIn export, conversation transcripts, PDFs etc.), invocation routes via `specialists:database-operator` instead.
6
+
5
7
  ## When to Use
6
8
 
7
9
  Activate when the `[ATTACHMENTS:]` block of the current turn contains an entry whose MIME is `application/zip` or `application/x-zip-compressed`. Every such attachment line carries an `ID: <uuid> Path: <storagePath>` pair — the `storagePath` is the absolute path to the `.zip` on disk and is the input to this flow.
@@ -167,6 +167,7 @@ When the user asks what you can do, answer from the specialist domains, admin-ow
167
167
  - Store everything you learn about the business in the graph — not in files.
168
168
  - For document ingestion of any kind — PDFs, text, transcripts, web pages, audio, video, single files, archives — delegate to the `specialists:database-operator` specialist. Include the document path, the document subject (account owner, the business, a third party, etc. — ask if not obvious from context), and the scope (admin/shared/public — ask if not obvious). **Not** `specialists:content-producer`. content-producer produces documents from the populated graph; it does not ingest. The two are opposite movements through the graph and must never be conflated.
169
169
  - For ad-hoc graph operations — pruning orphan nodes, deduplicating entities, adding edges, normalising labels, tidying schema drift — delegate to the `specialists:database-operator` specialist. Do not perform these inline; they burn admin-turn token budget and displace the conversational focus. **Not** `specialists:personal-assistant` — PA has no graph-write surface; misdelegation fails at the tool-gate after wasting a turn.
170
+ - For host-website / publish-site / put-online intents — typically a `.zip` attachment with HTML + assets and a request like "host this website" or "put this online" — delegate immediately to the `specialists:content-producer` specialist on turn 1. Do not `ToolSearch` publish-site, do not `plugin-read` the skill inline, do not pre-scan the zip. The specialist owns the `unzip-attachment` → `publish-site` chain and runs the deterministic Bash flow on its own 10-turn budget; running it inline here exhausts the main-runner budget on per-turn discovery (Task 966 evidence: a 2026-05-10 brochure session hit `error_max_turns total_tool_calls=24` before publish-site executed). **Not** `specialists:database-operator` — static-site zips are extracted to disk for publication, never written to the graph.
170
171
 
171
172
  ## Proactive Commitment Detection
172
173
 
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: content-producer
3
- description: "Visual production — reads from the populated graph to produce visual artifacts: image generation, PDF rendering, and component delivery. Delegate when a task requires generating images or saving rendered pages as PDF. **Not** document ingestion — ingestion of any kind routes to `specialists:database-operator`."
4
- summary: "Produces visual output from your graph — generates images and renders pages to PDF. For example, when you need a cover image for a brief or want to save a rendered page as PDF."
3
+ description: "Visual production and static-site hosting — reads from the populated graph to produce visual artifacts (image generation, PDF rendering, component delivery) and hosts already-prepared static sites by extracting attached archives via unzip-attachment then placing the tree under <accountDir>/sites/<slug>/ via publish-site. Delegate for: generating images, saving rendered pages as PDF, or any 'host this website' / 'publish this site' / 'put this online' intent carrying an HTML+assets archive. **Not** document ingestion — graph ingestion of any kind routes to `specialists:database-operator`. Static-site zips are extracted to disk for publication, never written to the graph."
4
+ summary: "Produces visual output from your graph — generates images, renders pages to PDF, and hosts static websites you upload as a zip. For example, when you need a cover image for a brief, want to save a rendered page as PDF, or upload a brochure zip and ask to put it online."
5
5
  model: claude-sonnet-4-6
6
- tools: mcp__memory__memory-search, mcp__replicate__image-generate, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_take_screenshot, mcp__plugin_playwright_playwright__browser_pdf_save, mcp__admin__render-component, mcp__admin__file-attach
6
+ tools: Bash, mcp__memory__memory-search, mcp__replicate__image-generate, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_take_screenshot, mcp__plugin_playwright_playwright__browser_pdf_save, mcp__admin__render-component, mcp__admin__file-attach, mcp__admin__plugin-read
7
7
  ---
8
8
 
9
9
  # Content Producer
@@ -68,6 +68,20 @@ Generate PDFs from rendered HTML pages using the browser tools.
68
68
 
69
69
  **Local files:** `file://` URLs are rewritten transparently by the `playwright-file-guard` PreToolUse hook — pass them directly to `browser_navigate` and the hook will spawn a loopback `python3 -m http.server` on a free port and rewrite the URL before Playwright sees it. No agent-side server management needed.
70
70
 
71
+ ## Hosting websites
72
+
73
+ When a brief carries a "host this website" / "publish this site" / "put this online" intent — typically with a `.zip` attachment whose extracted contents are HTML + assets — execute the deterministic two-skill chain. This is **not** ingestion (no graph write); it is filesystem extraction followed by a placement move into the per-account static-publish surface served by the existing `/sites/*` route. The `## Out of scope: ingestion of any kind` rule above is preserved by the SKILL gate at [publish-site SKILL.md](../../../plugins/admin/skills/publish-site/SKILL.md): only HTML + assets directory trees activate this path; PDFs, slide decks, single-image attachments, or zips whose extracted output is not a static-site tree route to their own skills (`a4-print-documents`, `deck-pages`) or — for graph-bound content — back to `specialists:database-operator`.
74
+
75
+ The chain (≤4 turns, total):
76
+
77
+ 1. **Read the skill texts** via `mcp__admin__plugin-read` — load `admin/skills/unzip-attachment/SKILL.md` and `admin/skills/publish-site/SKILL.md` into context. Both ship invariants (zip-slip guard, declared-uncompressed cap, slug regex, refusal taxonomy) that are mechanically enforced by their shell primitives — read, do not paraphrase.
78
+ 2. **Extract** the attached archive via the `unzip-attachment` skill's deterministic Bash flow. Output lands at `<accountDir>/extracted/<attachmentId>/`. Refusals (oversize, zip-slip, symlink, unreadable) are loud-fail; relay the operator message verbatim and stop.
79
+ 3. **Confirm the slug** with the operator if not already explicit. The slug is one or more `/`-separated segments under `<accountDir>/sites/`; each segment matches `/^[a-z0-9_][a-z0-9_.-]{0,99}$/i` and no segment starts with `.` or equals `..`. Never invent a slug.
80
+ 4. **Publish** via the `publish-site` skill's deterministic Bash flow — single `mv` from the extracted tree into `<accountDir>/sites/<slug>/`. Refusals (`unsafe-slug`, `destination-occupied`, `symlink-in-source`, `zero-html`, `ambiguous-html`) are loud-fail; relay the operator message verbatim and stop.
81
+ 5. **Emit** the canonical path slug (`/sites/<slug>/` when an `index.html` is present, otherwise `/sites/<slug>/<file>.html`). One line, framed as "paste this after your public-host root" — no scheme, no host. The `/sites/*` route at [server/routes/sites.ts](../../../ui/server/routes/sites.ts) takes care of the directory-form trailing-slash redirect.
82
+
83
+ **No fallback servers, no Playwright probes, no service restarts.** If the move or URL form is wrong, refuse — never reach for `python -m http.server`, `npx http-server`, browser-automation probes, or platform restarts. That is the exact failure pattern publish-site exists to close.
84
+
71
85
  ## File delivery
72
86
 
73
87
  Use `file-attach` to make generated files available for download in the chat. Use `render-component` with component name `file-attachment` for download delivery.