agentplugged 1.0.2 → 1.0.3
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-commands.js
CHANGED
|
@@ -14500,6 +14500,10 @@ retrospective, an installation and a validation point never wait for it.
|
|
|
14500
14500
|
scope: \`guard.creator_action\` \`scope_widen\`) or a decision of the architecture contradicted, and
|
|
14501
14501
|
lets the write through in doubt. Reading, and writes in other tools, stay governed by the
|
|
14502
14502
|
permission rules alone: \`read_secrets\` is always denied, whatever the session.
|
|
14503
|
+
5. A write the engine refused is never redone by another path: not by a terminal command
|
|
14504
|
+
(\`sed -i\`, a redirection \`>\`, \`Set-Content\`, \`Out-File\`, a copy, a script), not by another tool.
|
|
14505
|
+
The agent stops, tells the coordinator which file it needs and why, and the coordinator offers
|
|
14506
|
+
the creator to widen the scope (\`guard.creator_action\` \`scope_widen\`) in one gesture.
|
|
14503
14507
|
`;
|
|
14504
14508
|
}
|
|
14505
14509
|
/** The folder layout and the seven rules: in the short constitution and in the reference alike. */
|
|
@@ -17783,6 +17787,21 @@ function claudeActionRules(action, mainBranch) {
|
|
|
17783
17787
|
push(rules, patternsOf(action, mainBranch).flatMap(claudeRules));
|
|
17784
17788
|
return rules;
|
|
17785
17789
|
}
|
|
17790
|
+
/**
|
|
17791
|
+
* The rules as Claude Code's settings hold them. A backslash right before the closing parenthesis
|
|
17792
|
+
* escapes it there, so such a rule is written with that one backslash doubled (the others are
|
|
17793
|
+
* read literally). Claude Code's `PowerShell` tool has its own rules: each `Bash(x)` rule gets
|
|
17794
|
+
* its `PowerShell(x)` twin, or a command would pass by being run through the other shell.
|
|
17795
|
+
*/
|
|
17796
|
+
function claudeCommandRules(rules) {
|
|
17797
|
+
const out = [];
|
|
17798
|
+
for (const rule of rules) {
|
|
17799
|
+
const escaped = rule.endsWith("\\)") && !rule.endsWith("\\\\)") ? `${rule.slice(0, -1)}\\)` : rule;
|
|
17800
|
+
push(out, [escaped]);
|
|
17801
|
+
if (escaped.startsWith("Bash(")) push(out, [`PowerShell${escaped.slice(4)}`]);
|
|
17802
|
+
}
|
|
17803
|
+
return out;
|
|
17804
|
+
}
|
|
17786
17805
|
/** The Claude Code rule that allows all the tools of the `agentplugged` MCP server. */
|
|
17787
17806
|
const ENGINE_MCP_RULE = "mcp__agentplugged";
|
|
17788
17807
|
/**
|
|
@@ -18991,13 +19010,22 @@ const WRITE_TOOLS = [
|
|
|
18991
19010
|
text: "new_source"
|
|
18992
19011
|
}
|
|
18993
19012
|
];
|
|
19013
|
+
/** The two tools that run a shell command in Claude Code: both carry it in `tool_input.command`. */
|
|
19014
|
+
const SHELL_MATCHER = "Bash|PowerShell";
|
|
19015
|
+
/**
|
|
19016
|
+
* The `if` conditions of a hook on the shell tools: each `Bash(x)` condition and its
|
|
19017
|
+
* `PowerShell(x)` twin, as a condition matches the calls of one tool only.
|
|
19018
|
+
*/
|
|
19019
|
+
function shellConditions(conditions) {
|
|
19020
|
+
return conditions.flatMap((condition) => [condition, `PowerShell${condition.slice(4)}`]);
|
|
19021
|
+
}
|
|
18994
19022
|
/** The hooks `sync` writes for Claude Code, from the rules in force. */
|
|
18995
19023
|
function claudeTrustHooks(rules, mainBranch) {
|
|
18996
19024
|
const session = hookValue("session_id");
|
|
18997
19025
|
const pre = [];
|
|
18998
|
-
const conditions = rules.install_dependency === "deny" ? [] : claudeActionRules("install_dependency", mainBranch).filter((entry) => entry.startsWith("Bash("));
|
|
19026
|
+
const conditions = rules.install_dependency === "deny" ? [] : shellConditions(claudeActionRules("install_dependency", mainBranch).filter((entry) => entry.startsWith("Bash(")));
|
|
18999
19027
|
if (conditions.length > 0) pre.push({
|
|
19000
|
-
matcher:
|
|
19028
|
+
matcher: SHELL_MATCHER,
|
|
19001
19029
|
hooks: conditions.map((condition) => handler("check_action", {
|
|
19002
19030
|
action: "install_dependency",
|
|
19003
19031
|
command: hookValue("tool_input.command"),
|
|
@@ -19032,9 +19060,9 @@ function claudeTrustHooks(rules, mainBranch) {
|
|
|
19032
19060
|
})]
|
|
19033
19061
|
},
|
|
19034
19062
|
{
|
|
19035
|
-
matcher:
|
|
19036
|
-
hooks: NETWORK_COMMANDS.map((condition) => handler("record_external_read", {
|
|
19037
|
-
tool: "Bash",
|
|
19063
|
+
matcher: SHELL_MATCHER,
|
|
19064
|
+
hooks: shellConditions(NETWORK_COMMANDS).map((condition) => handler("record_external_read", {
|
|
19065
|
+
tool: condition.startsWith("PowerShell(") ? "PowerShell" : "Bash",
|
|
19038
19066
|
source: hookValue("tool_input.command"),
|
|
19039
19067
|
session
|
|
19040
19068
|
}, condition))
|
|
@@ -19775,9 +19803,9 @@ const syncCommand = defineCommand({
|
|
|
19775
19803
|
flavor: claudeFlavor(loaded.config.permissions?.mode),
|
|
19776
19804
|
current: claudeSettings
|
|
19777
19805
|
}, has("claude-code") ? {
|
|
19778
|
-
deny:
|
|
19779
|
-
allow:
|
|
19780
|
-
ask:
|
|
19806
|
+
deny: claudeCommandRules(unique([...denyRules(permissionInputs), ...claudeRules.deny])),
|
|
19807
|
+
allow: claudeCommandRules(claudeRules.allow),
|
|
19808
|
+
ask: claudeCommandRules(claudeRules.ask)
|
|
19781
19809
|
} : {}, {
|
|
19782
19810
|
deny: manifest.permissions,
|
|
19783
19811
|
...previousLists[CLAUDE_SETTINGS_PATH]
|
|
@@ -19809,7 +19837,7 @@ const syncCommand = defineCommand({
|
|
|
19809
19837
|
count: owned.allow.length
|
|
19810
19838
|
});
|
|
19811
19839
|
}
|
|
19812
|
-
const conflicts = [...has("claude-code") ? allowConflicts(CLAUDE_SETTINGS_PATH, claudeSettings?.value, claudeRules.allow, {
|
|
19840
|
+
const conflicts = [...has("claude-code") ? allowConflicts(CLAUDE_SETTINGS_PATH, claudeSettings?.value, claudeCommandRules(claudeRules.allow), {
|
|
19813
19841
|
deny: manifest.permissions,
|
|
19814
19842
|
...previousLists[CLAUDE_SETTINGS_PATH]
|
|
19815
19843
|
}) : [], ...has("cursor") ? allowConflicts(CURSOR_CLI_PATH, cursorSettings?.value, cursorRules.allow, { deny: previousCursor }) : []];
|
|
@@ -19878,14 +19906,6 @@ const CODEX_HOME_DENY = [
|
|
|
19878
19906
|
function unique(rules) {
|
|
19879
19907
|
return [...new Set(rules)];
|
|
19880
19908
|
}
|
|
19881
|
-
/**
|
|
19882
|
-
* The rules Claude Code's settings can hold: a backslash before the closing parenthesis escapes it
|
|
19883
|
-
* there, so such a rule would be malformed (the `C:/` spelling of the same root stays). The
|
|
19884
|
-
* engine's own guards keep them: they read the rules themselves.
|
|
19885
|
-
*/
|
|
19886
|
-
function claudeWritable(rules) {
|
|
19887
|
-
return rules.filter((rule) => !rule.endsWith("\\)"));
|
|
19888
|
-
}
|
|
19889
19909
|
/** The tool a generated path belongs to, for the summary. */
|
|
19890
19910
|
function groupOf(path) {
|
|
19891
19911
|
if (path.startsWith(".claude/") || path === "CLAUDE.md") return "claude-code";
|
|
@@ -31012,7 +31032,7 @@ function readSource(tool, raw) {
|
|
|
31012
31032
|
const toolName = truncate(cleanText(tool), 200) || "unknown";
|
|
31013
31033
|
const given = cleanText(raw ?? "");
|
|
31014
31034
|
const usable = given !== "" && !given.includes("${");
|
|
31015
|
-
if (usable && toolName === "Bash") return {
|
|
31035
|
+
if (usable && (toolName === "Bash" || toolName === "PowerShell")) return {
|
|
31016
31036
|
tool: toolName,
|
|
31017
31037
|
source: truncate(hostOf$1(given, true) ?? commandName(given), 200)
|
|
31018
31038
|
};
|
|
@@ -59,6 +59,7 @@ back, and the decisions to take.
|
|
|
59
59
|
other tool under his id (`ROLE_FORBIDDEN`): he never opens a checkpoint (an end of phase
|
|
60
60
|
included), never starts or delivers a story, never submits a result in another agent's place.
|
|
61
61
|
He never reports under another agent's id.
|
|
62
|
+
- When a developer reports a write the engine refused, Noah never lets it be redone by another path (a terminal command, a redirection, a copy): he proposes to the creator to widen the scope (`guard.creator_action` `scope_widen`), in one gesture.
|
|
62
63
|
- Decisions belong to the creator: the scope, the options of a checkpoint, an approval, a new
|
|
63
64
|
agent, and every point they kept for themselves. Noah recommends; the creator decides. The points
|
|
64
65
|
they did not keep are decided by the agent responsible, never by Noah (`checkpoint.decide` is not
|
package/dist/product-root.js
CHANGED
|
@@ -16803,7 +16803,8 @@ function alreadyRecorded(listing, read, session) {
|
|
|
16803
16803
|
* source is a `${…}`), or for an absent source: when in doubt, the read counts.
|
|
16804
16804
|
*/
|
|
16805
16805
|
function isLocalShellCommand(tool, source) {
|
|
16806
|
-
|
|
16806
|
+
const shell = tool.trim();
|
|
16807
|
+
if (shell !== "Bash" && shell !== "PowerShell" || source === void 0) return false;
|
|
16807
16808
|
const command = source.trim();
|
|
16808
16809
|
if (command === "" || /^\$\{[^}]*\}$/.test(command) || /^https?:\/\//i.test(command)) return false;
|
|
16809
16810
|
return !isNetworkCommand(command);
|
|
@@ -17101,9 +17102,14 @@ const FILE_EXTENSIONS = "ts|tsx|js|jsx|mjs|cjs|json|jsonc|md|mdx|yaml|yml|toml|p
|
|
|
17101
17102
|
const CODE_SPAN = /`([^`\n]{1,200})`/g;
|
|
17102
17103
|
const BARE_PATH = new RegExp(`(?<![\\w@./:~-])((?:\\./)?[\\w@.-]+(?:/[\\w@.*-]+)*\\.(?:${FILE_EXTENSIONS}))(?![\\w/-])`, "g");
|
|
17103
17104
|
const BARE_FOLDER = /(?<![\w@./:~-])((?:\.\/)?[\w@.-]+(?:\/[\w@.*-]+)+\/)(?![\w])/g;
|
|
17105
|
+
const TEMPLATE_SEGMENT = /^(?:<[A-Za-z_][\w-]*>|\{[A-Za-z_][\w-]*\}|\[[A-Za-z_][\w-]*\]|:[A-Za-z_][\w-]*)$/;
|
|
17104
17106
|
/** A token read as a path of the project, or undefined (a URL, an absolute path, a word). */
|
|
17105
17107
|
function pathOf$1(token) {
|
|
17106
17108
|
let text = token.trim().replaceAll("\\", "/").replace(/^\{project-root\}\//, "").replace(/^\.\//, "");
|
|
17109
|
+
if (text.includes("/")) {
|
|
17110
|
+
if (TEMPLATE_SEGMENT.test(text.split("/")[0] ?? "")) return void 0;
|
|
17111
|
+
text = text.split("/").map((part) => TEMPLATE_SEGMENT.test(part) ? "*" : part).join("/");
|
|
17112
|
+
}
|
|
17107
17113
|
text = text.replace(/[:#][\w,-]*$/, "");
|
|
17108
17114
|
if (text === "" || text.length > 200) return void 0;
|
|
17109
17115
|
if (/^(?:[a-z][a-z0-9+.-]*:|\/|~|[A-Za-z]:)/.test(text) || text.includes("//")) return void 0;
|
|
@@ -18353,7 +18359,7 @@ async function judge(context, index, request, root) {
|
|
|
18353
18359
|
kind: "refuse",
|
|
18354
18360
|
rule: "scope",
|
|
18355
18361
|
story: owner.id,
|
|
18356
|
-
message: `AgentPlugged refused this write: rule scope, story ${owner.id} does not name ${oneLine(relative, 120)}. If it is needed, ask the creator to widen the scope (guard.creator_action scope_widen {story: "${owner.id}", paths: ["${oneLine(relative, 120)}"]}); otherwise leave that file alone. Nothing was written.`
|
|
18362
|
+
message: `AgentPlugged refused this write: rule scope, story ${owner.id} does not name ${oneLine(relative, 120)}. If it is needed, ask the creator to widen the scope (guard.creator_action scope_widen {story: "${owner.id}", paths: ["${oneLine(relative, 120)}"]}); otherwise leave that file alone: do not write it by another tool or command (sed -i, a redirection, Set-Content, a copy, a script), and tell the coordinator which file you need and why. Nothing was written.`
|
|
18357
18363
|
};
|
|
18358
18364
|
if (request.text !== void 0 && index.decisions !== void 0) {
|
|
18359
18365
|
const broken = decisionViolation(index.decisions.guards, relative, request.text);
|
|
@@ -18363,7 +18369,7 @@ async function judge(context, index, request, root) {
|
|
|
18363
18369
|
story: owner.id,
|
|
18364
18370
|
decision: broken.decision,
|
|
18365
18371
|
detail: broken.detail,
|
|
18366
|
-
message: `AgentPlugged refused this write: decision ${broken.decision} of the architecture forbids it (${oneLine(broken.detail, 120)}). Follow the decision, or ask the creator to change it first. Nothing was written.`
|
|
18372
|
+
message: `AgentPlugged refused this write: decision ${broken.decision} of the architecture forbids it (${oneLine(broken.detail, 120)}). Follow the decision, or ask the creator to change it first; do not write the file by another tool or command. Nothing was written.`
|
|
18367
18373
|
};
|
|
18368
18374
|
}
|
|
18369
18375
|
if (placed === void 0) return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentplugged",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Install the AgentPlugged method in a repository and make its agents callable from Claude Code, Codex, Antigravity/Gemini CLI and Cursor.",
|
|
5
5
|
"releaseSummary": "The engine updates itself: your session moves to a newer version between two calls, with nothing to reconnect.",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
"koffi": "~3.3.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@agentplugged/adapters-git": "1.0.
|
|
51
|
-
"@agentplugged/adapters-tools": "1.0.
|
|
52
|
-
"@agentplugged/core": "1.0.
|
|
53
|
-
"@agentplugged/crypto": "1.0.
|
|
54
|
-
"@agentplugged/i18n": "1.0.
|
|
55
|
-
"@agentplugged/mcp": "1.0.
|
|
50
|
+
"@agentplugged/adapters-git": "1.0.3",
|
|
51
|
+
"@agentplugged/adapters-tools": "1.0.3",
|
|
52
|
+
"@agentplugged/core": "1.0.3",
|
|
53
|
+
"@agentplugged/crypto": "1.0.3",
|
|
54
|
+
"@agentplugged/i18n": "1.0.3",
|
|
55
|
+
"@agentplugged/mcp": "1.0.3",
|
|
56
56
|
"@agentplugged/method": "0.0.0",
|
|
57
|
-
"@agentplugged/protocol": "1.0.
|
|
57
|
+
"@agentplugged/protocol": "1.0.3",
|
|
58
58
|
"@biomejs/biome": "~2.5.15",
|
|
59
59
|
"@modelcontextprotocol/client": "~2.3.0",
|
|
60
60
|
"@types/node": "^24.19.1",
|