@jaeboong/a2ab 0.1.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.
@@ -0,0 +1,24 @@
1
+ import type { Broker } from './broker.js';
2
+ export type WatchTick = 'none' | 'popped' | 'lock-lost' | 'offline';
3
+ export interface WatchContext {
4
+ readonly broker: Broker;
5
+ readonly sessionId: string;
6
+ readonly lockPath: string;
7
+ readonly nonce: string;
8
+ }
9
+ export interface RunWatchOptions {
10
+ readonly pollMs?: number;
11
+ readonly maxMs?: number;
12
+ }
13
+ export interface WatchResult {
14
+ readonly exitCode: number;
15
+ readonly payload?: string;
16
+ }
17
+ export declare function watchLockPath(rootDir: string, sessionId: string): string;
18
+ export declare function acquireLock(lockPath: string, nonce: string): void;
19
+ export declare function checkOnce(ctx: WatchContext): {
20
+ tick: WatchTick;
21
+ payload?: string;
22
+ };
23
+ export declare function runWatch(broker: Broker, sessionId: string, rootDir: string, opts?: RunWatchOptions): Promise<WatchResult>;
24
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGxE;AAGD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGjE;AAWD,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBlF;AAMD,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,WAAW,CAAC,CAqBtB"}
package/dist/watch.js ADDED
@@ -0,0 +1,68 @@
1
+ // 인박스 감시자 — idle 세션 깨우기.
2
+ // Stop/SessionStart hook에서 asyncRewake로 실행되어 백그라운드에서 인박스를 감시한다.
3
+ // request가 도착하면 pop 후 exit 2 → Claude Code가 모델을 깨워 페이로드를 주입한다.
4
+ // notification은 깨우지 않는다 (프로토콜 2.1: push 불가).
5
+ import { randomUUID } from 'node:crypto';
6
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
7
+ import { dirname, join } from 'node:path';
8
+ import { buildRequestInjection } from './hooks.js';
9
+ export function watchLockPath(rootDir, sessionId) {
10
+ const safe = sessionId.replace(/[^A-Za-z0-9._-]/g, '_');
11
+ return join(rootDir, 'watch', `${safe}.lock`);
12
+ }
13
+ // 세션당 watcher는 하나만: 최신 watcher가 lock을 덮어쓰면 이전 것은 스스로 물러난다.
14
+ export function acquireLock(lockPath, nonce) {
15
+ mkdirSync(dirname(lockPath), { recursive: true });
16
+ writeFileSync(lockPath, JSON.stringify({ nonce, pid: process.pid }), 'utf8');
17
+ }
18
+ function ownsLock(lockPath, nonce) {
19
+ try {
20
+ const lock = JSON.parse(readFileSync(lockPath, 'utf8'));
21
+ return lock.nonce === nonce;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ export function checkOnce(ctx) {
28
+ if (!ownsLock(ctx.lockPath, ctx.nonce)) {
29
+ return { tick: 'lock-lost' };
30
+ }
31
+ const session = ctx.broker.getSession(ctx.sessionId);
32
+ if (session === undefined || session.status === 'offline') {
33
+ return { tick: 'offline' };
34
+ }
35
+ const requests = ctx.broker.popRequests(ctx.sessionId);
36
+ if (requests.length > 0) {
37
+ return {
38
+ tick: 'popped',
39
+ payload: buildRequestInjection(ctx.sessionId, requests, ctx.broker),
40
+ };
41
+ }
42
+ return { tick: 'none' };
43
+ }
44
+ function sleep(ms) {
45
+ return new Promise((resolve) => setTimeout(resolve, ms));
46
+ }
47
+ export async function runWatch(broker, sessionId, rootDir, opts = {}) {
48
+ const pollMs = opts.pollMs ?? 1500;
49
+ // hook timeout(14400s)보다 약간 짧게 스스로 종료한다.
50
+ const maxMs = opts.maxMs ?? 14_100_000;
51
+ const lockPath = watchLockPath(rootDir, sessionId);
52
+ const nonce = randomUUID();
53
+ acquireLock(lockPath, nonce);
54
+ const ctx = { broker, sessionId, lockPath, nonce };
55
+ const deadline = Date.now() + maxMs;
56
+ while (Date.now() < deadline) {
57
+ const result = checkOnce(ctx);
58
+ if (result.tick === 'popped') {
59
+ return { exitCode: 2, ...(result.payload === undefined ? {} : { payload: result.payload }) };
60
+ }
61
+ if (result.tick === 'lock-lost' || result.tick === 'offline') {
62
+ return { exitCode: 0 };
63
+ }
64
+ await sleep(pollMs);
65
+ }
66
+ return { exitCode: 0 };
67
+ }
68
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@jaeboong/a2ab",
3
+ "version": "0.1.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "A2A terminal-agent broker: session registry, inbox, turn-boundary delivery",
8
+ "type": "module",
9
+ "license": "MIT",
10
+ "author": "Jaeboong",
11
+ "homepage": "https://github.com/Jaeboong/CLAUDE-CODE-A2A#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/Jaeboong/CLAUDE-CODE-A2A.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/Jaeboong/CLAUDE-CODE-A2A/issues"
18
+ },
19
+ "keywords": [
20
+ "a2a",
21
+ "agent",
22
+ "claude-code",
23
+ "cli",
24
+ "broker",
25
+ "multi-agent"
26
+ ],
27
+ "bin": {
28
+ "a2ab": "bin/a2ab.mjs"
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "bin/",
38
+ "dist/",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ "engines": {
43
+ "node": ">=20.11"
44
+ },
45
+ "scripts": {
46
+ "build": "tsc -p tsconfig.build.json",
47
+ "test": "node --import tsx --test test/*.test.ts",
48
+ "typecheck": "tsc --noEmit",
49
+ "prepack": "npm run build",
50
+ "prepublishOnly": "npm run typecheck && npm test"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^24.0.0",
54
+ "tsx": "^4.19.0",
55
+ "typescript": "^5.7.0"
56
+ }
57
+ }