@swarm-agent/sdk 0.1.47
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/APPLICATIONS.md +133 -0
- package/HEADLESS_UI.md +97 -0
- package/LICENSE +201 -0
- package/README.md +473 -0
- package/dist/app-results.d.ts +24 -0
- package/dist/app-results.js +167 -0
- package/dist/apps.d.ts +82 -0
- package/dist/apps.js +89 -0
- package/dist/auth.d.ts +45 -0
- package/dist/auth.js +89 -0
- package/dist/automations.d.ts +74 -0
- package/dist/automations.js +159 -0
- package/dist/client.d.ts +61 -0
- package/dist/client.js +103 -0
- package/dist/deliverables.d.ts +42 -0
- package/dist/deliverables.js +83 -0
- package/dist/deploy/dockerfile.d.ts +14 -0
- package/dist/deploy/dockerfile.js +14 -0
- package/dist/deploy/index.d.ts +67 -0
- package/dist/deploy/index.js +226 -0
- package/dist/deploy/manifest.d.ts +17 -0
- package/dist/deploy/manifest.js +220 -0
- package/dist/deploy/providers/gcp-cloud-run.d.ts +9 -0
- package/dist/deploy/providers/gcp-cloud-run.js +12 -0
- package/dist/deploy/providers/gcp-compute.d.ts +9 -0
- package/dist/deploy/providers/gcp-compute.js +12 -0
- package/dist/deploy/types.d.ts +211 -0
- package/dist/deploy/types.js +4 -0
- package/dist/deploy/worker-cloud-deployer.d.ts +33 -0
- package/dist/deploy/worker-cloud-deployer.js +14 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +68 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +20 -0
- package/dist/notifications.d.ts +28 -0
- package/dist/notifications.js +65 -0
- package/dist/projects.d.ts +147 -0
- package/dist/projects.js +513 -0
- package/dist/provider-auth.d.ts +160 -0
- package/dist/provider-auth.js +54 -0
- package/dist/realtime.d.ts +240 -0
- package/dist/realtime.js +312 -0
- package/dist/sessions.d.ts +60 -0
- package/dist/sessions.js +194 -0
- package/dist/settings.d.ts +85 -0
- package/dist/settings.js +26 -0
- package/dist/storage/adapters/memory.d.ts +13 -0
- package/dist/storage/adapters/memory.js +35 -0
- package/dist/storage/adapters/s3.d.ts +31 -0
- package/dist/storage/adapters/s3.js +171 -0
- package/dist/storage/client.d.ts +174 -0
- package/dist/storage/client.js +121 -0
- package/dist/storage/hub.d.ts +30 -0
- package/dist/storage/hub.js +372 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.js +6 -0
- package/dist/storage/runner.d.ts +48 -0
- package/dist/storage/runner.js +233 -0
- package/dist/storage/types.d.ts +198 -0
- package/dist/storage/types.js +1 -0
- package/dist/system.d.ts +14 -0
- package/dist/system.js +52 -0
- package/dist/transport.d.ts +17 -0
- package/dist/transport.js +243 -0
- package/dist/types.d.ts +1137 -0
- package/dist/types.js +1 -0
- package/dist/usage.d.ts +106 -0
- package/dist/usage.js +82 -0
- package/dist/workers.d.ts +146 -0
- package/dist/workers.js +822 -0
- package/dist/workspaces.d.ts +81 -0
- package/dist/workspaces.js +58 -0
- package/examples/headless-session.ts +85 -0
- package/package.json +56 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { SwarmTransport } from './transport.js';
|
|
2
|
+
import type { WorkspaceRecord } from './types.js';
|
|
3
|
+
export declare class SwarmWorkspacesNamespace {
|
|
4
|
+
private transport;
|
|
5
|
+
constructor(transport: SwarmTransport);
|
|
6
|
+
createFolder(parent_path: string, name: string): Promise<WorkspaceFolder>;
|
|
7
|
+
add(body: {
|
|
8
|
+
path: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
theme_id?: string;
|
|
11
|
+
make_current?: boolean;
|
|
12
|
+
confirm_committed_only?: boolean;
|
|
13
|
+
}): Promise<WorkspaceResolution>;
|
|
14
|
+
inspectRepository(path: string): Promise<WorkspaceRepository>;
|
|
15
|
+
setupRepository(path: string, expected_resolved_path: string): Promise<WorkspaceRepository>;
|
|
16
|
+
reviewRepository(path: string): Promise<WorkspaceRepositoryReview>;
|
|
17
|
+
baselineRepository(body: {
|
|
18
|
+
path: string;
|
|
19
|
+
expected_resolved_path: string;
|
|
20
|
+
review_digest: string;
|
|
21
|
+
selected_paths: string[];
|
|
22
|
+
confirm_baseline: boolean;
|
|
23
|
+
confirm_omissions: boolean;
|
|
24
|
+
}): Promise<WorkspaceRepository>;
|
|
25
|
+
/**
|
|
26
|
+
* Lists all workspaces registered with the daemon for the active principal.
|
|
27
|
+
*/
|
|
28
|
+
list(options?: {
|
|
29
|
+
limit?: number;
|
|
30
|
+
}): Promise<WorkspaceRecord[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Retrieves the currently active workspace.
|
|
33
|
+
*/
|
|
34
|
+
current(): Promise<WorkspaceRecord | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Resolves a host filesystem path to a registered workspace record.
|
|
37
|
+
*/
|
|
38
|
+
resolve(path: string): Promise<WorkspaceRecord>;
|
|
39
|
+
}
|
|
40
|
+
export interface WorkspaceFolder {
|
|
41
|
+
path: string;
|
|
42
|
+
name: string;
|
|
43
|
+
parent_path: string;
|
|
44
|
+
requires_sudo: boolean;
|
|
45
|
+
permission_error_message?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface WorkspaceResolution {
|
|
48
|
+
requested_path: string;
|
|
49
|
+
resolved_path: string;
|
|
50
|
+
workspace_path: string;
|
|
51
|
+
workspace_name: string;
|
|
52
|
+
workspace_id?: string;
|
|
53
|
+
local_workspace_binding_id?: string;
|
|
54
|
+
workspace_generation?: number;
|
|
55
|
+
workspace_state?: string;
|
|
56
|
+
[key: string]: unknown;
|
|
57
|
+
}
|
|
58
|
+
export interface WorkspaceRepository {
|
|
59
|
+
state: string;
|
|
60
|
+
path: string;
|
|
61
|
+
repository_root?: string;
|
|
62
|
+
head_commit?: string;
|
|
63
|
+
can_setup: boolean;
|
|
64
|
+
needs_review?: boolean;
|
|
65
|
+
message: string;
|
|
66
|
+
content_ready: boolean;
|
|
67
|
+
runtime_accessible: boolean;
|
|
68
|
+
actions?: string[];
|
|
69
|
+
}
|
|
70
|
+
export interface WorkspaceRepositoryReview {
|
|
71
|
+
repository: WorkspaceRepository;
|
|
72
|
+
digest: string;
|
|
73
|
+
warning: string;
|
|
74
|
+
files: {
|
|
75
|
+
path: string;
|
|
76
|
+
size: number;
|
|
77
|
+
mode: number;
|
|
78
|
+
digest: string;
|
|
79
|
+
selectable: boolean;
|
|
80
|
+
}[];
|
|
81
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export class SwarmWorkspacesNamespace {
|
|
2
|
+
transport;
|
|
3
|
+
constructor(transport) {
|
|
4
|
+
this.transport = transport;
|
|
5
|
+
}
|
|
6
|
+
async createFolder(parent_path, name) {
|
|
7
|
+
return (await this.transport.request('/v1/workspace/folders/create', { method: 'POST', body: { parent_path, name } })).data.folder;
|
|
8
|
+
}
|
|
9
|
+
async add(body) {
|
|
10
|
+
return (await this.transport.request('/v1/workspace/add', { method: 'POST', body })).data.workspace;
|
|
11
|
+
}
|
|
12
|
+
async inspectRepository(path) {
|
|
13
|
+
return (await this.transport.request(`/v1/workspace/repository?${new URLSearchParams({ path })}`)).data.repository;
|
|
14
|
+
}
|
|
15
|
+
async setupRepository(path, expected_resolved_path) {
|
|
16
|
+
return (await this.transport.request('/v1/workspace/repository/setup', { method: 'POST', body: { path, expected_resolved_path } })).data.repository;
|
|
17
|
+
}
|
|
18
|
+
async reviewRepository(path) {
|
|
19
|
+
return (await this.transport.request(`/v1/workspace/repository/review?${new URLSearchParams({ path })}`)).data.review;
|
|
20
|
+
}
|
|
21
|
+
async baselineRepository(body) {
|
|
22
|
+
return (await this.transport.request('/v1/workspace/repository/baseline', { method: 'POST', body })).data.repository;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Lists all workspaces registered with the daemon for the active principal.
|
|
26
|
+
*/
|
|
27
|
+
async list(options = {}) {
|
|
28
|
+
const q = new URLSearchParams();
|
|
29
|
+
if (options.limit && options.limit > 0) {
|
|
30
|
+
q.set('limit', options.limit.toString());
|
|
31
|
+
}
|
|
32
|
+
const queryStr = q.toString() ? `?${q.toString()}` : '';
|
|
33
|
+
const res = await this.transport.request(`/v1/workspace/list${queryStr}`, { method: 'GET' });
|
|
34
|
+
const workspaces = res.data?.workspaces ?? [];
|
|
35
|
+
return workspaces.map((w) => ({
|
|
36
|
+
...w,
|
|
37
|
+
name: w.name || w.workspace_name || '',
|
|
38
|
+
workspace_name: w.workspace_name || w.name || '',
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves the currently active workspace.
|
|
43
|
+
*/
|
|
44
|
+
async current() {
|
|
45
|
+
const res = await this.transport.request('/v1/workspace/current', { method: 'GET' });
|
|
46
|
+
return res.data?.workspace ?? null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves a host filesystem path to a registered workspace record.
|
|
50
|
+
*/
|
|
51
|
+
async resolve(path) {
|
|
52
|
+
const res = await this.transport.request('/v1/workspace/resolve', {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
body: { path },
|
|
55
|
+
});
|
|
56
|
+
return res.data.workspace;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { open } from 'node:fs/promises';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { SwarmClient } from '@swarm-agent/sdk';
|
|
6
|
+
|
|
7
|
+
// Uses the installed package (or package self-reference after npm run build).
|
|
8
|
+
// No Desktop bootstrap, privileged socket, automatic approval, or status polling.
|
|
9
|
+
export async function runHeadlessSession(
|
|
10
|
+
client: SwarmClient,
|
|
11
|
+
prompt: string,
|
|
12
|
+
ask: (question: string) => Promise<string>,
|
|
13
|
+
show: (value: string) => void,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
const session = await client.sessions.create({
|
|
16
|
+
title: 'Headless SDK session', workspace_path: '/project', mode: 'auto',
|
|
17
|
+
});
|
|
18
|
+
show(`Session: ${session.id}`);
|
|
19
|
+
const receipt = await client.sessions.sendMessage(session.id, { content: prompt });
|
|
20
|
+
if (!receipt?.run_intent?.run_id) throw new Error('Prompt accepted without a run receipt; inspect the session before retrying');
|
|
21
|
+
show(`Run: ${receipt.run_intent.run_id}; receipt is not completion.`);
|
|
22
|
+
for (;;) {
|
|
23
|
+
const detail = await client.sessions.get(session.id);
|
|
24
|
+
const raw = detail.raw as Record<string, any>;
|
|
25
|
+
show(JSON.stringify({
|
|
26
|
+
state: detail.state, messages: detail.messages,
|
|
27
|
+
active_run_intent: raw.active_run_intent,
|
|
28
|
+
current_run_state: raw.current_run_state,
|
|
29
|
+
pending_permissions: raw.pending_permissions,
|
|
30
|
+
active_plan: raw.active_plan,
|
|
31
|
+
}, null, 2));
|
|
32
|
+
const command = (await ask('refresh | allow <permission-id> | deny <permission-id> | stop | quit: ')).trim();
|
|
33
|
+
if (command === 'quit') return; // Disconnecting does NOT stop a durable run.
|
|
34
|
+
if (command === 'refresh') continue; // Explicit user refresh, never a timer.
|
|
35
|
+
if (command === 'stop') {
|
|
36
|
+
const runId = raw.active_run_intent?.run_id;
|
|
37
|
+
if (!runId) { show('No active run in the current snapshot.'); continue; }
|
|
38
|
+
await client.sessions.stopRun(session.id, { run_id: runId });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const match = /^(allow|deny) (\S+)$/.exec(command);
|
|
42
|
+
const pending = Array.isArray(raw.pending_permissions) ? raw.pending_permissions : [];
|
|
43
|
+
const permission = match && pending.find((p: any) => p.id === match[2]);
|
|
44
|
+
if (!match || !permission) { show('Choose an exact permission ID from the current snapshot, or refresh.'); continue; }
|
|
45
|
+
// A second explicit confirmation prevents accidental approval on pasted input.
|
|
46
|
+
if (match[1] === 'allow') {
|
|
47
|
+
if (await ask(`Approve ONLY ${permission.id} once? Type yes: `) !== 'yes') continue;
|
|
48
|
+
await client.sessions.approvePermissionOnce(session.id, permission.id, 'Explicit SDK operator approval');
|
|
49
|
+
} else {
|
|
50
|
+
await client.sessions.denyPermission(session.id, permission.id, 'SDK operator denied');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main(): Promise<void> {
|
|
56
|
+
const file = process.env.SWARM_SDK_TOKEN_FILE;
|
|
57
|
+
if (!file) throw new Error('Set SWARM_SDK_TOKEN_FILE to the private token JSON export');
|
|
58
|
+
const handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
59
|
+
let token: string;
|
|
60
|
+
try {
|
|
61
|
+
const st = await handle.stat();
|
|
62
|
+
if (!st.isFile() || (st.mode & 0o077) !== 0 || st.size > 16384) throw new Error('Token file must be a private regular file, at most 16384 bytes');
|
|
63
|
+
token = JSON.parse(await handle.readFile('utf8')).token;
|
|
64
|
+
if (typeof token !== 'string' || !token.startsWith('swk_')) throw new Error('Invalid scoped token file');
|
|
65
|
+
} finally { await handle.close(); }
|
|
66
|
+
const url = new URL(process.env.SWARM_SDK_URL ?? 'http://127.0.0.1:7783');
|
|
67
|
+
if (url.protocol !== 'http:' || !['127.0.0.1', '[::1]'].includes(url.hostname) || url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
|
|
68
|
+
throw new Error('This example requires the loopback-published HTTP endpoint');
|
|
69
|
+
}
|
|
70
|
+
const client = new SwarmClient({ baseUrl: url.origin, token, timeoutMs: 15000 });
|
|
71
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
72
|
+
try {
|
|
73
|
+
const prompt = await rl.question('Prompt for /project: ');
|
|
74
|
+
if (!prompt.trim()) throw new Error('Prompt is required');
|
|
75
|
+
await runHeadlessSession(client, prompt, q => rl.question(q), text => console.log(text));
|
|
76
|
+
} finally { rl.close(); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
80
|
+
main().catch(() => {
|
|
81
|
+
// API/transport errors may carry private response bodies. Do not dump them.
|
|
82
|
+
console.error('SDK operation failed. Check listener, token expiry/scopes and session state before retrying; details withheld.');
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
});
|
|
85
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@swarm-agent/sdk",
|
|
3
|
+
"version": "0.1.47",
|
|
4
|
+
"description": "Official TypeScript SDK for Swarm local AI coding workspace",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"examples/headless-session.ts",
|
|
17
|
+
"README.md",
|
|
18
|
+
"APPLICATIONS.md",
|
|
19
|
+
"HEADLESS_UI.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public",
|
|
24
|
+
"registry": "https://registry.npmjs.org/"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/swarm-agent/swarm.git"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "node scripts/build.mjs",
|
|
32
|
+
"prepack": "npm run build",
|
|
33
|
+
"test": "tsx --test --test-concurrency=1 ./src/__tests__/*.spec.ts"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"ws": "8.18.3"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "22.19.15",
|
|
43
|
+
"tsx": "4.21.0",
|
|
44
|
+
"typescript": "5.9.3"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"swarm",
|
|
48
|
+
"sdk",
|
|
49
|
+
"ai",
|
|
50
|
+
"agents",
|
|
51
|
+
"automation",
|
|
52
|
+
"workers"
|
|
53
|
+
],
|
|
54
|
+
"author": "Swarm Team",
|
|
55
|
+
"license": "Apache-2.0"
|
|
56
|
+
}
|