@staix/agent-hub 0.29.0 → 0.30.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/CHANGELOG.md +12 -0
- package/README.md +5 -3
- package/docs/agent-notes/README.md +12 -0
- package/docs/agent-notes/adapters.md +2 -1
- package/docs/agent-notes/bus.md +1 -0
- package/docs/agent-notes/daemon.md +2 -1
- package/docs/agent-notes/tasks.md +4 -2
- package/docs/agent-notes/tests.md +2 -0
- package/docs/design/adapters.md +56 -0
- package/docs/design/agent-hub-architecture.md +12 -0
- package/docs/design/bus.md +8 -0
- package/docs/design/task-board.md +18 -0
- package/docs/dogfood.md +7 -4
- package/docs/operations.md +106 -11
- package/docs/quickstart.md +10 -3
- package/docs/sdlc.md +1 -1
- package/docs/security.md +28 -2
- package/docs/smoke.md +13 -2
- package/docs/specs/2026-10-12-office-view-design.md +86 -3
- package/docs/verification/2026-11-03-0.30.0.md +54 -0
- package/docs/verification/2026-11-03-agy-1.4.12-launcher-nonce.md +42 -0
- package/docs/verification/2026-11-03-agy-1.4.12.md +90 -0
- package/docs/verification/2026-11-03-agy-tui-close.md +49 -0
- package/docs/verification/2026-11-03-grok-1.0.62-t0.md +150 -0
- package/docs/verification/2026-11-03-pi-150-compat.md +40 -0
- package/docs/verification/2026-11-03-pi-title-api.md +26 -0
- package/docs/verification/2026-11-03-qwen-0265-acp.md +55 -0
- package/docs/verification/2026-11-03-qwen-0265-dual-output.md +40 -0
- package/docs/verification/dogfood/2026-11-03.md +3095 -0
- package/docs/verification/pi-150-model-free.ts +57 -0
- package/docs/verification/pi-150-native.mjs +21 -0
- package/docs/verification/pi-150-title-api.mjs +31 -0
- package/docs/verified.json +14 -14
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +193 -29
- package/src/adapters/compat.ts +10 -10
- package/src/adapters/definitions/builtin-metadata.ts +2 -2
- package/src/adapters/local-worker.ts +22 -6
- package/src/adapters/pi.ts +92 -10
- package/src/adapters/registry-types.ts +4 -0
- package/src/adapters/registry.ts +2 -0
- package/src/cli/autonomy.ts +66 -1
- package/src/cli/console-state.ts +6 -2
- package/src/cli/help.ts +2 -0
- package/src/cli/identity.ts +8 -1
- package/src/cli/main.ts +39 -0
- package/src/cli/worktree-tidy.ts +158 -0
- package/src/cli/worktrees-output.ts +43 -0
- package/src/hub/board.ts +28 -3
- package/src/hub/bus.ts +4 -4
- package/src/hub/conductor.ts +4 -3
- package/src/hub/config-apply.ts +2 -1
- package/src/hub/daemon.ts +237 -19
- package/src/hub/dogfood-read.ts +62 -9
- package/src/hub/hub-tools.ts +11 -5
- package/src/hub/manager.ts +9 -1
- package/src/hub/peer-doing.ts +33 -3
- package/src/hub/peers.ts +7 -0
- package/src/hub/settings.ts +3 -0
- package/src/hub/tasks.ts +30 -8
- package/src/hub/ui.ts +2 -0
- package/src/hub/worktree-prs.ts +100 -0
- package/src/hub/worktree-shelf.ts +246 -0
- package/src/memory/capture.ts +1 -1
- package/src/pi/extension.ts +43 -3
- package/src/ui/index.html +133 -10
- package/src/ui/office-model.ts +64 -8
- package/src/ui/office-space.ts +1 -0
- package/src/ui/plugin.ts +14 -3
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {mkdtempSync, mkdirSync, readFileSync} from 'node:fs';
|
|
2
|
+
import {join, resolve} from 'node:path';
|
|
3
|
+
import {homedir} from 'node:os';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
const launcher=resolve(process.argv[2] ?? join(homedir(),'.pi/agent/bin/pi'));
|
|
7
|
+
const packageRoot=resolve(process.argv[3] ?? join(homedir(),'.pi/agent/install/releases/1.5.0/node_modules/@earendil-works/pi-coding-agent'));
|
|
8
|
+
const extension=fileURLToPath(new URL('../../src/pi/extension.ts',import.meta.url));
|
|
9
|
+
const driver=fileURLToPath(new URL('./pi-150-native.mjs',import.meta.url));
|
|
10
|
+
import {PiToolReceipts} from '../../src/pi/tool-receipts.ts';
|
|
11
|
+
const home=mkdtempSync('/tmp/ahub-684-pi-native-home.'); mkdirSync(join(home,'agent'));
|
|
12
|
+
const pkg=JSON.parse(readFileSync(join(packageRoot,'package.json'),'utf8'));
|
|
13
|
+
assert.equal(pkg.name,'@earendil-works/pi-coding-agent');assert.equal(pkg.version,'1.5.0');
|
|
14
|
+
const version=Bun.spawn([launcher,'--version'],{cwd:home,env:{HOME:home,PATH:process.env.PATH!,PI_CODING_AGENT_DIR:join(home,'agent')},stdin:'ignore',stdout:'pipe',stderr:'pipe'});
|
|
15
|
+
const versionTimer=setTimeout(()=>version.kill(),10000);
|
|
16
|
+
const [versionCode,versionOut,versionErr]=await Promise.all([version.exited,new Response(version.stdout).text(),new Response(version.stderr).text()]);clearTimeout(versionTimer);
|
|
17
|
+
assert.equal(versionCode,0);assert.equal(versionOut.trim(),'1.5.0');assert.equal(versionErr,'');
|
|
18
|
+
const ledger=new PiToolReceipts(join(home,'hub.db'));
|
|
19
|
+
let effects=0, providers=0; const events:any[]=[];
|
|
20
|
+
const bridge=Bun.serve({hostname:'127.0.0.1',port:0,async fetch(req){
|
|
21
|
+
const url=new URL(req.url); if(req.headers.get('authorization')!=='Bearer fixture')return new Response('forbidden',{status:403});
|
|
22
|
+
if(url.pathname==='/commands') {await Bun.sleep(25);return Response.json({command:null});}
|
|
23
|
+
const body=await req.json() as any;
|
|
24
|
+
if(url.pathname==='/event'){events.push(body.type);return Response.json({ok:true});}
|
|
25
|
+
if(url.pathname==='/budget')return Response.json({decisions:[]});
|
|
26
|
+
if(url.pathname==='/tool') {
|
|
27
|
+
const text=await ledger.execute(body.sessionId,body.toolCallId,body.name,body.args,async()=>{
|
|
28
|
+
if(body.args.value==='deny')return 'error: fixture permission denied';
|
|
29
|
+
effects++;return 'fixture success';
|
|
30
|
+
});
|
|
31
|
+
return Response.json({text,failed:text.startsWith('error:')});
|
|
32
|
+
}
|
|
33
|
+
providers++;return new Response('provider forbidden',{status:500});
|
|
34
|
+
}});
|
|
35
|
+
const env={HOME:home,PATH:process.env.PATH!,PI_CODING_AGENT_DIR:join(home,'agent'),HUB_EXTENSION:extension,PI_COMPAT_PACKAGE:packageRoot,
|
|
36
|
+
AGENTHUB_PI_BRIDGE_URL:`http://127.0.0.1:${bridge.port}`,AGENTHUB_PI_BRIDGE_TOKEN:'fixture',AGENTHUB_PI_OWNER_TOKEN:'fixture',
|
|
37
|
+
AGENTHUB_PI_TOOLS:JSON.stringify([{name:'compat_probe',description:'model-free fixture',parameters:{type:'object',properties:{value:{type:'string'}},required:['value']}}])};
|
|
38
|
+
const child=Bun.spawn(['node',driver],{cwd:home,env,stdin:'ignore',stdout:'pipe',stderr:'pipe'});
|
|
39
|
+
const timer=setTimeout(()=>child.kill(),10000);
|
|
40
|
+
const [code,stdout,stderr]=await Promise.all([child.exited,new Response(child.stdout).text(),new Response(child.stderr).text()]);clearTimeout(timer);
|
|
41
|
+
console.log(JSON.stringify({code,stdout,stderr,effects,providers,events,isolatedHome:home}));
|
|
42
|
+
const native=Bun.spawn([launcher,'--mode','rpc','--provider','agent-hub-local','--model','fixture','--no-builtin-tools','--no-skills','--no-prompt-templates','--no-extensions','--extension',env.HUB_EXTENSION,'--session-dir',join(home,'native-sessions')],{
|
|
43
|
+
cwd:home,env:{...env,AGENTHUB_PI_RELAY_URL:`http://127.0.0.1:${bridge.port}/v1`,AGENTHUB_PI_RELAY_TOKEN:'fixture',AGENTHUB_PI_MODELS:JSON.stringify([{id:'fixture',name:'fixture'}])},stdin:'pipe',stdout:'pipe',stderr:'pipe'});
|
|
44
|
+
native.stdin.write(JSON.stringify({id:'probe',type:'get_state'})+'\n');
|
|
45
|
+
const nativeTimer=setTimeout(()=>native.kill(),10000);
|
|
46
|
+
let wire='';for await(const chunk of native.stdout){wire+=new TextDecoder().decode(chunk);if(wire.includes('"command":"get_state"')){native.kill();break;}}
|
|
47
|
+
await native.exited;clearTimeout(nativeTimer);const nativeErr=await new Response(native.stderr).text();
|
|
48
|
+
console.log(JSON.stringify({nativeRpc:wire,nativeStderr:nativeErr,providers,events}));
|
|
49
|
+
bridge.stop(true);await ledger.close();
|
|
50
|
+
assert.equal(code,0);assert.equal(stderr,'');
|
|
51
|
+
const result=JSON.parse(stdout);
|
|
52
|
+
assert.equal(result.extension,'loaded');assert.equal(result.first.isError,false);assert.deepEqual(result.first,result.replay);assert.equal(result.denied.isError,true);
|
|
53
|
+
assert.equal(effects,1);assert.equal(providers,0);assert.equal(nativeErr,'');
|
|
54
|
+
const state=wire.trim().split('\n').map(line=>JSON.parse(line)).find(item=>item.command==='get_state');
|
|
55
|
+
assert.equal(state?.success,true);assert.equal(state.data.messageCount,0);assert.ok(state.data.sessionId);assert.ok(state.data.sessionFile);
|
|
56
|
+
assert.ok(events.includes('session_start'));assert.ok(events.includes('session_shutdown'));
|
|
57
|
+
console.log('pi 1.5.0 model-free receipt: PASS');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
const { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager } = await import(pathToFileURL(`${process.env.PI_COMPAT_PACKAGE}/dist/index.js`).href);
|
|
3
|
+
const cwd = process.env.HOME;
|
|
4
|
+
const settingsManager = SettingsManager.create(cwd, process.env.PI_CODING_AGENT_DIR);
|
|
5
|
+
const loader = new DefaultResourceLoader({cwd, agentDir:process.env.PI_CODING_AGENT_DIR, settingsManager,
|
|
6
|
+
noExtensions:true, additionalExtensionPaths:[process.env.HUB_EXTENSION], noSkills:true, noPromptTemplates:true, noThemes:true});
|
|
7
|
+
await loader.reload();
|
|
8
|
+
const {session, extensionsResult} = await createAgentSession({cwd, agentDir:process.env.PI_CODING_AGENT_DIR,
|
|
9
|
+
resourceLoader:loader, settingsManager, sessionManager:SessionManager.create(cwd, `${cwd}/sessions`), noTools:'builtin'});
|
|
10
|
+
if (extensionsResult.errors.length) throw new Error(JSON.stringify(extensionsResult.errors));
|
|
11
|
+
await session.bindExtensions({mode:'rpc'});
|
|
12
|
+
const tool = session.extensionRunner.getAllRegisteredTools().find(t=>t.definition.name==='compat_probe');
|
|
13
|
+
if (!tool) throw new Error('hub extension tool not registered');
|
|
14
|
+
const invoke = async (id, args) => tool.definition.execute(id, args, new AbortController().signal);
|
|
15
|
+
const first = await invoke('same-call', {value:'fixture'});
|
|
16
|
+
const replay = await invoke('same-call', {value:'fixture'});
|
|
17
|
+
const denied = await invoke('denied-call', {value:'deny'});
|
|
18
|
+
console.log(JSON.stringify({extension:'loaded',first,replay,denied,tools:session.getActiveToolNames()}));
|
|
19
|
+
await session.extensionRunner.emit({type:'session_shutdown'});
|
|
20
|
+
session.dispose();
|
|
21
|
+
process.exit(0);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import {pathToFileURL} from 'node:url';
|
|
3
|
+
import {writeFileSync,readFileSync} from 'node:fs';
|
|
4
|
+
import {userInfo} from 'node:os';
|
|
5
|
+
const root=process.env.PI_TITLE_PACKAGE;
|
|
6
|
+
assert.equal(JSON.parse(readFileSync(`${root}/package.json`)).version,'1.5.0');
|
|
7
|
+
const cwd=process.env.HOME, agentDir=process.env.PI_CODING_AGENT_DIR;
|
|
8
|
+
assert.ok(cwd && cwd !== userInfo().homedir, 'fresh isolated HOME required');
|
|
9
|
+
assert.equal(process.cwd(),cwd,'run from disposable HOME');
|
|
10
|
+
assert.ok(agentDir?.startsWith(`${cwd}/`),'tool home must be inside disposable HOME');
|
|
11
|
+
const {createAgentSession,DefaultResourceLoader,SessionManager,SettingsManager}=await import(pathToFileURL(`${root}/dist/index.js`));
|
|
12
|
+
const extension=`${cwd}/title-extension.mjs`;
|
|
13
|
+
writeFileSync(extension,`export default function(pi) { let observedName; pi.on('session_info_changed',event=>{observedName=event.name;}); pi.registerTool({name:'title_probe', label:'Title probe',description:'Model-free title API probe',parameters:{type:'object',properties:{}},async execute(){ const before=pi.getSessionName(); pi.setSessionName('Fixture session title'); const after=pi.getSessionName(); return {content:[{type:'text',text:JSON.stringify({before:before??null,after,observedName})}],details:{}}; }}); }`);
|
|
14
|
+
const settingsManager=SettingsManager.create(cwd,agentDir);
|
|
15
|
+
const loader=new DefaultResourceLoader({cwd,agentDir,settingsManager,noExtensions:true,additionalExtensionPaths:[extension],noSkills:true,noPromptTemplates:true,noThemes:true});
|
|
16
|
+
await loader.reload();
|
|
17
|
+
const manager=SessionManager.create(cwd,`${cwd}/sessions`);
|
|
18
|
+
manager.appendMessage({role:'user',content:[{type:'text',text:'Synthetic session persistence fixture; never sent to a model.'}],timestamp:Date.now()});
|
|
19
|
+
const {session,extensionsResult}=await createAgentSession({cwd,agentDir,settingsManager,resourceLoader:loader,sessionManager:manager,noTools:'builtin'});
|
|
20
|
+
assert.deepEqual(extensionsResult.errors,[]);
|
|
21
|
+
await session.bindExtensions({mode:'rpc'});
|
|
22
|
+
const tool=session.extensionRunner.getAllRegisteredTools().find(t=>t.definition.name==='title_probe');
|
|
23
|
+
assert.ok(tool);
|
|
24
|
+
const result=await tool.definition.execute('probe',{},new AbortController().signal);
|
|
25
|
+
assert.deepEqual(JSON.parse(result.content[0].text),{before:null,after:'Fixture session title',observedName:'Fixture session title'});
|
|
26
|
+
assert.equal(manager.getSessionName(),'Fixture session title');
|
|
27
|
+
assert.equal(session.sessionName,'Fixture session title');
|
|
28
|
+
const file=manager.getSessionFile();
|
|
29
|
+
session.dispose();
|
|
30
|
+
assert.equal(SessionManager.open(file).getSessionName(),'Fixture session title');
|
|
31
|
+
console.log(JSON.stringify({version:'1.5.0',setter:'ExtensionAPI.setSessionName(name: string): void',reader:'ExtensionAPI.getSessionName(): string | undefined',sessionReader:'SessionManager.getSessionName()',reopen:'PASS',nativeTitleEvent:'PASS',modelRequests:0,result:'PASS'}));
|
package/docs/verified.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"documents": {
|
|
4
4
|
"README.md": {
|
|
5
|
-
"verifiedAgainst": "
|
|
5
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
6
6
|
"paths": [
|
|
7
7
|
"package.json",
|
|
8
8
|
"src/",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"docs/security.md": {
|
|
14
|
-
"verifiedAgainst": "
|
|
14
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
15
15
|
"paths": [
|
|
16
16
|
"src/",
|
|
17
17
|
"templates/"
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
"docs/operations.md": {
|
|
21
|
-
"verifiedAgainst": "
|
|
21
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
22
22
|
"paths": [
|
|
23
23
|
"package.json",
|
|
24
24
|
"src/",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
]
|
|
36
36
|
},
|
|
37
37
|
"docs/quickstart.md": {
|
|
38
|
-
"verifiedAgainst": "
|
|
38
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
39
39
|
"paths": [
|
|
40
40
|
"package.json",
|
|
41
41
|
"src/",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
45
|
"docs/agent-notes/adapters.md": {
|
|
46
|
-
"verifiedAgainst": "
|
|
46
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
47
47
|
"paths": [
|
|
48
48
|
"src/adapters/",
|
|
49
49
|
"src/pi/",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
83
|
"docs/agent-notes/benchmarks.md": {
|
|
84
|
-
"verifiedAgainst": "
|
|
84
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
85
85
|
"paths": [
|
|
86
86
|
"scripts/benchmarks/",
|
|
87
87
|
"test/benchmarks/",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
]
|
|
94
94
|
},
|
|
95
95
|
"docs/agent-notes/budget.md": {
|
|
96
|
-
"verifiedAgainst": "
|
|
96
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
97
97
|
"paths": [
|
|
98
98
|
"src/hub/budget.ts",
|
|
99
99
|
"src/cli/statusline-tee.ts",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
]
|
|
118
118
|
},
|
|
119
119
|
"docs/agent-notes/bus.md": {
|
|
120
|
-
"verifiedAgainst": "
|
|
120
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
121
121
|
"paths": [
|
|
122
122
|
"src/hub/bus.ts",
|
|
123
123
|
"src/hub/envelope.ts",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
]
|
|
133
133
|
},
|
|
134
134
|
"docs/agent-notes/daemon.md": {
|
|
135
|
-
"verifiedAgainst": "
|
|
135
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
136
136
|
"paths": [
|
|
137
137
|
"src/hub/daemon.ts",
|
|
138
138
|
"src/hub/control-client.ts",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
]
|
|
224
224
|
},
|
|
225
225
|
"docs/agent-notes/local-worker.md": {
|
|
226
|
-
"verifiedAgainst": "
|
|
226
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
227
227
|
"paths": [
|
|
228
228
|
"src/adapters/local-worker.ts",
|
|
229
229
|
"src/local/",
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
]
|
|
244
244
|
},
|
|
245
245
|
"docs/agent-notes/tasks.md": {
|
|
246
|
-
"verifiedAgainst": "
|
|
246
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
247
247
|
"paths": [
|
|
248
248
|
"src/hub/tasks.ts",
|
|
249
249
|
"src/hub/board.ts",
|
|
@@ -291,7 +291,7 @@
|
|
|
291
291
|
]
|
|
292
292
|
},
|
|
293
293
|
"docs/agent-notes/tests.md": {
|
|
294
|
-
"verifiedAgainst": "
|
|
294
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
295
295
|
"paths": [
|
|
296
296
|
"test/",
|
|
297
297
|
"scripts/check.sh",
|
|
@@ -320,7 +320,7 @@
|
|
|
320
320
|
]
|
|
321
321
|
},
|
|
322
322
|
"docs/agent-notes/README.md": {
|
|
323
|
-
"verifiedAgainst": "
|
|
323
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
324
324
|
"paths": [
|
|
325
325
|
"src/cli/console-state.ts",
|
|
326
326
|
"src/cli/attention.ts",
|
|
@@ -329,7 +329,7 @@
|
|
|
329
329
|
]
|
|
330
330
|
},
|
|
331
331
|
"src/cli/help.ts": {
|
|
332
|
-
"verifiedAgainst": "
|
|
332
|
+
"verifiedAgainst": "8612cfd740abd013689532d993ebc981548510bb",
|
|
333
333
|
"paths": [
|
|
334
334
|
"src/cli/main.ts",
|
|
335
335
|
"src/cli/launch.ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staix/agent-hub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Native multi-agent hub: Claude Code, Codex, Kimi Code, Pi and local inference as peers in one project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"bun": ">=1.4.2"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@staix/agent-mem": "0.20.
|
|
20
|
+
"@staix/agent-mem": "0.20.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-hub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Channel between Claude Code and the agent-hub daemon: peer messages from Codex, Kimi and the local worker arrive as channel events; hub_send replies.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Young Joon Lee",
|