@agentmeshhq/agent 0.1.13 → 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.
Files changed (89) hide show
  1. package/dist/__tests__/loader.test.js +44 -1
  2. package/dist/__tests__/loader.test.js.map +1 -1
  3. package/dist/__tests__/runner.test.js.map +1 -1
  4. package/dist/__tests__/sandbox.test.js.map +1 -1
  5. package/dist/__tests__/watchdog.test.d.ts +1 -0
  6. package/dist/__tests__/watchdog.test.js +290 -0
  7. package/dist/__tests__/watchdog.test.js.map +1 -0
  8. package/dist/cli/attach.js +20 -1
  9. package/dist/cli/attach.js.map +1 -1
  10. package/dist/cli/build.js +8 -2
  11. package/dist/cli/build.js.map +1 -1
  12. package/dist/cli/context.js.map +1 -1
  13. package/dist/cli/deploy.js +1 -1
  14. package/dist/cli/deploy.js.map +1 -1
  15. package/dist/cli/init.js +1 -1
  16. package/dist/cli/init.js.map +1 -1
  17. package/dist/cli/list.js +3 -3
  18. package/dist/cli/list.js.map +1 -1
  19. package/dist/cli/local.js +5 -3
  20. package/dist/cli/local.js.map +1 -1
  21. package/dist/cli/migrate.js +1 -1
  22. package/dist/cli/migrate.js.map +1 -1
  23. package/dist/cli/nudge.js +16 -3
  24. package/dist/cli/nudge.js.map +1 -1
  25. package/dist/cli/restart.js.map +1 -1
  26. package/dist/cli/slack.js +1 -1
  27. package/dist/cli/slack.js.map +1 -1
  28. package/dist/cli/stop.js +13 -5
  29. package/dist/cli/stop.js.map +1 -1
  30. package/dist/cli/test.js +1 -1
  31. package/dist/cli/test.js.map +1 -1
  32. package/dist/cli/token.js +2 -2
  33. package/dist/cli/token.js.map +1 -1
  34. package/dist/config/loader.d.ts +5 -1
  35. package/dist/config/loader.js +27 -2
  36. package/dist/config/loader.js.map +1 -1
  37. package/dist/config/schema.d.ts +13 -0
  38. package/dist/core/daemon.d.ts +32 -1
  39. package/dist/core/daemon.js +362 -19
  40. package/dist/core/daemon.js.map +1 -1
  41. package/dist/core/injector.d.ts +2 -2
  42. package/dist/core/injector.js +23 -4
  43. package/dist/core/injector.js.map +1 -1
  44. package/dist/core/runner.d.ts +1 -1
  45. package/dist/core/runner.js +23 -1
  46. package/dist/core/runner.js.map +1 -1
  47. package/dist/core/sandbox.d.ts +11 -0
  48. package/dist/core/sandbox.js +34 -2
  49. package/dist/core/sandbox.js.map +1 -1
  50. package/dist/core/tmux.d.ts +8 -0
  51. package/dist/core/tmux.js +28 -1
  52. package/dist/core/tmux.js.map +1 -1
  53. package/dist/core/watchdog.d.ts +41 -0
  54. package/dist/core/watchdog.js +198 -0
  55. package/dist/core/watchdog.js.map +1 -0
  56. package/dist/core/websocket.js +1 -1
  57. package/dist/core/websocket.js.map +1 -1
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +5 -5
  60. package/dist/index.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/__tests__/loader.test.ts +52 -4
  63. package/src/__tests__/runner.test.ts +1 -2
  64. package/src/__tests__/sandbox.test.ts +1 -1
  65. package/src/__tests__/watchdog.test.ts +368 -0
  66. package/src/cli/attach.ts +22 -1
  67. package/src/cli/build.ts +12 -4
  68. package/src/cli/context.ts +0 -1
  69. package/src/cli/deploy.ts +7 -5
  70. package/src/cli/init.ts +7 -19
  71. package/src/cli/list.ts +6 -10
  72. package/src/cli/local.ts +21 -12
  73. package/src/cli/migrate.ts +6 -4
  74. package/src/cli/nudge.ts +29 -14
  75. package/src/cli/restart.ts +1 -1
  76. package/src/cli/slack.ts +16 -15
  77. package/src/cli/stop.ts +14 -5
  78. package/src/cli/test.ts +5 -3
  79. package/src/cli/token.ts +4 -4
  80. package/src/config/loader.ts +29 -2
  81. package/src/config/schema.ts +14 -0
  82. package/src/core/daemon.ts +439 -24
  83. package/src/core/injector.ts +27 -4
  84. package/src/core/runner.ts +26 -1
  85. package/src/core/sandbox.ts +47 -2
  86. package/src/core/tmux.ts +35 -2
  87. package/src/core/watchdog.ts +238 -0
  88. package/src/core/websocket.ts +2 -2
  89. package/src/index.ts +6 -5
