@agentmeshhq/agent 0.1.12 → 0.1.14
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/dist/__tests__/loader.test.js +44 -1
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/sandbox.test.d.ts +1 -0
- package/dist/__tests__/sandbox.test.js +362 -0
- package/dist/__tests__/sandbox.test.js.map +1 -0
- package/dist/__tests__/watchdog.test.d.ts +1 -0
- package/dist/__tests__/watchdog.test.js +290 -0
- package/dist/__tests__/watchdog.test.js.map +1 -0
- package/dist/cli/attach.js +20 -1
- package/dist/cli/attach.js.map +1 -1
- package/dist/cli/build.js +8 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/context.js.map +1 -1
- package/dist/cli/deploy.js +1 -1
- package/dist/cli/deploy.js.map +1 -1
- package/dist/cli/inbox.d.ts +5 -0
- package/dist/cli/inbox.js +123 -0
- package/dist/cli/inbox.js.map +1 -0
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/issue.d.ts +42 -0
- package/dist/cli/issue.js +297 -0
- package/dist/cli/issue.js.map +1 -0
- package/dist/cli/list.js +3 -3
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/local.js +5 -3
- package/dist/cli/local.js.map +1 -1
- package/dist/cli/migrate.js +1 -1
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/nudge.js +16 -3
- package/dist/cli/nudge.js.map +1 -1
- package/dist/cli/ready.d.ts +5 -0
- package/dist/cli/ready.js +131 -0
- package/dist/cli/ready.js.map +1 -0
- package/dist/cli/restart.js.map +1 -1
- package/dist/cli/slack.js +1 -1
- package/dist/cli/slack.js.map +1 -1
- package/dist/cli/start.d.ts +8 -0
- package/dist/cli/start.js +9 -0
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/stop.js +13 -5
- package/dist/cli/stop.js.map +1 -1
- package/dist/cli/sync.d.ts +8 -0
- package/dist/cli/sync.js +154 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/test.js +1 -1
- package/dist/cli/test.js.map +1 -1
- package/dist/cli/token.js +2 -2
- package/dist/cli/token.js.map +1 -1
- package/dist/config/loader.d.ts +5 -1
- package/dist/config/loader.js +27 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +13 -0
- package/dist/core/daemon.d.ts +50 -0
- package/dist/core/daemon.js +445 -11
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.d.ts +2 -2
- package/dist/core/injector.js +23 -4
- package/dist/core/injector.js.map +1 -1
- package/dist/core/issue-cache.d.ts +44 -0
- package/dist/core/issue-cache.js +75 -0
- package/dist/core/issue-cache.js.map +1 -0
- package/dist/core/registry.d.ts +5 -0
- package/dist/core/registry.js +8 -1
- package/dist/core/registry.js.map +1 -1
- package/dist/core/runner.d.ts +1 -1
- package/dist/core/runner.js +23 -1
- package/dist/core/runner.js.map +1 -1
- package/dist/core/sandbox.d.ts +138 -0
- package/dist/core/sandbox.js +409 -0
- package/dist/core/sandbox.js.map +1 -0
- package/dist/core/tmux.d.ts +8 -0
- package/dist/core/tmux.js +28 -1
- package/dist/core/tmux.js.map +1 -1
- package/dist/core/watchdog.d.ts +41 -0
- package/dist/core/watchdog.js +198 -0
- package/dist/core/watchdog.js.map +1 -0
- package/dist/core/websocket.js +1 -1
- package/dist/core/websocket.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/loader.test.ts +52 -4
- package/src/__tests__/runner.test.ts +1 -2
- package/src/__tests__/sandbox.test.ts +435 -0
- package/src/__tests__/watchdog.test.ts +368 -0
- package/src/cli/attach.ts +22 -1
- package/src/cli/build.ts +12 -4
- package/src/cli/context.ts +0 -1
- package/src/cli/deploy.ts +7 -5
- package/src/cli/index.ts +8 -1
- package/src/cli/init.ts +7 -19
- package/src/cli/list.ts +6 -10
- package/src/cli/local.ts +21 -12
- package/src/cli/migrate.ts +6 -4
- package/src/cli/nudge.ts +29 -14
- package/src/cli/restart.ts +1 -1
- package/src/cli/slack.ts +16 -15
- package/src/cli/start.ts +14 -0
- package/src/cli/stop.ts +14 -5
- package/src/cli/test.ts +5 -3
- package/src/cli/token.ts +4 -4
- package/src/config/loader.ts +29 -2
- package/src/config/schema.ts +14 -0
- package/src/core/daemon.ts +540 -17
- package/src/core/injector.ts +27 -4
- package/src/core/registry.ts +14 -1
- package/src/core/runner.ts +26 -1
- package/src/core/sandbox.ts +550 -0
- package/src/core/tmux.ts +35 -2
- package/src/core/watchdog.ts +238 -0
- package/src/core/websocket.ts +2 -2
- package/src/index.ts +6 -5
package/src/cli/migrate.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
|
|
@@ -14,14 +14,16 @@ function findProjectRoot(): string {
|
|
|
14
14
|
dir = path.dirname(dir);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
throw new Error(
|
|
17
|
+
throw new Error(
|
|
18
|
+
"Could not find AgentMesh project root. Make sure you're in the agentmesh repository.",
|
|
19
|
+
);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function isLocalStackRunning(): boolean {
|
|
21
23
|
try {
|
|
22
24
|
const result = execSync(
|
|
23
25
|
'docker inspect --format="{{.State.Running}}" agentmesh_postgres 2>/dev/null',
|
|
24
|
-
{ encoding: "utf-8" }
|
|
26
|
+
{ encoding: "utf-8" },
|
|
25
27
|
).trim();
|
|
26
28
|
return result === "true";
|
|
27
29
|
} catch {
|
|
@@ -84,7 +86,7 @@ async function generateMigration(projectRoot: string): Promise<void> {
|
|
|
84
86
|
|
|
85
87
|
async function migrationStatus(projectRoot: string, options: MigrateOptions): Promise<void> {
|
|
86
88
|
const env = getEnvironmentConfig(options);
|
|
87
|
-
|
|
89
|
+
|
|
88
90
|
console.log(pc.cyan(`Checking migration status for ${env.name}...`));
|
|
89
91
|
console.log();
|
|
90
92
|
|
package/src/cli/nudge.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sendKeys, sessionExists, getSessionName } from "../core/tmux.js";
|
|
3
|
-
import { registerAgent } from "../core/registry.js";
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
4
2
|
import pc from "picocolors";
|
|
3
|
+
import { getAgentState, loadConfig, loadState } from "../config/loader.js";
|
|
4
|
+
import { registerAgent } from "../core/registry.js";
|
|
5
|
+
import { getSessionName, sendKeys, sessionExists } from "../core/tmux.js";
|
|
5
6
|
|
|
6
7
|
export async function nudge(name: string, message: string): Promise<void> {
|
|
7
8
|
const config = loadConfig();
|
|
@@ -24,6 +25,23 @@ export async function nudge(name: string, message: string): Promise<void> {
|
|
|
24
25
|
// Check if this is a local agent
|
|
25
26
|
const localAgent = getAgentState(name);
|
|
26
27
|
|
|
28
|
+
// Sandbox agent - route nudge through docker exec
|
|
29
|
+
if (localAgent?.sandboxContainer) {
|
|
30
|
+
const result = spawnSync(
|
|
31
|
+
"docker",
|
|
32
|
+
["exec", localAgent.sandboxContainer, "agentmesh", "nudge", name, message],
|
|
33
|
+
{ encoding: "utf-8", stdio: "pipe" },
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (result.status === 0) {
|
|
37
|
+
console.log(pc.green(`Nudged "${name}" in sandbox.`));
|
|
38
|
+
} else {
|
|
39
|
+
console.log(pc.red(`Failed to nudge "${name}" in sandbox: ${result.stderr}`));
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Local agent with tmux session on host
|
|
27
45
|
if (localAgent && sessionExists(getSessionName(name))) {
|
|
28
46
|
// Local nudge via tmux send-keys
|
|
29
47
|
const formatted = `[AgentMesh] Nudge from CLI:
|
|
@@ -60,17 +78,14 @@ ${message}`;
|
|
|
60
78
|
model: "cli",
|
|
61
79
|
});
|
|
62
80
|
|
|
63
|
-
const response = await fetch(
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
body: JSON.stringify({ message }),
|
|
72
|
-
}
|
|
73
|
-
);
|
|
81
|
+
const response = await fetch(`${config.hubUrl}/api/v1/agents/${agentState.agentId}/nudge`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: {
|
|
84
|
+
Authorization: `Bearer ${registration.token}`,
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify({ message }),
|
|
88
|
+
});
|
|
74
89
|
|
|
75
90
|
if (response.ok) {
|
|
76
91
|
console.log(pc.green(`Nudged "${name}" via API.`));
|
package/src/cli/restart.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
2
|
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getSessionName, sessionExists } from "../core/tmux.js";
|
|
4
4
|
import { start } from "./start.js";
|
|
5
5
|
import { stop } from "./stop.js";
|
|
6
6
|
|
package/src/cli/slack.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { loadConfig, getAgentState } from "../config/loader.js";
|
|
2
1
|
import pc from "picocolors";
|
|
2
|
+
import { getAgentState, loadConfig } from "../config/loader.js";
|
|
3
3
|
|
|
4
4
|
export async function slack(
|
|
5
5
|
action: string,
|
|
6
6
|
channel: string | undefined,
|
|
7
7
|
message: string | undefined,
|
|
8
|
-
options: { name?: string }
|
|
8
|
+
options: { name?: string },
|
|
9
9
|
): Promise<void> {
|
|
10
10
|
const config = loadConfig();
|
|
11
11
|
|
|
@@ -16,12 +16,16 @@ export async function slack(
|
|
|
16
16
|
|
|
17
17
|
if (action === "respond" || action === "reply") {
|
|
18
18
|
if (!channel) {
|
|
19
|
-
console.log(
|
|
19
|
+
console.log(
|
|
20
|
+
pc.red("Channel is required. Usage: agentmesh slack respond <channel> <message>"),
|
|
21
|
+
);
|
|
20
22
|
process.exit(1);
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
if (!message) {
|
|
24
|
-
console.log(
|
|
26
|
+
console.log(
|
|
27
|
+
pc.red("Message is required. Usage: agentmesh slack respond <channel> <message>"),
|
|
28
|
+
);
|
|
25
29
|
process.exit(1);
|
|
26
30
|
}
|
|
27
31
|
|
|
@@ -36,17 +40,14 @@ export async function slack(
|
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
try {
|
|
39
|
-
const response = await fetch(
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
body: JSON.stringify({ channel, text: message }),
|
|
48
|
-
}
|
|
49
|
-
);
|
|
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
|
+
});
|
|
50
51
|
|
|
51
52
|
if (response.ok) {
|
|
52
53
|
console.log(pc.green(`Message sent to Slack channel ${channel}`));
|
package/src/cli/start.ts
CHANGED
|
@@ -18,6 +18,14 @@ export interface StartOptions {
|
|
|
18
18
|
serve?: boolean;
|
|
19
19
|
/** Port for opencode serve (default: 3001) */
|
|
20
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;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
export async function start(options: StartOptions): Promise<void> {
|
|
@@ -78,6 +86,12 @@ export async function start(options: StartOptions): Promise<void> {
|
|
|
78
86
|
args.push("--serve");
|
|
79
87
|
if (options.servePort) args.push("--serve-port", String(options.servePort));
|
|
80
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
|
+
}
|
|
81
95
|
|
|
82
96
|
// Spawn detached background process
|
|
83
97
|
const child = spawn("node", [cliPath, ...args], {
|
package/src/cli/stop.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { removeAgentFromState, getAgentState } from "../config/loader.js";
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
3
2
|
import pc from "picocolors";
|
|
3
|
+
import { getAgentState, removeAgentFromState } from "../config/loader.js";
|
|
4
|
+
import { destroySession } from "../core/tmux.js";
|
|
4
5
|
|
|
5
6
|
export async function stop(name: string): Promise<void> {
|
|
6
7
|
if (!name) {
|
|
@@ -32,8 +33,16 @@ export async function stop(name: string): Promise<void> {
|
|
|
32
33
|
console.log(pc.green(`Destroyed tmux session for "${name}"`));
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
//
|
|
36
|
-
|
|
36
|
+
// Clean up Docker sandbox container if it exists
|
|
37
|
+
if (state.sandboxContainer) {
|
|
38
|
+
console.log(`Stopping sandbox container: ${state.sandboxContainer}`);
|
|
39
|
+
spawnSync("docker", ["stop", "-t", "5", state.sandboxContainer], { encoding: "utf-8" });
|
|
40
|
+
spawnSync("docker", ["rm", "-f", state.sandboxContainer], { encoding: "utf-8" });
|
|
41
|
+
console.log(pc.green(`Removed sandbox container`));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Remove from state but preserve agentId for re-registration
|
|
45
|
+
removeAgentFromState(name, true);
|
|
37
46
|
|
|
38
|
-
console.log(pc.green(`Agent "${name}" stopped.`));
|
|
47
|
+
console.log(pc.green(`Agent "${name}" stopped (agentId preserved for restart).`));
|
|
39
48
|
}
|
package/src/cli/test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
|
|
@@ -14,14 +14,16 @@ function findProjectRoot(): string {
|
|
|
14
14
|
dir = path.dirname(dir);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
throw new Error(
|
|
17
|
+
throw new Error(
|
|
18
|
+
"Could not find AgentMesh project root. Make sure you're in the agentmesh repository.",
|
|
19
|
+
);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function isLocalStackRunning(): boolean {
|
|
21
23
|
try {
|
|
22
24
|
const result = execSync(
|
|
23
25
|
'docker inspect --format="{{.State.Running}}" agentmesh_postgres 2>/dev/null',
|
|
24
|
-
{ encoding: "utf-8" }
|
|
26
|
+
{ encoding: "utf-8" },
|
|
25
27
|
).trim();
|
|
26
28
|
return result === "true";
|
|
27
29
|
} catch {
|
package/src/cli/token.ts
CHANGED
|
@@ -39,9 +39,9 @@ export async function token(action: string, agentName?: string): Promise<void> {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
async function showToken(
|
|
42
|
-
|
|
42
|
+
_config: ReturnType<typeof loadConfig>,
|
|
43
43
|
agentName?: string,
|
|
44
|
-
|
|
44
|
+
_envAgentId?: string,
|
|
45
45
|
envToken?: string,
|
|
46
46
|
): Promise<void> {
|
|
47
47
|
// If running as agent, show env token
|
|
@@ -134,9 +134,9 @@ async function refreshToken(
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
async function tokenInfo(
|
|
137
|
-
|
|
137
|
+
_config: ReturnType<typeof loadConfig>,
|
|
138
138
|
agentName?: string,
|
|
139
|
-
|
|
139
|
+
_envAgentId?: string,
|
|
140
140
|
envToken?: string,
|
|
141
141
|
): Promise<void> {
|
|
142
142
|
// Get token to inspect
|
package/src/config/loader.ts
CHANGED
|
@@ -58,12 +58,39 @@ export function addAgentToState(agent: AgentState): void {
|
|
|
58
58
|
saveState(state);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export function removeAgentFromState(name: string): void {
|
|
61
|
+
export function removeAgentFromState(name: string, preserveAgentId = false): void {
|
|
62
62
|
const state = loadState();
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
if (preserveAgentId) {
|
|
65
|
+
// Keep minimal state with agentId for re-registration
|
|
66
|
+
const existing = state.agents.find((a) => a.name === name);
|
|
67
|
+
if (existing) {
|
|
68
|
+
state.agents = state.agents.filter((a) => a.name !== name);
|
|
69
|
+
// Save only the agentId and restartCount for next startup
|
|
70
|
+
state.agents.push({
|
|
71
|
+
name: existing.name,
|
|
72
|
+
agentId: existing.agentId,
|
|
73
|
+
pid: 0,
|
|
74
|
+
tmuxSession: "",
|
|
75
|
+
startedAt: existing.startedAt,
|
|
76
|
+
restartCount: existing.restartCount,
|
|
77
|
+
status: "stopped",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
state.agents = state.agents.filter((a) => a.name !== name);
|
|
82
|
+
}
|
|
83
|
+
|
|
64
84
|
saveState(state);
|
|
65
85
|
}
|
|
66
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Reset restart count for an agent (called on manual start or after stable period)
|
|
89
|
+
*/
|
|
90
|
+
export function resetAgentRestartCount(name: string): void {
|
|
91
|
+
updateAgentInState(name, { restartCount: 0, stuckSince: undefined, status: "running" });
|
|
92
|
+
}
|
|
93
|
+
|
|
67
94
|
export function getAgentState(name: string): AgentState | undefined {
|
|
68
95
|
const state = loadState();
|
|
69
96
|
return state.agents.find((a) => a.name === name);
|
package/src/config/schema.ts
CHANGED
|
@@ -32,6 +32,8 @@ export const STATE_PATH = `${process.env.HOME}/.agentmesh/state.json`;
|
|
|
32
32
|
|
|
33
33
|
export type RunnerType = "opencode" | "claude" | "custom";
|
|
34
34
|
|
|
35
|
+
export type AgentStatus = "running" | "stopped" | "failed" | "stuck";
|
|
36
|
+
|
|
35
37
|
export interface AgentState {
|
|
36
38
|
name: string;
|
|
37
39
|
agentId: string;
|
|
@@ -45,6 +47,18 @@ export interface AgentState {
|
|
|
45
47
|
runtimeModel?: string;
|
|
46
48
|
/** The runner type (opencode, claude, custom) */
|
|
47
49
|
runnerType?: RunnerType;
|
|
50
|
+
/** Docker container name if running in sandbox mode */
|
|
51
|
+
sandboxContainer?: string;
|
|
52
|
+
/** Number of auto-restart attempts since last manual start */
|
|
53
|
+
restartCount?: number;
|
|
54
|
+
/** ISO timestamp of last auto-restart */
|
|
55
|
+
lastRestartAt?: string;
|
|
56
|
+
/** ISO timestamp of last detected activity */
|
|
57
|
+
lastActivityAt?: string;
|
|
58
|
+
/** ISO timestamp when agent was detected as stuck */
|
|
59
|
+
stuckSince?: string;
|
|
60
|
+
/** Current agent status */
|
|
61
|
+
status?: AgentStatus;
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
export interface State {
|