@synadia-ai/agent-fabric-claude-code 0.2.0 → 0.3.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.
- package/.claude-plugin/plugin.json +1 -1
- package/BUILD +3 -3
- package/README.md +4 -2
- package/hooks/hooks.json +22 -0
- package/hooks/session-event.js +12 -9
- package/package.json +1 -1
- package/runtime/chunk-5ke4ws7r.js +38 -0
- package/runtime/fabric.js +5 -5
- package/runtime/server.js +38 -35
- package/skills/scratchpad/SKILL.md +87 -6
- package/skills/scratchpad/scripts/sp +13 -7
- package/runtime/chunk-prncr0vg.js +0 -38
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nats-channel",
|
|
3
|
-
"version": "0.6.0+fabric.
|
|
3
|
+
"version": "0.6.0+fabric.1ed73c1.e770d25",
|
|
4
4
|
"description": "NATS channel plugin for Claude Code — bridges NATS messaging to Claude Code sessions, with the Synadia Agent Fabric add-on and ScratchPad",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Synadia"
|
package/BUILD
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
plugin nats-channel 0.6.0
|
|
2
|
-
synadia-agents
|
|
3
|
-
agent-fabric-sdk
|
|
4
|
-
built 2026-10-
|
|
2
|
+
synadia-agents 1ed73c1
|
|
3
|
+
agent-fabric-sdk e770d25
|
|
4
|
+
built 2026-10-26T16:11:31.796Z
|
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ plugin for Claude Code (`nats-channel`), the fabric's tracing and
|
|
|
5
5
|
ScratchPad's skill. The Claude Code session becomes an agent on the fabric:
|
|
6
6
|
other agents find it and prompt it, its model calls join the prompt's
|
|
7
7
|
thread, and its own prompts to other agents hang under the tool call that
|
|
8
|
-
sent them.
|
|
8
|
+
sent them. A turn typed at the terminal is traced as a task of its own,
|
|
9
|
+
with the agents it prompts beneath it.
|
|
9
10
|
|
|
10
11
|
## Install
|
|
11
12
|
|
|
@@ -17,7 +18,7 @@ plugin; a marketplace names it with an npm source:
|
|
|
17
18
|
"name": "agent-fabric",
|
|
18
19
|
"owner": { "name": "Synadia" },
|
|
19
20
|
"plugins": [
|
|
20
|
-
{ "name": "nats-channel", "source": { "source": "npm", "package": "@synadia-ai/agent-fabric-claude-code", "version": "^0.
|
|
21
|
+
{ "name": "nats-channel", "source": { "source": "npm", "package": "@synadia-ai/agent-fabric-claude-code", "version": "^0.3.0" } }
|
|
21
22
|
]
|
|
22
23
|
}
|
|
23
24
|
```
|
|
@@ -52,6 +53,7 @@ environment:
|
|
|
52
53
|
| `SCRATCHPAD_VOLUME`, `SCRATCHPAD_DIR` | optional: the agent's ScratchPad volume and its private workspace |
|
|
53
54
|
|
|
54
55
|
`NATS_CONTEXT`, a NATS CLI context, wins over `NATS_URL` and `NATS_CREDS`.
|
|
56
|
+
A context in the plugin's own config file counts only when neither is set.
|
|
55
57
|
|
|
56
58
|
Start it with the channel, which is not on Claude Code's list of channels,
|
|
57
59
|
so it loads as a development channel, with the warning Claude Code shows
|
package/hooks/hooks.json
CHANGED
|
@@ -31,6 +31,28 @@
|
|
|
31
31
|
]
|
|
32
32
|
}
|
|
33
33
|
],
|
|
34
|
+
"UserPromptSubmit": [
|
|
35
|
+
{
|
|
36
|
+
"hooks": [
|
|
37
|
+
{
|
|
38
|
+
"type": "command",
|
|
39
|
+
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/hooks/session-event.js\"",
|
|
40
|
+
"timeout": 10
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"StopFailure": [
|
|
46
|
+
{
|
|
47
|
+
"hooks": [
|
|
48
|
+
{
|
|
49
|
+
"type": "command",
|
|
50
|
+
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/hooks/session-event.js\"",
|
|
51
|
+
"timeout": 10
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
34
56
|
"PreToolUse": [
|
|
35
57
|
{
|
|
36
58
|
"hooks": [
|
package/hooks/session-event.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{writeSync as
|
|
4
|
-
`)
|
|
5
|
-
`),
|
|
6
|
-
`),
|
|
7
|
-
`)}function
|
|
8
|
-
`)}function
|
|
9
|
-
`)){
|
|
10
|
-
`).trim()
|
|
11
|
-
`)}
|
|
3
|
+
import{writeSync as _n}from"fs";import{homedir as yn}from"os";import{join as bn}from"path";import{appendFileSync as Z,existsSync as hn,mkdirSync as y,readdirSync as kn,readFileSync as A,renameSync as z,rmSync as B,writeFileSync as G}from"fs";import{join as a}from"path";var X=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/,W=/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/,Q=["discover_agents","prompt_agent","wait_agent","answer_agent","cancel_agent","list_agent_calls"];function l(n){return typeof n==="string"&&X.test(n)}function K(n){return typeof n==="string"&&W.test(n)}function f(n){return a(n,"sessions")}function V(n,t){return a(f(n),String(t))}function w(n,t){return a(f(n),`${t}.stop`)}function E(n,t){return a(f(n),`${t}.nudge`)}function M(n,t){return a(f(n),`${t}.turn`)}function Y(n,t){return a(f(n),`${t}.open`)}function nn(n,t){return a(f(n),`${t}.tools`)}function T(n,t){return a(f(n),`${t}.events`)}function I(n,t){let e=`${n}.${process.pid}.tmp`;G(e,t),z(e,n)}var en=new RegExp(`^mcp__.+__(${Q.join("|")})$`);function tn(n){return en.test(n)}function q(n){if(!("background_tasks"in n)&&!("session_crons"in n))return;return N(n.background_tasks)||N(n.session_crons)}function N(n){if(n===void 0||n===null||n===!1||n===0||n==="")return!1;if(Array.isArray(n))return n.length>0;if(typeof n==="object")return Object.keys(n).length>0;return!0}var P=/^plugin:[^"]+:nats$/,v=/^[A-Za-z0-9_-]{1,64}$/,rn=1024,sn=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/,J=64,U=200;function on(n){if(typeof n!=="string"||!n.startsWith("<channel "))return;let t=n.indexOf(">");if(t<0||t>rn)return;let e=n.slice(0,t),r=/\ssource="([^"]*)"/.exec(e)?.[1],o=/\srequest_id="([^"]*)"/.exec(e)?.[1];if(r===void 0||o===void 0)return;if(!P.test(r)||!v.test(o))return;let s=/\sts="([^"]*)"/.exec(e)?.[1];return{requestId:o,source:r,...s!==void 0&&j(s)!==void 0?{ts:s}:{}}}function j(n){if(typeof n!=="string"||!sn.test(n))return;let t=Date.parse(n);return Number.isFinite(t)?t:void 0}function k(n,t){if(typeof n!=="string")return;let e=Array.from(n.replace(/[\u0000-\u001f\u007f]+/g," ").trim()).slice(0,t).join("");return e.length>0?e:void 0}function R(n,t,e){y(f(n),{recursive:!0}),Z(T(n,t),`${JSON.stringify(e)}
|
|
4
|
+
`)}function F(n,t,e,r=Date.now()){let o=e.hook_event_name,s=l(e.session_id)?e.session_id:void 0,i=l(e.prompt_id)?e.prompt_id:void 0;if(o==="UserPromptSubmit"){let d=on(e.prompt);return R(n,t,{event:"submit",...s?{session_id:s}:{},...i?{prompt_id:i}:{},...d?{request_id:d.requestId,source:d.source}:{},...d?.ts!==void 0?{ts:d.ts}:{},at_ms:r}),"submit"}if(o==="StopFailure"){let d=k(e.error,J),u=k(e.error_details,U);return R(n,t,{event:"failure",...s?{session_id:s}:{},...i?{prompt_id:i}:{},...d!==void 0?{error:d}:{},...u!==void 0?{error_details:u}:{},at_ms:r}),"failure"}if(o==="SessionStart"){if(s===void 0)return;let d=typeof e.source==="string"?e.source:"unknown";return y(f(n),{recursive:!0}),I(V(n,t),`${JSON.stringify({session_id:s,source:d,at_ms:r})}
|
|
5
|
+
`),"session"}if(o==="Stop"){let d=q(e),u=D(n,t,e),c=u===void 0||u.length>0?un(n,t)??H(e):void 0,m={...s?{session_id:s}:{},...d!==void 0?{background:d}:{},...c!==void 0?{final_text:c}:{},at_ms:r};return y(f(n),{recursive:!0}),I(w(n,t),`${JSON.stringify(m)}
|
|
6
|
+
`),R(n,t,{event:"stop",...i?{prompt_id:i}:{},...m}),ln(E(n,t)),"stop"}if(o==="PreToolUse"){let{tool_use_id:d,tool_name:u}=e;if(typeof u!=="string"||u.length===0)return;if(y(f(n),{recursive:!0}),dn(n,t,e.prompt_id,r),!tn(u)||!K(d))return"turn";let c=nn(n,t);return y(c,{recursive:!0}),I(a(c,d),`${JSON.stringify({tool_use_id:d,tool_name:u,tool_input:e.tool_input??null,...i?{prompt_id:i}:{},at_ms:r})}
|
|
7
|
+
`),"tool"}return}function dn(n,t,e,r){let o=l(e)?e:void 0,s=x(M(n,t)),i=g(s?.at_ms),d=g(s?.first_ms),u=g(x(w(n,t))?.at_ms),c=s!==void 0&&s.prompt_id===o&&i!==void 0&&d!==void 0&&(u===void 0||i>u);I(M(n,t),`${JSON.stringify({...o!==void 0?{prompt_id:o}:{},first_ms:c?d:r,at_ms:r})}
|
|
8
|
+
`)}function L(n,t,e){if(e.hook_event_name!=="Stop"||e.stop_hook_active===!0)return;if(q(e)!==!1)return;let r=D(n,t,e);if(r===void 0||r.length===0)return;let o=r.map((s)=>`"${s}"`).join(", ");return`The NATS channel ${r.length===1?"request":"requests"} ${o} ${r.length===1?"is":"are"} still open: the sender has not received an answer, and cannot see this session's own output. Send your answer with the reply tool (load it with ToolSearch if it is deferred), with the request_id and done: true.`}function C(n,t,e,r=Date.now()){let o=H(e);y(f(n),{recursive:!0}),I(E(n,t),`${JSON.stringify({...o!==void 0?{final_text:o}:{},at_ms:r})}
|
|
9
|
+
`)}function un(n,t){let e=x(E(n,t)),r=g(e?.at_ms);if(e===void 0||r===void 0)return;let o=g(x(w(n,t))?.at_ms);if(o!==void 0&&r<=o)return;let s=e.final_text;return typeof s==="string"&&s.length>0?s:void 0}function cn(n,t){let e=x(Y(n,t));if(!e)return;let r=e.server_pid,o=O(e.request_ids),s=e.open_ids===void 0?o:O(e.open_ids);if(typeof r!=="number"||!Number.isSafeInteger(r)||r<=0)return;if(o===void 0||s===void 0)return;if(!mn(r))return;let i=g(e.since_ms);return{requestIds:o,openIds:s,...i!==void 0?{sinceMs:i}:{}}}function O(n){return Array.isArray(n)&&n.every((t)=>typeof t==="string"&&v.test(t))?n:void 0}function D(n,t,e){let r=cn(n,t);if(r===void 0)return;let o=l(e.prompt_id)?e.prompt_id:void 0;if(o===void 0)return r.requestIds;let s=gn(n,t);if(!s.some((u)=>u.kind==="submit"&&u.submit.promptId!==void 0))return r.requestIds;let i=new Map,d;for(let u of s){if(u.kind!=="submit"||u.submit.requestId===void 0){d=void 0;continue}let{requestId:c,promptId:m,atMs:b,sentAtMs:_}=u.submit,S=d!==void 0&&b-d.atMs<=fn?d.promptIds:new Set;S.add(m);let p=r.sinceMs;if(p===void 0||b>=p&&(_??p)>=p)i.set(c,S);d={atMs:b,promptIds:S}}return r.openIds.filter((u)=>i.get(u)?.has(o)===!0)}var fn=30000;function H(n){if("last_assistant_message"in n){let i=n.last_assistant_message;return typeof i==="string"&&i.trim().length>0?i.trim():void 0}let t=n.transcript_path;if(typeof t!=="string"||t.length===0)return;let e;try{e=A(t,"utf8")}catch{return}let r,o=[];for(let i of e.split(`
|
|
10
|
+
`)){if(i.trim().length===0)continue;let d;try{d=JSON.parse(i)}catch{continue}if(typeof d!=="object"||d===null)continue;let{type:u,message:c,uuid:m}=d;if(u!=="assistant"||typeof c!=="object"||c===null)continue;let{id:b,content:_}=c,h=b??m;if(h===void 0||h!==r)r=h,o=[];if(typeof _==="string")o.push(_);else if(Array.isArray(_))for(let S of _){let p=S;if(p?.type==="text"&&typeof p.text==="string")o.push(p.text)}}let s=o.join(`
|
|
11
|
+
`).trim();return s.length>0?s:void 0}function x(n){let t;try{t=A(n,"utf8")}catch{return}try{let e=JSON.parse(t);return typeof e==="object"&&e!==null&&!Array.isArray(e)?e:void 0}catch{return}}function g(n){return typeof n==="number"&&Number.isSafeInteger(n)&&n>=0?n:void 0}function an(n){if(!n)return;let t=g(n.at_ms);if(t===void 0)return;return{...l(n.session_id)?{sessionId:n.session_id}:{},...l(n.prompt_id)?{promptId:n.prompt_id}:{},...typeof n.background==="boolean"?{background:n.background}:{},...typeof n.final_text==="string"&&n.final_text.length>0?{finalText:n.final_text}:{},atMs:t}}function pn(n){let t;try{t=JSON.parse(n)}catch{return}if(typeof t!=="object"||t===null||Array.isArray(t))return;let e=t,r=g(e.at_ms);if(r===void 0)return;let o={...l(e.session_id)?{sessionId:e.session_id}:{},...l(e.prompt_id)?{promptId:e.prompt_id}:{}};switch(e.event){case"submit":{let s=typeof e.request_id==="string"&&v.test(e.request_id)&&typeof e.source==="string"&&P.test(e.source)?{requestId:e.request_id,source:e.source}:{},i=s.requestId!==void 0?j(e.ts):void 0;return{kind:"submit",submit:{...o,...s,...i!==void 0?{sentAtMs:i}:{},atMs:r}}}case"stop":{let s=an(e);return s?{kind:"stop",stop:s}:void 0}case"failure":{let s=k(e.error,J),i=k(e.error_details,U);return{kind:"failure",failure:{...o,...s!==void 0?{error:s}:{},...i!==void 0?{errorDetails:i}:{},atMs:r}}}default:return}}function gn(n,t){let e;try{e=A(T(n,t),"utf8")}catch{return[]}let r=[],o=e.lastIndexOf(`
|
|
12
|
+
`);for(let s of e.slice(0,o+1).split(`
|
|
13
|
+
`)){if(s.length===0)continue;let i=pn(s);if(i)r.push(i)}return r}function ln(n){try{B(n,{recursive:!0,force:!0})}catch{}}function mn(n){try{return process.kill(n,0),!0}catch(t){return t.code==="EPERM"}}var Sn=5000;setTimeout(()=>process.exit(0),Sn).unref();async function In(){let n=[];for await(let t of process.stdin)n.push(Buffer.from(t));return Buffer.concat(n).toString("utf8")}try{let n=process.env.CLAUDE_PID;if(n!==void 0&&/^\d+$/.test(n)){let t=JSON.parse(await In());if(typeof t==="object"&&t!==null&&!Array.isArray(t)){let e=process.env.NATS_STATE_DIR??bn(yn(),".claude","channels","nats"),r=t,o=L(e,n,r);if(o!==void 0){try{C(e,n,r)}catch{}_n(1,`${JSON.stringify({decision:"block",reason:o})}
|
|
14
|
+
`)}else F(e,n,r)}}}catch{}process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synadia-ai/agent-fabric-claude-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Claude Code on the Synadia Agent Fabric: the NATS channel plugin for Claude Code with the fabric's tracing and ScratchPad, in one plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|