@swarm-agent/sdk 0.1.49 → 0.1.50
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/HEADLESS_UI.md +4 -6
- package/README.md +121 -56
- package/dist/agents.d.ts +114 -0
- package/dist/agents.js +183 -0
- package/dist/auth.d.ts +14 -0
- package/dist/auth.js +16 -0
- package/dist/box.d.ts +68 -0
- package/dist/box.js +13 -0
- package/dist/browser.d.ts +6 -2
- package/dist/browser.js +11 -3
- package/dist/chat.d.ts +41 -7
- package/dist/chat.js +148 -83
- package/dist/client.d.ts +12 -0
- package/dist/client.js +19 -6
- package/dist/copy-tags.d.ts +26 -0
- package/dist/copy-tags.js +133 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +21 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/local-connection.d.ts +39 -0
- package/dist/local-connection.js +56 -0
- package/dist/permission-ui.d.ts +1 -0
- package/dist/permission-ui.js +37 -0
- package/dist/permissions.d.ts +4 -0
- package/dist/permissions.js +7 -0
- package/dist/projects.d.ts +25 -3
- package/dist/projects.js +65 -6
- package/dist/provider-auth.d.ts +5 -3
- package/dist/provider-auth.js +6 -8
- package/dist/realtime.d.ts +40 -6
- package/dist/realtime.js +156 -52
- package/dist/remote.d.ts +59 -0
- package/dist/remote.js +46 -0
- package/dist/sessions.d.ts +31 -1
- package/dist/sessions.js +49 -1
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +19 -3
- package/dist/signals.d.ts +148 -0
- package/dist/signals.js +97 -0
- package/dist/types.d.ts +70 -2
- package/dist/websocket.d.ts +3 -1
- package/dist/websocket.js +1 -1
- package/dist/workspaces.d.ts +11 -0
- package/dist/workspaces.js +17 -0
- package/package.json +1 -1
package/dist/settings.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SwarmNotFoundError } from './errors.js';
|
|
1
2
|
/** Account-scoped settings. Requires the local administrative connection, not a session token. */
|
|
2
3
|
export class SwarmSettingsNamespace {
|
|
3
4
|
transport;
|
|
@@ -23,12 +24,22 @@ export class SwarmSettingsNamespace {
|
|
|
23
24
|
/**
|
|
24
25
|
* Restores verified recommended defaults across all system agent and swarm core roles.
|
|
25
26
|
* If expectedUpdatedAt is omitted, automatically reads the current setting's revision first.
|
|
27
|
+
* An account with no model settings yet (a provider is connected but its
|
|
28
|
+
* models were never set up) restores from revision 0: the daemon then sets
|
|
29
|
+
* up the recommended models from a ready provider.
|
|
26
30
|
*/
|
|
27
31
|
async restoreDefaults(expectedUpdatedAt) {
|
|
28
32
|
let updatedAt = expectedUpdatedAt;
|
|
29
33
|
if (typeof updatedAt !== 'number') {
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
try {
|
|
35
|
+
const current = await this.agentModels();
|
|
36
|
+
updatedAt = current.agent_model_settings.updated_at;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (!(error instanceof SwarmNotFoundError))
|
|
40
|
+
throw error;
|
|
41
|
+
updatedAt = 0;
|
|
42
|
+
}
|
|
32
43
|
}
|
|
33
44
|
return (await this.transport.request('/v1/agent-model-settings/restore-defaults', {
|
|
34
45
|
method: 'POST',
|
|
@@ -87,7 +98,12 @@ export class SwarmSettingsNamespace {
|
|
|
87
98
|
*/
|
|
88
99
|
async applyProviderFleet(provider) {
|
|
89
100
|
const fleet = await this.getRecommendationsForProvider(provider);
|
|
90
|
-
|
|
101
|
+
// The daemon takes one target per PATCH: the swarm pair, then each system agent.
|
|
102
|
+
let result = await this.patch({ swarm: fleet.swarm });
|
|
103
|
+
for (const [slot, assignment] of Object.entries(fleet.system_agents)) {
|
|
104
|
+
result = await this.patch({ system_agents: { [slot]: assignment } });
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
91
107
|
}
|
|
92
108
|
async patch(body) {
|
|
93
109
|
return (await this.transport.request('/v1/agent-model-settings', { method: 'PATCH', body })).data;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { SwarmTransport } from './transport.js';
|
|
2
|
+
export type SignalSeverity = 'info' | 'warning' | 'critical';
|
|
3
|
+
/**
|
|
4
|
+
* One entry in a machine's signal feed: a high-level event such as an agent
|
|
5
|
+
* waiting on a person, a failed run, a refused key or an event an outside
|
|
6
|
+
* source reported. Signals carry ids and a one-line summary, never transcripts,
|
|
7
|
+
* command arguments or secret values.
|
|
8
|
+
*/
|
|
9
|
+
export interface Signal {
|
|
10
|
+
/** Position in this machine's feed; pass the last one back as `after`. */
|
|
11
|
+
seq: number;
|
|
12
|
+
/** Unique id, stable across forwarding (use it to drop duplicates). */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Unix milliseconds. */
|
|
15
|
+
at: number;
|
|
16
|
+
/** Dotted kind, e.g. `agent.blocked`, `run.failed`, `external.falco`. */
|
|
17
|
+
kind: string;
|
|
18
|
+
severity: SignalSeverity;
|
|
19
|
+
/** `swarmd` for Swarm's own signals, `external:<name>` for reported ones. */
|
|
20
|
+
source: string;
|
|
21
|
+
/** Empty for machine-wide signals. */
|
|
22
|
+
account?: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
/** Signals with the same key describe the same ongoing condition. */
|
|
25
|
+
dedup_key?: string;
|
|
26
|
+
refs?: Record<string, string>;
|
|
27
|
+
attrs?: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
export interface SignalPage {
|
|
30
|
+
signals: Signal[];
|
|
31
|
+
/** The last position examined; pass it as `after` to continue. */
|
|
32
|
+
next_after: number;
|
|
33
|
+
oldest_seq: number;
|
|
34
|
+
latest_seq: number;
|
|
35
|
+
/**
|
|
36
|
+
* True when signals after your cursor were already dropped (the feed keeps
|
|
37
|
+
* the newest entries only) or your cursor is ahead of the feed. Resync
|
|
38
|
+
* from `next_after` and treat the missed range as unknown.
|
|
39
|
+
*/
|
|
40
|
+
gap: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface ListSignalsParams {
|
|
43
|
+
/** Return signals numbered after this position (default 0: from the oldest kept). */
|
|
44
|
+
after?: number;
|
|
45
|
+
/** At most this many signals (default 100, maximum 500). */
|
|
46
|
+
limit?: number;
|
|
47
|
+
/** Kind prefixes, e.g. `['agent', 'run.failed']`. */
|
|
48
|
+
kinds?: string[];
|
|
49
|
+
/** Only signals at least this severe. */
|
|
50
|
+
minSeverity?: SignalSeverity;
|
|
51
|
+
}
|
|
52
|
+
export interface ReportSignalParams {
|
|
53
|
+
/** Must start with `external.`, e.g. `external.falco`. */
|
|
54
|
+
kind: string;
|
|
55
|
+
/** One line; longer text is cut to 300 characters. */
|
|
56
|
+
summary: string;
|
|
57
|
+
severity?: SignalSeverity;
|
|
58
|
+
/** Lowercase name of the reporting source, e.g. `falco`. */
|
|
59
|
+
source?: string;
|
|
60
|
+
dedup_key?: string;
|
|
61
|
+
refs?: Record<string, string>;
|
|
62
|
+
attrs?: Record<string, string>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The machine signal feed. Reading needs a key with `signals:read`; reporting
|
|
66
|
+
* an outside event needs `signals:write`. Readers see their own account's
|
|
67
|
+
* signals and machine-wide ones.
|
|
68
|
+
*/
|
|
69
|
+
export declare class SwarmSignalsNamespace {
|
|
70
|
+
private readonly transport;
|
|
71
|
+
/** Where this machine forwards its feed (owner only). */
|
|
72
|
+
readonly sinks: SwarmSignalSinksNamespace;
|
|
73
|
+
constructor(transport: SwarmTransport);
|
|
74
|
+
/** Lists signals after a cursor, oldest first. */
|
|
75
|
+
list(params?: ListSignalsParams): Promise<SignalPage>;
|
|
76
|
+
/**
|
|
77
|
+
* Reports an outside event (a host security monitor, a backup script) into
|
|
78
|
+
* the feed. Swarm records the source as `external:<source>` and, for a
|
|
79
|
+
* scoped key, which key reported it.
|
|
80
|
+
*/
|
|
81
|
+
report(params: ReportSignalParams): Promise<Signal>;
|
|
82
|
+
}
|
|
83
|
+
/** Where a machine forwards its signal feed (owner only). */
|
|
84
|
+
export interface SignalSink {
|
|
85
|
+
id: string;
|
|
86
|
+
account: string;
|
|
87
|
+
name: string;
|
|
88
|
+
url: string;
|
|
89
|
+
kinds?: string[];
|
|
90
|
+
min_severity?: SignalSeverity;
|
|
91
|
+
heartbeat_seconds: number;
|
|
92
|
+
/** Last signal position the sink accepted. */
|
|
93
|
+
cursor: number;
|
|
94
|
+
created_at: number;
|
|
95
|
+
last_delivered_at?: number;
|
|
96
|
+
last_attempt_at?: number;
|
|
97
|
+
last_error?: string;
|
|
98
|
+
failures?: number;
|
|
99
|
+
}
|
|
100
|
+
export interface CreateSignalSinkParams {
|
|
101
|
+
name: string;
|
|
102
|
+
/** https URL (http only to this machine's loopback). */
|
|
103
|
+
url: string;
|
|
104
|
+
/** Kind prefixes to forward, e.g. `['agent', 'worker.run.failed']`; empty forwards all. */
|
|
105
|
+
kinds?: string[];
|
|
106
|
+
minSeverity?: SignalSeverity;
|
|
107
|
+
/** Idle heartbeat interval, 30 to 3600 seconds (default 60). */
|
|
108
|
+
heartbeatSeconds?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Signal sinks: the machine POSTs batches of its feed to each sink, signed
|
|
112
|
+
* with the sink's secret (see `verifySignalDelivery`). Owner only: scoped
|
|
113
|
+
* keys, including admin keys, are refused.
|
|
114
|
+
*/
|
|
115
|
+
export declare class SwarmSignalSinksNamespace {
|
|
116
|
+
private readonly transport;
|
|
117
|
+
constructor(transport: SwarmTransport);
|
|
118
|
+
list(): Promise<SignalSink[]>;
|
|
119
|
+
/** Creates a sink. The signing secret is returned only here; store it in the receiver. */
|
|
120
|
+
create(params: CreateSignalSinkParams): Promise<{
|
|
121
|
+
sink: SignalSink;
|
|
122
|
+
secret: string;
|
|
123
|
+
}>;
|
|
124
|
+
delete(id: string): Promise<void>;
|
|
125
|
+
}
|
|
126
|
+
/** Body of one signal delivery (version 1). */
|
|
127
|
+
export interface SignalDelivery {
|
|
128
|
+
version: 1;
|
|
129
|
+
sink_id: string;
|
|
130
|
+
machine?: string;
|
|
131
|
+
sent_at: number;
|
|
132
|
+
/** True for an idle heartbeat with no signals. */
|
|
133
|
+
heartbeat: boolean;
|
|
134
|
+
signals: Signal[];
|
|
135
|
+
next_after: number;
|
|
136
|
+
latest_seq: number;
|
|
137
|
+
gap: boolean;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Checks a delivery's `X-Swarm-Signature` for a receiver: HMAC-SHA256 of
|
|
141
|
+
* `${X-Swarm-Timestamp}.${rawBody}` with the sink secret, and a timestamp
|
|
142
|
+
* within `maxSkewMs` of now (rejects replays). Pass the raw request body,
|
|
143
|
+
* not re-serialized JSON. Works with WebCrypto (Node 18+, Workers, browsers).
|
|
144
|
+
*/
|
|
145
|
+
export declare function verifySignalDelivery(secret: string, timestamp: string | number, rawBody: string | Uint8Array, signature: string, { now, maxSkewMs }?: {
|
|
146
|
+
now?: number;
|
|
147
|
+
maxSkewMs?: number;
|
|
148
|
+
}): Promise<boolean>;
|
package/dist/signals.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The machine signal feed. Reading needs a key with `signals:read`; reporting
|
|
3
|
+
* an outside event needs `signals:write`. Readers see their own account's
|
|
4
|
+
* signals and machine-wide ones.
|
|
5
|
+
*/
|
|
6
|
+
export class SwarmSignalsNamespace {
|
|
7
|
+
transport;
|
|
8
|
+
/** Where this machine forwards its feed (owner only). */
|
|
9
|
+
sinks;
|
|
10
|
+
constructor(transport) {
|
|
11
|
+
this.transport = transport;
|
|
12
|
+
this.sinks = new SwarmSignalSinksNamespace(transport);
|
|
13
|
+
}
|
|
14
|
+
/** Lists signals after a cursor, oldest first. */
|
|
15
|
+
async list(params = {}) {
|
|
16
|
+
const q = new URLSearchParams();
|
|
17
|
+
if (typeof params.after === 'number')
|
|
18
|
+
q.set('after', String(params.after));
|
|
19
|
+
if (typeof params.limit === 'number')
|
|
20
|
+
q.set('limit', String(params.limit));
|
|
21
|
+
if (params.kinds?.length)
|
|
22
|
+
q.set('kind', params.kinds.join(','));
|
|
23
|
+
if (params.minSeverity)
|
|
24
|
+
q.set('min_severity', params.minSeverity);
|
|
25
|
+
const path = q.toString() ? `/v3/signals?${q.toString()}` : '/v3/signals';
|
|
26
|
+
const res = await this.transport.request(path, { method: 'GET' });
|
|
27
|
+
const { signals, next_after, oldest_seq, latest_seq, gap } = res.data;
|
|
28
|
+
return { signals: signals ?? [], next_after, oldest_seq, latest_seq, gap };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reports an outside event (a host security monitor, a backup script) into
|
|
32
|
+
* the feed. Swarm records the source as `external:<source>` and, for a
|
|
33
|
+
* scoped key, which key reported it.
|
|
34
|
+
*/
|
|
35
|
+
async report(params) {
|
|
36
|
+
const res = await this.transport.request('/v3/signals', {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
body: params,
|
|
39
|
+
});
|
|
40
|
+
return res.data.signal;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Signal sinks: the machine POSTs batches of its feed to each sink, signed
|
|
45
|
+
* with the sink's secret (see `verifySignalDelivery`). Owner only: scoped
|
|
46
|
+
* keys, including admin keys, are refused.
|
|
47
|
+
*/
|
|
48
|
+
export class SwarmSignalSinksNamespace {
|
|
49
|
+
transport;
|
|
50
|
+
constructor(transport) {
|
|
51
|
+
this.transport = transport;
|
|
52
|
+
}
|
|
53
|
+
async list() {
|
|
54
|
+
const res = await this.transport.request('/v3/signals/sinks', { method: 'GET' });
|
|
55
|
+
return res.data.sinks ?? [];
|
|
56
|
+
}
|
|
57
|
+
/** Creates a sink. The signing secret is returned only here; store it in the receiver. */
|
|
58
|
+
async create(params) {
|
|
59
|
+
const res = await this.transport.request('/v3/signals/sinks', {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
body: {
|
|
62
|
+
name: params.name,
|
|
63
|
+
url: params.url,
|
|
64
|
+
kinds: params.kinds,
|
|
65
|
+
min_severity: params.minSeverity,
|
|
66
|
+
heartbeat_seconds: params.heartbeatSeconds,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
return { sink: res.data.sink, secret: res.data.secret };
|
|
70
|
+
}
|
|
71
|
+
async delete(id) {
|
|
72
|
+
await this.transport.request(`/v3/signals/sinks/${encodeURIComponent(id)}`, { method: 'DELETE' });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Checks a delivery's `X-Swarm-Signature` for a receiver: HMAC-SHA256 of
|
|
77
|
+
* `${X-Swarm-Timestamp}.${rawBody}` with the sink secret, and a timestamp
|
|
78
|
+
* within `maxSkewMs` of now (rejects replays). Pass the raw request body,
|
|
79
|
+
* not re-serialized JSON. Works with WebCrypto (Node 18+, Workers, browsers).
|
|
80
|
+
*/
|
|
81
|
+
export async function verifySignalDelivery(secret, timestamp, rawBody, signature, { now = Date.now(), maxSkewMs = 5 * 60 * 1000 } = {}) {
|
|
82
|
+
const ts = Number(timestamp);
|
|
83
|
+
if (!Number.isFinite(ts) || Math.abs(now - ts) > maxSkewMs || !signature.startsWith('v1='))
|
|
84
|
+
return false;
|
|
85
|
+
const enc = new TextEncoder();
|
|
86
|
+
const body = typeof rawBody === 'string' ? enc.encode(rawBody) : rawBody;
|
|
87
|
+
const message = new Uint8Array([...enc.encode(`${ts}.`), ...body]);
|
|
88
|
+
const key = await crypto.subtle.importKey('raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
89
|
+
const mac = new Uint8Array(await crypto.subtle.sign('HMAC', key, message));
|
|
90
|
+
const expected = 'v1=' + Array.from(mac, (b) => b.toString(16).padStart(2, '0')).join('');
|
|
91
|
+
if (expected.length !== signature.length)
|
|
92
|
+
return false;
|
|
93
|
+
let diff = 0;
|
|
94
|
+
for (let i = 0; i < expected.length; i++)
|
|
95
|
+
diff |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
|
|
96
|
+
return diff === 0;
|
|
97
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export type TokenScope = 'automations:trigger' | 'automations:read' | 'automations:write' | 'sessions:read' | 'sessions:write' | 'projects:read' | 'projects:write' | 'admin' | string;
|
|
2
2
|
export interface SwarmClientConfig {
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Base URL of the Swarm daemon API (default http://127.0.0.1:7781). With no
|
|
5
|
+
* `baseUrl`, `socketPath` or environment override, Node clients use the
|
|
6
|
+
* owner socket of a system install when this process may connect to it.
|
|
7
|
+
*/
|
|
4
8
|
baseUrl?: string;
|
|
5
9
|
/** Bearer authentication token (attach token or scoped token starting with 'swk_') */
|
|
6
10
|
token?: string;
|
|
7
|
-
/** Unix
|
|
11
|
+
/** Unix socket for local IPC (owner socket: /var/lib/swarmd/local-transport/api.sock) */
|
|
8
12
|
socketPath?: string;
|
|
9
13
|
/** Custom default HTTP headers */
|
|
10
14
|
defaultHeaders?: Record<string, string>;
|
|
@@ -535,6 +539,43 @@ export interface ProjectTaskPlanBinding {
|
|
|
535
539
|
session_id?: string;
|
|
536
540
|
receipt?: string;
|
|
537
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Backend-inspected delivery facts for a task's captured worktree lane. Only the
|
|
544
|
+
* task-detail GET (`getTask`) observes Git; collection rows carry `freshness: 'stale'`.
|
|
545
|
+
*/
|
|
546
|
+
export interface ProjectTaskDeliveryAssessment {
|
|
547
|
+
task_id?: string;
|
|
548
|
+
task_revision?: number;
|
|
549
|
+
attempt_id?: string;
|
|
550
|
+
session_id?: string;
|
|
551
|
+
base_oid?: string;
|
|
552
|
+
source_oid?: string;
|
|
553
|
+
target_oid?: string;
|
|
554
|
+
source_branch?: string;
|
|
555
|
+
target_branch?: string;
|
|
556
|
+
state?: 'candidate_work' | 'integrated' | 'unavailable' | string;
|
|
557
|
+
reason_code?: string;
|
|
558
|
+
reason?: string;
|
|
559
|
+
freshness?: 'observed' | 'stale' | 'unknown' | string;
|
|
560
|
+
source_dirty?: boolean;
|
|
561
|
+
target_dirty?: boolean;
|
|
562
|
+
candidate_commits?: number;
|
|
563
|
+
files?: string[];
|
|
564
|
+
allowed_actions?: string[];
|
|
565
|
+
[key: string]: unknown;
|
|
566
|
+
}
|
|
567
|
+
/** One coordinator attempt (session reservation) on a project task. */
|
|
568
|
+
export interface ProjectTaskAttempt {
|
|
569
|
+
id: string;
|
|
570
|
+
session_id?: string;
|
|
571
|
+
status?: string;
|
|
572
|
+
role?: string;
|
|
573
|
+
workspace_path?: string;
|
|
574
|
+
worktree_branch?: string;
|
|
575
|
+
base_branch?: string;
|
|
576
|
+
base_commit?: string;
|
|
577
|
+
[key: string]: unknown;
|
|
578
|
+
}
|
|
538
579
|
export interface ProjectTaskRecord {
|
|
539
580
|
id: string;
|
|
540
581
|
project_id: string;
|
|
@@ -543,6 +584,9 @@ export interface ProjectTaskRecord {
|
|
|
543
584
|
description?: string;
|
|
544
585
|
status: 'queued' | 'in_progress' | 'needs_review' | 'completed' | 'failed' | 'pending_approval' | 'planning' | 'rejected' | string;
|
|
545
586
|
session_id?: string;
|
|
587
|
+
active_attempt_id?: string;
|
|
588
|
+
attempts?: ProjectTaskAttempt[];
|
|
589
|
+
delivery_assessment?: ProjectTaskDeliveryAssessment;
|
|
546
590
|
agent?: string;
|
|
547
591
|
worker_name?: string;
|
|
548
592
|
outcome_type?: string;
|
|
@@ -744,6 +788,30 @@ export interface RefineProjectTaskResult {
|
|
|
744
788
|
status: 'refined' | string;
|
|
745
789
|
task: ProjectTaskRecord;
|
|
746
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Selection body for POST /v3/projects/{id}/tasks/{taskId}/integrate. The daemon
|
|
793
|
+
* requires `session_id` (must equal the task's current session) plus the captured
|
|
794
|
+
* `source_branch`/`target_branch` (must equal the session worktree branch and its
|
|
795
|
+
* base branch). The remaining fields are the stale-state guards the daemon's
|
|
796
|
+
* `recover-integrate` path checks; plain integrate accepts and ignores them.
|
|
797
|
+
*/
|
|
798
|
+
export interface IntegrateProjectTaskSelection {
|
|
799
|
+
session_id: string;
|
|
800
|
+
source_branch: string;
|
|
801
|
+
target_branch: string;
|
|
802
|
+
revision?: number;
|
|
803
|
+
attempt_id?: string;
|
|
804
|
+
source_head?: string;
|
|
805
|
+
target_head?: string;
|
|
806
|
+
}
|
|
807
|
+
export interface IntegrateProjectTaskOptions extends RequestOptions {
|
|
808
|
+
/**
|
|
809
|
+
* Overrides merged over the selection the SDK derives from a fresh `getTask`.
|
|
810
|
+
* When `session_id`, `source_branch` and `target_branch` are all supplied, the
|
|
811
|
+
* SDK skips the task fetch and sends them as given.
|
|
812
|
+
*/
|
|
813
|
+
selection?: Partial<IntegrateProjectTaskSelection>;
|
|
814
|
+
}
|
|
747
815
|
export interface IntegrateProjectTaskResult {
|
|
748
816
|
status: 'integrated' | 'already_integrated' | string;
|
|
749
817
|
message?: string;
|
package/dist/websocket.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Server as HttpsServer } from 'node:https';
|
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
import type { SwarmChatNamespace, ToolStreamItem } from './chat.js';
|
|
5
5
|
import type { PendingPermissionRecord, SwarmPermissionsNamespace, PermissionResolver, ResolvePermissionOptions, ResolvePermissionResult } from './permissions.js';
|
|
6
|
-
import type { SessionWatchState, V3Message } from './realtime.js';
|
|
6
|
+
import type { SessionWatchState, V3Message, V3RunState } from './realtime.js';
|
|
7
7
|
export interface SwarmWebSocketBridgeOptions {
|
|
8
8
|
path?: string;
|
|
9
9
|
/** Server-owned policy. Browser frames cannot enable auto approval. Questions always require a reply. */
|
|
@@ -37,6 +37,8 @@ export interface SwarmWebSocketServerMessage {
|
|
|
37
37
|
result?: ResolvePermissionResult;
|
|
38
38
|
permissionId?: string;
|
|
39
39
|
messages?: V3Message[];
|
|
40
|
+
/** Finished run on `done`: `status` is completed, failed, cancelled, ... */
|
|
41
|
+
run?: V3RunState;
|
|
40
42
|
error?: string;
|
|
41
43
|
}
|
|
42
44
|
/** Application-owned bridge to canonical V3 realtime. A subscription survives every turn.
|
package/dist/websocket.js
CHANGED
|
@@ -165,7 +165,7 @@ export class SwarmWebSocketBridge {
|
|
|
165
165
|
},
|
|
166
166
|
onPermissionRemoved: permissionId => send({ type: 'permission_removed', permissionId }),
|
|
167
167
|
onPermissionError: (error, permission) => send({ type: 'permission_error', permissionId: permission.id, error: error.message }),
|
|
168
|
-
onComplete: messages => send({ type: 'done', messages }),
|
|
168
|
+
onComplete: (messages, run) => send({ type: 'done', messages, run }),
|
|
169
169
|
onError: error => {
|
|
170
170
|
send({ type: 'error', error: error.message });
|
|
171
171
|
if (this.activeWatches.get(ws)?.watch === watch) {
|
package/dist/workspaces.d.ts
CHANGED
|
@@ -4,6 +4,17 @@ export declare class SwarmWorkspacesNamespace {
|
|
|
4
4
|
private transport;
|
|
5
5
|
constructor(transport: SwarmTransport);
|
|
6
6
|
createFolder(parent_path: string, name: string): Promise<WorkspaceFolder>;
|
|
7
|
+
/**
|
|
8
|
+
* Creates `parent_path/name` as a new, empty Git repository with one initial
|
|
9
|
+
* commit and registers it as a workspace, in one call. The daemon refuses a
|
|
10
|
+
* folder that already holds other content. Calling it again for a folder
|
|
11
|
+
* that is already registered returns that workspace.
|
|
12
|
+
*/
|
|
13
|
+
create(body: {
|
|
14
|
+
parent_path: string;
|
|
15
|
+
name: string;
|
|
16
|
+
make_current?: boolean;
|
|
17
|
+
}): Promise<WorkspaceResolution>;
|
|
7
18
|
add(body: {
|
|
8
19
|
path: string;
|
|
9
20
|
name?: string;
|
package/dist/workspaces.js
CHANGED
|
@@ -6,6 +6,23 @@ export class SwarmWorkspacesNamespace {
|
|
|
6
6
|
async createFolder(parent_path, name) {
|
|
7
7
|
return (await this.transport.request('/v1/workspace/folders/create', { method: 'POST', body: { parent_path, name } })).data.folder;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates `parent_path/name` as a new, empty Git repository with one initial
|
|
11
|
+
* commit and registers it as a workspace, in one call. The daemon refuses a
|
|
12
|
+
* folder that already holds other content. Calling it again for a folder
|
|
13
|
+
* that is already registered returns that workspace.
|
|
14
|
+
*/
|
|
15
|
+
async create(body) {
|
|
16
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,62}$/.test(body.name)) {
|
|
17
|
+
throw new Error('Workspace name must be letters, digits, dashes and underscores (at most 63).');
|
|
18
|
+
}
|
|
19
|
+
const parent = body.parent_path.replace(/\/+$/, '');
|
|
20
|
+
if (!parent.startsWith('/'))
|
|
21
|
+
throw new Error('parent_path must be absolute.');
|
|
22
|
+
const path = `${parent}/${body.name}`;
|
|
23
|
+
await this.setupRepository(path, path);
|
|
24
|
+
return this.add({ path, name: body.name, make_current: body.make_current ?? false });
|
|
25
|
+
}
|
|
9
26
|
async add(body) {
|
|
10
27
|
return (await this.transport.request('/v1/workspace/add', { method: 'POST', body })).data.workspace;
|
|
11
28
|
}
|