package/src/cli/list.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { loadState, loadConfig } from "../config/loader.js";
2
- import { sessionExists, getSessionName, getSessionInfo } from "../core/tmux.js";
3
- import { checkInbox, fetchAssignments } from "../core/registry.js";
4
1
  import pc from "picocolors";
2
+ import { loadConfig, loadState } from "../config/loader.js";
3
+ import { checkInbox, fetchAssignments } from "../core/registry.js";
4
+ import { getSessionInfo, getSessionName, sessionExists } from "../core/tmux.js";
5
5
 
6
6
  export async function list(): Promise<void> {
7
7
  const state = loadState();
@@ -15,7 +15,7 @@ export async function list(): Promise<void> {
15
15
 
16
16
  console.log(pc.bold("Running Agents:\n"));
17
17
  console.log(
18
- `${"NAME".padEnd(20)} ${"STATUS".padEnd(10)} ${"SESSION".padEnd(25)} ${"PENDING ID".padEnd(18)} ${"WORKDIR".padEnd(38)} ${"PROJECT"}`
18
+ `${"NAME".padEnd(20)} ${"STATUS".padEnd(10)} ${"SESSION".padEnd(25)} ${"PENDING ID".padEnd(18)} ${"WORKDIR".padEnd(38)} ${"PROJECT"}`,
19
19
  );
20
20
  console.log("-".repeat(140));
21
21
 
@@ -35,11 +35,7 @@ export async function list(): Promise<void> {
35
35
  // Try to check inbox if we have a token
36
36
  if (config && agent.token) {
37
37
  try {
38
- const items = await checkInbox(
39
- config.hubUrl,
40
- config.workspace,
41
- agent.token
42
- );
38
+ const items = await checkInbox(config.hubUrl, config.workspace, agent.token);
43
39
  if (items.length > 0) {
44
40
  const firstId = items[0]?.id || "-";
45
41
  pendingId = pc.yellow(items.length === 1 ? firstId : `${firstId} (+${items.length - 1})`);
@@ -62,7 +58,7 @@ export async function list(): Promise<void> {
62
58
  const workdir = agent.workdir || "-";
63
59
 
64
60
  console.log(
65
- `${agent.name.padEnd(20)} ${status.padEnd(19)} ${sessionName.padEnd(25)} ${pendingId.padEnd(18)} ${workdir.padEnd(38)} ${assignedProject}`
61
+ `${agent.name.padEnd(20)} ${status.padEnd(19)} ${sessionName.padEnd(25)} ${pendingId.padEnd(18)} ${workdir.padEnd(38)} ${assignedProject}`,
66
62
  );
67
63
 
68
64
  if (command) {
package/src/cli/local.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { spawn, execSync, spawnSync } from "node:child_process";
1
+ import { execSync, spawn, spawnSync } from "node:child_process";
2
2
  import path from "node:path";
3
3
  import pc from "picocolors";
4
4
 
@@ -24,14 +24,20 @@ function findProjectRoot(): string {
24
24
  dir = path.dirname(dir);
25
25
  }
26
26
  }
27
- throw new Error("Could not find AgentMesh project root. Make sure you're in the agentmesh repository.");
27
+ throw new Error(
28
+ "Could not find AgentMesh project root. Make sure you're in the agentmesh repository.",
29
+ );
28
30
  }
29
31
 
30
- function getContainerStatus(containerName: string): { running: boolean; healthy: boolean; port?: string } {
32
+ function getContainerStatus(containerName: string): {
33
+ running: boolean;
34
+ healthy: boolean;
35
+ port?: string;
36
+ } {
31
37
  try {
32
38
  const result = execSync(
33
39
  `docker inspect --format='{{.State.Running}}:{{.State.Health.Status}}' ${containerName} 2>/dev/null`,
34
- { encoding: "utf-8" }
40
+ { encoding: "utf-8" },
35
41
  ).trim();
36
42
  const [running, health] = result.split(":");
37
43
  return {
@@ -45,10 +51,9 @@ function getContainerStatus(containerName: string): { running: boolean; healthy:
45
51
 
46
52
  function getContainerPort(containerName: string, internalPort: number): string | null {
47
53
  try {
48
- const result = execSync(
49
- `docker port ${containerName} ${internalPort} 2>/dev/null | head -1`,
50
- { encoding: "utf-8" }
51
- ).trim();
54
+ const result = execSync(`docker port ${containerName} ${internalPort} 2>/dev/null | head -1`, {
55
+ encoding: "utf-8",
56
+ }).trim();
52
57
  // Format: 0.0.0.0:5432 -> 5432
53
58
  const match = result.match(/:(\d+)$/);
54
59
  return match ? match[1] : null;
@@ -119,7 +124,7 @@ export async function localStatus(): Promise<void> {
119
124
 
120
125
  console.log(pc.bold("AgentMesh Local Stack Status"));
121
126
  console.log();
122
- console.log(pc.dim("Service".padEnd(15) + "Status".padEnd(12) + "Health".padEnd(10) + "Port"));
127
+ console.log(pc.dim(`${"Service".padEnd(15) + "Status".padEnd(12) + "Health".padEnd(10)}Port`));
123
128
  console.log(pc.dim("-".repeat(50)));
124
129
 
125
130
  let anyRunning = false;
@@ -137,7 +142,7 @@ export async function localStatus(): Promise<void> {
137
142
  const portText = port ? pc.cyan(port) : pc.dim("-");
138
143
 
139
144
  console.log(
140
- `${service.name.padEnd(15)}${statusText.padEnd(20)}${healthText.padEnd(18)}${portText}`
145
+ `${service.name.padEnd(15)}${statusText.padEnd(20)}${healthText.padEnd(18)}${portText}`,
141
146
  );
142
147
 
143
148
  if (status.running) anyRunning = true;
@@ -153,13 +158,17 @@ export async function localStatus(): Promise<void> {
153
158
  console.log();
154
159
  console.log(pc.bold("Commands:"));
155
160
  console.log(` Stop: ${pc.cyan("agentmesh local down")}`);
156
- console.log(` Logs: ${pc.cyan("docker compose -f docker/docker-compose.local.yml logs -f")}`);
161
+ console.log(
162
+ ` Logs: ${pc.cyan("docker compose -f docker/docker-compose.local.yml logs -f")}`,
163
+ );
157
164
  } else {
158
165
  console.log(pc.dim("No services running. Start with: agentmesh local up"));
159
166
  }
160
167
  }
161
168
 
162
- export async function localLogs(options: { follow?: boolean; service?: string } = {}): Promise<void> {
169
+ export async function localLogs(
170
+ options: { follow?: boolean; service?: string } = {},
171
+ ): Promise<void> {
163
172
  const projectRoot = findProjectRoot();
164
173
  const composePath = path.join(projectRoot, COMPOSE_FILE);
165
174
 
@@ -1,4 +1,4 @@
1
- import { spawnSync, execSync } from "node:child_process";
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("Could not find AgentMesh project root. Make sure you're in the agentmesh repository.");
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 { loadConfig, getAgentState, loadState } from "../config/loader.js";
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
- `${config.hubUrl}/api/v1/agents/${agentState.agentId}/nudge`,
65
- {
66
- method: "POST",
67
- headers: {
68
- Authorization: `Bearer ${registration.token}`,
69
- "Content-Type": "application/json",
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.`));
@@ -1,6 +1,6 @@
1
1
  import pc from "picocolors";
2
2
  import { getAgentState, loadConfig } from "../config/loader.js";
3
- import { destroySession, getSessionName, sessionExists } from "../core/tmux.js";
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(pc.red("Channel is required. Usage: agentmesh slack respond <channel> <message>"));
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(pc.red("Message is required. Usage: agentmesh slack respond <channel> <message>"));
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
- `${config.hubUrl}/api/v1/integrations/slack/respond`,
41
- {
42
- method: "POST",
43
- headers: {
44
- Authorization: `Bearer ${token}`,
45
- "Content-Type": "application/json",
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/stop.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { destroySession } from "../core/tmux.js";
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
- // Remove from state
36
- removeAgentFromState(name);
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 { spawnSync, execSync } from "node:child_process";
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("Could not find AgentMesh project root. Make sure you're in the agentmesh repository.");
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
- config: ReturnType<typeof loadConfig>,
42
+ _config: ReturnType<typeof loadConfig>,
43
43
  agentName?: string,
44
- envAgentId?: string,
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
- config: ReturnType<typeof loadConfig>,
137
+ _config: ReturnType<typeof loadConfig>,
138
138
  agentName?: string,
139
- envAgentId?: string,
139
+ _envAgentId?: string,
140
140
  envToken?: string,
141
141
  ): Promise<void> {
142
142
  // Get token to inspect
@@ -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
- state.agents = state.agents.filter((a) => a.name !== name);
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);
@@ -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 {