@agentmeshhq/agent 0.1.17 → 0.2.1
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 +39 -0
- package/dist/__tests__/orphan-process.test.d.ts +11 -0
- package/dist/__tests__/orphan-process.test.js +286 -0
- package/dist/__tests__/orphan-process.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +16 -0
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/watchdog.test.js +138 -12
- package/dist/__tests__/watchdog.test.js.map +1 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/start.d.ts +2 -1
- package/dist/cli/start.js +6 -3
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/status.js +11 -0
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/stop.js +7 -2
- package/dist/cli/stop.js.map +1 -1
- package/dist/config/schema.d.ts +4 -2
- package/dist/core/daemon/assignment-message.d.ts +12 -0
- package/dist/core/daemon/assignment-message.js +36 -0
- package/dist/core/daemon/assignment-message.js.map +1 -0
- package/dist/core/daemon/bootstrap.d.ts +35 -0
- package/dist/core/daemon/bootstrap.js +52 -0
- package/dist/core/daemon/bootstrap.js.map +1 -0
- package/dist/core/daemon/crash-log.d.ts +16 -0
- package/dist/core/daemon/crash-log.js +24 -0
- package/dist/core/daemon/crash-log.js.map +1 -0
- package/dist/core/daemon/health-policy.d.ts +21 -0
- package/dist/core/daemon/health-policy.js +32 -0
- package/dist/core/daemon/health-policy.js.map +1 -0
- package/dist/core/daemon/sandbox-config.d.ts +9 -0
- package/dist/core/daemon/sandbox-config.js +17 -0
- package/dist/core/daemon/sandbox-config.js.map +1 -0
- package/dist/core/daemon/state.d.ts +33 -0
- package/dist/core/daemon/state.js +77 -0
- package/dist/core/daemon/state.js.map +1 -0
- package/dist/core/daemon/tmux-session.d.ts +17 -0
- package/dist/core/daemon/tmux-session.js +34 -0
- package/dist/core/daemon/tmux-session.js.map +1 -0
- package/dist/core/daemon/workspace.d.ts +10 -0
- package/dist/core/daemon/workspace.js +51 -0
- package/dist/core/daemon/workspace.js.map +1 -0
- package/dist/core/daemon.d.ts +4 -7
- package/dist/core/daemon.js +143 -259
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.js +6 -0
- package/dist/core/injector.js.map +1 -1
- package/dist/core/registry.js +1 -1
- package/dist/core/registry.js.map +1 -1
- package/dist/core/runner/build.d.ts +9 -0
- package/dist/core/runner/build.js +53 -0
- package/dist/core/runner/build.js.map +1 -0
- package/dist/core/runner/detect.d.ts +5 -0
- package/dist/core/runner/detect.js +14 -0
- package/dist/core/runner/detect.js.map +1 -0
- package/dist/core/runner/index.d.ts +5 -0
- package/dist/core/runner/index.js +5 -0
- package/dist/core/runner/index.js.map +1 -0
- package/dist/core/runner/model.d.ts +5 -0
- package/dist/core/runner/model.js +7 -0
- package/dist/core/runner/model.js.map +1 -0
- package/dist/core/runner/opencode-models.d.ts +15 -0
- package/dist/core/runner/opencode-models.js +70 -0
- package/dist/core/runner/opencode-models.js.map +1 -0
- package/dist/core/runner/types.d.ts +19 -0
- package/dist/core/runner/types.js +8 -0
- package/dist/core/runner/types.js.map +1 -0
- package/dist/core/runner.d.ts +5 -47
- package/dist/core/runner.js +5 -167
- package/dist/core/runner.js.map +1 -1
- package/dist/core/tmux-runtime.d.ts +13 -0
- package/dist/core/tmux-runtime.js +72 -0
- package/dist/core/tmux-runtime.js.map +1 -0
- package/dist/core/tmux.d.ts +7 -1
- package/dist/core/tmux.js +75 -45
- package/dist/core/tmux.js.map +1 -1
- package/dist/core/watchdog.d.ts +18 -1
- package/dist/core/watchdog.js +78 -29
- package/dist/core/watchdog.js.map +1 -1
- package/package.json +30 -11
- package/dist/cli/inbox.d.ts +0 -5
- package/dist/cli/inbox.js +0 -123
- package/dist/cli/inbox.js.map +0 -1
- package/dist/cli/issue.d.ts +0 -42
- package/dist/cli/issue.js +0 -297
- package/dist/cli/issue.js.map +0 -1
- package/dist/cli/ready.d.ts +0 -5
- package/dist/cli/ready.js +0 -131
- package/dist/cli/ready.js.map +0 -1
- package/dist/cli/sync.d.ts +0 -8
- package/dist/cli/sync.js +0 -154
- package/dist/cli/sync.js.map +0 -1
- package/dist/core/issue-cache.d.ts +0 -44
- package/dist/core/issue-cache.js +0 -75
- package/dist/core/issue-cache.js.map +0 -1
- package/src/__tests__/context.test.ts +0 -464
- package/src/__tests__/injector.test.ts +0 -29
- package/src/__tests__/jwt.test.ts +0 -112
- package/src/__tests__/loader.test.ts +0 -239
- package/src/__tests__/runner.test.ts +0 -104
- package/src/__tests__/sandbox.test.ts +0 -435
- package/src/__tests__/watchdog.test.ts +0 -368
- package/src/cli/attach.ts +0 -22
- package/src/cli/build.ts +0 -145
- package/src/cli/config.ts +0 -148
- package/src/cli/context.ts +0 -231
- package/src/cli/deploy.ts +0 -155
- package/src/cli/index.ts +0 -375
- package/src/cli/init.ts +0 -75
- package/src/cli/list.ts +0 -70
- package/src/cli/local.ts +0 -183
- package/src/cli/logs.ts +0 -64
- package/src/cli/migrate.ts +0 -212
- package/src/cli/nudge.ts +0 -81
- package/src/cli/restart.ts +0 -59
- package/src/cli/slack.ts +0 -70
- package/src/cli/start.ts +0 -115
- package/src/cli/status.ts +0 -91
- package/src/cli/stop.ts +0 -48
- package/src/cli/test.ts +0 -143
- package/src/cli/token.ts +0 -188
- package/src/cli/whoami.ts +0 -142
- package/src/config/loader.ts +0 -121
- package/src/config/schema.ts +0 -68
- package/src/context/handoff.ts +0 -122
- package/src/context/index.ts +0 -8
- package/src/context/schema.ts +0 -111
- package/src/context/storage.ts +0 -197
- package/src/core/daemon.ts +0 -1308
- package/src/core/heartbeat.ts +0 -129
- package/src/core/injector.ts +0 -292
- package/src/core/registry.ts +0 -159
- package/src/core/runner.ts +0 -225
- package/src/core/sandbox.ts +0 -547
- package/src/core/session-id.ts +0 -111
- package/src/core/tmux.ts +0 -405
- package/src/core/watchdog.ts +0 -238
- package/src/core/websocket.ts +0 -94
- package/src/index.ts +0 -10
- package/src/utils/jwt.ts +0 -87
- package/tsconfig.json +0 -8
- package/vitest.config.ts +0 -12
package/src/cli/logs.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import pc from "picocolors";
|
|
3
|
-
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
4
|
-
import { getSessionName, sessionExists } from "../core/tmux.js";
|
|
5
|
-
|
|
6
|
-
export async function logs(
|
|
7
|
-
name: string,
|
|
8
|
-
options: { follow?: boolean; lines?: number },
|
|
9
|
-
): Promise<void> {
|
|
10
|
-
const config = loadConfig();
|
|
11
|
-
|
|
12
|
-
if (!config) {
|
|
13
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const agent = getAgentState(name);
|
|
18
|
-
if (!agent) {
|
|
19
|
-
console.log(pc.red(`Agent "${name}" not found.`));
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const sessionName = getSessionName(name);
|
|
24
|
-
if (!sessionExists(sessionName)) {
|
|
25
|
-
console.log(pc.red(`Session "${sessionName}" not running.`));
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const lines = options.lines || 50;
|
|
30
|
-
|
|
31
|
-
// Capture pane content using tmux capture-pane
|
|
32
|
-
if (options.follow) {
|
|
33
|
-
// Follow mode - attach in view-only mode
|
|
34
|
-
console.log(pc.dim(`Following logs for "${name}"... (Ctrl+C to exit)`));
|
|
35
|
-
console.log(pc.dim("─".repeat(60)));
|
|
36
|
-
|
|
37
|
-
// Use tmux pipe-pane to stream output
|
|
38
|
-
const tmux = spawn("tmux", ["attach-session", "-t", sessionName, "-r"], {
|
|
39
|
-
stdio: "inherit",
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
tmux.on("exit", (code) => {
|
|
43
|
-
process.exit(code ?? 0);
|
|
44
|
-
});
|
|
45
|
-
} else {
|
|
46
|
-
// Static mode - capture and print
|
|
47
|
-
try {
|
|
48
|
-
const { execSync } = await import("node:child_process");
|
|
49
|
-
|
|
50
|
-
// Capture the pane history
|
|
51
|
-
const output = execSync(`tmux capture-pane -t "${sessionName}" -p -S -${lines}`, {
|
|
52
|
-
encoding: "utf-8",
|
|
53
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
console.log(pc.dim(`Last ${lines} lines from "${name}":`));
|
|
57
|
-
console.log(pc.dim("─".repeat(60)));
|
|
58
|
-
console.log(output);
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.log(pc.red(`Failed to capture logs: ${(error as Error).message}`));
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
package/src/cli/migrate.ts
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { execSync, spawnSync } from "node:child_process";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import pc from "picocolors";
|
|
4
|
-
|
|
5
|
-
function findProjectRoot(): string {
|
|
6
|
-
let dir = process.cwd();
|
|
7
|
-
for (let i = 0; i < 10; i++) {
|
|
8
|
-
const packageJson = path.join(dir, "package.json");
|
|
9
|
-
const pnpmWorkspace = path.join(dir, "pnpm-workspace.yaml");
|
|
10
|
-
try {
|
|
11
|
-
execSync(`test -f "${packageJson}" && test -f "${pnpmWorkspace}"`, { stdio: "ignore" });
|
|
12
|
-
return dir;
|
|
13
|
-
} catch {
|
|
14
|
-
dir = path.dirname(dir);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
throw new Error(
|
|
18
|
-
"Could not find AgentMesh project root. Make sure you're in the agentmesh repository.",
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function isLocalStackRunning(): boolean {
|
|
23
|
-
try {
|
|
24
|
-
const result = execSync(
|
|
25
|
-
'docker inspect --format="{{.State.Running}}" agentmesh_postgres 2>/dev/null',
|
|
26
|
-
{ encoding: "utf-8" },
|
|
27
|
-
).trim();
|
|
28
|
-
return result === "true";
|
|
29
|
-
} catch {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getLocalDbUrl(): string {
|
|
35
|
-
// Default local stack connection
|
|
36
|
-
return "postgresql://postgres:postgres@localhost:5432/agentmesh";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface MigrateOptions {
|
|
40
|
-
dev?: boolean;
|
|
41
|
-
staging?: boolean;
|
|
42
|
-
generate?: boolean;
|
|
43
|
-
status?: boolean;
|
|
44
|
-
rollback?: boolean;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function migrate(options: MigrateOptions = {}): Promise<void> {
|
|
48
|
-
const projectRoot = findProjectRoot();
|
|
49
|
-
|
|
50
|
-
if (options.generate) {
|
|
51
|
-
await generateMigration(projectRoot);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (options.status) {
|
|
56
|
-
await migrationStatus(projectRoot, options);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (options.rollback) {
|
|
61
|
-
console.error(pc.red("Rollback is not supported. Use a new migration to revert changes."));
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await runMigrations(projectRoot, options);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function generateMigration(projectRoot: string): Promise<void> {
|
|
69
|
-
console.log(pc.cyan("Generating migration from schema changes..."));
|
|
70
|
-
console.log();
|
|
71
|
-
|
|
72
|
-
const result = spawnSync("pnpm", ["--filter", "@agentmesh/hub", "db:generate"], {
|
|
73
|
-
cwd: projectRoot,
|
|
74
|
-
stdio: "inherit",
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
if (result.status !== 0) {
|
|
78
|
-
console.error(pc.red("Migration generation failed"));
|
|
79
|
-
process.exit(1);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
console.log();
|
|
83
|
-
console.log(pc.green("Migration generated successfully!"));
|
|
84
|
-
console.log(pc.dim("Review the migration in packages/hub/drizzle/"));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function migrationStatus(projectRoot: string, options: MigrateOptions): Promise<void> {
|
|
88
|
-
const env = getEnvironmentConfig(options);
|
|
89
|
-
|
|
90
|
-
console.log(pc.cyan(`Checking migration status for ${env.name}...`));
|
|
91
|
-
console.log();
|
|
92
|
-
|
|
93
|
-
// Check if we can connect
|
|
94
|
-
if (!env.canConnect) {
|
|
95
|
-
console.error(pc.red(`Cannot connect to ${env.name}: ${env.reason}`));
|
|
96
|
-
process.exit(1);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const result = spawnSync("pnpm", ["--filter", "@agentmesh/hub", "db:status"], {
|
|
100
|
-
cwd: projectRoot,
|
|
101
|
-
stdio: "inherit",
|
|
102
|
-
env: {
|
|
103
|
-
...process.env,
|
|
104
|
-
DATABASE_URL: env.databaseUrl,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
if (result.status !== 0) {
|
|
109
|
-
console.error(pc.red("Failed to check migration status"));
|
|
110
|
-
process.exit(1);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface EnvironmentConfig {
|
|
115
|
-
name: string;
|
|
116
|
-
databaseUrl: string;
|
|
117
|
-
canConnect: boolean;
|
|
118
|
-
reason?: string;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getEnvironmentConfig(options: MigrateOptions): EnvironmentConfig {
|
|
122
|
-
if (options.dev) {
|
|
123
|
-
// Dev environment uses cloud database via environment variable
|
|
124
|
-
const devUrl = process.env.AGENTMESH_DEV_DATABASE_URL;
|
|
125
|
-
if (!devUrl) {
|
|
126
|
-
return {
|
|
127
|
-
name: "dev (agentmeshhq.dev)",
|
|
128
|
-
databaseUrl: "",
|
|
129
|
-
canConnect: false,
|
|
130
|
-
reason: "AGENTMESH_DEV_DATABASE_URL environment variable not set",
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
name: "dev (agentmeshhq.dev)",
|
|
135
|
-
databaseUrl: devUrl,
|
|
136
|
-
canConnect: true,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (options.staging) {
|
|
141
|
-
const stagingUrl = process.env.AGENTMESH_STAGING_DATABASE_URL;
|
|
142
|
-
if (!stagingUrl) {
|
|
143
|
-
return {
|
|
144
|
-
name: "staging",
|
|
145
|
-
databaseUrl: "",
|
|
146
|
-
canConnect: false,
|
|
147
|
-
reason: "AGENTMESH_STAGING_DATABASE_URL environment variable not set",
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
name: "staging",
|
|
152
|
-
databaseUrl: stagingUrl,
|
|
153
|
-
canConnect: true,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Default: local stack
|
|
158
|
-
const localRunning = isLocalStackRunning();
|
|
159
|
-
if (!localRunning) {
|
|
160
|
-
return {
|
|
161
|
-
name: "local",
|
|
162
|
-
databaseUrl: getLocalDbUrl(),
|
|
163
|
-
canConnect: false,
|
|
164
|
-
reason: "Local stack is not running. Start it with: agentmesh local up",
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
name: "local",
|
|
170
|
-
databaseUrl: getLocalDbUrl(),
|
|
171
|
-
canConnect: true,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function runMigrations(projectRoot: string, options: MigrateOptions): Promise<void> {
|
|
176
|
-
const env = getEnvironmentConfig(options);
|
|
177
|
-
|
|
178
|
-
console.log(pc.cyan(`Running migrations against ${env.name}...`));
|
|
179
|
-
console.log();
|
|
180
|
-
|
|
181
|
-
if (!env.canConnect) {
|
|
182
|
-
console.error(pc.red(`Cannot connect to ${env.name}: ${env.reason}`));
|
|
183
|
-
process.exit(1);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Safety confirmation for non-local environments
|
|
187
|
-
if (options.dev || options.staging) {
|
|
188
|
-
console.log(pc.yellow(`WARNING: You are about to run migrations against ${env.name}`));
|
|
189
|
-
console.log(pc.yellow("This will modify the database schema."));
|
|
190
|
-
console.log();
|
|
191
|
-
console.log(pc.dim("Press Ctrl+C to cancel, or wait 5 seconds to continue..."));
|
|
192
|
-
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
193
|
-
console.log();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const result = spawnSync("pnpm", ["--filter", "@agentmesh/hub", "db:migrate"], {
|
|
197
|
-
cwd: projectRoot,
|
|
198
|
-
stdio: "inherit",
|
|
199
|
-
env: {
|
|
200
|
-
...process.env,
|
|
201
|
-
DATABASE_URL: env.databaseUrl,
|
|
202
|
-
},
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
if (result.status !== 0) {
|
|
206
|
-
console.error(pc.red("Migration failed"));
|
|
207
|
-
process.exit(1);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
console.log();
|
|
211
|
-
console.log(pc.green(`Migrations applied successfully to ${env.name}!`));
|
|
212
|
-
}
|
package/src/cli/nudge.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
import { getAgentState, loadConfig, loadState } from "../config/loader.js";
|
|
3
|
-
import { registerAgent } from "../core/registry.js";
|
|
4
|
-
import { getSessionName, sendKeys, sessionExists } from "../core/tmux.js";
|
|
5
|
-
|
|
6
|
-
export async function nudge(name: string, message: string): Promise<void> {
|
|
7
|
-
const config = loadConfig();
|
|
8
|
-
|
|
9
|
-
if (!config) {
|
|
10
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
11
|
-
process.exit(1);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (!name) {
|
|
15
|
-
console.log(pc.red("Agent name is required."));
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!message) {
|
|
20
|
-
console.log(pc.red("Message is required."));
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Check if this is a local agent
|
|
25
|
-
const localAgent = getAgentState(name);
|
|
26
|
-
|
|
27
|
-
if (localAgent && sessionExists(getSessionName(name))) {
|
|
28
|
-
// Local nudge via tmux send-keys
|
|
29
|
-
const formatted = `[AgentMesh] Nudge from CLI:
|
|
30
|
-
${message}`;
|
|
31
|
-
|
|
32
|
-
const sent = sendKeys(name, formatted);
|
|
33
|
-
|
|
34
|
-
if (sent) {
|
|
35
|
-
console.log(pc.green(`Nudged "${name}" locally.`));
|
|
36
|
-
} else {
|
|
37
|
-
console.log(pc.red(`Failed to nudge "${name}".`));
|
|
38
|
-
}
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Remote nudge via API
|
|
43
|
-
// First we need to find the agent ID
|
|
44
|
-
const state = loadState();
|
|
45
|
-
const agentState = state.agents.find((a) => a.name === name);
|
|
46
|
-
|
|
47
|
-
if (!agentState?.agentId) {
|
|
48
|
-
console.log(pc.red(`Agent "${name}" not found.`));
|
|
49
|
-
console.log(pc.dim("For remote nudges, provide the agent ID instead."));
|
|
50
|
-
process.exit(1);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Register ourselves to get a token
|
|
54
|
-
try {
|
|
55
|
-
const registration = await registerAgent({
|
|
56
|
-
url: config.hubUrl,
|
|
57
|
-
apiKey: config.apiKey,
|
|
58
|
-
workspace: config.workspace,
|
|
59
|
-
agentName: "cli-nudger",
|
|
60
|
-
model: "cli",
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const response = await fetch(`${config.hubUrl}/api/v1/agents/${agentState.agentId}/nudge`, {
|
|
64
|
-
method: "POST",
|
|
65
|
-
headers: {
|
|
66
|
-
Authorization: `Bearer ${registration.token}`,
|
|
67
|
-
"Content-Type": "application/json",
|
|
68
|
-
},
|
|
69
|
-
body: JSON.stringify({ message }),
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
if (response.ok) {
|
|
73
|
-
console.log(pc.green(`Nudged "${name}" via API.`));
|
|
74
|
-
} else {
|
|
75
|
-
const error = await response.text();
|
|
76
|
-
console.log(pc.red(`Failed to nudge: ${error}`));
|
|
77
|
-
}
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.log(pc.red(`Failed to nudge: ${(error as Error).message}`));
|
|
80
|
-
}
|
|
81
|
-
}
|
package/src/cli/restart.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
3
|
-
import { getSessionName, sessionExists } from "../core/tmux.js";
|
|
4
|
-
import { start } from "./start.js";
|
|
5
|
-
import { stop } from "./stop.js";
|
|
6
|
-
|
|
7
|
-
export async function restart(name: string, options?: { model?: string }): Promise<void> {
|
|
8
|
-
const config = loadConfig();
|
|
9
|
-
|
|
10
|
-
if (!config) {
|
|
11
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const agent = getAgentState(name);
|
|
16
|
-
if (!agent) {
|
|
17
|
-
console.log(pc.red(`Agent "${name}" not found in state.`));
|
|
18
|
-
console.log(pc.dim("Use 'agentmesh start' to create a new agent."));
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
console.log(pc.dim(`Restarting agent "${name}"...`));
|
|
23
|
-
|
|
24
|
-
// Preserve runtime model from previous session unless overridden
|
|
25
|
-
const preservedModel = options?.model || agent.runtimeModel;
|
|
26
|
-
if (preservedModel) {
|
|
27
|
-
console.log(pc.dim(`Preserving runtime model: ${preservedModel}`));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Stop the agent (but preserve the agent ID for re-registration)
|
|
31
|
-
const sessionName = getSessionName(name);
|
|
32
|
-
if (sessionExists(sessionName)) {
|
|
33
|
-
console.log(pc.dim("Stopping current session..."));
|
|
34
|
-
await stop(name);
|
|
35
|
-
|
|
36
|
-
// Small delay to ensure clean shutdown
|
|
37
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Find agent config to get workdir and other settings
|
|
41
|
-
const agentConfig = config.agents.find((a) => a.name === name);
|
|
42
|
-
|
|
43
|
-
console.log(pc.dim("Starting new session..."));
|
|
44
|
-
|
|
45
|
-
// Start with preserved model (prioritize: CLI override > previous runtime > agent config)
|
|
46
|
-
await start({
|
|
47
|
-
name,
|
|
48
|
-
command: agentConfig?.command,
|
|
49
|
-
workdir: agentConfig?.workdir,
|
|
50
|
-
model: preservedModel || agentConfig?.model,
|
|
51
|
-
foreground: false,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
console.log(pc.green(`Agent "${name}" restarted.`));
|
|
55
|
-
console.log(pc.dim(`Agent ID preserved: ${agent.agentId}`));
|
|
56
|
-
if (preservedModel) {
|
|
57
|
-
console.log(pc.dim(`Runtime model: ${preservedModel}`));
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/cli/slack.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
3
|
-
|
|
4
|
-
export async function slack(
|
|
5
|
-
action: string,
|
|
6
|
-
channel: string | undefined,
|
|
7
|
-
message: string | undefined,
|
|
8
|
-
options: { name?: string },
|
|
9
|
-
): Promise<void> {
|
|
10
|
-
const config = loadConfig();
|
|
11
|
-
|
|
12
|
-
if (!config) {
|
|
13
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (action === "respond" || action === "reply") {
|
|
18
|
-
if (!channel) {
|
|
19
|
-
console.log(
|
|
20
|
-
pc.red("Channel is required. Usage: agentmesh slack respond <channel> <message>"),
|
|
21
|
-
);
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!message) {
|
|
26
|
-
console.log(
|
|
27
|
-
pc.red("Message is required. Usage: agentmesh slack respond <channel> <message>"),
|
|
28
|
-
);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Get token from agent state or config
|
|
33
|
-
const agentName = options.name || "concierge";
|
|
34
|
-
const agentState = getAgentState(agentName);
|
|
35
|
-
const token = agentState?.token;
|
|
36
|
-
|
|
37
|
-
if (!token) {
|
|
38
|
-
console.log(pc.red(`No token found for agent "${agentName}". Is the agent running?`));
|
|
39
|
-
process.exit(1);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const response = await fetch(`${config.hubUrl}/api/v1/integrations/slack/respond`, {
|
|
44
|
-
method: "POST",
|
|
45
|
-
headers: {
|
|
46
|
-
Authorization: `Bearer ${token}`,
|
|
47
|
-
"Content-Type": "application/json",
|
|
48
|
-
},
|
|
49
|
-
body: JSON.stringify({ channel, text: message }),
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (response.ok) {
|
|
53
|
-
console.log(pc.green(`Message sent to Slack channel ${channel}`));
|
|
54
|
-
} else {
|
|
55
|
-
const error = await response.text();
|
|
56
|
-
console.log(pc.red(`Failed to send: ${error}`));
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.log(pc.red(`Failed to send: ${(error as Error).message}`));
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
console.log(pc.yellow("Usage:"));
|
|
65
|
-
console.log(" agentmesh slack respond <channel> <message> - Send a message to Slack");
|
|
66
|
-
console.log("");
|
|
67
|
-
console.log(pc.dim("Examples:"));
|
|
68
|
-
console.log(' agentmesh slack respond C0123456 "Hello from AgentMesh!"');
|
|
69
|
-
}
|
|
70
|
-
}
|
package/src/cli/start.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import pc from "picocolors";
|
|
5
|
-
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
6
|
-
import { AgentDaemon } from "../core/daemon.js";
|
|
7
|
-
import { getSessionName, sessionExists } from "../core/tmux.js";
|
|
8
|
-
|
|
9
|
-
export interface StartOptions {
|
|
10
|
-
name: string;
|
|
11
|
-
command?: string;
|
|
12
|
-
workdir?: string;
|
|
13
|
-
model?: string;
|
|
14
|
-
foreground?: boolean;
|
|
15
|
-
noContext?: boolean;
|
|
16
|
-
autoSetup?: boolean;
|
|
17
|
-
/** Run opencode serve instead of tmux TUI (for Integration Service) */
|
|
18
|
-
serve?: boolean;
|
|
19
|
-
/** Port for opencode serve (default: 3001) */
|
|
20
|
-
servePort?: number;
|
|
21
|
-
/** Run agent in Docker sandbox container */
|
|
22
|
-
sandbox?: boolean;
|
|
23
|
-
/** Docker image for sandbox */
|
|
24
|
-
sandboxImage?: string;
|
|
25
|
-
/** CPU limit for sandbox */
|
|
26
|
-
sandboxCpu?: string;
|
|
27
|
-
/** Memory limit for sandbox */
|
|
28
|
-
sandboxMemory?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function start(options: StartOptions): Promise<void> {
|
|
32
|
-
const config = loadConfig();
|
|
33
|
-
|
|
34
|
-
if (!config) {
|
|
35
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!options.name) {
|
|
40
|
-
console.log(pc.red("Agent name is required. Use --name <name>"));
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Check if already running
|
|
45
|
-
const existingState = getAgentState(options.name);
|
|
46
|
-
const sessionName = getSessionName(options.name);
|
|
47
|
-
|
|
48
|
-
if (existingState && sessionExists(sessionName)) {
|
|
49
|
-
console.log(pc.yellow(`Agent "${options.name}" is already running.`));
|
|
50
|
-
console.log(`Attach with: ${pc.cyan(`agentmesh attach ${options.name}`)}`);
|
|
51
|
-
process.exit(0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// If --foreground flag is set, run in foreground (blocking)
|
|
55
|
-
if (options.foreground) {
|
|
56
|
-
try {
|
|
57
|
-
const daemon = new AgentDaemon({
|
|
58
|
-
...options,
|
|
59
|
-
restoreContext: !options.noContext,
|
|
60
|
-
autoSetup: options.autoSetup,
|
|
61
|
-
});
|
|
62
|
-
await daemon.start();
|
|
63
|
-
// Keep process alive
|
|
64
|
-
await new Promise(() => {});
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error(pc.red(`Failed to start agent: ${(error as Error).message}`));
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Default: run as background daemon
|
|
73
|
-
console.log(`Starting agent "${options.name}" in background...`);
|
|
74
|
-
|
|
75
|
-
// Get the path to this CLI
|
|
76
|
-
const cliPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../cli/index.js");
|
|
77
|
-
|
|
78
|
-
// Build args for the background process
|
|
79
|
-
const args = ["start", "--name", options.name, "--foreground"];
|
|
80
|
-
if (options.command) args.push("--command", options.command);
|
|
81
|
-
if (options.workdir) args.push("--workdir", options.workdir);
|
|
82
|
-
if (options.model) args.push("--model", options.model);
|
|
83
|
-
if (options.noContext) args.push("--no-context");
|
|
84
|
-
if (options.autoSetup) args.push("--auto-setup");
|
|
85
|
-
if (options.serve) {
|
|
86
|
-
args.push("--serve");
|
|
87
|
-
if (options.servePort) args.push("--serve-port", String(options.servePort));
|
|
88
|
-
}
|
|
89
|
-
if (options.sandbox) {
|
|
90
|
-
args.push("--sandbox");
|
|
91
|
-
if (options.sandboxImage) args.push("--sandbox-image", options.sandboxImage);
|
|
92
|
-
if (options.sandboxCpu) args.push("--sandbox-cpu", options.sandboxCpu);
|
|
93
|
-
if (options.sandboxMemory) args.push("--sandbox-memory", options.sandboxMemory);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Spawn detached background process
|
|
97
|
-
const child = spawn("node", [cliPath, ...args], {
|
|
98
|
-
detached: true,
|
|
99
|
-
stdio: "ignore",
|
|
100
|
-
env: process.env,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
child.unref();
|
|
104
|
-
|
|
105
|
-
console.log(pc.green(`Agent "${options.name}" started in background (PID: ${child.pid})`));
|
|
106
|
-
console.log();
|
|
107
|
-
console.log(`Attach to session:`);
|
|
108
|
-
console.log(` ${pc.cyan(`agentmesh attach ${options.name}`)}`);
|
|
109
|
-
console.log();
|
|
110
|
-
console.log(`Stop agent:`);
|
|
111
|
-
console.log(` ${pc.cyan(`agentmesh stop ${options.name}`)}`);
|
|
112
|
-
console.log();
|
|
113
|
-
console.log(`List agents:`);
|
|
114
|
-
console.log(` ${pc.cyan(`agentmesh list`)}`);
|
|
115
|
-
}
|
package/src/cli/status.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
import { loadConfig, loadState } from "../config/loader.js";
|
|
3
|
-
import { getSessionName, sessionExists } from "../core/tmux.js";
|
|
4
|
-
|
|
5
|
-
interface HealthResponse {
|
|
6
|
-
status: string;
|
|
7
|
-
service?: string;
|
|
8
|
-
version?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function status(): Promise<void> {
|
|
12
|
-
const config = loadConfig();
|
|
13
|
-
|
|
14
|
-
if (!config) {
|
|
15
|
-
console.log(pc.red("No config found. Run 'agentmesh init' first."));
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
console.log(pc.bold("AgentMesh Status\n"));
|
|
20
|
-
|
|
21
|
-
// Check hub connectivity
|
|
22
|
-
console.log(pc.dim("Hub:"));
|
|
23
|
-
try {
|
|
24
|
-
const response = await fetch(`${config.hubUrl}/health`, {
|
|
25
|
-
signal: AbortSignal.timeout(5000),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
if (response.ok) {
|
|
29
|
-
const data = (await response.json()) as HealthResponse;
|
|
30
|
-
console.log(` URL: ${pc.cyan(config.hubUrl)}`);
|
|
31
|
-
console.log(` Status: ${pc.green("connected")}`);
|
|
32
|
-
if (data.version) {
|
|
33
|
-
console.log(` Version: ${pc.dim(data.version)}`);
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
console.log(` URL: ${pc.cyan(config.hubUrl)}`);
|
|
37
|
-
console.log(` Status: ${pc.yellow(`HTTP ${response.status}`)}`);
|
|
38
|
-
}
|
|
39
|
-
} catch (error) {
|
|
40
|
-
console.log(` URL: ${pc.cyan(config.hubUrl)}`);
|
|
41
|
-
console.log(` Status: ${pc.red("unreachable")}`);
|
|
42
|
-
console.log(` Error: ${pc.dim((error as Error).message)}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Check local agents
|
|
46
|
-
const state = loadState();
|
|
47
|
-
const runningAgents = state.agents.filter((a) => {
|
|
48
|
-
if (!a.pid) return false;
|
|
49
|
-
try {
|
|
50
|
-
process.kill(a.pid, 0);
|
|
51
|
-
return sessionExists(getSessionName(a.name));
|
|
52
|
-
} catch {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
console.log();
|
|
58
|
-
console.log(pc.dim("Local Agents:"));
|
|
59
|
-
console.log(` Running: ${pc.cyan(String(runningAgents.length))}`);
|
|
60
|
-
console.log(` Total: ${pc.dim(String(state.agents.length))}`);
|
|
61
|
-
|
|
62
|
-
if (runningAgents.length > 0) {
|
|
63
|
-
console.log(` Names: ${pc.dim(runningAgents.map((a) => a.name).join(", "))}`);
|
|
64
|
-
|
|
65
|
-
// Show models for running agents
|
|
66
|
-
const modelsInfo = runningAgents
|
|
67
|
-
.filter((a) => a.runtimeModel)
|
|
68
|
-
.map((a) => `${a.name}:${a.runtimeModel}`);
|
|
69
|
-
if (modelsInfo.length > 0) {
|
|
70
|
-
console.log(` Models: ${pc.dim(modelsInfo.join(", "))}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Check tmux
|
|
75
|
-
console.log();
|
|
76
|
-
console.log(pc.dim("Dependencies:"));
|
|
77
|
-
try {
|
|
78
|
-
const { execSync } = await import("node:child_process");
|
|
79
|
-
const tmuxVersion = execSync("tmux -V", { encoding: "utf-8" }).trim();
|
|
80
|
-
console.log(` tmux: ${pc.green(tmuxVersion)}`);
|
|
81
|
-
} catch {
|
|
82
|
-
console.log(` tmux: ${pc.red("not found")}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Config info
|
|
86
|
-
console.log();
|
|
87
|
-
console.log(pc.dim("Config:"));
|
|
88
|
-
console.log(` Workspace: ${pc.cyan(config.workspace)}`);
|
|
89
|
-
console.log(` Command: ${pc.dim(config.defaults.command)}`);
|
|
90
|
-
console.log(` Model: ${pc.dim(config.defaults.model)}`);
|
|
91
|
-
}
|