@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.
Files changed (117) 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.d.ts +1 -0
  5. package/dist/__tests__/sandbox.test.js +362 -0
  6. package/dist/__tests__/sandbox.test.js.map +1 -0
  7. package/dist/__tests__/watchdog.test.d.ts +1 -0
  8. package/dist/__tests__/watchdog.test.js +290 -0
  9. package/dist/__tests__/watchdog.test.js.map +1 -0
  10. package/dist/cli/attach.js +20 -1
  11. package/dist/cli/attach.js.map +1 -1
  12. package/dist/cli/build.js +8 -2
  13. package/dist/cli/build.js.map +1 -1
  14. package/dist/cli/context.js.map +1 -1
  15. package/dist/cli/deploy.js +1 -1
  16. package/dist/cli/deploy.js.map +1 -1
  17. package/dist/cli/inbox.d.ts +5 -0
  18. package/dist/cli/inbox.js +123 -0
  19. package/dist/cli/inbox.js.map +1 -0
  20. package/dist/cli/index.js +5 -1
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/init.js +1 -1
  23. package/dist/cli/init.js.map +1 -1
  24. package/dist/cli/issue.d.ts +42 -0
  25. package/dist/cli/issue.js +297 -0
  26. package/dist/cli/issue.js.map +1 -0
  27. package/dist/cli/list.js +3 -3
  28. package/dist/cli/list.js.map +1 -1
  29. package/dist/cli/local.js +5 -3
  30. package/dist/cli/local.js.map +1 -1
  31. package/dist/cli/migrate.js +1 -1
  32. package/dist/cli/migrate.js.map +1 -1
  33. package/dist/cli/nudge.js +16 -3
  34. package/dist/cli/nudge.js.map +1 -1
  35. package/dist/cli/ready.d.ts +5 -0
  36. package/dist/cli/ready.js +131 -0
  37. package/dist/cli/ready.js.map +1 -0
  38. package/dist/cli/restart.js.map +1 -1
  39. package/dist/cli/slack.js +1 -1
  40. package/dist/cli/slack.js.map +1 -1
  41. package/dist/cli/start.d.ts +8 -0
  42. package/dist/cli/start.js +9 -0
  43. package/dist/cli/start.js.map +1 -1
  44. package/dist/cli/stop.js +13 -5
  45. package/dist/cli/stop.js.map +1 -1
  46. package/dist/cli/sync.d.ts +8 -0
  47. package/dist/cli/sync.js +154 -0
  48. package/dist/cli/sync.js.map +1 -0
  49. package/dist/cli/test.js +1 -1
  50. package/dist/cli/test.js.map +1 -1
  51. package/dist/cli/token.js +2 -2
  52. package/dist/cli/token.js.map +1 -1
  53. package/dist/config/loader.d.ts +5 -1
  54. package/dist/config/loader.js +27 -2
  55. package/dist/config/loader.js.map +1 -1
  56. package/dist/config/schema.d.ts +13 -0
  57. package/dist/core/daemon.d.ts +50 -0
  58. package/dist/core/daemon.js +445 -11
  59. package/dist/core/daemon.js.map +1 -1
  60. package/dist/core/injector.d.ts +2 -2
  61. package/dist/core/injector.js +23 -4
  62. package/dist/core/injector.js.map +1 -1
  63. package/dist/core/issue-cache.d.ts +44 -0
  64. package/dist/core/issue-cache.js +75 -0
  65. package/dist/core/issue-cache.js.map +1 -0
  66. package/dist/core/registry.d.ts +5 -0
  67. package/dist/core/registry.js +8 -1
  68. package/dist/core/registry.js.map +1 -1
  69. package/dist/core/runner.d.ts +1 -1
  70. package/dist/core/runner.js +23 -1
  71. package/dist/core/runner.js.map +1 -1
  72. package/dist/core/sandbox.d.ts +138 -0
  73. package/dist/core/sandbox.js +409 -0
  74. package/dist/core/sandbox.js.map +1 -0
  75. package/dist/core/tmux.d.ts +8 -0
  76. package/dist/core/tmux.js +28 -1
  77. package/dist/core/tmux.js.map +1 -1
  78. package/dist/core/watchdog.d.ts +41 -0
  79. package/dist/core/watchdog.js +198 -0
  80. package/dist/core/watchdog.js.map +1 -0
  81. package/dist/core/websocket.js +1 -1
  82. package/dist/core/websocket.js.map +1 -1
  83. package/dist/index.d.ts +5 -5
  84. package/dist/index.js +5 -5
  85. package/dist/index.js.map +1 -1
  86. package/package.json +1 -1
  87. package/src/__tests__/loader.test.ts +52 -4
  88. package/src/__tests__/runner.test.ts +1 -2
  89. package/src/__tests__/sandbox.test.ts +435 -0
  90. package/src/__tests__/watchdog.test.ts +368 -0
  91. package/src/cli/attach.ts +22 -1
  92. package/src/cli/build.ts +12 -4
  93. package/src/cli/context.ts +0 -1
  94. package/src/cli/deploy.ts +7 -5
  95. package/src/cli/index.ts +8 -1
  96. package/src/cli/init.ts +7 -19
  97. package/src/cli/list.ts +6 -10
  98. package/src/cli/local.ts +21 -12
  99. package/src/cli/migrate.ts +6 -4
  100. package/src/cli/nudge.ts +29 -14
  101. package/src/cli/restart.ts +1 -1
  102. package/src/cli/slack.ts +16 -15
  103. package/src/cli/start.ts +14 -0
  104. package/src/cli/stop.ts +14 -5
  105. package/src/cli/test.ts +5 -3
  106. package/src/cli/token.ts +4 -4
  107. package/src/config/loader.ts +29 -2
  108. package/src/config/schema.ts +14 -0
  109. package/src/core/daemon.ts +540 -17
  110. package/src/core/injector.ts +27 -4
  111. package/src/core/registry.ts +14 -1
  112. package/src/core/runner.ts +26 -1
  113. package/src/core/sandbox.ts +550 -0
  114. package/src/core/tmux.ts +35 -2
  115. package/src/core/watchdog.ts +238 -0
  116. package/src/core/websocket.ts +2 -2
  117. package/src/index.ts +6 -5
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Agent Progress Watchdog
3
+ *
4
+ * Monitors agent activity and detects stuck agents.
5
+ * Checks OpenCode logs for activity and tmux pane for permission prompts.
6
+ */
7
+ import { execSync, spawnSync } from "node:child_process";
8
+ import { captureSessionOutput } from "./tmux.js";
9
+ // Patterns that indicate a permission prompt is blocking the agent
10
+ const PERMISSION_PROMPT_PATTERNS = [
11
+ "Permission required",
12
+ "Allow once",
13
+ "Allow always",
14
+ "Reject",
15
+ "Access external directory",
16
+ "△ Permission required",
17
+ ];
18
+ // Idle threshold: 2 minutes
19
+ const IDLE_THRESHOLD_MS = 2 * 60 * 1000;
20
+ // Stuck threshold: 5 minutes
21
+ const STUCK_THRESHOLD_MS = 5 * 60 * 1000;
22
+ /**
23
+ * Check agent progress by analyzing OpenCode logs and tmux output
24
+ */
25
+ export function checkAgentProgress(agentName, containerName) {
26
+ // First check for permission prompts (highest priority)
27
+ const permissionPrompt = detectPermissionPrompt(agentName);
28
+ if (permissionPrompt) {
29
+ return {
30
+ status: "permission_blocked",
31
+ blockedOn: permissionPrompt,
32
+ details: "Agent is waiting for permission approval",
33
+ };
34
+ }
35
+ // Check last activity from OpenCode logs
36
+ const lastActivity = getLastActivityTime(agentName, containerName);
37
+ if (!lastActivity) {
38
+ // Can't determine activity, assume active
39
+ return {
40
+ status: "active",
41
+ details: "Unable to determine activity time",
42
+ };
43
+ }
44
+ const timeSinceActivity = Date.now() - lastActivity.getTime();
45
+ if (timeSinceActivity > STUCK_THRESHOLD_MS) {
46
+ return {
47
+ status: "stuck",
48
+ lastActivity,
49
+ details: `No activity for ${Math.round(timeSinceActivity / 60000)} minutes`,
50
+ };
51
+ }
52
+ if (timeSinceActivity > IDLE_THRESHOLD_MS) {
53
+ return {
54
+ status: "idle",
55
+ lastActivity,
56
+ details: `Idle for ${Math.round(timeSinceActivity / 60000)} minutes`,
57
+ };
58
+ }
59
+ return {
60
+ status: "active",
61
+ lastActivity,
62
+ };
63
+ }
64
+ /**
65
+ * Detect if a permission prompt is blocking the agent
66
+ */
67
+ export function detectPermissionPrompt(agentName) {
68
+ try {
69
+ const output = captureSessionOutput(agentName, 50);
70
+ if (!output)
71
+ return null;
72
+ for (const pattern of PERMISSION_PROMPT_PATTERNS) {
73
+ if (output.includes(pattern)) {
74
+ // Try to extract what permission is being requested
75
+ const lines = output.split("\n");
76
+ for (const line of lines) {
77
+ if (line.includes("Access external directory")) {
78
+ const match = line.match(/Access external directory\s+(\S+)/);
79
+ if (match)
80
+ return `External directory: ${match[1]}`;
81
+ }
82
+ if (line.includes("Permission required")) {
83
+ return "Permission prompt detected";
84
+ }
85
+ }
86
+ return "Permission prompt detected";
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ /**
96
+ * Get the last activity time from OpenCode logs
97
+ */
98
+ export function getLastActivityTime(agentName, containerName) {
99
+ try {
100
+ let logLine;
101
+ if (containerName) {
102
+ // Sandbox mode: read from container
103
+ const result = spawnSync("docker", [
104
+ "exec",
105
+ containerName,
106
+ "sh",
107
+ "-c",
108
+ "ls -t /home/node/.local/share/opencode/log/*.log 2>/dev/null | head -1 | xargs tail -1 2>/dev/null",
109
+ ], { encoding: "utf-8", timeout: 5000 });
110
+ if (result.status !== 0 || !result.stdout.trim()) {
111
+ return null;
112
+ }
113
+ logLine = result.stdout.trim();
114
+ }
115
+ else {
116
+ // Non-sandbox mode: read from local logs
117
+ const logDir = `${process.env.HOME}/.local/share/opencode/log`;
118
+ const result = spawnSync("sh", ["-c", `ls -t ${logDir}/*.log 2>/dev/null | head -1 | xargs tail -1 2>/dev/null`], { encoding: "utf-8", timeout: 5000 });
119
+ if (result.status !== 0 || !result.stdout.trim()) {
120
+ return null;
121
+ }
122
+ logLine = result.stdout.trim();
123
+ }
124
+ // Parse timestamp from log line
125
+ // Format: INFO 2026-02-26T00:14:42 +0ms service=...
126
+ const match = logLine.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})/);
127
+ if (match) {
128
+ return new Date(match[1] + "Z");
129
+ }
130
+ return null;
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ }
136
+ /**
137
+ * Send a nudge to the agent to continue working
138
+ */
139
+ export function sendNudge(agentName, message) {
140
+ try {
141
+ const sessionName = `agentmesh-${agentName}`;
142
+ // Send keys to tmux session
143
+ execSync(`tmux send-keys -t "${sessionName}" "${message.replace(/"/g, '\\"')}" Enter`, {
144
+ encoding: "utf-8",
145
+ timeout: 5000,
146
+ });
147
+ return true;
148
+ }
149
+ catch {
150
+ return false;
151
+ }
152
+ }
153
+ /**
154
+ * Check if a process is actually running
155
+ */
156
+ export function isProcessRunning(pid) {
157
+ try {
158
+ process.kill(pid, 0);
159
+ return true;
160
+ }
161
+ catch {
162
+ return false;
163
+ }
164
+ }
165
+ /**
166
+ * Find orphan containers for an agent
167
+ */
168
+ export function findOrphanContainers(agentName) {
169
+ try {
170
+ const result = spawnSync("docker", ["ps", "-aq", "--filter", `name=agentmesh-sandbox-${agentName}-`], { encoding: "utf-8", timeout: 5000 });
171
+ if (result.status !== 0 || !result.stdout.trim()) {
172
+ return [];
173
+ }
174
+ return result.stdout.trim().split("\n").filter(Boolean);
175
+ }
176
+ catch {
177
+ return [];
178
+ }
179
+ }
180
+ /**
181
+ * Remove orphan containers for an agent
182
+ */
183
+ export function cleanupOrphanContainers(agentName) {
184
+ const containers = findOrphanContainers(agentName);
185
+ for (const containerId of containers) {
186
+ try {
187
+ spawnSync("docker", ["rm", "-f", containerId], {
188
+ encoding: "utf-8",
189
+ timeout: 10000,
190
+ });
191
+ }
192
+ catch {
193
+ // Ignore cleanup errors
194
+ }
195
+ }
196
+ return containers.length;
197
+ }
198
+ //# sourceMappingURL=watchdog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchdog.js","sourceRoot":"","sources":["../../src/core/watchdog.ts"],"names":[],"mappings":"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"}
@@ -45,7 +45,7 @@ export class AgentWebSocket {
45
45
  return;
46
46
  }
47
47
  this.reconnectAttempts++;
48
- const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
48
+ const delay = this.reconnectDelay * 2 ** (this.reconnectAttempts - 1);
49
49
  setTimeout(() => {
50
50
  console.log(`Reconnecting... (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
51
51
  this.connect();
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/core/websocket.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/core/websocket.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ export * from "./config/loader.js";
2
+ export * from "./config/schema.js";
1
3
  export { AgentDaemon } from "./core/daemon.js";
2
- export { AgentWebSocket } from "./core/websocket.js";
3
4
  export { Heartbeat } from "./core/heartbeat.js";
4
- export * from "./core/tmux.js";
5
- export * from "./core/registry.js";
6
5
  export * from "./core/injector.js";
7
- export * from "./config/schema.js";
8
- export * from "./config/loader.js";
6
+ export * from "./core/registry.js";
7
+ export * from "./core/tmux.js";
8
+ export { AgentWebSocket } from "./core/websocket.js";
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // Re-export core modules for programmatic usage
2
+ export * from "./config/loader.js";
3
+ export * from "./config/schema.js";
2
4
  export { AgentDaemon } from "./core/daemon.js";
3
- export { AgentWebSocket } from "./core/websocket.js";
4
5
  export { Heartbeat } from "./core/heartbeat.js";
5
- export * from "./core/tmux.js";
6
- export * from "./core/registry.js";
7
6
  export * from "./core/injector.js";
8
- export * from "./config/schema.js";
9
- export * from "./config/loader.js";
7
+ export * from "./core/registry.js";
8
+ export * from "./core/tmux.js";
9
+ export { AgentWebSocket } from "./core/websocket.js";
10
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentmeshhq/agent",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "AgentMesh Agent Wrapper - Turn any AI coding assistant into a dispatchable, nudge-able agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,14 +1,12 @@
1
1
  import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
4
3
  import {
5
4
  addAgentToState,
6
5
  getAgentState,
7
6
  loadConfig,
8
7
  loadState,
9
8
  removeAgentFromState,
10
- saveConfig,
11
- saveState,
9
+ resetAgentRestartCount,
12
10
  updateAgentInState,
13
11
  } from "../config/loader.js";
14
12
  import type { AgentState, Config, State } from "../config/schema.js";
@@ -187,5 +185,55 @@ describe("Config Loader", () => {
187
185
  // writeFileSync should not be called since agent doesn't exist
188
186
  // Actually it will be called but the state will be unchanged
189
187
  });
188
+
189
+ it("should update restart count and status fields", () => {
190
+ vi.mocked(fs.existsSync).mockReturnValue(true);
191
+ vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify(mockState));
192
+ vi.mocked(fs.writeFileSync).mockImplementation(() => {});
193
+
194
+ updateAgentInState("test-agent", {
195
+ restartCount: 2,
196
+ status: "stuck",
197
+ stuckSince: "2024-01-01T01:00:00Z",
198
+ });
199
+
200
+ const writtenContent = vi.mocked(fs.writeFileSync).mock.calls[0][1] as string;
201
+ const parsedState = JSON.parse(writtenContent);
202
+ expect(parsedState.agents[0].restartCount).toBe(2);
203
+ expect(parsedState.agents[0].status).toBe("stuck");
204
+ expect(parsedState.agents[0].stuckSince).toBe("2024-01-01T01:00:00Z");
205
+ });
206
+ });
207
+
208
+ describe("resetAgentRestartCount", () => {
209
+ it("should reset restart count and clear stuck status", () => {
210
+ const stuckState: State = {
211
+ agents: [
212
+ {
213
+ name: "test-agent",
214
+ agentId: "agent-123",
215
+ pid: 12345,
216
+ tmuxSession: "agentmesh-test-agent",
217
+ startedAt: "2024-01-01T00:00:00Z",
218
+ token: "test-token",
219
+ restartCount: 3,
220
+ status: "stuck",
221
+ stuckSince: "2024-01-01T01:00:00Z",
222
+ },
223
+ ],
224
+ };
225
+
226
+ vi.mocked(fs.existsSync).mockReturnValue(true);
227
+ vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify(stuckState));
228
+ vi.mocked(fs.writeFileSync).mockImplementation(() => {});
229
+
230
+ resetAgentRestartCount("test-agent");
231
+
232
+ const writtenContent = vi.mocked(fs.writeFileSync).mock.calls[0][1] as string;
233
+ const parsedState = JSON.parse(writtenContent);
234
+ expect(parsedState.agents[0].restartCount).toBe(0);
235
+ expect(parsedState.agents[0].status).toBe("running");
236
+ expect(parsedState.agents[0].stuckSince).toBeUndefined();
237
+ });
190
238
  });
191
239
  });
@@ -1,9 +1,8 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
1
+ import { describe, expect, it } from "vitest";
2
2
  import {
3
3
  buildRunnerConfig,
4
4
  detectRunner,
5
5
  getRunnerDisplayName,
6
- type RunnerType,
7
6
  resolveModel,
8
7
  } from "../core/runner.js";
9
8