@neurosquad/card-sdk 1.0.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/LICENSE +21 -0
- package/README.md +431 -0
- package/dist/card-sdk.js +5266 -0
- package/dist/cli.js +2838 -0
- package/dist/react.js +257 -0
- package/dist/testing.js +1150 -0
- package/dist/types/client/base64.d.ts +7 -0
- package/dist/types/client/card.d.ts +653 -0
- package/dist/types/client/channel.d.ts +49 -0
- package/dist/types/client/coalesce.d.ts +14 -0
- package/dist/types/client/connect.d.ts +39 -0
- package/dist/types/client/errors.d.ts +46 -0
- package/dist/types/client/helpers.d.ts +25 -0
- package/dist/types/client/net.d.ts +111 -0
- package/dist/types/client/theme.d.ts +31 -0
- package/dist/types/client/toolResult.d.ts +16 -0
- package/dist/types/contract/api.d.ts +812 -0
- package/dist/types/contract/index.d.ts +11 -0
- package/dist/types/contract/jsonSchema.d.ts +88 -0
- package/dist/types/contract/localized.d.ts +10 -0
- package/dist/types/contract/manifest.d.ts +179 -0
- package/dist/types/contract/network.d.ts +48 -0
- package/dist/types/contract/permissions.d.ts +180 -0
- package/dist/types/contract/ports.d.ts +237 -0
- package/dist/types/contract/protocol.d.ts +74 -0
- package/dist/types/contract/source.d.ts +111 -0
- package/dist/types/contract/theme.d.ts +21 -0
- package/dist/types/contract/version.d.ts +126 -0
- package/dist/types/i18n.d.ts +50 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/react/index.d.ts +132 -0
- package/dist/types/testing/index.d.ts +7 -0
- package/dist/types/testing/mockHost.d.ts +315 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/ui.css +581 -0
- package/package.json +77 -0
- package/schema/neurosquad-card.v1.json +434 -0
- package/templates/react/README.md +34 -0
- package/templates/react/_gitignore +10 -0
- package/templates/react/icon.png +0 -0
- package/templates/react/index.html +12 -0
- package/templates/react/neurosquad-card.json +94 -0
- package/templates/react/package.json +25 -0
- package/templates/react/src/App.tsx +131 -0
- package/templates/react/src/i18n.ts +61 -0
- package/templates/react/src/main.tsx +77 -0
- package/templates/react/src/styles.css +42 -0
- package/templates/react/tsconfig.json +18 -0
- package/templates/react/vite.config.ts +19 -0
- package/templates/vanilla/README.md +37 -0
- package/templates/vanilla/_gitignore +6 -0
- package/templates/vanilla/icon.png +0 -0
- package/templates/vanilla/index.html +41 -0
- package/templates/vanilla/main.js +256 -0
- package/templates/vanilla/neurosquad-card.json +94 -0
- package/templates/vanilla/style.css +41 -0
|
@@ -0,0 +1,812 @@
|
|
|
1
|
+
import type { CardJsonSchema, JsonValue } from './jsonSchema.js';
|
|
2
|
+
import type { CardLanguage, LocalizedText } from './localized.js';
|
|
3
|
+
import type { CardSize, SettingField, SettingValue } from './manifest.js';
|
|
4
|
+
import type { NormalizedPermission, PermissionId } from './permissions.js';
|
|
5
|
+
import type { PortInfo, PortTypeId } from './ports.js';
|
|
6
|
+
import { type CardTone, type HostIconName, type ThemeSnapshot } from './theme.js';
|
|
7
|
+
import { LIMITS } from './version.js';
|
|
8
|
+
/** Where the card is, as far as the user can see it. */
|
|
9
|
+
export type CardVisibility =
|
|
10
|
+
/** On screen, body shown. */
|
|
11
|
+
'visible'
|
|
12
|
+
/** Its workspace is shown but the card is outside the viewport. */
|
|
13
|
+
| 'offscreen'
|
|
14
|
+
/** Zoomed out past the overview threshold: the host shows the overview tile, the frame is hidden. */
|
|
15
|
+
| 'overview'
|
|
16
|
+
/** Its workspace is not the one shown, or the window is hidden. Suspended after LIMITS.hiddenSuspendMs unless `background`. */
|
|
17
|
+
| 'hidden';
|
|
18
|
+
export declare const CARD_VISIBILITIES: readonly CardVisibility[];
|
|
19
|
+
export type AgentStatus = 'working' | 'needs-input' | 'finished' | 'idle' | 'exited';
|
|
20
|
+
export interface CardInstanceInfo {
|
|
21
|
+
/** The card's id on the canvas (the Agent record id). */
|
|
22
|
+
instanceId: string;
|
|
23
|
+
packageId: string;
|
|
24
|
+
/** Manifest `name`. */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Manifest `displayName`, resolved to the app language. */
|
|
27
|
+
displayName: string;
|
|
28
|
+
version: string;
|
|
29
|
+
/** Installed commit; null for a dev-linked folder. */
|
|
30
|
+
commit: string | null;
|
|
31
|
+
/** The user's name for this card, else the card's own title, else null. */
|
|
32
|
+
title: string | null;
|
|
33
|
+
size: CardSize;
|
|
34
|
+
dev: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface WorkspaceInfo {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
/** Absolute folder path — only with `fs.read`. */
|
|
40
|
+
path?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface AgentInfo {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
/** Harness id (`claude-code`, `codex-cli`, `shell-bash`…). */
|
|
46
|
+
harness: string;
|
|
47
|
+
kind: 'ai' | 'shell';
|
|
48
|
+
status: AgentStatus;
|
|
49
|
+
/** An arrow connects it with this card (either direction). */
|
|
50
|
+
connected: boolean;
|
|
51
|
+
sessionTitle?: string;
|
|
52
|
+
/** Epoch ms the current turn started (status 'working'). */
|
|
53
|
+
turnStartedAt?: number;
|
|
54
|
+
/**
|
|
55
|
+
* The last finished turn since the app started, so a card whose frame was
|
|
56
|
+
* not mounted when it ended (zoomed out, hidden) can catch up. Absent on
|
|
57
|
+
* older hosts and before the first turn ends.
|
|
58
|
+
*/
|
|
59
|
+
lastTurn?: {
|
|
60
|
+
startedAt: number | null;
|
|
61
|
+
endedAt: number;
|
|
62
|
+
endedAs: 'finished' | 'needs-input';
|
|
63
|
+
};
|
|
64
|
+
model?: string;
|
|
65
|
+
}
|
|
66
|
+
export type PeerKind = 'custom' | 'note' | 'todo' | 'kanban' | 'sticky' | 'agent' | 'terminal' | 'other';
|
|
67
|
+
export interface PeerInfo {
|
|
68
|
+
cardId: string;
|
|
69
|
+
kind: PeerKind;
|
|
70
|
+
/** Card name as the user sees it. */
|
|
71
|
+
name: string;
|
|
72
|
+
/** Harness id for agents/terminals; manifest name for custom cards. */
|
|
73
|
+
type?: string;
|
|
74
|
+
/** `downstream`: this card → peer (our outputs reach its inputs). `upstream`: peer → this card. */
|
|
75
|
+
direction: 'downstream' | 'upstream' | 'both';
|
|
76
|
+
inputs: PortInfo[];
|
|
77
|
+
outputs: PortInfo[];
|
|
78
|
+
}
|
|
79
|
+
export interface PermissionState {
|
|
80
|
+
id: PermissionId;
|
|
81
|
+
hosts?: string[];
|
|
82
|
+
optional: boolean;
|
|
83
|
+
granted: boolean;
|
|
84
|
+
reason?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface SettingsSnapshot {
|
|
87
|
+
values: Record<string, SettingValue>;
|
|
88
|
+
/** Secret setting key → whether the user has set one. The value never reaches the card. */
|
|
89
|
+
secrets: Record<string, boolean>;
|
|
90
|
+
}
|
|
91
|
+
export interface MenuItem {
|
|
92
|
+
id: string;
|
|
93
|
+
label: string;
|
|
94
|
+
icon?: HostIconName;
|
|
95
|
+
tone?: 'default' | 'danger';
|
|
96
|
+
disabled?: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface OverviewContent {
|
|
99
|
+
/** Big line under the name (e.g. "3 / 11", "Build passing"). */
|
|
100
|
+
primary?: string | null;
|
|
101
|
+
secondary?: string | null;
|
|
102
|
+
/** 0..1 progress ring/bar. */
|
|
103
|
+
progress?: number | null;
|
|
104
|
+
tone?: CardTone;
|
|
105
|
+
icon?: HostIconName | null;
|
|
106
|
+
}
|
|
107
|
+
export interface HostContext {
|
|
108
|
+
protocol: number;
|
|
109
|
+
/** The app's version. */
|
|
110
|
+
appVersion: string;
|
|
111
|
+
instance: CardInstanceInfo;
|
|
112
|
+
workspace: WorkspaceInfo;
|
|
113
|
+
visibility: CardVisibility;
|
|
114
|
+
expanded: boolean;
|
|
115
|
+
theme: ThemeSnapshot;
|
|
116
|
+
i18n: I18nSnapshot;
|
|
117
|
+
settings: SettingsSnapshot;
|
|
118
|
+
permissions: PermissionState[];
|
|
119
|
+
ports: {
|
|
120
|
+
inputs: PortInfo[];
|
|
121
|
+
outputs: PortInfo[];
|
|
122
|
+
};
|
|
123
|
+
peers: PeerInfo[];
|
|
124
|
+
/** `init` passed by the card that spawned this one (card.spawn kind 'self'), once. */
|
|
125
|
+
spawnInit?: JsonValue;
|
|
126
|
+
/** Why the frame (re)started. */
|
|
127
|
+
launch: 'created' | 'opened' | 'resumed' | 'reloaded' | 'updated';
|
|
128
|
+
limits: typeof LIMITS;
|
|
129
|
+
/**
|
|
130
|
+
* The card's chrome as main holds it right now. It outlives frame reloads
|
|
131
|
+
* (dev reload, update, resume), so a card that raised `attention` before a
|
|
132
|
+
* reload can see the pulse is still on and clear it. Absent on hosts older
|
|
133
|
+
* than this field: treat it as unknown.
|
|
134
|
+
*/
|
|
135
|
+
chrome?: CardChromeState;
|
|
136
|
+
}
|
|
137
|
+
/** What main currently shows for this card (`HostContext.chrome`). */
|
|
138
|
+
export interface CardChromeState {
|
|
139
|
+
title: string | null;
|
|
140
|
+
status: {
|
|
141
|
+
text: string;
|
|
142
|
+
tone: CardTone;
|
|
143
|
+
busy: boolean;
|
|
144
|
+
} | null;
|
|
145
|
+
badge: {
|
|
146
|
+
count: number | null;
|
|
147
|
+
text: string | null;
|
|
148
|
+
tone: CardTone;
|
|
149
|
+
} | null;
|
|
150
|
+
overview: OverviewContent | null;
|
|
151
|
+
attention: {
|
|
152
|
+
level: 'info' | 'needs-input';
|
|
153
|
+
message: string | null;
|
|
154
|
+
} | null;
|
|
155
|
+
}
|
|
156
|
+
export interface I18nSnapshot {
|
|
157
|
+
language: CardLanguage;
|
|
158
|
+
/** BCP 47 for Intl (`en-US`, `ru-RU`, `zh-CN`). */
|
|
159
|
+
locale: string;
|
|
160
|
+
}
|
|
161
|
+
export interface ToolResultPayload {
|
|
162
|
+
content: ({
|
|
163
|
+
type: 'text';
|
|
164
|
+
text: string;
|
|
165
|
+
} | {
|
|
166
|
+
type: 'image';
|
|
167
|
+
data: string;
|
|
168
|
+
mimeType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';
|
|
169
|
+
})[];
|
|
170
|
+
isError?: boolean;
|
|
171
|
+
}
|
|
172
|
+
export interface NetResponse {
|
|
173
|
+
requestId: string;
|
|
174
|
+
status: number;
|
|
175
|
+
statusText: string;
|
|
176
|
+
/** Lowercased names; set-cookie removed. */
|
|
177
|
+
headers: Record<string, string>;
|
|
178
|
+
/** Final URL after redirects. */
|
|
179
|
+
url: string;
|
|
180
|
+
/** For responseType text/base64. */
|
|
181
|
+
body?: string;
|
|
182
|
+
/** For responseType json. */
|
|
183
|
+
json?: JsonValue;
|
|
184
|
+
/** Body was longer than the limit and was cut (text/base64 only; json fails with TOO_LARGE). */
|
|
185
|
+
truncated?: boolean;
|
|
186
|
+
}
|
|
187
|
+
export interface FsStat {
|
|
188
|
+
path: string;
|
|
189
|
+
type: 'file' | 'directory';
|
|
190
|
+
size: number;
|
|
191
|
+
mtimeMs: number;
|
|
192
|
+
}
|
|
193
|
+
export interface FsEntry {
|
|
194
|
+
path: string;
|
|
195
|
+
type: 'file' | 'directory';
|
|
196
|
+
size?: number;
|
|
197
|
+
}
|
|
198
|
+
export interface UsageRow {
|
|
199
|
+
agentId: string;
|
|
200
|
+
name: string;
|
|
201
|
+
harness: string;
|
|
202
|
+
inputTokens: number;
|
|
203
|
+
outputTokens: number;
|
|
204
|
+
cacheReadTokens: number;
|
|
205
|
+
cacheWriteTokens: number;
|
|
206
|
+
/** Micro-dollars; null when the model has no known price. */
|
|
207
|
+
costMicroUsd: number | null;
|
|
208
|
+
}
|
|
209
|
+
export interface UsageSummary {
|
|
210
|
+
period: 'today' | '7d' | '30d';
|
|
211
|
+
/** ISO timestamps, local days, end exclusive. */
|
|
212
|
+
from: string;
|
|
213
|
+
to: string;
|
|
214
|
+
rows: UsageRow[];
|
|
215
|
+
totalCostMicroUsd: number;
|
|
216
|
+
/** Some rows had no price and are not in the total. */
|
|
217
|
+
partial: boolean;
|
|
218
|
+
}
|
|
219
|
+
export type EventTopic = 'agents.status' | 'agents.turn' | 'agents.changed' | 'agents.output' | 'storage.changed';
|
|
220
|
+
export declare const EVENT_TOPICS: readonly EventTopic[];
|
|
221
|
+
/** Permission each subscribable topic needs. */
|
|
222
|
+
export declare const TOPIC_PERMISSION: Record<EventTopic, PermissionId | null>;
|
|
223
|
+
type StorageScope = 'instance' | 'package';
|
|
224
|
+
export interface CardMethods {
|
|
225
|
+
'host.ready': {
|
|
226
|
+
params: {
|
|
227
|
+
sdkVersion: string;
|
|
228
|
+
protocol: number;
|
|
229
|
+
};
|
|
230
|
+
result: HostContext;
|
|
231
|
+
};
|
|
232
|
+
'host.capabilities': {
|
|
233
|
+
params: void;
|
|
234
|
+
result: {
|
|
235
|
+
protocol: number;
|
|
236
|
+
methods: string[];
|
|
237
|
+
events: string[];
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
'host.log': {
|
|
241
|
+
params: {
|
|
242
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
243
|
+
message: string;
|
|
244
|
+
};
|
|
245
|
+
result: void;
|
|
246
|
+
};
|
|
247
|
+
'host.pong': {
|
|
248
|
+
params: {
|
|
249
|
+
seq: number;
|
|
250
|
+
};
|
|
251
|
+
result: void;
|
|
252
|
+
};
|
|
253
|
+
'events.subscribe': {
|
|
254
|
+
params: {
|
|
255
|
+
topics: EventTopic[];
|
|
256
|
+
agentIds?: string[];
|
|
257
|
+
};
|
|
258
|
+
result: {
|
|
259
|
+
topics: EventTopic[];
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
'events.unsubscribe': {
|
|
263
|
+
params: {
|
|
264
|
+
topics: EventTopic[];
|
|
265
|
+
};
|
|
266
|
+
result: void;
|
|
267
|
+
};
|
|
268
|
+
'card.getInfo': {
|
|
269
|
+
params: void;
|
|
270
|
+
result: CardInstanceInfo;
|
|
271
|
+
};
|
|
272
|
+
'card.setTitle': {
|
|
273
|
+
params: {
|
|
274
|
+
title: string | null;
|
|
275
|
+
};
|
|
276
|
+
result: void;
|
|
277
|
+
};
|
|
278
|
+
'card.setStatus': {
|
|
279
|
+
params: {
|
|
280
|
+
text?: string | null;
|
|
281
|
+
tone?: CardTone;
|
|
282
|
+
busy?: boolean;
|
|
283
|
+
};
|
|
284
|
+
result: void;
|
|
285
|
+
};
|
|
286
|
+
'card.setBadge': {
|
|
287
|
+
params: {
|
|
288
|
+
count?: number | null;
|
|
289
|
+
text?: string | null;
|
|
290
|
+
tone?: CardTone;
|
|
291
|
+
};
|
|
292
|
+
result: void;
|
|
293
|
+
};
|
|
294
|
+
'card.setOverview': {
|
|
295
|
+
params: OverviewContent;
|
|
296
|
+
result: void;
|
|
297
|
+
};
|
|
298
|
+
'card.attention': {
|
|
299
|
+
params: {
|
|
300
|
+
level: 'none' | 'info' | 'needs-input';
|
|
301
|
+
message?: string;
|
|
302
|
+
};
|
|
303
|
+
result: void;
|
|
304
|
+
};
|
|
305
|
+
'card.requestResize': {
|
|
306
|
+
params: CardSize;
|
|
307
|
+
result: CardSize;
|
|
308
|
+
};
|
|
309
|
+
'card.openLink': {
|
|
310
|
+
params: {
|
|
311
|
+
url: string;
|
|
312
|
+
};
|
|
313
|
+
result: {
|
|
314
|
+
opened: boolean;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
'card.focus': {
|
|
318
|
+
params: {
|
|
319
|
+
cardId: string;
|
|
320
|
+
};
|
|
321
|
+
result: void;
|
|
322
|
+
};
|
|
323
|
+
'card.spawn': {
|
|
324
|
+
params: {
|
|
325
|
+
kind: 'self' | 'note' | 'todo' | 'kanban' | 'sticky';
|
|
326
|
+
title?: string;
|
|
327
|
+
connect?: boolean;
|
|
328
|
+
init?: JsonValue;
|
|
329
|
+
};
|
|
330
|
+
result: {
|
|
331
|
+
cardId: string;
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
'ui.toast': {
|
|
335
|
+
params: {
|
|
336
|
+
message: string;
|
|
337
|
+
tone?: CardTone;
|
|
338
|
+
durationMs?: number;
|
|
339
|
+
};
|
|
340
|
+
result: void;
|
|
341
|
+
};
|
|
342
|
+
'ui.confirm': {
|
|
343
|
+
params: {
|
|
344
|
+
title: string;
|
|
345
|
+
message: string;
|
|
346
|
+
confirmLabel?: string;
|
|
347
|
+
cancelLabel?: string;
|
|
348
|
+
tone?: 'default' | 'danger';
|
|
349
|
+
};
|
|
350
|
+
result: {
|
|
351
|
+
confirmed: boolean;
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
'ui.setMenu': {
|
|
355
|
+
params: {
|
|
356
|
+
items: MenuItem[];
|
|
357
|
+
};
|
|
358
|
+
result: void;
|
|
359
|
+
};
|
|
360
|
+
'settings.get': {
|
|
361
|
+
params: void;
|
|
362
|
+
result: SettingsSnapshot;
|
|
363
|
+
};
|
|
364
|
+
'settings.set': {
|
|
365
|
+
params: {
|
|
366
|
+
values: Record<string, SettingValue>;
|
|
367
|
+
};
|
|
368
|
+
result: SettingsSnapshot;
|
|
369
|
+
};
|
|
370
|
+
'settings.open': {
|
|
371
|
+
params: void;
|
|
372
|
+
result: void;
|
|
373
|
+
};
|
|
374
|
+
'storage.get': {
|
|
375
|
+
params: {
|
|
376
|
+
scope: StorageScope;
|
|
377
|
+
key: string;
|
|
378
|
+
};
|
|
379
|
+
result: {
|
|
380
|
+
exists: boolean;
|
|
381
|
+
value: JsonValue | null;
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
'storage.set': {
|
|
385
|
+
params: {
|
|
386
|
+
scope: StorageScope;
|
|
387
|
+
key: string;
|
|
388
|
+
value: JsonValue;
|
|
389
|
+
};
|
|
390
|
+
result: void;
|
|
391
|
+
};
|
|
392
|
+
'storage.delete': {
|
|
393
|
+
params: {
|
|
394
|
+
scope: StorageScope;
|
|
395
|
+
key: string;
|
|
396
|
+
};
|
|
397
|
+
result: void;
|
|
398
|
+
};
|
|
399
|
+
'storage.keys': {
|
|
400
|
+
params: {
|
|
401
|
+
scope: StorageScope;
|
|
402
|
+
prefix?: string;
|
|
403
|
+
};
|
|
404
|
+
result: {
|
|
405
|
+
keys: string[];
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
'storage.clear': {
|
|
409
|
+
params: {
|
|
410
|
+
scope: StorageScope;
|
|
411
|
+
};
|
|
412
|
+
result: void;
|
|
413
|
+
};
|
|
414
|
+
'storage.usage': {
|
|
415
|
+
params: {
|
|
416
|
+
scope: StorageScope;
|
|
417
|
+
};
|
|
418
|
+
result: {
|
|
419
|
+
bytes: number;
|
|
420
|
+
quota: number;
|
|
421
|
+
keys: number;
|
|
422
|
+
};
|
|
423
|
+
};
|
|
424
|
+
'theme.get': {
|
|
425
|
+
params: void;
|
|
426
|
+
result: ThemeSnapshot;
|
|
427
|
+
};
|
|
428
|
+
'i18n.get': {
|
|
429
|
+
params: void;
|
|
430
|
+
result: I18nSnapshot;
|
|
431
|
+
};
|
|
432
|
+
'workspace.get': {
|
|
433
|
+
params: void;
|
|
434
|
+
result: WorkspaceInfo;
|
|
435
|
+
};
|
|
436
|
+
'permissions.list': {
|
|
437
|
+
params: void;
|
|
438
|
+
result: PermissionState[];
|
|
439
|
+
};
|
|
440
|
+
'permissions.request': {
|
|
441
|
+
params: {
|
|
442
|
+
ids: PermissionId[];
|
|
443
|
+
};
|
|
444
|
+
result: {
|
|
445
|
+
granted: PermissionId[];
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
'agents.list': {
|
|
449
|
+
params: void;
|
|
450
|
+
result: AgentInfo[];
|
|
451
|
+
};
|
|
452
|
+
'agents.get': {
|
|
453
|
+
params: {
|
|
454
|
+
agentId: string;
|
|
455
|
+
};
|
|
456
|
+
result: AgentInfo;
|
|
457
|
+
};
|
|
458
|
+
'agents.readScreen': {
|
|
459
|
+
params: {
|
|
460
|
+
agentId: string;
|
|
461
|
+
lines?: number;
|
|
462
|
+
};
|
|
463
|
+
result: {
|
|
464
|
+
text: string;
|
|
465
|
+
};
|
|
466
|
+
};
|
|
467
|
+
'agents.lastReply': {
|
|
468
|
+
params: {
|
|
469
|
+
agentId: string;
|
|
470
|
+
};
|
|
471
|
+
result: {
|
|
472
|
+
text: string | null;
|
|
473
|
+
at: number | null;
|
|
474
|
+
};
|
|
475
|
+
};
|
|
476
|
+
'agents.prompt': {
|
|
477
|
+
params: {
|
|
478
|
+
agentId: string;
|
|
479
|
+
text: string;
|
|
480
|
+
submit?: boolean;
|
|
481
|
+
whenBusy?: 'queue' | 'send' | 'fail';
|
|
482
|
+
};
|
|
483
|
+
result: {
|
|
484
|
+
delivered: 'sent' | 'queued' | 'inserted';
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
'terminals.run': {
|
|
488
|
+
params: {
|
|
489
|
+
agentId: string;
|
|
490
|
+
command: string;
|
|
491
|
+
timeoutMs?: number;
|
|
492
|
+
};
|
|
493
|
+
result: {
|
|
494
|
+
exitCode: number | null;
|
|
495
|
+
output: string;
|
|
496
|
+
truncated: boolean;
|
|
497
|
+
timedOut: boolean;
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
'terminals.write': {
|
|
501
|
+
params: {
|
|
502
|
+
agentId: string;
|
|
503
|
+
text: string;
|
|
504
|
+
submit?: boolean;
|
|
505
|
+
};
|
|
506
|
+
result: void;
|
|
507
|
+
};
|
|
508
|
+
'ports.describe': {
|
|
509
|
+
params: void;
|
|
510
|
+
result: {
|
|
511
|
+
inputs: PortInfo[];
|
|
512
|
+
outputs: PortInfo[];
|
|
513
|
+
};
|
|
514
|
+
};
|
|
515
|
+
'ports.peers': {
|
|
516
|
+
params: void;
|
|
517
|
+
result: PeerInfo[];
|
|
518
|
+
};
|
|
519
|
+
'ports.emit': {
|
|
520
|
+
params: {
|
|
521
|
+
port: string;
|
|
522
|
+
data: JsonValue;
|
|
523
|
+
};
|
|
524
|
+
result: {
|
|
525
|
+
delivered: number;
|
|
526
|
+
};
|
|
527
|
+
};
|
|
528
|
+
'ports.send': {
|
|
529
|
+
params: {
|
|
530
|
+
to: string;
|
|
531
|
+
port: string;
|
|
532
|
+
input?: string;
|
|
533
|
+
data: JsonValue;
|
|
534
|
+
};
|
|
535
|
+
result: {
|
|
536
|
+
delivered: number;
|
|
537
|
+
};
|
|
538
|
+
};
|
|
539
|
+
'ports.request': {
|
|
540
|
+
params: {
|
|
541
|
+
to: string;
|
|
542
|
+
input: string;
|
|
543
|
+
data: JsonValue;
|
|
544
|
+
timeoutMs?: number;
|
|
545
|
+
};
|
|
546
|
+
result: {
|
|
547
|
+
data: JsonValue;
|
|
548
|
+
};
|
|
549
|
+
};
|
|
550
|
+
'ports.respond': {
|
|
551
|
+
params: {
|
|
552
|
+
requestId: string;
|
|
553
|
+
data?: JsonValue;
|
|
554
|
+
error?: string;
|
|
555
|
+
};
|
|
556
|
+
result: void;
|
|
557
|
+
};
|
|
558
|
+
'ports.read': {
|
|
559
|
+
params: {
|
|
560
|
+
from: string;
|
|
561
|
+
port: string;
|
|
562
|
+
};
|
|
563
|
+
result: {
|
|
564
|
+
data: JsonValue;
|
|
565
|
+
at: number;
|
|
566
|
+
} | null;
|
|
567
|
+
};
|
|
568
|
+
'tools.respond': {
|
|
569
|
+
params: {
|
|
570
|
+
callId: string;
|
|
571
|
+
result?: ToolResultPayload;
|
|
572
|
+
error?: string;
|
|
573
|
+
};
|
|
574
|
+
result: void;
|
|
575
|
+
};
|
|
576
|
+
'tools.progress': {
|
|
577
|
+
params: {
|
|
578
|
+
callId: string;
|
|
579
|
+
message: string;
|
|
580
|
+
};
|
|
581
|
+
result: void;
|
|
582
|
+
};
|
|
583
|
+
'tools.setEnabled': {
|
|
584
|
+
params: {
|
|
585
|
+
tool: string;
|
|
586
|
+
enabled: boolean;
|
|
587
|
+
};
|
|
588
|
+
result: void;
|
|
589
|
+
};
|
|
590
|
+
'net.fetch': {
|
|
591
|
+
params: {
|
|
592
|
+
url: string;
|
|
593
|
+
method?: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
594
|
+
headers?: Record<string, string>;
|
|
595
|
+
body?: string;
|
|
596
|
+
bodyEncoding?: 'text' | 'base64';
|
|
597
|
+
responseType?: 'text' | 'json' | 'base64' | 'stream';
|
|
598
|
+
timeoutMs?: number;
|
|
599
|
+
/** Caller-chosen id for net.abort and stream chunks; generated when absent. */
|
|
600
|
+
requestId?: string;
|
|
601
|
+
};
|
|
602
|
+
result: NetResponse;
|
|
603
|
+
};
|
|
604
|
+
'net.abort': {
|
|
605
|
+
params: {
|
|
606
|
+
requestId: string;
|
|
607
|
+
};
|
|
608
|
+
result: void;
|
|
609
|
+
};
|
|
610
|
+
'fs.stat': {
|
|
611
|
+
params: {
|
|
612
|
+
path: string;
|
|
613
|
+
};
|
|
614
|
+
result: FsStat;
|
|
615
|
+
};
|
|
616
|
+
'fs.list': {
|
|
617
|
+
params: {
|
|
618
|
+
path: string;
|
|
619
|
+
recursive?: boolean;
|
|
620
|
+
maxEntries?: number;
|
|
621
|
+
};
|
|
622
|
+
result: {
|
|
623
|
+
entries: FsEntry[];
|
|
624
|
+
truncated: boolean;
|
|
625
|
+
};
|
|
626
|
+
};
|
|
627
|
+
'fs.read': {
|
|
628
|
+
params: {
|
|
629
|
+
path: string;
|
|
630
|
+
encoding?: 'utf8' | 'base64';
|
|
631
|
+
maxBytes?: number;
|
|
632
|
+
};
|
|
633
|
+
result: {
|
|
634
|
+
data: string;
|
|
635
|
+
encoding: 'utf8' | 'base64';
|
|
636
|
+
size: number;
|
|
637
|
+
truncated: boolean;
|
|
638
|
+
};
|
|
639
|
+
};
|
|
640
|
+
'fs.write': {
|
|
641
|
+
params: {
|
|
642
|
+
path: string;
|
|
643
|
+
data: string;
|
|
644
|
+
encoding?: 'utf8' | 'base64';
|
|
645
|
+
createDirs?: boolean;
|
|
646
|
+
ifMtimeMs?: number;
|
|
647
|
+
};
|
|
648
|
+
result: FsStat;
|
|
649
|
+
};
|
|
650
|
+
'fs.mkdir': {
|
|
651
|
+
params: {
|
|
652
|
+
path: string;
|
|
653
|
+
};
|
|
654
|
+
result: FsStat;
|
|
655
|
+
};
|
|
656
|
+
'fs.trash': {
|
|
657
|
+
params: {
|
|
658
|
+
path: string;
|
|
659
|
+
};
|
|
660
|
+
result: void;
|
|
661
|
+
};
|
|
662
|
+
'fs.watch': {
|
|
663
|
+
params: {
|
|
664
|
+
path: string;
|
|
665
|
+
recursive?: boolean;
|
|
666
|
+
};
|
|
667
|
+
result: {
|
|
668
|
+
watchId: string;
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
'fs.unwatch': {
|
|
672
|
+
params: {
|
|
673
|
+
watchId: string;
|
|
674
|
+
};
|
|
675
|
+
result: void;
|
|
676
|
+
};
|
|
677
|
+
'clipboard.writeText': {
|
|
678
|
+
params: {
|
|
679
|
+
text: string;
|
|
680
|
+
};
|
|
681
|
+
result: void;
|
|
682
|
+
};
|
|
683
|
+
'usage.summary': {
|
|
684
|
+
params: {
|
|
685
|
+
period: 'today' | '7d' | '30d';
|
|
686
|
+
};
|
|
687
|
+
result: UsageSummary;
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
export type CardMethodName = keyof CardMethods;
|
|
691
|
+
export type MethodParams<M extends CardMethodName> = CardMethods[M]['params'];
|
|
692
|
+
export type MethodResult<M extends CardMethodName> = CardMethods[M]['result'];
|
|
693
|
+
export interface CardEvents {
|
|
694
|
+
'host.ping': {
|
|
695
|
+
seq: number;
|
|
696
|
+
};
|
|
697
|
+
'lifecycle.visibility': {
|
|
698
|
+
state: CardVisibility;
|
|
699
|
+
};
|
|
700
|
+
/** Save what you need; the frame is unloaded after `graceMs`. It comes back with launch 'resumed'. */
|
|
701
|
+
'lifecycle.suspend': {
|
|
702
|
+
graceMs: number;
|
|
703
|
+
};
|
|
704
|
+
'lifecycle.expanded': {
|
|
705
|
+
expanded: boolean;
|
|
706
|
+
};
|
|
707
|
+
'lifecycle.resized': CardSize;
|
|
708
|
+
'settings.changed': SettingsSnapshot;
|
|
709
|
+
'theme.changed': ThemeSnapshot;
|
|
710
|
+
'i18n.changed': I18nSnapshot;
|
|
711
|
+
'permissions.changed': PermissionState[];
|
|
712
|
+
'ui.menu': {
|
|
713
|
+
id: string;
|
|
714
|
+
};
|
|
715
|
+
'ports.message': {
|
|
716
|
+
from: string;
|
|
717
|
+
fromKind: PeerKind;
|
|
718
|
+
/** The sender's output port id. */
|
|
719
|
+
output: string;
|
|
720
|
+
/** Our input port id it was delivered to. */
|
|
721
|
+
input: string;
|
|
722
|
+
/** The type after coercion (= our input's type). */
|
|
723
|
+
type: PortTypeId;
|
|
724
|
+
/** The sender's declared output type, before coercion (absent on older hosts). */
|
|
725
|
+
sourceType?: PortTypeId;
|
|
726
|
+
data: JsonValue;
|
|
727
|
+
at: number;
|
|
728
|
+
};
|
|
729
|
+
'ports.request': {
|
|
730
|
+
requestId: string;
|
|
731
|
+
from: string;
|
|
732
|
+
input: string;
|
|
733
|
+
data: JsonValue;
|
|
734
|
+
deadline: number;
|
|
735
|
+
};
|
|
736
|
+
'ports.peersChanged': PeerInfo[];
|
|
737
|
+
'tools.call': {
|
|
738
|
+
callId: string;
|
|
739
|
+
tool: string;
|
|
740
|
+
args: JsonValue;
|
|
741
|
+
agent: {
|
|
742
|
+
id: string;
|
|
743
|
+
name: string;
|
|
744
|
+
};
|
|
745
|
+
deadline: number;
|
|
746
|
+
};
|
|
747
|
+
'tools.cancel': {
|
|
748
|
+
callId: string;
|
|
749
|
+
};
|
|
750
|
+
'net.chunk': {
|
|
751
|
+
requestId: string;
|
|
752
|
+
chunk: string;
|
|
753
|
+
encoding: 'text' | 'base64';
|
|
754
|
+
done: boolean;
|
|
755
|
+
error?: string;
|
|
756
|
+
};
|
|
757
|
+
'fs.changed': {
|
|
758
|
+
watchId: string;
|
|
759
|
+
path: string;
|
|
760
|
+
type: 'change' | 'rename';
|
|
761
|
+
};
|
|
762
|
+
'storage.changed': {
|
|
763
|
+
scope: 'package';
|
|
764
|
+
key: string;
|
|
765
|
+
byInstance: string;
|
|
766
|
+
};
|
|
767
|
+
'agents.status': {
|
|
768
|
+
agentId: string;
|
|
769
|
+
status: AgentStatus;
|
|
770
|
+
at: number;
|
|
771
|
+
};
|
|
772
|
+
'agents.turn': {
|
|
773
|
+
agentId: string;
|
|
774
|
+
phase: 'start' | 'end';
|
|
775
|
+
at: number;
|
|
776
|
+
};
|
|
777
|
+
'agents.changed': {
|
|
778
|
+
agents: AgentInfo[];
|
|
779
|
+
};
|
|
780
|
+
'agents.output': {
|
|
781
|
+
agentId: string;
|
|
782
|
+
text: string;
|
|
783
|
+
at: number;
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
export type CardEventName = keyof CardEvents;
|
|
787
|
+
export declare const CARD_EVENT_NAMES: CardEventName[];
|
|
788
|
+
export interface MethodSpec {
|
|
789
|
+
/**
|
|
790
|
+
* Required grant. An array means *any one of* (net.fetch: main then picks the
|
|
791
|
+
* precise one from the URL). Absent = always allowed.
|
|
792
|
+
*/
|
|
793
|
+
permission?: PermissionId | readonly PermissionId[];
|
|
794
|
+
params: CardJsonSchema;
|
|
795
|
+
/** Refused with NOT_VISIBLE unless the card is 'visible' (and its window focused, for dialogs). */
|
|
796
|
+
visible?: boolean;
|
|
797
|
+
/** Extra per-method throttle on top of the global bucket. */
|
|
798
|
+
minIntervalMs?: number;
|
|
799
|
+
perMinute?: number;
|
|
800
|
+
/** Response may use LIMITS.largeMessageBytes. */
|
|
801
|
+
largeResponse?: boolean;
|
|
802
|
+
/** Allowed before host.ready (only host.ready itself). */
|
|
803
|
+
beforeReady?: boolean;
|
|
804
|
+
}
|
|
805
|
+
export declare const METHOD_SPECS: Record<CardMethodName, MethodSpec>;
|
|
806
|
+
export declare const CARD_METHOD_NAMES: CardMethodName[];
|
|
807
|
+
/** Is a method allowed by these (expanded) grants? */
|
|
808
|
+
export declare function methodAllowed(method: CardMethodName, granted: ReadonlySet<PermissionId>): boolean;
|
|
809
|
+
/** PermissionState list for a manifest's permissions and the current grants. */
|
|
810
|
+
export declare function permissionStates(declared: readonly NormalizedPermission[], granted: ReadonlySet<PermissionId>, resolveReason: (text: LocalizedText) => string): PermissionState[];
|
|
811
|
+
/** Settings fields as the SDK exposes them (for cards that render their own settings UI). */
|
|
812
|
+
export type { SettingField };
|