@agentuity/pi 1.0.36 → 2.0.16

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/client.js DELETED
@@ -1,116 +0,0 @@
1
- /** How long to wait for a response before rejecting the pending promise (ms). */
2
- const SEND_TIMEOUT_MS = 30_000;
3
- /** How long to wait for the init message after connecting (ms). */
4
- const CONNECT_TIMEOUT_MS = 30_000;
5
- export class HubClient {
6
- ws = null;
7
- pending = new Map();
8
- async connect(url) {
9
- // Guard against overlapping connections — old socket handlers would corrupt shared state
10
- if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
11
- throw new Error('Already connected or connecting — call close() first');
12
- }
13
- return new Promise((resolve, reject) => {
14
- // Ensure ws:// or wss:// protocol — upgrade http(s) URLs automatically
15
- let wsUrl = url;
16
- if (wsUrl.startsWith('http://')) {
17
- wsUrl = 'ws://' + wsUrl.slice(7);
18
- }
19
- else if (wsUrl.startsWith('https://')) {
20
- wsUrl = 'wss://' + wsUrl.slice(8);
21
- }
22
- else if (!wsUrl.startsWith('ws://') && !wsUrl.startsWith('wss://')) {
23
- wsUrl = 'ws://' + wsUrl;
24
- }
25
- this.ws = new WebSocket(wsUrl);
26
- // Guard against duplicate init messages re-invoking the resolve
27
- let initResolved = false;
28
- const connectTimer = setTimeout(() => {
29
- if (!initResolved) {
30
- reject(new Error(`Hub did not send init message within ${CONNECT_TIMEOUT_MS}ms`));
31
- this.ws?.close();
32
- }
33
- }, CONNECT_TIMEOUT_MS);
34
- this.ws.onmessage = (event) => {
35
- let data;
36
- try {
37
- const raw = typeof event.data === 'string'
38
- ? event.data
39
- : new TextDecoder().decode(event.data);
40
- data = JSON.parse(raw);
41
- }
42
- catch {
43
- // Malformed or non-JSON frame — ignore
44
- return;
45
- }
46
- // First message should be init
47
- if (data.type === 'init' && !initResolved) {
48
- initResolved = true;
49
- clearTimeout(connectTimer);
50
- resolve(data);
51
- return;
52
- }
53
- // Otherwise it's a response to a pending request
54
- const response = data;
55
- const entry = this.pending.get(response.id);
56
- if (entry) {
57
- clearTimeout(entry.timer);
58
- this.pending.delete(response.id);
59
- entry.resolve(response);
60
- }
61
- };
62
- this.ws.onerror = (err) => {
63
- // ErrorEvent has a message property; plain Event does not
64
- const message = 'message' in err && typeof err.message === 'string'
65
- ? err.message
66
- : `connection to ${wsUrl} failed`;
67
- clearTimeout(connectTimer);
68
- reject(new Error(`WebSocket error: ${message}`));
69
- };
70
- this.ws.onclose = () => {
71
- clearTimeout(connectTimer);
72
- // Reject connect() promise if init was never received
73
- if (!initResolved) {
74
- reject(new Error('WebSocket closed before init message received'));
75
- }
76
- // Reject all pending requests
77
- for (const [id, entry] of this.pending) {
78
- clearTimeout(entry.timer);
79
- entry.reject(new Error('WebSocket closed'));
80
- this.pending.delete(id);
81
- }
82
- this.ws = null;
83
- };
84
- });
85
- }
86
- nextId() {
87
- return crypto.randomUUID();
88
- }
89
- async send(request) {
90
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
91
- // Return a default ACK if not connected
92
- return { id: request.id, actions: [{ action: 'ACK' }] };
93
- }
94
- return new Promise((resolve, reject) => {
95
- const timer = setTimeout(() => {
96
- const entry = this.pending.get(request.id);
97
- if (entry) {
98
- this.pending.delete(request.id);
99
- entry.reject(new Error(`Hub response timeout after ${SEND_TIMEOUT_MS}ms for request ${request.id}`));
100
- }
101
- }, SEND_TIMEOUT_MS);
102
- this.pending.set(request.id, { resolve, reject, timer });
103
- this.ws.send(JSON.stringify(request));
104
- });
105
- }
106
- close() {
107
- if (this.ws) {
108
- this.ws.close();
109
- this.ws = null;
110
- }
111
- }
112
- get connected() {
113
- return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
114
- }
115
- }
116
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- import type { HubAction } from './protocol.ts';
2
- export interface ActionResult {
3
- block?: {
4
- block: true;
5
- reason: string;
6
- };
7
- returnValue?: unknown;
8
- }
9
- /** Minimal UI surface used by action handlers — avoids a hard dep on pi-coding-agent. */
10
- interface ActionContext {
11
- ui?: {
12
- notify(message: string, level?: 'info' | 'warning' | 'error'): void;
13
- confirm(title: string, message: string): Promise<boolean>;
14
- setStatus(key: string, text?: string): void;
15
- };
16
- }
17
- export declare function processActions(actions: HubAction[], ctx: ActionContext): Promise<ActionResult>;
18
- export {};
19
- //# sourceMappingURL=handlers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC5B,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;CAEtB;AAED,yFAAyF;AACzF,UAAU,aAAa;IACtB,EAAE,CAAC,EAAE;QACJ,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,IAAI,CAAC;QACpE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1D,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5C,CAAC;CACF;AAED,wBAAsB,cAAc,CACnC,OAAO,EAAE,SAAS,EAAE,EACpB,GAAG,EAAE,aAAa,GAChB,OAAO,CAAC,YAAY,CAAC,CA6DvB"}
package/dist/handlers.js DELETED
@@ -1,57 +0,0 @@
1
- export async function processActions(actions, ctx) {
2
- let result = {};
3
- for (const action of actions) {
4
- switch (action.action) {
5
- case 'ACK':
6
- // Terminal: proceed normally
7
- result = {};
8
- break;
9
- case 'BLOCK':
10
- // Terminal: block
11
- result = { block: { block: true, reason: action.reason } };
12
- break;
13
- case 'RETURN':
14
- // Terminal: return a specific result
15
- result = { returnValue: action.result };
16
- break;
17
- case 'NOTIFY':
18
- // Side effect: show notification, continue
19
- if (ctx?.ui) {
20
- ctx.ui.notify(action.message, action.level ?? 'info');
21
- }
22
- break;
23
- case 'STATUS':
24
- // Side effect: set status, continue
25
- if (ctx?.ui) {
26
- ctx.ui.setStatus(action.key, action.text);
27
- }
28
- break;
29
- case 'CONFIRM': {
30
- // Gate: if user denies, stop and block
31
- if (ctx?.ui) {
32
- const confirmed = await ctx.ui.confirm(action.title, action.message);
33
- if (!confirmed) {
34
- return {
35
- block: {
36
- block: true,
37
- reason: action.deny_reason ?? 'Denied by user',
38
- },
39
- };
40
- }
41
- }
42
- else {
43
- // No UI available — block by default for safety
44
- result = {
45
- block: {
46
- block: true,
47
- reason: action.deny_reason ?? 'Confirmation required but no UI available',
48
- },
49
- };
50
- }
51
- break;
52
- }
53
- }
54
- }
55
- return result;
56
- }
57
- //# sourceMappingURL=handlers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,OAAoB,EACpB,GAAkB;IAElB,IAAI,MAAM,GAAiB,EAAE,CAAC;IAE9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,KAAK,KAAK;gBACT,6BAA6B;gBAC7B,MAAM,GAAG,EAAE,CAAC;gBACZ,MAAM;YAEP,KAAK,OAAO;gBACX,kBAAkB;gBAClB,MAAM,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC3D,MAAM;YAEP,KAAK,QAAQ;gBACZ,qCAAqC;gBACrC,MAAM,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;gBACxC,MAAM;YAEP,KAAK,QAAQ;gBACZ,2CAA2C;gBAC3C,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC;oBACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM;YAEP,KAAK,QAAQ;gBACZ,oCAAoC;gBACpC,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC;oBACb,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3C,CAAC;gBACD,MAAM;YAEP,KAAK,SAAS,CAAC,CAAC,CAAC;gBAChB,uCAAuC;gBACvC,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC;oBACb,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;oBACrE,IAAI,CAAC,SAAS,EAAE,CAAC;wBAChB,OAAO;4BACN,KAAK,EAAE;gCACN,KAAK,EAAE,IAAI;gCACX,MAAM,EAAE,MAAM,CAAC,WAAW,IAAI,gBAAgB;6BAC9C;yBACD,CAAC;oBACH,CAAC;gBACF,CAAC;qBAAM,CAAC;oBACP,gDAAgD;oBAChD,MAAM,GAAG;wBACR,KAAK,EAAE;4BACN,KAAK,EAAE,IAAI;4BACX,MAAM,EAAE,MAAM,CAAC,WAAW,IAAI,2CAA2C;yBACzE;qBACD,CAAC;gBACH,CAAC;gBACD,MAAM;YACP,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -1,68 +0,0 @@
1
- export interface HubToolDefinition {
2
- name: string;
3
- label: string;
4
- description: string;
5
- parameters: Record<string, unknown>;
6
- }
7
- export interface HubCommandDefinition {
8
- name: string;
9
- description: string;
10
- }
11
- export interface InitMessage {
12
- type: 'init';
13
- tools?: HubToolDefinition[];
14
- commands?: HubCommandDefinition[];
15
- }
16
- export interface EventRequest {
17
- id: string;
18
- type: 'event';
19
- event: string;
20
- data: Record<string, unknown>;
21
- }
22
- export interface ToolRequest {
23
- id: string;
24
- type: 'tool';
25
- name: string;
26
- toolCallId: string;
27
- params: Record<string, unknown>;
28
- }
29
- export interface CommandRequest {
30
- id: string;
31
- type: 'command';
32
- name: string;
33
- args: string;
34
- }
35
- export type HubRequest = EventRequest | ToolRequest | CommandRequest;
36
- export interface AckAction {
37
- action: 'ACK';
38
- }
39
- export interface BlockAction {
40
- action: 'BLOCK';
41
- reason: string;
42
- }
43
- export interface ConfirmAction {
44
- action: 'CONFIRM';
45
- title: string;
46
- message: string;
47
- deny_reason?: string;
48
- }
49
- export interface NotifyAction {
50
- action: 'NOTIFY';
51
- message: string;
52
- level?: 'info' | 'warning' | 'error';
53
- }
54
- export interface ReturnAction {
55
- action: 'RETURN';
56
- result: unknown;
57
- }
58
- export interface StatusAction {
59
- action: 'STATUS';
60
- key: string;
61
- text?: string;
62
- }
63
- export type HubAction = AckAction | BlockAction | ConfirmAction | NotifyAction | ReturnAction | StatusAction;
64
- export interface HubResponse {
65
- id: string;
66
- actions: HubAction[];
67
- }
68
- //# sourceMappingURL=protocol.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAID,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAIrE,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,QAAQ,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,QAAQ,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,SAAS,GAClB,SAAS,GACT,WAAW,GACX,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,YAAY,CAAC;AAIhB,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,SAAS,EAAE,CAAC;CACrB"}
package/dist/protocol.js DELETED
@@ -1,3 +0,0 @@
1
- // ---- Init Message (Server → Client on connect) ----
2
- export {};
3
- //# sourceMappingURL=protocol.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,sDAAsD"}
package/src/client.ts DELETED
@@ -1,144 +0,0 @@
1
- import type { InitMessage, HubRequest, HubResponse } from './protocol.ts';
2
-
3
- /** How long to wait for a response before rejecting the pending promise (ms). */
4
- const SEND_TIMEOUT_MS = 30_000;
5
-
6
- /** How long to wait for the init message after connecting (ms). */
7
- const CONNECT_TIMEOUT_MS = 30_000;
8
-
9
- export class HubClient {
10
- private ws: WebSocket | null = null;
11
- private pending = new Map<
12
- string,
13
- {
14
- resolve: (resp: HubResponse) => void;
15
- reject: (err: Error) => void;
16
- timer: ReturnType<typeof setTimeout>;
17
- }
18
- >();
19
- async connect(url: string): Promise<InitMessage> {
20
- // Guard against overlapping connections — old socket handlers would corrupt shared state
21
- if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
22
- throw new Error('Already connected or connecting — call close() first');
23
- }
24
-
25
- return new Promise((resolve, reject) => {
26
- // Ensure ws:// or wss:// protocol — upgrade http(s) URLs automatically
27
- let wsUrl = url;
28
- if (wsUrl.startsWith('http://')) {
29
- wsUrl = 'ws://' + wsUrl.slice(7);
30
- } else if (wsUrl.startsWith('https://')) {
31
- wsUrl = 'wss://' + wsUrl.slice(8);
32
- } else if (!wsUrl.startsWith('ws://') && !wsUrl.startsWith('wss://')) {
33
- wsUrl = 'ws://' + wsUrl;
34
- }
35
-
36
- this.ws = new WebSocket(wsUrl);
37
-
38
- // Guard against duplicate init messages re-invoking the resolve
39
- let initResolved = false;
40
-
41
- const connectTimer = setTimeout(() => {
42
- if (!initResolved) {
43
- reject(new Error(`Hub did not send init message within ${CONNECT_TIMEOUT_MS}ms`));
44
- this.ws?.close();
45
- }
46
- }, CONNECT_TIMEOUT_MS);
47
-
48
- this.ws.onmessage = (event: MessageEvent) => {
49
- let data: Record<string, unknown>;
50
- try {
51
- const raw =
52
- typeof event.data === 'string'
53
- ? event.data
54
- : new TextDecoder().decode(event.data as ArrayBuffer);
55
- data = JSON.parse(raw) as Record<string, unknown>;
56
- } catch {
57
- // Malformed or non-JSON frame — ignore
58
- return;
59
- }
60
-
61
- // First message should be init
62
- if (data.type === 'init' && !initResolved) {
63
- initResolved = true;
64
- clearTimeout(connectTimer);
65
- resolve(data as unknown as InitMessage);
66
- return;
67
- }
68
-
69
- // Otherwise it's a response to a pending request
70
- const response = data as unknown as HubResponse;
71
- const entry = this.pending.get(response.id);
72
- if (entry) {
73
- clearTimeout(entry.timer);
74
- this.pending.delete(response.id);
75
- entry.resolve(response);
76
- }
77
- };
78
-
79
- this.ws.onerror = (err: Event) => {
80
- // ErrorEvent has a message property; plain Event does not
81
- const message =
82
- 'message' in err && typeof (err as ErrorEvent).message === 'string'
83
- ? (err as ErrorEvent).message
84
- : `connection to ${wsUrl} failed`;
85
- clearTimeout(connectTimer);
86
- reject(new Error(`WebSocket error: ${message}`));
87
- };
88
-
89
- this.ws.onclose = () => {
90
- clearTimeout(connectTimer);
91
- // Reject connect() promise if init was never received
92
- if (!initResolved) {
93
- reject(new Error('WebSocket closed before init message received'));
94
- }
95
- // Reject all pending requests
96
- for (const [id, entry] of this.pending) {
97
- clearTimeout(entry.timer);
98
- entry.reject(new Error('WebSocket closed'));
99
- this.pending.delete(id);
100
- }
101
- this.ws = null;
102
- };
103
- });
104
- }
105
-
106
- nextId(): string {
107
- return crypto.randomUUID();
108
- }
109
-
110
- async send(request: HubRequest): Promise<HubResponse> {
111
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
112
- // Return a default ACK if not connected
113
- return { id: request.id, actions: [{ action: 'ACK' }] };
114
- }
115
-
116
- return new Promise<HubResponse>((resolve, reject) => {
117
- const timer = setTimeout(() => {
118
- const entry = this.pending.get(request.id);
119
- if (entry) {
120
- this.pending.delete(request.id);
121
- entry.reject(
122
- new Error(
123
- `Hub response timeout after ${SEND_TIMEOUT_MS}ms for request ${request.id}`
124
- )
125
- );
126
- }
127
- }, SEND_TIMEOUT_MS);
128
-
129
- this.pending.set(request.id, { resolve, reject, timer });
130
- this.ws!.send(JSON.stringify(request));
131
- });
132
- }
133
-
134
- close(): void {
135
- if (this.ws) {
136
- this.ws.close();
137
- this.ws = null;
138
- }
139
- }
140
-
141
- get connected(): boolean {
142
- return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
143
- }
144
- }
package/src/handlers.ts DELETED
@@ -1,82 +0,0 @@
1
- import type { HubAction } from './protocol.ts';
2
-
3
- export interface ActionResult {
4
- block?: { block: true; reason: string };
5
- returnValue?: unknown;
6
- // undefined means ACK (proceed normally)
7
- }
8
-
9
- /** Minimal UI surface used by action handlers — avoids a hard dep on pi-coding-agent. */
10
- interface ActionContext {
11
- ui?: {
12
- notify(message: string, level?: 'info' | 'warning' | 'error'): void;
13
- confirm(title: string, message: string): Promise<boolean>;
14
- setStatus(key: string, text?: string): void;
15
- };
16
- }
17
-
18
- export async function processActions(
19
- actions: HubAction[],
20
- ctx: ActionContext
21
- ): Promise<ActionResult> {
22
- let result: ActionResult = {};
23
-
24
- for (const action of actions) {
25
- switch (action.action) {
26
- case 'ACK':
27
- // Terminal: proceed normally
28
- result = {};
29
- break;
30
-
31
- case 'BLOCK':
32
- // Terminal: block
33
- result = { block: { block: true, reason: action.reason } };
34
- break;
35
-
36
- case 'RETURN':
37
- // Terminal: return a specific result
38
- result = { returnValue: action.result };
39
- break;
40
-
41
- case 'NOTIFY':
42
- // Side effect: show notification, continue
43
- if (ctx?.ui) {
44
- ctx.ui.notify(action.message, action.level ?? 'info');
45
- }
46
- break;
47
-
48
- case 'STATUS':
49
- // Side effect: set status, continue
50
- if (ctx?.ui) {
51
- ctx.ui.setStatus(action.key, action.text);
52
- }
53
- break;
54
-
55
- case 'CONFIRM': {
56
- // Gate: if user denies, stop and block
57
- if (ctx?.ui) {
58
- const confirmed = await ctx.ui.confirm(action.title, action.message);
59
- if (!confirmed) {
60
- return {
61
- block: {
62
- block: true,
63
- reason: action.deny_reason ?? 'Denied by user',
64
- },
65
- };
66
- }
67
- } else {
68
- // No UI available — block by default for safety
69
- result = {
70
- block: {
71
- block: true,
72
- reason: action.deny_reason ?? 'Confirmation required but no UI available',
73
- },
74
- };
75
- }
76
- break;
77
- }
78
- }
79
- }
80
-
81
- return result;
82
- }
package/src/protocol.ts DELETED
@@ -1,95 +0,0 @@
1
- // ---- Init Message (Server → Client on connect) ----
2
-
3
- export interface HubToolDefinition {
4
- name: string;
5
- label: string;
6
- description: string;
7
- parameters: Record<string, unknown>; // JSON Schema object
8
- }
9
-
10
- export interface HubCommandDefinition {
11
- name: string;
12
- description: string;
13
- }
14
-
15
- export interface InitMessage {
16
- type: 'init';
17
- tools?: HubToolDefinition[];
18
- commands?: HubCommandDefinition[];
19
- }
20
-
21
- // ---- Request Messages (Client → Server) ----
22
-
23
- export interface EventRequest {
24
- id: string;
25
- type: 'event';
26
- event: string;
27
- data: Record<string, unknown>;
28
- }
29
-
30
- export interface ToolRequest {
31
- id: string;
32
- type: 'tool';
33
- name: string;
34
- toolCallId: string;
35
- params: Record<string, unknown>;
36
- }
37
-
38
- export interface CommandRequest {
39
- id: string;
40
- type: 'command';
41
- name: string;
42
- args: string;
43
- }
44
-
45
- export type HubRequest = EventRequest | ToolRequest | CommandRequest;
46
-
47
- // ---- Actions ----
48
-
49
- export interface AckAction {
50
- action: 'ACK';
51
- }
52
-
53
- export interface BlockAction {
54
- action: 'BLOCK';
55
- reason: string;
56
- }
57
-
58
- export interface ConfirmAction {
59
- action: 'CONFIRM';
60
- title: string;
61
- message: string;
62
- deny_reason?: string;
63
- }
64
-
65
- export interface NotifyAction {
66
- action: 'NOTIFY';
67
- message: string;
68
- level?: 'info' | 'warning' | 'error';
69
- }
70
-
71
- export interface ReturnAction {
72
- action: 'RETURN';
73
- result: unknown;
74
- }
75
-
76
- export interface StatusAction {
77
- action: 'STATUS';
78
- key: string;
79
- text?: string; // undefined = clear status
80
- }
81
-
82
- export type HubAction =
83
- | AckAction
84
- | BlockAction
85
- | ConfirmAction
86
- | NotifyAction
87
- | ReturnAction
88
- | StatusAction;
89
-
90
- // ---- Response Message (Server → Client) ----
91
-
92
- export interface HubResponse {
93
- id: string;
94
- actions: HubAction[];
95
- }