@agentbean/daemon 0.1.34 → 0.2.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.
Files changed (52) hide show
  1. package/dist/apps/daemon-next/src/bin.d.ts +2 -0
  2. package/dist/apps/daemon-next/src/bin.js +6 -0
  3. package/dist/apps/daemon-next/src/cli.d.ts +26 -0
  4. package/dist/apps/daemon-next/src/cli.js +124 -0
  5. package/dist/apps/daemon-next/src/executor.d.ts +6 -0
  6. package/dist/apps/daemon-next/src/executor.js +51 -0
  7. package/dist/apps/daemon-next/src/index.d.ts +60 -0
  8. package/dist/apps/daemon-next/src/index.js +87 -0
  9. package/dist/apps/daemon-next/src/scanner.d.ts +15 -0
  10. package/dist/apps/daemon-next/src/scanner.js +94 -0
  11. package/dist/packages/contracts/src/agent.d.ts +69 -0
  12. package/dist/packages/contracts/src/agent.js +4 -0
  13. package/dist/packages/contracts/src/auth.d.ts +20 -0
  14. package/dist/packages/contracts/src/auth.js +1 -0
  15. package/dist/packages/contracts/src/channel.d.ts +58 -0
  16. package/dist/packages/contracts/src/channel.js +1 -0
  17. package/dist/packages/contracts/src/common.d.ts +17 -0
  18. package/dist/packages/contracts/src/common.js +27 -0
  19. package/dist/packages/contracts/src/device.d.ts +27 -0
  20. package/dist/packages/contracts/src/device.js +1 -0
  21. package/dist/packages/contracts/src/dispatch.d.ts +46 -0
  22. package/dist/packages/contracts/src/dispatch.js +1 -0
  23. package/dist/packages/contracts/src/index.d.ts +9 -0
  24. package/dist/packages/contracts/src/index.js +9 -0
  25. package/dist/packages/contracts/src/message.d.ts +20 -0
  26. package/dist/packages/contracts/src/message.js +1 -0
  27. package/dist/packages/contracts/src/socket.d.ts +74 -0
  28. package/dist/packages/contracts/src/socket.js +74 -0
  29. package/dist/packages/contracts/src/team.d.ts +13 -0
  30. package/dist/packages/contracts/src/team.js +1 -0
  31. package/package.json +14 -25
  32. package/README.md +0 -158
  33. package/dist/adapters/adapter.js +0 -9
  34. package/dist/adapters/claude-code.js +0 -83
  35. package/dist/adapters/codex.js +0 -280
  36. package/dist/adapters/factory.js +0 -38
  37. package/dist/adapters/hermes.js +0 -178
  38. package/dist/adapters/openclaw.js +0 -129
  39. package/dist/agent-instance.js +0 -181
  40. package/dist/auth-store.js +0 -24
  41. package/dist/bin.js +0 -6
  42. package/dist/config.js +0 -148
  43. package/dist/connection.js +0 -211
  44. package/dist/device-daemon.js +0 -529
  45. package/dist/index.js +0 -329
  46. package/dist/log.js +0 -7
  47. package/dist/post-process.js +0 -177
  48. package/dist/sandbox.js +0 -53
  49. package/dist/scanner.js +0 -421
  50. package/dist/uploader.js +0 -46
  51. package/dist/workspace-manager.js +0 -196
  52. package/dist/workspace-sync.js +0 -69
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { runDaemonNextCli } from './cli.js';
3
+ runDaemonNextCli().catch((error) => {
4
+ console.error(error instanceof Error ? error.message : error);
5
+ process.exitCode = 1;
6
+ });
@@ -0,0 +1,26 @@
1
+ import { type DaemonProtocolSocket } from './index.js';
2
+ interface SocketIoClientLike {
3
+ connected: boolean;
4
+ connect(): void;
5
+ disconnect(): void;
6
+ emitWithAck(event: string, payload: unknown): Promise<unknown>;
7
+ on(event: string, handler: (...args: unknown[]) => void): void;
8
+ }
9
+ export interface DaemonNextCliConfig {
10
+ serverUrl: string;
11
+ teamId: string;
12
+ ownerId: string;
13
+ machineId?: string;
14
+ profileId: string;
15
+ hostname: string;
16
+ fallbackPrefix: string;
17
+ }
18
+ export interface ParseDaemonNextCliConfigInput {
19
+ argv?: string[];
20
+ env?: NodeJS.ProcessEnv;
21
+ hostname?: string;
22
+ }
23
+ export declare function parseDaemonNextCliConfig(input?: ParseDaemonNextCliConfigInput): DaemonNextCliConfig;
24
+ export declare function createSocketIoDaemonSocket(socket: SocketIoClientLike): DaemonProtocolSocket;
25
+ export declare function runDaemonNextCli(config?: DaemonNextCliConfig): Promise<void>;
26
+ export {};
@@ -0,0 +1,124 @@
1
+ import { hostname as readHostname } from 'node:os';
2
+ import { createRequire } from 'node:module';
3
+ import { join } from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { createBuiltinScanProvider } from './scanner.js';
6
+ import { createCommandExecutor } from './executor.js';
7
+ import { createDaemonProtocolClient } from './index.js';
8
+ export function parseDaemonNextCliConfig(input = {}) {
9
+ const argv = input.argv ?? process.argv.slice(2);
10
+ const env = input.env ?? process.env;
11
+ const args = parseArgs(argv);
12
+ const teamId = args['team-id'] ?? env.AGENTBEAN_NEXT_TEAM_ID;
13
+ const ownerId = args['owner-id'] ?? env.AGENTBEAN_NEXT_OWNER_ID;
14
+ if (!teamId) {
15
+ throw new Error('AGENTBEAN_NEXT_TEAM_ID or --team-id is required');
16
+ }
17
+ if (!ownerId) {
18
+ throw new Error('AGENTBEAN_NEXT_OWNER_ID or --owner-id is required');
19
+ }
20
+ return {
21
+ serverUrl: trimTrailingSlash(args['server-url'] ?? env.AGENTBEAN_NEXT_SERVER_URL ?? 'http://127.0.0.1:4000'),
22
+ teamId,
23
+ ownerId,
24
+ machineId: args['machine-id'] ?? env.AGENTBEAN_NEXT_MACHINE_ID,
25
+ profileId: args['profile-id'] ?? env.AGENTBEAN_NEXT_PROFILE_ID ?? 'default',
26
+ hostname: args.hostname ?? env.AGENTBEAN_NEXT_HOSTNAME ?? input.hostname ?? readHostname(),
27
+ fallbackPrefix: args['fallback-prefix'] ?? env.AGENTBEAN_NEXT_FALLBACK_PREFIX ?? 'daemon-next:',
28
+ };
29
+ }
30
+ export function createSocketIoDaemonSocket(socket) {
31
+ return {
32
+ emitWithAck(event, payload) {
33
+ return socket.emitWithAck(event, payload);
34
+ },
35
+ on(event, handler) {
36
+ socket.on(event, (payload) => {
37
+ void handler(payload);
38
+ });
39
+ },
40
+ onReconnect(handler) {
41
+ let hasConnected = socket.connected;
42
+ socket.on('connect', () => {
43
+ if (!hasConnected) {
44
+ hasConnected = true;
45
+ return;
46
+ }
47
+ void handler();
48
+ });
49
+ },
50
+ };
51
+ }
52
+ export async function runDaemonNextCli(config = parseDaemonNextCliConfig()) {
53
+ const socket = await connectSocketIoClient(config.serverUrl);
54
+ const snapshot = await createBuiltinScanProvider()();
55
+ const device = {
56
+ teamId: config.teamId,
57
+ ownerId: config.ownerId,
58
+ machineId: config.machineId,
59
+ profileId: config.profileId,
60
+ hostname: config.hostname,
61
+ };
62
+ await createDaemonProtocolClient({
63
+ socket: createSocketIoDaemonSocket(socket),
64
+ executor: createCommandExecutor({ fallbackPrefix: config.fallbackPrefix }),
65
+ device,
66
+ runtimes: snapshot.runtimes,
67
+ agents: snapshot.agents,
68
+ scan: createBuiltinScanProvider(),
69
+ }).start();
70
+ }
71
+ async function connectSocketIoClient(serverUrl) {
72
+ const { io } = loadSocketIoClient();
73
+ const socket = io(`${trimTrailingSlash(serverUrl)}/agent`, {
74
+ autoConnect: false,
75
+ reconnection: true,
76
+ reconnectionDelay: 1000,
77
+ transports: ['websocket', 'polling'],
78
+ });
79
+ await new Promise((resolve, reject) => {
80
+ socket.on('connect', () => resolve());
81
+ socket.on('connect_error', (error) => reject(error instanceof Error ? error : new Error(String(error))));
82
+ socket.connect();
83
+ });
84
+ return socket;
85
+ }
86
+ function loadSocketIoClient() {
87
+ const requireUrls = [
88
+ new URL('../../../../package.json', import.meta.url),
89
+ new URL('../../../../../server/package.json', import.meta.url),
90
+ new URL('../../server/package.json', import.meta.url),
91
+ new URL('../package.json', import.meta.url),
92
+ pathToFileURL(join(process.cwd(), 'apps/server/package.json')),
93
+ pathToFileURL(join(process.cwd(), 'apps/daemon-next/package.json')),
94
+ ];
95
+ for (const requireUrl of requireUrls) {
96
+ try {
97
+ return createRequire(requireUrl)('socket.io-client');
98
+ }
99
+ catch {
100
+ // Try the next known repository layout.
101
+ }
102
+ }
103
+ throw new Error('socket.io-client is not installed; run npm ci in apps/server or provide a workspace install');
104
+ }
105
+ function parseArgs(argv) {
106
+ const parsed = {};
107
+ for (let index = 0; index < argv.length; index += 1) {
108
+ const arg = argv[index];
109
+ if (!arg?.startsWith('--')) {
110
+ continue;
111
+ }
112
+ const key = arg.slice(2);
113
+ const value = argv[index + 1];
114
+ if (!value || value.startsWith('--')) {
115
+ throw new Error(`Missing value for --${key}`);
116
+ }
117
+ parsed[key] = value;
118
+ index += 1;
119
+ }
120
+ return parsed;
121
+ }
122
+ function trimTrailingSlash(value) {
123
+ return value.replace(/\/+$/, '');
124
+ }
@@ -0,0 +1,6 @@
1
+ import type { StubExecutor } from './index.js';
2
+ export interface CommandExecutorOptions {
3
+ fallbackPrefix?: string;
4
+ timeoutMs?: number;
5
+ }
6
+ export declare function createCommandExecutor(options?: CommandExecutorOptions): StubExecutor;
@@ -0,0 +1,51 @@
1
+ import { spawn } from 'node:child_process';
2
+ export function createCommandExecutor(options = {}) {
3
+ const fallbackPrefix = options.fallbackPrefix ?? 'daemon-next:';
4
+ const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;
5
+ return async (request) => {
6
+ if (!request.customAgent?.command) {
7
+ return `${fallbackPrefix}${request.prompt}`;
8
+ }
9
+ return runCustomAgentCommand(request, timeoutMs);
10
+ };
11
+ }
12
+ async function runCustomAgentCommand(request, timeoutMs) {
13
+ const customAgent = request.customAgent;
14
+ if (!customAgent?.command) {
15
+ throw new Error('custom agent command is required');
16
+ }
17
+ return new Promise((resolve, reject) => {
18
+ const child = spawn(customAgent.command, customAgent.args ?? [], {
19
+ cwd: customAgent.cwd,
20
+ env: { ...process.env, ...(customAgent.env ?? {}) },
21
+ stdio: ['pipe', 'pipe', 'pipe'],
22
+ });
23
+ let stdout = '';
24
+ let stderr = '';
25
+ const timer = setTimeout(() => {
26
+ child.kill('SIGTERM');
27
+ reject(new Error(`custom agent command timed out after ${timeoutMs}ms`));
28
+ }, timeoutMs);
29
+ child.stdout.setEncoding('utf8');
30
+ child.stdout.on('data', (chunk) => {
31
+ stdout += chunk;
32
+ });
33
+ child.stderr.setEncoding('utf8');
34
+ child.stderr.on('data', (chunk) => {
35
+ stderr += chunk;
36
+ });
37
+ child.on('error', (error) => {
38
+ clearTimeout(timer);
39
+ reject(error);
40
+ });
41
+ child.on('close', (code) => {
42
+ clearTimeout(timer);
43
+ if (code === 0) {
44
+ resolve(stdout.trimEnd());
45
+ return;
46
+ }
47
+ reject(new Error(stderr.trim() || `custom agent command exited with code ${code ?? 'unknown'}`));
48
+ });
49
+ child.stdin.end(request.prompt);
50
+ });
51
+ }
@@ -0,0 +1,60 @@
1
+ import { type AgentCategory, type DispatchCustomAgentDto } from '../../../packages/contracts/src/index.js';
2
+ export { createBuiltinScanProvider, scanBuiltinRuntimeAgents } from './scanner.js';
3
+ export type { BuiltinScannerOptions } from './scanner.js';
4
+ export { createCommandExecutor } from './executor.js';
5
+ export type { CommandExecutorOptions } from './executor.js';
6
+ export interface DaemonProtocolSocket {
7
+ emitWithAck(event: string, payload: unknown): Promise<unknown>;
8
+ on(event: string, handler: (payload: unknown) => Promise<void>): void;
9
+ onReconnect?(handler: () => Promise<void>): void;
10
+ }
11
+ export type StubExecutor = (request: DispatchRequestPayload) => Promise<string>;
12
+ export interface DaemonDeviceConfig {
13
+ teamId: string;
14
+ ownerId: string;
15
+ machineId?: string;
16
+ profileId?: string;
17
+ hostname?: string;
18
+ }
19
+ export interface DaemonRuntimeReport {
20
+ adapterKind: string;
21
+ name: string;
22
+ command?: string;
23
+ cwd?: string;
24
+ version?: string;
25
+ installed?: boolean;
26
+ }
27
+ export interface DaemonAgentReport {
28
+ name: string;
29
+ adapterKind: string;
30
+ category: AgentCategory;
31
+ gatewayInstanceKey?: string;
32
+ }
33
+ export interface DaemonScanSnapshot {
34
+ runtimes: DaemonRuntimeReport[];
35
+ agents: DaemonAgentReport[];
36
+ }
37
+ export type DaemonScanProvider = () => Promise<DaemonScanSnapshot>;
38
+ export interface DispatchRequestPayload {
39
+ id: string;
40
+ teamId: string;
41
+ channelId: string;
42
+ messageId: string;
43
+ agentId: string;
44
+ deviceId?: string;
45
+ requestId: string;
46
+ prompt: string;
47
+ customAgent?: DispatchCustomAgentDto | null;
48
+ }
49
+ export interface CreateDaemonProtocolClientInput {
50
+ socket: DaemonProtocolSocket;
51
+ executor: StubExecutor;
52
+ device: DaemonDeviceConfig;
53
+ runtimes: DaemonRuntimeReport[];
54
+ agents: DaemonAgentReport[];
55
+ scan?: DaemonScanProvider;
56
+ }
57
+ export interface DaemonProtocolClient {
58
+ start(): Promise<void>;
59
+ }
60
+ export declare function createDaemonProtocolClient(input: CreateDaemonProtocolClientInput): DaemonProtocolClient;
@@ -0,0 +1,87 @@
1
+ import { AGENT_EVENTS } from '../../../packages/contracts/src/index.js';
2
+ export { createBuiltinScanProvider, scanBuiltinRuntimeAgents } from './scanner.js';
3
+ export { createCommandExecutor } from './executor.js';
4
+ export function createDaemonProtocolClient(input) {
5
+ const { socket, executor, device, runtimes, agents, scan } = input;
6
+ return {
7
+ async start() {
8
+ let currentDeviceId = await announceDeviceSnapshot(socket, device, runtimes, agents);
9
+ socket.onReconnect?.(async () => {
10
+ currentDeviceId = await announceDeviceSnapshot(socket, device, runtimes, agents);
11
+ });
12
+ socket.on(AGENT_EVENTS.device.scanRequested, async (payload) => {
13
+ const request = readScanRequest(payload);
14
+ if (request.deviceId !== currentDeviceId) {
15
+ return;
16
+ }
17
+ const snapshot = scan ? await scan() : { runtimes, agents };
18
+ await reportDeviceSnapshot(socket, device.teamId, currentDeviceId, snapshot.runtimes, snapshot.agents);
19
+ });
20
+ socket.on(AGENT_EVENTS.dispatch.request, async (payload) => {
21
+ const request = payload;
22
+ try {
23
+ const body = await executor(request);
24
+ await socket.emitWithAck(AGENT_EVENTS.dispatch.result, {
25
+ dispatchId: request.id,
26
+ agentId: request.agentId,
27
+ body,
28
+ });
29
+ }
30
+ catch (error) {
31
+ await socket.emitWithAck(AGENT_EVENTS.dispatch.error, {
32
+ dispatchId: request.id,
33
+ agentId: request.agentId,
34
+ error: readErrorMessage(error),
35
+ });
36
+ }
37
+ });
38
+ },
39
+ };
40
+ }
41
+ async function announceDeviceSnapshot(socket, device, runtimes, agents) {
42
+ const helloAck = await socket.emitWithAck(AGENT_EVENTS.device.hello, device);
43
+ const deviceId = readAckDeviceId(helloAck);
44
+ await reportDeviceSnapshot(socket, device.teamId, deviceId, runtimes, agents);
45
+ return deviceId;
46
+ }
47
+ async function reportDeviceSnapshot(socket, teamId, deviceId, runtimes, agents) {
48
+ await socket.emitWithAck(AGENT_EVENTS.device.runtimes, {
49
+ teamId,
50
+ deviceId,
51
+ runtimes,
52
+ });
53
+ await socket.emitWithAck(AGENT_EVENTS.agent.registerBatch, {
54
+ teamId,
55
+ deviceId,
56
+ agents,
57
+ });
58
+ }
59
+ function readScanRequest(payload) {
60
+ if (!payload || typeof payload !== 'object') {
61
+ throw new Error('device:scan-requested payload missing request');
62
+ }
63
+ const request = payload;
64
+ if (typeof request.requestId !== 'string' || typeof request.deviceId !== 'string') {
65
+ throw new Error('device:scan-requested payload missing request id or device id');
66
+ }
67
+ return { requestId: request.requestId, deviceId: request.deviceId };
68
+ }
69
+ function readAckDeviceId(ack) {
70
+ if (!ack || typeof ack !== 'object') {
71
+ throw new Error('device:hello ack missing device');
72
+ }
73
+ const device = ack.device;
74
+ if (!device || typeof device.id !== 'string') {
75
+ throw new Error('device:hello ack missing device id');
76
+ }
77
+ return device.id;
78
+ }
79
+ function readErrorMessage(error) {
80
+ if (error instanceof Error && error.message) {
81
+ return error.message;
82
+ }
83
+ if (typeof error === 'string' && error) {
84
+ return error;
85
+ }
86
+ return 'Dispatch executor failed';
87
+ }
@@ -0,0 +1,15 @@
1
+ import type { DaemonScanProvider, DaemonScanSnapshot } from './index.js';
2
+ interface RuntimeSpec {
3
+ bin: string;
4
+ name: string;
5
+ adapterKind: string;
6
+ candidates?: string[];
7
+ }
8
+ export interface BuiltinScannerOptions {
9
+ envPath?: string;
10
+ homeDir?: string;
11
+ findExecutable?: (bin: string, candidates: string[]) => Promise<string | null>;
12
+ }
13
+ export declare function createBuiltinScanProvider(options?: BuiltinScannerOptions): DaemonScanProvider;
14
+ export declare function scanBuiltinRuntimeAgents(options?: BuiltinScannerOptions, specs?: RuntimeSpec[]): Promise<DaemonScanSnapshot>;
15
+ export {};
@@ -0,0 +1,94 @@
1
+ import { accessSync, constants, existsSync, statSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ export function createBuiltinScanProvider(options = {}) {
5
+ return () => scanBuiltinRuntimeAgents(options);
6
+ }
7
+ export async function scanBuiltinRuntimeAgents(options = {}, specs = defaultRuntimeSpecs(options.homeDir ?? homedir())) {
8
+ const findExecutable = options.findExecutable ?? ((bin, candidates) => findExecutableOnPath(bin, candidates, options));
9
+ const runtimes = [];
10
+ for (const spec of specs) {
11
+ const command = await findExecutable(spec.bin, spec.candidates ?? []);
12
+ const installed = command !== null;
13
+ runtimes.push({
14
+ adapterKind: spec.adapterKind,
15
+ name: spec.name,
16
+ command: command ?? undefined,
17
+ cwd: command ? dirname(command) : undefined,
18
+ installed,
19
+ });
20
+ }
21
+ return { runtimes, agents: [] };
22
+ }
23
+ function defaultRuntimeSpecs(home) {
24
+ return [
25
+ {
26
+ bin: 'claude',
27
+ name: 'Claude Code',
28
+ adapterKind: 'claude-code',
29
+ candidates: claudeCandidates(home),
30
+ },
31
+ {
32
+ bin: 'codex',
33
+ name: 'Codex CLI',
34
+ adapterKind: 'codex',
35
+ },
36
+ {
37
+ bin: 'gemini',
38
+ name: 'Gemini CLI',
39
+ adapterKind: 'gemini',
40
+ },
41
+ ];
42
+ }
43
+ async function findExecutableOnPath(bin, candidates, options) {
44
+ for (const candidate of candidates) {
45
+ if (isExecutableFile(candidate)) {
46
+ return candidate;
47
+ }
48
+ }
49
+ for (const directory of pathEntries(options)) {
50
+ const candidate = join(directory, bin);
51
+ if (isExecutableFile(candidate)) {
52
+ return candidate;
53
+ }
54
+ }
55
+ return null;
56
+ }
57
+ function pathEntries(options) {
58
+ const home = options.homeDir ?? homedir();
59
+ return [
60
+ ...(options.envPath ?? process.env.PATH ?? '').split(':').filter(Boolean),
61
+ '/usr/local/bin',
62
+ '/opt/homebrew/bin',
63
+ join(home, '.local/bin'),
64
+ join(home, '.bun/bin'),
65
+ join(home, '.npm-global/bin'),
66
+ join(home, '.asdf/shims'),
67
+ join(home, '.local/share/mise/shims'),
68
+ ];
69
+ }
70
+ function claudeCandidates(home) {
71
+ return [
72
+ join(home, '.local/share/claude-latest/current/claude'),
73
+ join(home, '.local/share/claude/current/claude'),
74
+ '/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js',
75
+ '/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js',
76
+ ];
77
+ }
78
+ function isExecutableFile(path) {
79
+ try {
80
+ return existsSync(path) && statSync(path).isFile() && isExecutable(path);
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ function isExecutable(path) {
87
+ try {
88
+ accessSync(path, constants.X_OK);
89
+ return true;
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
@@ -0,0 +1,69 @@
1
+ import type { ID, UnixMs } from './common.js';
2
+ export declare const ADAPTER_KINDS: readonly ["codex", "claude-code", "gemini", "kimi-cli", "hermes", "openclaw"];
3
+ export type AdapterKind = (typeof ADAPTER_KINDS)[number];
4
+ export declare const AGENT_CATEGORIES: readonly ["executor-hosted", "agentos-hosted"];
5
+ export type AgentCategory = (typeof AGENT_CATEGORIES)[number];
6
+ export declare const AGENT_SOURCES: readonly ["custom", "self-register", "scanned"];
7
+ export type AgentSource = (typeof AGENT_SOURCES)[number];
8
+ export declare const AGENT_STATUSES: readonly ["connecting", "online", "busy", "offline", "error"];
9
+ export type AgentStatus = (typeof AGENT_STATUSES)[number];
10
+ export interface RuntimeDto {
11
+ id: ID;
12
+ deviceId: ID;
13
+ adapterKind: AdapterKind;
14
+ name: string;
15
+ installed: boolean;
16
+ command?: string;
17
+ cwd?: string;
18
+ normalizedCommandKey?: string;
19
+ normalizedCwdKey?: string;
20
+ version?: string;
21
+ lastSeenAt?: UnixMs;
22
+ }
23
+ export interface AgentDto {
24
+ id: ID;
25
+ primaryTeamId: ID;
26
+ visibleTeamIds: ID[];
27
+ name: string;
28
+ adapterKind: AdapterKind;
29
+ category: AgentCategory;
30
+ source: AgentSource;
31
+ status: AgentStatus;
32
+ ownerId?: ID;
33
+ deviceId?: ID;
34
+ command?: string;
35
+ args?: string[];
36
+ cwd?: string;
37
+ envKeys?: string[];
38
+ description?: string;
39
+ lastSeenAt?: UnixMs;
40
+ lastError?: string;
41
+ }
42
+ export interface DiscoveredAgentDto {
43
+ deviceId: ID;
44
+ teamId: ID;
45
+ adapterKind: AdapterKind;
46
+ name: string;
47
+ category: AgentCategory;
48
+ source: 'scanned' | 'self-register';
49
+ command?: string;
50
+ args?: string[];
51
+ cwd?: string;
52
+ gatewayId?: string;
53
+ gatewayName?: string;
54
+ gatewayInstanceKey?: string;
55
+ metadata?: Record<string, unknown>;
56
+ }
57
+ export interface CreateAgentCommandDto {
58
+ userId: ID;
59
+ teamId: ID;
60
+ deviceId: ID;
61
+ runtimeId?: ID;
62
+ name: string;
63
+ description?: string;
64
+ adapterKind?: AdapterKind;
65
+ command?: string;
66
+ args?: string[];
67
+ cwd?: string;
68
+ env?: Record<string, string>;
69
+ }
@@ -0,0 +1,4 @@
1
+ export const ADAPTER_KINDS = ['codex', 'claude-code', 'gemini', 'kimi-cli', 'hermes', 'openclaw'];
2
+ export const AGENT_CATEGORIES = ['executor-hosted', 'agentos-hosted'];
3
+ export const AGENT_SOURCES = ['custom', 'self-register', 'scanned'];
4
+ export const AGENT_STATUSES = ['connecting', 'online', 'busy', 'offline', 'error'];
@@ -0,0 +1,20 @@
1
+ import type { ID } from './common.js';
2
+ export type UserRole = 'user' | 'admin';
3
+ export type TeamMemberRole = 'owner' | 'admin' | 'member';
4
+ export interface UserDto {
5
+ id: ID;
6
+ username: string;
7
+ role: UserRole;
8
+ displayName?: string;
9
+ avatarUrl?: string;
10
+ primaryTeamId?: ID;
11
+ }
12
+ export interface HumanMemberDto {
13
+ id: ID;
14
+ teamId: ID;
15
+ userId: ID;
16
+ username: string;
17
+ role: TeamMemberRole;
18
+ displayName?: string;
19
+ avatarUrl?: string;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,58 @@
1
+ import type { ID, UnixMs } from './common.js';
2
+ import type { AgentDto } from './agent.js';
3
+ import type { HumanMemberDto } from './auth.js';
4
+ export type ChannelKind = 'channel' | 'direct';
5
+ export type ChannelVisibility = 'public' | 'private';
6
+ export interface ChannelDto {
7
+ id: ID;
8
+ teamId: ID;
9
+ kind: ChannelKind;
10
+ name: string;
11
+ visibility: ChannelVisibility;
12
+ title?: string;
13
+ createdBy?: ID;
14
+ createdAt: UnixMs;
15
+ updatedAt?: UnixMs;
16
+ }
17
+ export interface CreateChannelCommandDto {
18
+ userId: ID;
19
+ teamId: ID;
20
+ name: string;
21
+ title?: string;
22
+ visibility: ChannelVisibility;
23
+ humanMemberIds?: ID[];
24
+ agentMemberIds?: ID[];
25
+ }
26
+ export interface UpdateChannelCommandDto {
27
+ userId: ID;
28
+ teamId: ID;
29
+ channelId: ID;
30
+ name?: string;
31
+ title?: string;
32
+ visibility?: ChannelVisibility;
33
+ humanMemberIds?: ID[];
34
+ agentMemberIds?: ID[];
35
+ }
36
+ export interface ChannelHumanMemberCommandDto {
37
+ userId: ID;
38
+ teamId: ID;
39
+ channelId: ID;
40
+ memberUserId: ID;
41
+ }
42
+ export interface ChannelAgentMemberCommandDto {
43
+ userId: ID;
44
+ teamId: ID;
45
+ channelId: ID;
46
+ agentId: ID;
47
+ }
48
+ export interface ListChannelMembersCommandDto {
49
+ userId: ID;
50
+ teamId: ID;
51
+ channelId: ID;
52
+ }
53
+ export interface ChannelMembersDto {
54
+ humanMemberIds: ID[];
55
+ agentMemberIds: ID[];
56
+ humans: HumanMemberDto[];
57
+ agents: AgentDto[];
58
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ export type ID = string;
2
+ export type UnixMs = number;
3
+ export declare const ERROR_CODES: readonly ["BAD_REQUEST", "UNAUTHENTICATED", "FORBIDDEN", "NOT_FOUND", "CONFLICT", "VALIDATION_ERROR", "DEVICE_OFFLINE", "AGENT_OFFLINE", "DISPATCH_TIMEOUT", "INTERNAL_ERROR"];
4
+ export type ErrorCode = (typeof ERROR_CODES)[number];
5
+ export type SuccessAck<T extends object = Record<string, never>> = {
6
+ ok: true;
7
+ } & T;
8
+ export interface FailureAck {
9
+ ok: false;
10
+ error: ErrorCode;
11
+ message?: string;
12
+ details?: Record<string, unknown>;
13
+ }
14
+ export type Ack<T extends object = Record<string, never>> = SuccessAck<T> | FailureAck;
15
+ export declare function isErrorCode(value: string): value is ErrorCode;
16
+ export declare function makeSuccess<T extends object = Record<string, never>>(payload?: T): SuccessAck<T>;
17
+ export declare function makeFailure(error: ErrorCode, message?: string, details?: Record<string, unknown>): FailureAck;