@rubytech/create-maxy-code 0.1.498 → 0.1.500
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/package.json +1 -1
- package/payload/platform/lib/active-rules/dist/index.d.ts +3 -7
- package/payload/platform/lib/active-rules/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/active-rules/dist/index.js +20 -52
- package/payload/platform/lib/active-rules/dist/index.js.map +1 -1
- package/payload/platform/lib/active-rules/src/index.test.ts +35 -69
- package/payload/platform/lib/active-rules/src/index.ts +17 -58
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/admin-authoring-observer.test.sh +135 -0
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-directive.test.sh +11 -2
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-directive.sh +6 -3
- package/payload/platform/plugins/admin/mcp/dist/index.js +52 -107
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts +8 -4
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +67 -50
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/store-skill-core.d.ts +33 -0
- package/payload/platform/plugins/admin/mcp/dist/store-skill-core.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/store-skill-core.js +122 -0
- package/payload/platform/plugins/admin/mcp/dist/store-skill-core.js.map +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +11 -5
- package/payload/platform/plugins/contacts/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/index.js +3 -12
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js +105 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +11 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +56 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
- package/payload/platform/plugins/docs/references/contacts-guide.md +2 -0
- package/payload/platform/plugins/docs/references/internals.md +2 -2
- package/payload/platform/plugins/docs/references/outlook-guide.md +4 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -2
- package/payload/platform/plugins/email/mcp/dist/__tests__/compose-signature.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/compose-signature.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/compose-signature.test.js +53 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/compose-signature.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/signature.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/signature.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/signature.test.js +50 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/signature.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/compose.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/compose.js +15 -2
- package/payload/platform/plugins/email/mcp/dist/lib/compose.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/signature.d.ts +29 -0
- package/payload/platform/plugins/email/mcp/dist/lib/signature.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/signature.js +55 -0
- package/payload/platform/plugins/email/mcp/dist/lib/signature.js.map +1 -0
- package/payload/platform/plugins/email/references/email-reference.md +10 -0
- package/payload/platform/plugins/email/skills/email-composition/SKILL.md +9 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js +10 -9
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js.map +1 -1
- package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/preference-audit/SKILL.md +16 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +6 -0
- package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/SKILL.md +1 -1
- package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh +2 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +26 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts +19 -19
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.js +28 -34
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/skill-registration-drift.d.ts +15 -0
- package/payload/platform/services/claude-session-manager/dist/skill-registration-drift.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/skill-registration-drift.js +61 -0
- package/payload/platform/services/claude-session-manager/dist/skill-registration-drift.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-Ce5aBBWF.js → AdminLoginScreens-CKg_Dlpv.js} +1 -1
- package/payload/server/public/assets/{admin-BWb8me-E.js → admin-wtSUU5N0.js} +1 -1
- package/payload/server/public/assets/chat-DRuIxGtE.js +1 -0
- package/payload/server/public/assets/data-BdZCvyvN.js +1 -0
- package/payload/server/public/assets/{operator-icJwMkZF.js → operator-DglDYmdV.js} +1 -1
- package/payload/server/public/assets/{page-iG57nKOg.js → page-C-5sTAE-.js} +2 -2
- package/payload/server/public/assets/{page-DUgrGrJp.js → page-C8G5p4jr.js} +1 -1
- package/payload/server/public/assets/{public-CkOumzpf.js → public-DqJjXR4p.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-Cu6zvuFx.js → useVoiceRecorder-Cj-VZDKO.js} +1 -1
- package/payload/server/public/chat.html +3 -3
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/public/operator.html +4 -4
- package/payload/server/public/public.html +3 -3
- package/payload/server/server.js +89 -63
- package/payload/server/public/assets/chat-qtOiJX-Y.js +0 -1
- package/payload/server/public/assets/data-BjqC4hyM.js +0 -1
|
@@ -65,7 +65,7 @@ else
|
|
|
65
65
|
fi
|
|
66
66
|
rm -rf "$FAKEBIN"
|
|
67
67
|
|
|
68
|
-
# Case 4 — both generated lists present: the ladder carries all
|
|
68
|
+
# Case 4 — both generated lists present: the ladder carries all four rungs, both
|
|
69
69
|
# full lists, and the relocated outcome-only-brief contract. The hook reads the
|
|
70
70
|
# lists from $PWD/agents/admin, so run it from a temp account dir.
|
|
71
71
|
WD=$(mktemp -d); mkdir -p "$WD/agents/admin"
|
|
@@ -78,11 +78,20 @@ if printf '%s' "$ctx" | grep -q "specialists:content-producer" \
|
|
|
78
78
|
&& printf '%s' "$ctx" | grep -qE '(^|[^0-9])1\)' \
|
|
79
79
|
&& printf '%s' "$ctx" | grep -qE '(^|[^0-9])2\)' \
|
|
80
80
|
&& printf '%s' "$ctx" | grep -qE '(^|[^0-9])3\)' \
|
|
81
|
+
&& printf '%s' "$ctx" | grep -qE '(^|[^0-9])4\)' \
|
|
81
82
|
&& printf '%s' "$ctx" | grep -qiE "freestyle|last resort"; then
|
|
82
|
-
echo "PASS: both lists injected in
|
|
83
|
+
echo "PASS: both lists injected in four-rung ladder"; PASS=$((PASS+1))
|
|
83
84
|
else
|
|
84
85
|
echo "FAIL: ladder/lists missing from additionalContext: $ctx" >&2; FAIL=$((FAIL+1))
|
|
85
86
|
fi
|
|
87
|
+
# Task 1959: recurring-deliverable rung sits before the freestyle last resort.
|
|
88
|
+
if printf '%s' "$ctx" | grep -qi "skill-builder" \
|
|
89
|
+
&& printf '%s' "$ctx" | grep -qiE "recurs|issues repeatedly|repeatable" \
|
|
90
|
+
&& printf '%s' "$ctx" | grep -qi "agent-builder"; then
|
|
91
|
+
echo "PASS: recurring-deliverable rung present in ladder"; PASS=$((PASS+1))
|
|
92
|
+
else
|
|
93
|
+
echo "FAIL: recurring-deliverable rung missing from ladder: $ctx" >&2; FAIL=$((FAIL+1))
|
|
94
|
+
fi
|
|
86
95
|
# Relocated outcome-only-brief contract.
|
|
87
96
|
if printf '%s' "$ctx" | grep -qi "outcome" \
|
|
88
97
|
&& printf '%s' "$ctx" | grep -qi "binding constraints" \
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# UserPromptSubmit hook: inject the standing prompt-optimiser directive plus the
|
|
3
|
-
# per-turn
|
|
3
|
+
# per-turn four-rung routing ladder as additionalContext on every turn, so the
|
|
4
4
|
# agent restates each non-trivial prompt and routes it before acting. Mirrors
|
|
5
5
|
# doctrine.sh: emit hookSpecificOutput.additionalContext via python3, fail-open
|
|
6
6
|
# with exit 0.
|
|
7
7
|
#
|
|
8
8
|
# The ladder ranks, in order: (1) delegate to a specialist that owns the
|
|
9
9
|
# deliverable via the Agent tool; (2) only if none fits, load an admin-usable
|
|
10
|
-
# skill; (3) only if
|
|
10
|
+
# skill; (3) only if the deliverable recurs and no specialist or skill owns it,
|
|
11
|
+
# author its owning skill via skill-builder (or agent-builder) and produce
|
|
12
|
+
# through it; (4) only if it is a genuine one-off, author inline as the last
|
|
11
13
|
# resort. The full agent roster and admin-usable skills list are re-emitted every
|
|
12
14
|
# turn by reading two generated files from the account dir; the hook never walks
|
|
13
15
|
# the plugins tree per turn (Task 698).
|
|
@@ -102,7 +104,8 @@ IFS= read -r -d '' DIRECTIVE_MID <<'DIRECTIVE_EOF' || true
|
|
|
102
104
|
DIRECTIVE_EOF
|
|
103
105
|
|
|
104
106
|
IFS= read -r -d '' DIRECTIVE_TAIL <<'DIRECTIVE_EOF' || true
|
|
105
|
-
3) Only if neither a specialist nor an admin skill
|
|
107
|
+
3) Only if neither a specialist nor an admin skill already owns it, decide whether the deliverable recurs. A deliverable the business issues repeatedly, or one the operator gives a fixed template, numbering, naming, or filing rule for, is authored once as its own skill: load skill-builder with skill-load (or agent-builder for a worker agent), create the owning skill, then produce the deliverable through it. This rung owns every repeatable business document or process; hand-building a recurring deliverable here is not a route.
|
|
108
|
+
4) Only if the deliverable is a genuine one-off, author it directly. Freestyle inline authoring is the last resort, not a peer of the routes above.
|
|
106
109
|
DIRECTIVE_EOF
|
|
107
110
|
|
|
108
111
|
DIRECTIVE=$(printf '%s\n%s\n%s\n%s\n%s' \
|
|
@@ -5,7 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { readFile, writeFile } from "node:fs/promises";
|
|
6
6
|
import { resolve, join } from "node:path";
|
|
7
7
|
import { execFile, execFileSync } from "node:child_process";
|
|
8
|
-
import { appendFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync,
|
|
8
|
+
import { appendFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { writeAdminEntry, removeAdminFromAccount, logUsersAudit, formatAuditRowIds } from "../../../../lib/admins-write/dist/index.js";
|
|
10
10
|
import { setAccessPassword as setAccessPasswordHash, clearAccessPassword as clearAccessPasswordHash, accessPasswordCollides } from "../../../../lib/admin-access-password/dist/index.js";
|
|
11
11
|
import { resolveCredentialTarget } from "./credential-identity.js";
|
|
@@ -20,6 +20,7 @@ import { homedir, hostname as osHostname } from "node:os";
|
|
|
20
20
|
import QRCode from "qrcode";
|
|
21
21
|
import { getSession, closeDriver } from "./lib/neo4j.js";
|
|
22
22
|
import { findSkillOwners, searchSkills, computePluginReadHint, loadSkill, parseRequiredInputs, adminAuthoringSkillBlock, skillSlugFromReadArgs, AUTHORING_DISPATCH_HINT } from "./skill-resolution.js";
|
|
23
|
+
import { storeSkillToAccount } from "./store-skill-core.js";
|
|
23
24
|
import { resolvePublicHostname } from "./lib/public-hostname.js";
|
|
24
25
|
import { resolveAdminHostname } from "./lib/admin-hostname.js";
|
|
25
26
|
import { publishSite } from "./tools/publish-site.js";
|
|
@@ -1808,15 +1809,16 @@ eagerTool(server, "cpu-triage-read", "Read a cpu-triage run started by cpu-triag
|
|
|
1808
1809
|
}
|
|
1809
1810
|
return { content: [{ type: "text", text: JSON.stringify(out, null, 2) }] };
|
|
1810
1811
|
});
|
|
1811
|
-
// operator-authored skills are written
|
|
1812
|
-
//
|
|
1813
|
-
//
|
|
1814
|
-
//
|
|
1815
|
-
//
|
|
1816
|
-
//
|
|
1817
|
-
//
|
|
1818
|
-
//
|
|
1819
|
-
//
|
|
1812
|
+
// Task 1962 — operator-authored skills are written as a plugin under the
|
|
1813
|
+
// per-account root <accountDir>/plugins/<plugin>/ ONLY. That copy survives the
|
|
1814
|
+
// installer wipe (data/ is excluded) and is loaded directly by the spawn
|
|
1815
|
+
// manifest (computeActivePlugins) and the admin skill resolvers, which walk the
|
|
1816
|
+
// account root. Nothing is written to the immutable PLATFORM_ROOT/plugins tree
|
|
1817
|
+
// (chattr +i) and there is no platform mirror. The write+resolve core lives in
|
|
1818
|
+
// store-skill-core.ts and fails closed if the written skill does not resolve,
|
|
1819
|
+
// so success is never reported for a skill that cannot load. The agent supplies
|
|
1820
|
+
// pluginName/skillName/body — the path is computed from ACCOUNT_ID. Symmetric
|
|
1821
|
+
// write counterpart to plugin-read.
|
|
1820
1822
|
eagerTool(server, "store-skill", "Save an operator-authored skill on disk as part of an admin-managed plugin. " +
|
|
1821
1823
|
"The skill becomes immediately discoverable by the admin agent (and the public agent if publicEmbed=true). " +
|
|
1822
1824
|
"Path is computed internally from the active account; the agent supplies content + names only. " +
|
|
@@ -1850,97 +1852,31 @@ eagerTool(server, "store-skill", "Save an operator-authored skill on disk as par
|
|
|
1850
1852
|
}
|
|
1851
1853
|
}
|
|
1852
1854
|
const accountDir = getAccountDir();
|
|
1853
|
-
const
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
requires: []
|
|
1879
|
-
metadata: {"platform":{"embed":["admin","public"],"optional":false}}
|
|
1880
|
-
---
|
|
1881
|
-
|
|
1882
|
-
# ${pluginName}
|
|
1883
|
-
|
|
1884
|
-
Operator-authored plugin. Skills under \`skills/\` were created via the admin skill-builder.
|
|
1885
|
-
`;
|
|
1886
|
-
writeFileSync(canonicalPluginMd, pluginMd);
|
|
1887
|
-
}
|
|
1888
|
-
// Reset skill dir before write so removed reference files don't linger.
|
|
1889
|
-
if (existsSync(skillDir)) {
|
|
1890
|
-
rmSync(skillDir, { recursive: true, force: true });
|
|
1891
|
-
}
|
|
1892
|
-
mkdirSync(skillDir, { recursive: true });
|
|
1893
|
-
// Normalise description — strip newlines and tabs to keep YAML
|
|
1894
|
-
// frontmatter on a single line. parsePluginFrontmatter uses a
|
|
1895
|
-
// single-line regex; an embedded newline (or `\n---\n`) would
|
|
1896
|
-
// otherwise corrupt the frontmatter parse and silently drop body
|
|
1897
|
-
// content from the agent prompt.
|
|
1898
|
-
const singleLineDescription = description.replace(/[\r\n\t]+/g, " ").trim();
|
|
1899
|
-
const escapedDescription = singleLineDescription.replace(/"/g, '\\"');
|
|
1900
|
-
const skillMd = `---
|
|
1901
|
-
name: ${skillName}
|
|
1902
|
-
description: "${escapedDescription}"
|
|
1903
|
-
publicEmbed: ${publicEmbed}
|
|
1904
|
-
---
|
|
1905
|
-
|
|
1906
|
-
${body}
|
|
1907
|
-
`;
|
|
1908
|
-
writeFileSync(resolve(skillDir, "SKILL.md"), skillMd);
|
|
1909
|
-
let refCount = 0;
|
|
1910
|
-
if (references.length > 0) {
|
|
1911
|
-
const refsDir = resolve(skillDir, "references");
|
|
1912
|
-
mkdirSync(refsDir, { recursive: true });
|
|
1913
|
-
for (const ref of references) {
|
|
1914
|
-
writeFileSync(resolve(refsDir, ref.filename), ref.content);
|
|
1915
|
-
refCount++;
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
// Write the `.user-mirror` marker to CANONICAL first — cpSync will
|
|
1919
|
-
// carry it into the platform-side mirror as part of the same recursive
|
|
1920
|
-
// copy. This eliminates the post-cpSync writeFileSync race: if cpSync
|
|
1921
|
-
// succeeds, the marker is already in target; if cpSync fails partway,
|
|
1922
|
-
// canonical's marker is intact and the next autoDeliverUserPlugins
|
|
1923
|
-
// call retries the copy. autoDeliverUserPlugins relies on the marker
|
|
1924
|
-
// arriving with the source tree — never writes its own marker.
|
|
1925
|
-
writeFileSync(resolve(canonicalPluginDir, ".user-mirror"), `pluginName=${pluginName}\nsource=${canonicalPluginDir}\n`);
|
|
1926
|
-
// Mirror to <PLATFORM_ROOT>/plugins/<pluginName>/ so the change is
|
|
1927
|
-
// visible to the loader without a session restart.
|
|
1928
|
-
mkdirSync(mirrorPluginDir, { recursive: true });
|
|
1929
|
-
cpSync(canonicalPluginDir, mirrorPluginDir, { recursive: true, force: true });
|
|
1930
|
-
const bodyBytes = Buffer.byteLength(body, "utf-8");
|
|
1931
|
-
console.log(`[store-skill] write pluginName=${pluginName} skillName=${skillName} publicEmbed=${publicEmbed} path=${canonicalPluginDir} bodyBytes=${bodyBytes} referenceCount=${refCount} action=${action}`);
|
|
1932
|
-
return {
|
|
1933
|
-
content: [{
|
|
1934
|
-
type: "text",
|
|
1935
|
-
text: `Skill "${skillName}" saved to plugin "${pluginName}" (${action}). publicEmbed=${publicEmbed}, references=${refCount}. Active immediately for the admin agent${publicEmbed ? "; surfaces in the public agent on next session start" : ""}.`,
|
|
1936
|
-
}],
|
|
1937
|
-
};
|
|
1938
|
-
}
|
|
1939
|
-
catch (err) {
|
|
1940
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1941
|
-
console.error(`[store-skill] ERROR pluginName=${pluginName} skillName=${skillName} reason=${msg.slice(0, 120)} path=${canonicalPluginDir}`);
|
|
1942
|
-
return { content: [{ type: "text", text: `Failed to write skill: ${msg}` }], isError: true };
|
|
1943
|
-
}
|
|
1855
|
+
const result = await storeSkillToAccount({
|
|
1856
|
+
accountDir,
|
|
1857
|
+
platformRoot: PLATFORM_ROOT,
|
|
1858
|
+
pluginName,
|
|
1859
|
+
skillName,
|
|
1860
|
+
description,
|
|
1861
|
+
publicEmbed,
|
|
1862
|
+
body,
|
|
1863
|
+
references,
|
|
1864
|
+
});
|
|
1865
|
+
if (!result.ok) {
|
|
1866
|
+
const isCollision = result.reason === "collision-with-shipped";
|
|
1867
|
+
console.error(`[store-skill] op=store-skill root=account path=${result.canonicalPluginDir} resolved=false reason=${result.reason} pluginName=${pluginName} skillName=${skillName} detail=${result.detail.slice(0, 120)}`);
|
|
1868
|
+
const text = isCollision
|
|
1869
|
+
? `pluginName "${pluginName}" collides with a shipped plugin. Choose a different pluginName.`
|
|
1870
|
+
: `Skill "${skillName}" was written to "${pluginName}" but did not register: ${result.detail}. Not activating.`;
|
|
1871
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
1872
|
+
}
|
|
1873
|
+
console.log(`[store-skill] op=store-skill root=account path=${result.canonicalPluginDir} resolved=true pluginName=${pluginName} skillName=${skillName} publicEmbed=${publicEmbed} bodyBytes=${result.bodyBytes} referenceCount=${result.refCount} action=${result.action}`);
|
|
1874
|
+
return {
|
|
1875
|
+
content: [{
|
|
1876
|
+
type: "text",
|
|
1877
|
+
text: `Skill "${skillName}" saved to plugin "${pluginName}" (${result.action}). publicEmbed=${publicEmbed}, references=${result.refCount}. Active immediately for the admin agent${publicEmbed ? "; surfaces in the public agent on next session start" : ""}.`,
|
|
1878
|
+
}],
|
|
1879
|
+
};
|
|
1944
1880
|
});
|
|
1945
1881
|
eagerTool(server, "plugin-read", "Read a plugin definition (PLUGIN.md) or one of its reference files.", {
|
|
1946
1882
|
pluginName: z.string().describe("Name of the plugin directory (e.g. 'sales', 'business-assistant')"),
|
|
@@ -1960,14 +1896,23 @@ eagerTool(server, "plugin-read", "Read a plugin definition (PLUGIN.md) or one of
|
|
|
1960
1896
|
console.log(`[admin-skill-gate] role=admin skill=${authoringSlug} decision=block reason=content-producer-owned`);
|
|
1961
1897
|
return { content: [{ type: "text", text: AUTHORING_DISPATCH_HINT }], isError: true };
|
|
1962
1898
|
}
|
|
1963
|
-
|
|
1899
|
+
// Task 1962 — operator-authored plugins live under the account root, not
|
|
1900
|
+
// the platform tree. Prefer the platform copy; fall back to the account
|
|
1901
|
+
// root so an operator plugin's PLUGIN.md / SKILL.md / references resolve.
|
|
1902
|
+
const accountPluginsDir = resolve(getAccountDir(), "plugins");
|
|
1903
|
+
const platformPath = resolve(PLATFORM_ROOT, "plugins", pluginName, resolvedFile);
|
|
1904
|
+
const accountPath = resolve(accountPluginsDir, pluginName, resolvedFile);
|
|
1905
|
+
const pluginPath = existsSync(platformPath) ? platformPath : accountPath;
|
|
1906
|
+
const pluginRootDir = existsSync(platformPath)
|
|
1907
|
+
? resolve(PLATFORM_ROOT, "plugins", pluginName)
|
|
1908
|
+
: resolve(accountPluginsDir, pluginName);
|
|
1964
1909
|
if (!existsSync(pluginPath)) {
|
|
1965
1910
|
// when the agent's pluginName/file combination misses
|
|
1966
1911
|
// a skill that DOES live under `plugins/*/skills/<slug>/SKILL.md`,
|
|
1967
1912
|
// surface the corrected pluginName AND the canonical file path so
|
|
1968
1913
|
// the next call is deterministic. Both wrong-`file` and wrong-`pluginName`
|
|
1969
1914
|
// shapes feed through `computePluginReadHint`.
|
|
1970
|
-
const hint = computePluginReadHint(PLATFORM_ROOT, pluginName, resolvedFile);
|
|
1915
|
+
const hint = computePluginReadHint(PLATFORM_ROOT, pluginName, resolvedFile, accountPluginsDir);
|
|
1971
1916
|
const hintText = hint ? ` Did you mean pluginName="${hint.pluginName}", file="${hint.file}"?` : "";
|
|
1972
1917
|
console.log(`[plugin-read] ${pluginName}/${resolvedFile} not-found hint=${hint ? hint.pluginName : "none"}`);
|
|
1973
1918
|
return {
|
|
@@ -1984,7 +1929,7 @@ eagerTool(server, "plugin-read", "Read a plugin definition (PLUGIN.md) or one of
|
|
|
1984
1929
|
// Append file inventory on default calls (PLUGIN.md) so agents can discover
|
|
1985
1930
|
// skill and reference paths without guessing
|
|
1986
1931
|
if (resolvedFile === "PLUGIN.md") {
|
|
1987
|
-
const pluginRoot =
|
|
1932
|
+
const pluginRoot = pluginRootDir;
|
|
1988
1933
|
const skills = [];
|
|
1989
1934
|
const references = [];
|
|
1990
1935
|
const scanDir = (base, prefix, target) => {
|
|
@@ -2044,7 +1989,7 @@ lifelineTool(server, "skill-find", "Find which plugin owns a skill by name. Walk
|
|
|
2044
1989
|
if (!ACCOUNT_ID)
|
|
2045
1990
|
return refuseNoAccount("skill-find");
|
|
2046
1991
|
const start = Date.now();
|
|
2047
|
-
const result = findSkillOwners(PLATFORM_ROOT, skillName);
|
|
1992
|
+
const result = findSkillOwners(PLATFORM_ROOT, skillName, resolve(getAccountDir(), "plugins"));
|
|
2048
1993
|
const ms = Date.now() - start;
|
|
2049
1994
|
console.log(`[skill-find] skillName=${skillName} result=${result.status} candidates=${result.candidates.length} ms=${ms}`);
|
|
2050
1995
|
if (result.status === "unique") {
|
|
@@ -2085,7 +2030,7 @@ eagerTool(server, "skill-search", "Find skills by free-text intent when you do n
|
|
|
2085
2030
|
if (!ACCOUNT_ID)
|
|
2086
2031
|
return refuseNoAccount("skill-search");
|
|
2087
2032
|
const start = Date.now();
|
|
2088
|
-
const hits = searchSkills(PLATFORM_ROOT, query);
|
|
2033
|
+
const hits = searchSkills(PLATFORM_ROOT, query, 5, resolve(getAccountDir(), "plugins"));
|
|
2089
2034
|
const ms = Date.now() - start;
|
|
2090
2035
|
const top = hits.length > 0 ? `${hits[0].pluginName}:${hits[0].skillName}` : "none";
|
|
2091
2036
|
console.log(`[skill-search] query=${JSON.stringify(query)} hits=${hits.length} top=${top} ms=${ms}`);
|
|
@@ -2134,7 +2079,7 @@ eagerTool(server, "skill-load", "Load a plugin skill's SKILL.md body by skill na
|
|
|
2134
2079
|
}
|
|
2135
2080
|
const start = Date.now();
|
|
2136
2081
|
try {
|
|
2137
|
-
const outcome = await loadSkill(PLATFORM_ROOT, skillName);
|
|
2082
|
+
const outcome = await loadSkill(PLATFORM_ROOT, skillName, resolve(getAccountDir(), "plugins"));
|
|
2138
2083
|
if (outcome.status === "ambiguous") {
|
|
2139
2084
|
const ms = Date.now() - start;
|
|
2140
2085
|
console.log(`[skill-load] skillName=${skillName} result=ambiguous pluginName=none file=none bodyBytes=0 ms=${ms}`);
|