@action-llama/action-llama 0.10.2 → 0.11.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 (257) hide show
  1. package/AGENTS.md +17 -6
  2. package/README.md +8 -4
  3. package/dist/agents/container-entry.d.ts.map +1 -1
  4. package/dist/agents/container-entry.js +37 -0
  5. package/dist/agents/container-entry.js.map +1 -1
  6. package/dist/agents/container-runner.d.ts +4 -0
  7. package/dist/agents/container-runner.d.ts.map +1 -1
  8. package/dist/agents/container-runner.js +82 -5
  9. package/dist/agents/container-runner.js.map +1 -1
  10. package/dist/agents/execution-engine.d.ts +2 -0
  11. package/dist/agents/execution-engine.d.ts.map +1 -1
  12. package/dist/agents/execution-engine.js +5 -1
  13. package/dist/agents/execution-engine.js.map +1 -1
  14. package/dist/agents/runner.d.ts +3 -0
  15. package/dist/agents/runner.d.ts.map +1 -1
  16. package/dist/agents/runner.js +45 -2
  17. package/dist/agents/runner.js.map +1 -1
  18. package/dist/cli/commands/chat.d.ts +5 -2
  19. package/dist/cli/commands/chat.d.ts.map +1 -1
  20. package/dist/cli/commands/chat.js +240 -23
  21. package/dist/cli/commands/chat.js.map +1 -1
  22. package/dist/cli/commands/cloud-deploy.d.ts.map +1 -1
  23. package/dist/cli/commands/cloud-deploy.js +5 -47
  24. package/dist/cli/commands/cloud-deploy.js.map +1 -1
  25. package/dist/cli/commands/cloud-setup.d.ts.map +1 -1
  26. package/dist/cli/commands/cloud-setup.js +20 -33
  27. package/dist/cli/commands/cloud-setup.js.map +1 -1
  28. package/dist/cli/commands/cloud-teardown.d.ts.map +1 -1
  29. package/dist/cli/commands/cloud-teardown.js +6 -126
  30. package/dist/cli/commands/cloud-teardown.js.map +1 -1
  31. package/dist/cli/commands/doctor.d.ts +0 -1
  32. package/dist/cli/commands/doctor.d.ts.map +1 -1
  33. package/dist/cli/commands/doctor.js +19 -14
  34. package/dist/cli/commands/doctor.js.map +1 -1
  35. package/dist/cli/commands/kill.d.ts +1 -1
  36. package/dist/cli/commands/kill.d.ts.map +1 -1
  37. package/dist/cli/commands/kill.js +17 -6
  38. package/dist/cli/commands/kill.js.map +1 -1
  39. package/dist/cli/commands/logs.d.ts.map +1 -1
  40. package/dist/cli/commands/logs.js +104 -58
  41. package/dist/cli/commands/logs.js.map +1 -1
  42. package/dist/cli/commands/pause.d.ts +1 -1
  43. package/dist/cli/commands/pause.d.ts.map +1 -1
  44. package/dist/cli/commands/pause.js +9 -6
  45. package/dist/cli/commands/pause.js.map +1 -1
  46. package/dist/cli/commands/resume.d.ts +1 -1
  47. package/dist/cli/commands/resume.d.ts.map +1 -1
  48. package/dist/cli/commands/resume.js +9 -6
  49. package/dist/cli/commands/resume.js.map +1 -1
  50. package/dist/cli/commands/run.d.ts.map +1 -1
  51. package/dist/cli/commands/run.js +12 -54
  52. package/dist/cli/commands/run.js.map +1 -1
  53. package/dist/cli/commands/status.d.ts.map +1 -1
  54. package/dist/cli/commands/status.js +22 -39
  55. package/dist/cli/commands/status.js.map +1 -1
  56. package/dist/cli/gateway-client.d.ts +12 -0
  57. package/dist/cli/gateway-client.d.ts.map +1 -0
  58. package/dist/cli/gateway-client.js +27 -0
  59. package/dist/cli/gateway-client.js.map +1 -0
  60. package/dist/cli/main.js +49 -14
  61. package/dist/cli/main.js.map +1 -1
  62. package/dist/{shared/aws-constants.d.ts → cloud/aws/constants.d.ts} +3 -34
  63. package/dist/cloud/aws/constants.d.ts.map +1 -0
  64. package/dist/{shared/aws-constants.js → cloud/aws/constants.js} +3 -34
  65. package/dist/cloud/aws/constants.js.map +1 -0
  66. package/dist/cloud/{deploy-apprunner.d.ts → aws/deploy.d.ts} +6 -6
  67. package/dist/cloud/aws/deploy.d.ts.map +1 -0
  68. package/dist/cloud/{deploy-apprunner.js → aws/deploy.js} +2 -2
  69. package/dist/cloud/aws/deploy.js.map +1 -0
  70. package/dist/cloud/aws/iam.d.ts +37 -0
  71. package/dist/cloud/aws/iam.d.ts.map +1 -0
  72. package/dist/{cli/commands/cloud-iam.js → cloud/aws/iam.js} +30 -179
  73. package/dist/cloud/aws/iam.js.map +1 -0
  74. package/dist/cloud/aws/provider.d.ts +69 -0
  75. package/dist/cloud/aws/provider.d.ts.map +1 -0
  76. package/dist/cloud/aws/provider.js +173 -0
  77. package/dist/cloud/aws/provider.js.map +1 -0
  78. package/dist/cloud/aws/provision.d.ts +9 -0
  79. package/dist/cloud/aws/provision.d.ts.map +1 -0
  80. package/dist/{cli/commands/cloud-setup-ecs.js → cloud/aws/provision.js} +10 -9
  81. package/dist/cloud/aws/provision.js.map +1 -0
  82. package/dist/cloud/aws/teardown.d.ts +15 -0
  83. package/dist/cloud/aws/teardown.d.ts.map +1 -0
  84. package/dist/cloud/aws/teardown.js +74 -0
  85. package/dist/cloud/aws/teardown.js.map +1 -0
  86. package/dist/cloud/gcp/constants.d.ts +16 -0
  87. package/dist/cloud/gcp/constants.d.ts.map +1 -0
  88. package/dist/cloud/gcp/constants.js +16 -0
  89. package/dist/cloud/gcp/constants.js.map +1 -0
  90. package/dist/cloud/{deploy-cloudrun.d.ts → gcp/deploy.d.ts} +6 -6
  91. package/dist/cloud/gcp/deploy.d.ts.map +1 -0
  92. package/dist/cloud/{deploy-cloudrun.js → gcp/deploy.js} +7 -7
  93. package/dist/cloud/gcp/deploy.js.map +1 -0
  94. package/dist/cloud/gcp/iam.d.ts +20 -0
  95. package/dist/cloud/gcp/iam.d.ts.map +1 -0
  96. package/dist/cloud/gcp/iam.js +179 -0
  97. package/dist/cloud/gcp/iam.js.map +1 -0
  98. package/dist/cloud/gcp/provider.d.ts +28 -0
  99. package/dist/cloud/gcp/provider.d.ts.map +1 -0
  100. package/dist/cloud/gcp/provider.js +84 -0
  101. package/dist/cloud/gcp/provider.js.map +1 -0
  102. package/dist/cloud/gcp/provision.d.ts +14 -0
  103. package/dist/cloud/gcp/provision.d.ts.map +1 -0
  104. package/dist/cloud/gcp/provision.js +37 -0
  105. package/dist/cloud/gcp/provision.js.map +1 -0
  106. package/dist/cloud/gcp/teardown.d.ts +12 -0
  107. package/dist/cloud/gcp/teardown.d.ts.map +1 -0
  108. package/dist/cloud/gcp/teardown.js +67 -0
  109. package/dist/cloud/gcp/teardown.js.map +1 -0
  110. package/dist/cloud/image-builder.d.ts.map +1 -1
  111. package/dist/cloud/image-builder.js +115 -18
  112. package/dist/cloud/image-builder.js.map +1 -1
  113. package/dist/cloud/provider.d.ts +57 -0
  114. package/dist/cloud/provider.d.ts.map +1 -0
  115. package/dist/cloud/provider.js +21 -0
  116. package/dist/cloud/provider.js.map +1 -0
  117. package/dist/cloud/scheduler-image.d.ts.map +1 -1
  118. package/dist/cloud/scheduler-image.js +16 -3
  119. package/dist/cloud/scheduler-image.js.map +1 -1
  120. package/dist/cloud/state.d.ts +17 -0
  121. package/dist/cloud/state.d.ts.map +1 -0
  122. package/dist/cloud/state.js +48 -0
  123. package/dist/cloud/state.js.map +1 -0
  124. package/dist/docker/aws-shared.d.ts +6 -4
  125. package/dist/docker/aws-shared.d.ts.map +1 -1
  126. package/dist/docker/aws-shared.js +405 -23
  127. package/dist/docker/aws-shared.js.map +1 -1
  128. package/dist/docker/cloud-run-runtime.d.ts.map +1 -1
  129. package/dist/docker/cloud-run-runtime.js +10 -9
  130. package/dist/docker/cloud-run-runtime.js.map +1 -1
  131. package/dist/docker/ecs-runtime.d.ts +3 -1
  132. package/dist/docker/ecs-runtime.d.ts.map +1 -1
  133. package/dist/docker/ecs-runtime.js +78 -29
  134. package/dist/docker/ecs-runtime.js.map +1 -1
  135. package/dist/docker/image.d.ts +7 -0
  136. package/dist/docker/image.d.ts.map +1 -1
  137. package/dist/docker/image.js +31 -4
  138. package/dist/docker/image.js.map +1 -1
  139. package/dist/docker/lambda-runtime.js +1 -1
  140. package/dist/docker/lambda-runtime.js.map +1 -1
  141. package/dist/docker/local-runtime.js +4 -4
  142. package/dist/docker/local-runtime.js.map +1 -1
  143. package/dist/docker/network.d.ts.map +1 -1
  144. package/dist/docker/network.js +2 -2
  145. package/dist/docker/network.js.map +1 -1
  146. package/dist/docker/runtime.d.ts +23 -0
  147. package/dist/docker/runtime.d.ts.map +1 -1
  148. package/dist/gateway/api-key.d.ts +10 -0
  149. package/dist/gateway/api-key.d.ts.map +1 -0
  150. package/dist/gateway/api-key.js +19 -0
  151. package/dist/gateway/api-key.js.map +1 -0
  152. package/dist/gateway/auth.d.ts +16 -0
  153. package/dist/gateway/auth.d.ts.map +1 -0
  154. package/dist/gateway/auth.js +60 -0
  155. package/dist/gateway/auth.js.map +1 -0
  156. package/dist/gateway/index.d.ts +1 -0
  157. package/dist/gateway/index.d.ts.map +1 -1
  158. package/dist/gateway/index.js +33 -2
  159. package/dist/gateway/index.js.map +1 -1
  160. package/dist/gateway/routes/control.d.ts +6 -0
  161. package/dist/gateway/routes/control.d.ts.map +1 -1
  162. package/dist/gateway/routes/control.js +117 -0
  163. package/dist/gateway/routes/control.js.map +1 -1
  164. package/dist/gateway/routes/dashboard.d.ts +1 -1
  165. package/dist/gateway/routes/dashboard.d.ts.map +1 -1
  166. package/dist/gateway/routes/dashboard.js +144 -53
  167. package/dist/gateway/routes/dashboard.js.map +1 -1
  168. package/dist/gateway/views/dashboard-page.d.ts.map +1 -1
  169. package/dist/gateway/views/dashboard-page.js +93 -20
  170. package/dist/gateway/views/dashboard-page.js.map +1 -1
  171. package/dist/gateway/views/login-page.d.ts +2 -0
  172. package/dist/gateway/views/login-page.d.ts.map +1 -0
  173. package/dist/gateway/views/login-page.js +54 -0
  174. package/dist/gateway/views/login-page.js.map +1 -0
  175. package/dist/scheduler/index.d.ts.map +1 -1
  176. package/dist/scheduler/index.js +154 -36
  177. package/dist/scheduler/index.js.map +1 -1
  178. package/dist/scheduler/runner-pool.d.ts +5 -0
  179. package/dist/scheduler/runner-pool.d.ts.map +1 -1
  180. package/dist/scheduler/runner-pool.js +14 -0
  181. package/dist/scheduler/runner-pool.js.map +1 -1
  182. package/dist/scheduler/runtime-factory.d.ts +2 -0
  183. package/dist/scheduler/runtime-factory.d.ts.map +1 -1
  184. package/dist/scheduler/runtime-factory.js +35 -65
  185. package/dist/scheduler/runtime-factory.js.map +1 -1
  186. package/dist/setup/scaffold.d.ts.map +1 -1
  187. package/dist/setup/scaffold.js +25 -0
  188. package/dist/setup/scaffold.js.map +1 -1
  189. package/dist/shared/asm-backend.d.ts.map +1 -1
  190. package/dist/shared/asm-backend.js +2 -2
  191. package/dist/shared/asm-backend.js.map +1 -1
  192. package/dist/shared/config.d.ts +28 -13
  193. package/dist/shared/config.d.ts.map +1 -1
  194. package/dist/shared/config.js +40 -4
  195. package/dist/shared/config.js.map +1 -1
  196. package/dist/shared/constants.d.ts +34 -0
  197. package/dist/shared/constants.d.ts.map +1 -0
  198. package/dist/shared/constants.js +34 -0
  199. package/dist/shared/constants.js.map +1 -0
  200. package/dist/shared/credential-backend.d.ts +1 -1
  201. package/dist/shared/filesystem-backend.d.ts +1 -1
  202. package/dist/shared/filesystem-backend.js +1 -1
  203. package/dist/shared/gsm-backend.d.ts.map +1 -1
  204. package/dist/shared/gsm-backend.js +2 -2
  205. package/dist/shared/gsm-backend.js.map +1 -1
  206. package/dist/shared/paths.d.ts +2 -0
  207. package/dist/shared/paths.d.ts.map +1 -1
  208. package/dist/shared/paths.js +3 -1
  209. package/dist/shared/paths.js.map +1 -1
  210. package/dist/shared/remote.d.ts +1 -0
  211. package/dist/shared/remote.d.ts.map +1 -1
  212. package/dist/shared/remote.js +4 -16
  213. package/dist/shared/remote.js.map +1 -1
  214. package/dist/shared/usage.d.ts +22 -0
  215. package/dist/shared/usage.d.ts.map +1 -0
  216. package/dist/shared/usage.js +43 -0
  217. package/dist/shared/usage.js.map +1 -0
  218. package/dist/telemetry/index.d.ts +57 -0
  219. package/dist/telemetry/index.d.ts.map +1 -0
  220. package/dist/telemetry/index.js +189 -0
  221. package/dist/telemetry/index.js.map +1 -0
  222. package/dist/telemetry/providers/otel.d.ts +15 -0
  223. package/dist/telemetry/providers/otel.d.ts.map +1 -0
  224. package/dist/telemetry/providers/otel.js +77 -0
  225. package/dist/telemetry/providers/otel.js.map +1 -0
  226. package/dist/telemetry/providers/xray.d.ts +13 -0
  227. package/dist/telemetry/providers/xray.d.ts.map +1 -0
  228. package/dist/telemetry/providers/xray.js +33 -0
  229. package/dist/telemetry/providers/xray.js.map +1 -0
  230. package/dist/telemetry/types.d.ts +59 -0
  231. package/dist/telemetry/types.d.ts.map +1 -0
  232. package/dist/telemetry/types.js +2 -0
  233. package/dist/telemetry/types.js.map +1 -0
  234. package/dist/tui/App.d.ts.map +1 -1
  235. package/dist/tui/App.js +2 -0
  236. package/dist/tui/App.js.map +1 -1
  237. package/dist/tui/plain-logger.d.ts.map +1 -1
  238. package/dist/tui/plain-logger.js +8 -2
  239. package/dist/tui/plain-logger.js.map +1 -1
  240. package/dist/tui/status-tracker.d.ts +4 -1
  241. package/dist/tui/status-tracker.d.ts.map +1 -1
  242. package/dist/tui/status-tracker.js +11 -1
  243. package/dist/tui/status-tracker.js.map +1 -1
  244. package/docker/adot-collector-config.yaml +57 -0
  245. package/package.json +9 -1
  246. package/dist/cli/commands/cloud-iam.d.ts +0 -17
  247. package/dist/cli/commands/cloud-iam.d.ts.map +0 -1
  248. package/dist/cli/commands/cloud-iam.js.map +0 -1
  249. package/dist/cli/commands/cloud-setup-ecs.d.ts +0 -9
  250. package/dist/cli/commands/cloud-setup-ecs.d.ts.map +0 -1
  251. package/dist/cli/commands/cloud-setup-ecs.js.map +0 -1
  252. package/dist/cloud/deploy-apprunner.d.ts.map +0 -1
  253. package/dist/cloud/deploy-apprunner.js.map +0 -1
  254. package/dist/cloud/deploy-cloudrun.d.ts.map +0 -1
  255. package/dist/cloud/deploy-cloudrun.js.map +0 -1
  256. package/dist/shared/aws-constants.d.ts.map +0 -1
  257. package/dist/shared/aws-constants.js.map +0 -1
@@ -41,30 +41,44 @@ function formatScale(agent) {
41
41
  function renderAgentRow(agent) {
42
42
  const color = stateColor(agent.state);
43
43
  const statusText = agent.statusText || agent.lastError || "\u2014";
44
- return `<tr>
44
+ const toggleLabel = agent.enabled ? "Disable" : "Enable";
45
+ const toggleAction = agent.enabled ? "disable" : "enable";
46
+ return `<tr data-agent="${escapeHtml(agent.name)}">
45
47
  <td><a href="/dashboard/agents/${escapeHtml(agent.name)}/logs">${escapeHtml(agent.name)}</a></td>
46
48
  <td><span class="state-dot" style="background:${color}"></span> ${escapeHtml(formatScale(agent))}</td>
47
49
  <td class="status-text">${escapeHtml(statusText)}</td>
48
50
  <td>${formatTime(agent.lastRunAt)}</td>
49
51
  <td>${agent.lastRunDuration != null ? formatDuration(agent.lastRunDuration) : "\u2014"}</td>
50
52
  <td>${formatTime(agent.nextRunAt)}</td>
53
+ <td class="actions">
54
+ <button class="btn btn-sm" onclick="triggerAgent('${escapeHtml(agent.name)}')">Run</button>
55
+ <button class="btn btn-sm btn-outline" onclick="toggleAgent('${escapeHtml(agent.name)}','${toggleAction}')">${toggleLabel}</button>
56
+ </td>
51
57
  </tr>`;
52
58
  }
53
59
  function renderAgentCard(agent) {
54
60
  const color = stateColor(agent.state);
55
61
  const statusText = agent.statusText || agent.lastError || "\u2014";
56
- return `<a href="/dashboard/agents/${escapeHtml(agent.name)}/logs" class="agent-card">
57
- <div class="card-header">
58
- <span class="card-name">${escapeHtml(agent.name)}</span>
59
- <span><span class="state-dot" style="background:${color}"></span>${escapeHtml(formatScale(agent))}</span>
62
+ const toggleLabel = agent.enabled ? "Disable" : "Enable";
63
+ const toggleAction = agent.enabled ? "disable" : "enable";
64
+ return `<div class="agent-card">
65
+ <a href="/dashboard/agents/${escapeHtml(agent.name)}/logs" class="card-link">
66
+ <div class="card-header">
67
+ <span class="card-name">${escapeHtml(agent.name)}</span>
68
+ <span><span class="state-dot" style="background:${color}"></span>${escapeHtml(formatScale(agent))}</span>
69
+ </div>
70
+ <div class="card-status">${escapeHtml(statusText)}</div>
71
+ <div class="card-meta">
72
+ <span>Last: ${formatTime(agent.lastRunAt)}</span>
73
+ <span>${agent.lastRunDuration != null ? formatDuration(agent.lastRunDuration) : ""}</span>
74
+ <span>Next: ${formatTime(agent.nextRunAt)}</span>
75
+ </div>
76
+ </a>
77
+ <div class="card-actions">
78
+ <button class="btn btn-sm" onclick="triggerAgent('${escapeHtml(agent.name)}')">Run</button>
79
+ <button class="btn btn-sm btn-outline" onclick="toggleAgent('${escapeHtml(agent.name)}','${toggleAction}')">${toggleLabel}</button>
60
80
  </div>
61
- <div class="card-status">${escapeHtml(statusText)}</div>
62
- <div class="card-meta">
63
- <span>Last: ${formatTime(agent.lastRunAt)}</span>
64
- <span>${agent.lastRunDuration != null ? formatDuration(agent.lastRunDuration) : ""}</span>
65
- <span>Next: ${formatTime(agent.nextRunAt)}</span>
66
- </div>
67
- </a>`;
81
+ </div>`;
68
82
  }
69
83
  export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
70
84
  const mode = schedulerInfo?.mode || "host";
@@ -113,6 +127,21 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
113
127
  .log-agent { color: #818cf8; }
114
128
  .empty { color: #475569; font-style: italic; }
115
129
 
130
+ .btn { background: #334155; color: #e2e8f0; border: 1px solid #475569; border-radius: 4px; padding: 4px 10px; font-size: 0.75rem; cursor: pointer; transition: background 0.15s; }
131
+ .btn:hover { background: #475569; }
132
+ .btn-sm { padding: 3px 8px; font-size: 0.7rem; }
133
+ .btn-outline { background: transparent; }
134
+ .btn-outline:hover { background: #1e293b; }
135
+ .btn-primary { background: #3b82f6; border-color: #3b82f6; color: #fff; }
136
+ .btn-primary:hover { background: #2563eb; }
137
+ .actions { white-space: nowrap; }
138
+ .actions button { margin-right: 4px; }
139
+ .card-actions { display: flex; gap: 6px; margin-top: 8px; }
140
+ .card-link { display: block; text-decoration: none; color: #e2e8f0; }
141
+ .header-actions { display: flex; gap: 8px; align-items: center; margin-left: auto; }
142
+ .header-actions a { color: #94a3b8; font-size: 0.85rem; text-decoration: none; }
143
+ .header-actions a:hover { color: #e2e8f0; }
144
+
116
145
  @media (max-width: 640px) {
117
146
  body { padding: 12px; }
118
147
  h1 { font-size: 1.25rem; }
@@ -138,6 +167,10 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
138
167
  <span class="header-stat">Cron: <strong>${cronCount}</strong></span>
139
168
  <span class="header-stat">Webhooks: <strong>${escapeHtml(webhooks)}</strong></span>
140
169
  <span class="header-stat">Uptime: <strong id="uptime">${escapeHtml(uptime)}</strong></span>
170
+ <span class="header-actions">
171
+ <button id="pause-btn" class="btn btn-sm" onclick="togglePause()">${schedulerInfo?.paused ? "Resume" : "Pause"}</button>
172
+ <a href="#" onclick="doLogout(); return false;">Logout</a>
173
+ </span>
141
174
  </div>
142
175
 
143
176
  <table class="agent-table">
@@ -149,10 +182,11 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
149
182
  <th>Last Run</th>
150
183
  <th>Duration</th>
151
184
  <th>Next Run</th>
185
+ <th>Actions</th>
152
186
  </tr>
153
187
  </thead>
154
188
  <tbody id="agent-table-body">
155
- ${agents.length > 0 ? agents.map(renderAgentRow).join("\n ") : '<tr><td colspan="6" class="empty">No agents registered</td></tr>'}
189
+ ${agents.length > 0 ? agents.map(renderAgentRow).join("\n ") : '<tr><td colspan="7" class="empty">No agents registered</td></tr>'}
156
190
  </tbody>
157
191
  </table>
158
192
 
@@ -191,26 +225,34 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
191
225
  function renderRow(a) {
192
226
  const color = stateColors[a.state] || "#6b7280";
193
227
  const status = a.statusText || a.lastError || "\\u2014";
194
- return '<tr>' +
228
+ const toggleLabel = a.enabled ? "Disable" : "Enable";
229
+ const toggleAction = a.enabled ? "disable" : "enable";
230
+ return '<tr data-agent="' + esc(a.name) + '">' +
195
231
  '<td><a href="/dashboard/agents/' + esc(a.name) + '/logs">' + esc(a.name) + '</a></td>' +
196
232
  '<td><span class="state-dot" style="background:' + color + '"></span> ' + esc(fmtScale(a)) + '</td>' +
197
233
  '<td class="status-text">' + esc(status) + '</td>' +
198
234
  '<td>' + fmtTime(a.lastRunAt) + '</td>' +
199
235
  '<td>' + (a.lastRunDuration != null ? fmtDur(a.lastRunDuration) : "\\u2014") + '</td>' +
200
236
  '<td>' + fmtTime(a.nextRunAt) + '</td>' +
237
+ '<td class="actions"><button class="btn btn-sm" onclick="triggerAgent(\\'' + esc(a.name) + '\\')">Run</button>' +
238
+ '<button class="btn btn-sm btn-outline" onclick="toggleAgent(\\'' + esc(a.name) + '\\',\\'' + toggleAction + '\\')">' + toggleLabel + '</button></td>' +
201
239
  '</tr>';
202
240
  }
203
241
 
204
242
  function renderCard(a) {
205
243
  const color = stateColors[a.state] || "#6b7280";
206
244
  const status = a.statusText || a.lastError || "\\u2014";
207
- return '<a href="/dashboard/agents/' + esc(a.name) + '/logs" class="agent-card">' +
245
+ const toggleLabel = a.enabled ? "Disable" : "Enable";
246
+ const toggleAction = a.enabled ? "disable" : "enable";
247
+ return '<div class="agent-card"><a href="/dashboard/agents/' + esc(a.name) + '/logs" class="card-link">' +
208
248
  '<div class="card-header"><span class="card-name">' + esc(a.name) + '</span>' +
209
249
  '<span><span class="state-dot" style="background:' + color + '"></span>' + esc(fmtScale(a)) + '</span></div>' +
210
250
  '<div class="card-status">' + esc(status) + '</div>' +
211
251
  '<div class="card-meta"><span>Last: ' + fmtTime(a.lastRunAt) + '</span>' +
212
252
  '<span>' + (a.lastRunDuration != null ? fmtDur(a.lastRunDuration) : "") + '</span>' +
213
- '<span>Next: ' + fmtTime(a.nextRunAt) + '</span></div></a>';
253
+ '<span>Next: ' + fmtTime(a.nextRunAt) + '</span></div></a>' +
254
+ '<div class="card-actions"><button class="btn btn-sm" onclick="triggerAgent(\\'' + esc(a.name) + '\\')">Run</button>' +
255
+ '<button class="btn btn-sm btn-outline" onclick="toggleAgent(\\'' + esc(a.name) + '\\',\\'' + toggleAction + '\\')">' + toggleLabel + '</button></div></div>';
214
256
  }
215
257
 
216
258
  function renderLog(l) {
@@ -228,7 +270,7 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
228
270
  if (data.agents.length > 0) {
229
271
  tbody.innerHTML = data.agents.map(renderRow).join("");
230
272
  } else {
231
- tbody.innerHTML = '<tr><td colspan="6" class="empty">No agents registered</td></tr>';
273
+ tbody.innerHTML = '<tr><td colspan="7" class="empty">No agents registered</td></tr>';
232
274
  }
233
275
 
234
276
  // Update mobile cards
@@ -247,11 +289,42 @@ export function renderDashboardPage(agents, schedulerInfo, recentLogs) {
247
289
  logsDiv.scrollTop = logsDiv.scrollHeight;
248
290
  }
249
291
 
250
- // Update uptime
251
- if (data.schedulerInfo && data.schedulerInfo.startedAt) {
252
- document.getElementById("uptime").textContent = fmtDur(Date.now() - new Date(data.schedulerInfo.startedAt).getTime());
292
+ // Update uptime and pause button
293
+ if (data.schedulerInfo) {
294
+ if (data.schedulerInfo.startedAt) {
295
+ document.getElementById("uptime").textContent = fmtDur(Date.now() - new Date(data.schedulerInfo.startedAt).getTime());
296
+ }
297
+ var btn = document.getElementById("pause-btn");
298
+ if (btn) {
299
+ schedulerPaused = !!data.schedulerInfo.paused;
300
+ btn.textContent = schedulerPaused ? "Resume" : "Pause";
301
+ }
253
302
  }
254
303
  };
304
+
305
+ var schedulerPaused = ${schedulerInfo?.paused ? "true" : "false"};
306
+
307
+ function ctrlPost(path) {
308
+ return fetch(path, { method: "POST", credentials: "same-origin" }).then(function(r) { return r.json(); });
309
+ }
310
+
311
+ function triggerAgent(name) {
312
+ ctrlPost("/control/trigger/" + encodeURIComponent(name));
313
+ }
314
+
315
+ function toggleAgent(name, action) {
316
+ ctrlPost("/control/agents/" + encodeURIComponent(name) + "/" + action);
317
+ }
318
+
319
+ function togglePause() {
320
+ ctrlPost(schedulerPaused ? "/control/resume" : "/control/pause");
321
+ }
322
+
323
+ function doLogout() {
324
+ fetch("/logout", { method: "POST", credentials: "same-origin" }).then(function() {
325
+ window.location.href = "/login";
326
+ });
327
+ }
255
328
  </script>
256
329
  </body>
257
330
  </html>`;
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../../../src/gateway/views/dashboard-page.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../../../src/gateway/views/dashboard-page.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,UAAU,CAAC,KAA2B;IAC7C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;QACjC,KAAK,UAAU,CAAC,CAAC,OAAO,SAAS,CAAC;QAClC,KAAK,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;QAC/B,KAAK,MAAM,CAAC,CAAC,OAAO,SAAS,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,EAAU;IAChC,IAAI,EAAE,GAAG,IAAI;QAAE,OAAO,GAAG,EAAE,IAAI,CAAC;IAChC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;AAC5B,CAAC;AAED,SAAS,UAAU,CAAC,IAAiB;IACnC,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC3B,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,aAAa,CAAC,GAAY;IACjC,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,CAAC;IAChD,OAAO,0BAA0B,UAAU,CAAC,IAAI,CAAC,oCAAoC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;AAClJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAkB;IACrC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;QAAE,OAAO,WAAW,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;IACxG,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,CAAC,KAAK,GAAG,CAAC;IACpE,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC;AAED,SAAS,cAAc,CAAC,KAAkB;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC;IACnE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1D,OAAO,mBAAmB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;qCACb,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;oDACvC,KAAK,aAAa,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;8BACtE,UAAU,CAAC,UAAU,CAAC;UAC1C,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;UAC3B,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ;UAChF,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;;0DAEqB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;qEACX,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,YAAY,OAAO,WAAW;;QAEvH,CAAC;AACT,CAAC;AAED,SAAS,eAAe,CAAC,KAAkB;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC;IACnE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1D,OAAO;iCACwB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;;kCAErB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;0DACE,KAAK,YAAY,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;;iCAExE,UAAU,CAAC,UAAU,CAAC;;sBAEjC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;gBACjC,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE;sBACpE,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;;;;0DAIS,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;qEACX,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,YAAY,OAAO,WAAW;;SAEtH,CAAC;AACV,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAqB,EAAE,aAAmC,EAAE,UAAqB;IACnH,MAAM,IAAI,GAAG,aAAa,EAAE,IAAI,IAAI,MAAM,CAAC;IAC3C,MAAM,OAAO,GAAG,aAAa,EAAE,OAAO,IAAI,QAAQ,CAAC;IACnD,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzG,MAAM,SAAS,GAAG,aAAa,EAAE,YAAY,IAAI,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAEvE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CA2EqC,UAAU,CAAC,IAAI,CAAC;iDACb,UAAU,CAAC,OAAO,CAAC;gDACpB,MAAM,CAAC,MAAM;8CACf,SAAS;kDACL,UAAU,CAAC,QAAQ,CAAC;4DACV,UAAU,CAAC,MAAM,CAAC;;0EAEJ,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;;;;;;;;;;;;;;;;;QAkB5G,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,kEAAkE;;;;;MAKtI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,+CAA+C;;;;;MAKhH,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,yBAAyB,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,6CAA6C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA0GzI,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;QAyB5D,CAAC;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function renderLoginPage(error?: string): string;
2
+ //# sourceMappingURL=login-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-page.d.ts","sourceRoot":"","sources":["../../../src/gateway/views/login-page.ts"],"names":[],"mappings":"AAQA,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CA8CtD"}
@@ -0,0 +1,54 @@
1
+ function escapeHtml(str) {
2
+ return str
3
+ .replace(/&/g, "&amp;")
4
+ .replace(/</g, "&lt;")
5
+ .replace(/>/g, "&gt;")
6
+ .replace(/"/g, "&quot;");
7
+ }
8
+ export function renderLoginPage(error) {
9
+ const errorHtml = error
10
+ ? `<div class="error">${escapeHtml(error)}</div>`
11
+ : "";
12
+ return `<!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta charset="utf-8">
16
+ <meta name="viewport" content="width=device-width, initial-scale=1">
17
+ <title>Login \u2014 Action Llama</title>
18
+ <style>
19
+ * { margin: 0; padding: 0; box-sizing: border-box; }
20
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; background: #0f172a; color: #e2e8f0; display: flex; align-items: center; justify-content: center; min-height: 100vh; }
21
+ .login-box { background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 32px; width: 100%; max-width: 380px; margin: 16px; }
22
+ h1 { font-size: 1.4rem; margin-bottom: 8px; color: #f8fafc; text-align: center; }
23
+ .subtitle { color: #94a3b8; font-size: 0.85rem; text-align: center; margin-bottom: 24px; }
24
+ label { display: block; font-size: 0.85rem; color: #94a3b8; margin-bottom: 6px; }
25
+ input[type="password"] {
26
+ width: 100%; padding: 10px 12px; background: #0f172a; border: 1px solid #334155; border-radius: 6px;
27
+ color: #e2e8f0; font-size: 0.95rem; outline: none; transition: border-color 0.15s;
28
+ }
29
+ input[type="password"]:focus { border-color: #60a5fa; }
30
+ button {
31
+ width: 100%; padding: 10px; margin-top: 16px; background: #3b82f6; color: #fff; border: none;
32
+ border-radius: 6px; font-size: 0.95rem; font-weight: 500; cursor: pointer; transition: background 0.15s;
33
+ }
34
+ button:hover { background: #2563eb; }
35
+ .error { background: #7f1d1d40; border: 1px solid #ef4444; border-radius: 6px; padding: 8px 12px; margin-bottom: 16px; font-size: 0.85rem; color: #fca5a5; text-align: center; }
36
+ .hint { color: #64748b; font-size: 0.75rem; text-align: center; margin-top: 16px; }
37
+ </style>
38
+ </head>
39
+ <body>
40
+ <div class="login-box">
41
+ <h1>Action Llama</h1>
42
+ <div class="subtitle">Enter your API key to access the dashboard</div>
43
+ ${errorHtml}
44
+ <form method="POST" action="/login">
45
+ <label for="key">API Key</label>
46
+ <input type="password" id="key" name="key" placeholder="Paste your gateway API key" autofocus required>
47
+ <button type="submit">Log in</button>
48
+ </form>
49
+ <div class="hint">Key is stored at ~/.action-llama/credentials/gateway_api_key/default/key</div>
50
+ </div>
51
+ </body>
52
+ </html>`;
53
+ }
54
+ //# sourceMappingURL=login-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-page.js","sourceRoot":"","sources":["../../../src/gateway/views/login-page.ts"],"names":[],"mappings":"AAAA,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,SAAS,GAAG,KAAK;QACrB,CAAC,CAAC,sBAAsB,UAAU,CAAC,KAAK,CAAC,QAAQ;QACjD,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA+BH,SAAS;;;;;;;;;QASP,CAAC;AACT,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,OAAO,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAmJ/D,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO;;;;;;;GAyY3L"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,OAAO,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAmM/D,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO;;;;;;;GAke3L"}
@@ -3,12 +3,15 @@ import { loadGlobalConfig, loadAgentConfig, discoverAgents, validateAgentConfig
3
3
  import { requireCredentialRef } from "../shared/credentials.js";
4
4
  import { createLogger, createFileOnlyLogger } from "../shared/logger.js";
5
5
  import { buildScheduledPrompt, buildWebhookPrompt, buildCalledPrompt, buildScheduledSuffix, buildWebhookSuffix, buildCalledSuffix, } from "../agents/prompt.js";
6
- import { AWS_CONSTANTS } from "../shared/aws-constants.js";
6
+ import { CONSTANTS } from "../shared/constants.js";
7
7
  import { ConfigError } from "../shared/errors.js";
8
8
  import { WorkQueue } from "./event-queue.js";
9
9
  import { RunnerPool } from "./runner-pool.js";
10
10
  import { createContainerRuntime, buildAgentImages } from "./runtime-factory.js";
11
11
  import { resolveWebhookSource, buildFilterFromTrigger, setupWebhookRegistry } from "./webhook-setup.js";
12
+ import { initTelemetry, withSpan } from "../telemetry/index.js";
13
+ import { SpanKind } from "@opentelemetry/api";
14
+ import { ensureGatewayApiKey } from "../gateway/api-key.js";
12
15
  const DEFAULT_MAX_RERUNS = 10;
13
16
  const DEFAULT_MAX_TRIGGER_DEPTH = 3;
14
17
  // Prompt helpers: when images have baked-in static files, only pass the dynamic suffix.
@@ -55,14 +58,28 @@ function dispatchTriggers(triggers, sourceAgent, depth, ctx) {
55
58
  }
56
59
  }
57
60
  async function runTriggered(runner, agentConfig, prompt, sourceAgent, depth, ctx) {
58
- const { result, triggers } = await runner.run(prompt, { type: 'agent', source: sourceAgent });
59
- if (triggers.length > 0) {
60
- dispatchTriggers(triggers, agentConfig.name, depth, ctx);
61
- }
62
- // No reruns for triggered runs — they respond to a specific event
63
- if (result === "completed") {
64
- ctx.logger.info(`${agentConfig.name} triggered run completed`);
65
- }
61
+ await withSpan("scheduler.run_triggered", async (span) => {
62
+ span.setAttributes({
63
+ "agent.name": agentConfig.name,
64
+ "agent.trigger_type": "agent",
65
+ "agent.source_agent": sourceAgent,
66
+ "agent.model_provider": agentConfig.model?.provider,
67
+ "agent.model_name": agentConfig.model?.model,
68
+ "execution.depth": depth,
69
+ });
70
+ const { result, triggers } = await runner.run(prompt, { type: 'agent', source: sourceAgent });
71
+ if (triggers.length > 0) {
72
+ dispatchTriggers(triggers, agentConfig.name, depth, ctx);
73
+ }
74
+ span.setAttributes({
75
+ "execution.result": result,
76
+ "execution.triggers_fired": triggers.length,
77
+ });
78
+ // No reruns for triggered runs — they respond to a specific event
79
+ if (result === "completed") {
80
+ ctx.logger.info(`${agentConfig.name} triggered run completed`);
81
+ }
82
+ }, {}, SpanKind.INTERNAL);
66
83
  }
67
84
  async function drainWebhookQueue(agentConfig, ctx) {
68
85
  const pool = ctx.runnerPools[agentConfig.name];
@@ -89,30 +106,57 @@ async function drainWebhookQueue(agentConfig, ctx) {
89
106
  }
90
107
  }
91
108
  async function runWithReruns(runner, agentConfig, depth, ctx) {
92
- let { result, triggers } = await runner.run(makeScheduledPrompt(agentConfig, ctx), { type: 'schedule' });
93
- if (triggers.length > 0) {
94
- dispatchTriggers(triggers, agentConfig.name, depth, ctx);
95
- }
96
- let reruns = 0;
97
- while (result === "rerun" && reruns < ctx.maxReruns) {
98
- reruns++;
99
- ctx.logger.info({ rerun: reruns, maxReruns: ctx.maxReruns }, `${agentConfig.name} requested rerun, re-running immediately`);
100
- ({ result, triggers } = await runner.run(makeScheduledPrompt(agentConfig, ctx), { type: 'schedule', source: `rerun ${reruns}/${ctx.maxReruns}` }));
109
+ await withSpan("scheduler.run_with_reruns", async (span) => {
110
+ span.setAttributes({
111
+ "agent.name": agentConfig.name,
112
+ "agent.trigger_type": "schedule",
113
+ "agent.model_provider": agentConfig.model?.provider,
114
+ "agent.model_name": agentConfig.model?.model,
115
+ "execution.max_reruns": ctx.maxReruns,
116
+ });
117
+ let { result, triggers } = await runner.run(makeScheduledPrompt(agentConfig, ctx), { type: 'schedule' });
101
118
  if (triggers.length > 0) {
102
119
  dispatchTriggers(triggers, agentConfig.name, depth, ctx);
103
120
  }
104
- }
105
- if (result === "rerun" && reruns >= ctx.maxReruns) {
106
- ctx.logger.warn({ maxReruns: ctx.maxReruns }, `${agentConfig.name} hit max reruns limit`);
107
- }
108
- // Drain any webhook events that arrived during the rerun cycle
109
- await drainWebhookQueue(agentConfig, ctx);
121
+ let reruns = 0;
122
+ while (result === "rerun" && reruns < ctx.maxReruns) {
123
+ reruns++;
124
+ ctx.logger.info({ rerun: reruns, maxReruns: ctx.maxReruns }, `${agentConfig.name} requested rerun, re-running immediately`);
125
+ ({ result, triggers } = await runner.run(makeScheduledPrompt(agentConfig, ctx), { type: 'schedule', source: `rerun ${reruns}/${ctx.maxReruns}` }));
126
+ if (triggers.length > 0) {
127
+ dispatchTriggers(triggers, agentConfig.name, depth, ctx);
128
+ }
129
+ }
130
+ span.setAttributes({
131
+ "execution.reruns": reruns,
132
+ "execution.result": result,
133
+ "execution.triggers_fired": triggers.length,
134
+ });
135
+ if (result === "rerun" && reruns >= ctx.maxReruns) {
136
+ ctx.logger.warn({ maxReruns: ctx.maxReruns }, `${agentConfig.name} hit max reruns limit`);
137
+ span.setAttribute("execution.max_reruns_reached", true);
138
+ }
139
+ // Drain any webhook events that arrived during the rerun cycle
140
+ await drainWebhookQueue(agentConfig, ctx);
141
+ }, {}, SpanKind.INTERNAL);
110
142
  }
111
143
  export async function startScheduler(projectPath, globalConfigOverride, statusTracker, cloudMode, gatewayEnabled, webUI) {
112
144
  const mkLogger = statusTracker ? createFileOnlyLogger : createLogger;
113
145
  const logger = mkLogger(projectPath, "scheduler");
114
146
  logger.info("Starting scheduler...");
115
147
  const globalConfig = globalConfigOverride || loadGlobalConfig(projectPath);
148
+ // Initialize telemetry if enabled
149
+ let telemetry;
150
+ if (globalConfig.telemetry?.enabled) {
151
+ try {
152
+ telemetry = initTelemetry(globalConfig.telemetry);
153
+ await telemetry.init();
154
+ logger.info("Telemetry initialized successfully");
155
+ }
156
+ catch (error) {
157
+ logger.warn({ error: error.message }, "Failed to initialize telemetry");
158
+ }
159
+ }
116
160
  // Discover all agents in the project
117
161
  const agentNames = discoverAgents(projectPath);
118
162
  if (agentNames.length === 0) {
@@ -129,17 +173,18 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
129
173
  for (const credRef of allCredentials) {
130
174
  await requireCredentialRef(credRef);
131
175
  }
132
- // Validate ECS IAM roles exist if using cloud ECS mode
133
- if (cloudMode && globalConfig.cloud?.provider === "ecs") {
134
- logger.info("Validating ECS IAM task roles...");
135
- const { validateEcsRoles } = await import("../cli/commands/doctor.js");
176
+ // Validate IAM roles exist if using cloud mode
177
+ if (cloudMode && globalConfig.cloud) {
178
+ logger.info("Validating cloud IAM roles...");
179
+ const { createCloudProvider } = await import("../cloud/provider.js");
136
180
  try {
137
- await validateEcsRoles(projectPath, globalConfig.cloud);
138
- logger.info("All ECS IAM task roles validated successfully");
181
+ const provider = await createCloudProvider(globalConfig.cloud);
182
+ await provider.validateRoles(projectPath);
183
+ logger.info("All cloud IAM roles validated successfully");
139
184
  }
140
185
  catch (err) {
141
- logger.error("ECS IAM role validation failed");
142
- throw new Error(`❌ ECS IAM role validation failed\n\n` +
186
+ logger.error("Cloud IAM role validation failed");
187
+ throw new Error(`❌ Cloud IAM role validation failed\n\n` +
143
188
  `${err.message}\n\n` +
144
189
  `This validation prevents runtime failures when agents try to start.\n` +
145
190
  `Fix the IAM roles before starting the scheduler.`);
@@ -171,7 +216,7 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
171
216
  const { registry: webhookRegistry, secrets: webhookSecrets } = anyWebhooks
172
217
  ? await setupWebhookRegistry(globalConfig, logger)
173
218
  : { registry: undefined, secrets: {} };
174
- let baseImage = AWS_CONSTANTS.DEFAULT_IMAGE;
219
+ let baseImage = CONSTANTS.DEFAULT_IMAGE;
175
220
  const agentImages = {};
176
221
  const useCloudRuntime = cloudMode && globalConfig.cloud;
177
222
  // Register agents early so the TUI shows them during image builds
@@ -189,6 +234,11 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
189
234
  // Start gateway early if needed (before Docker builds) so users can see build status
190
235
  let gateway;
191
236
  if (gatewayEnabled) {
237
+ // Ensure gateway API key exists (fallback generation if doctor wasn't run)
238
+ const { key: gatewayApiKey, generated } = await ensureGatewayApiKey();
239
+ if (generated) {
240
+ logger.info("Generated gateway API key (run 'al doctor' to view it)");
241
+ }
192
242
  const { startGateway } = await import("../gateway/index.js");
193
243
  const gatewayPort = globalConfig.gateway?.port || 8080;
194
244
  gateway = await startGateway({
@@ -202,6 +252,7 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
202
252
  projectPath,
203
253
  webUI: cloudMode ? false : webUI,
204
254
  lockTimeout: globalConfig.gateway?.lockTimeout,
255
+ apiKey: gatewayApiKey,
205
256
  // Control routes, dashboard, and lock status are local-only.
206
257
  // In cloud mode, use cloud-native tools (console, CLI) for these operations.
207
258
  controlDeps: cloudMode ? undefined : {
@@ -213,6 +264,14 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
213
264
  }
214
265
  return false;
215
266
  },
267
+ killAgent: async (name) => {
268
+ const pool = runnerPools[name];
269
+ if (!pool)
270
+ return null;
271
+ const killed = pool.killAll();
272
+ logger.info({ agent: name, killed }, "kill all instances requested via control API");
273
+ return { killed };
274
+ },
216
275
  pauseScheduler: async () => {
217
276
  for (const job of cronJobs) {
218
277
  job.pause();
@@ -227,6 +286,40 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
227
286
  statusTracker?.setPaused(false);
228
287
  logger.info("Scheduler resumed via control API");
229
288
  },
289
+ triggerAgent: async (name) => {
290
+ const pool = runnerPools[name];
291
+ if (!pool)
292
+ return false;
293
+ const runner = pool.getAvailableRunner();
294
+ if (!runner)
295
+ return false;
296
+ const config = agentConfigs.find((a) => a.name === name);
297
+ if (!config)
298
+ return false;
299
+ logger.info({ agent: name }, "manual trigger via control API");
300
+ runWithReruns(runner, config, 0, schedulerCtx).catch((err) => {
301
+ logger.error({ err, agent: name }, "manual trigger run failed");
302
+ });
303
+ return true;
304
+ },
305
+ enableAgent: async (name) => {
306
+ if (!statusTracker)
307
+ return false;
308
+ const config = agentConfigs.find((a) => a.name === name);
309
+ if (!config)
310
+ return false;
311
+ statusTracker.enableAgent(name);
312
+ return true;
313
+ },
314
+ disableAgent: async (name) => {
315
+ if (!statusTracker)
316
+ return false;
317
+ const config = agentConfigs.find((a) => a.name === name);
318
+ if (!config)
319
+ return false;
320
+ statusTracker.disableAgent(name);
321
+ return true;
322
+ },
230
323
  },
231
324
  });
232
325
  logger.info({ port: gatewayPort }, "Gateway started early to show build progress");
@@ -310,13 +403,28 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
310
403
  }
311
404
  logger.info({ agent: agentConfig.name, event: context.event, action: context.action, running: pool.runningJobCount, scale: pool.size }, "webhook triggering agent");
312
405
  const prompt = makeWebhookPrompt(agentConfig, context, schedulerCtx);
313
- availableRunner.run(prompt, { type: 'webhook', source: context.event }).then(({ triggers }) => {
406
+ withSpan("scheduler.webhook_trigger", async (span) => {
407
+ span.setAttributes({
408
+ "agent.name": agentConfig.name,
409
+ "agent.trigger_type": "webhook",
410
+ "webhook.event": context.event,
411
+ "webhook.action": context.action || "",
412
+ "webhook.source": trigger.source,
413
+ "agent.model_provider": agentConfig.model?.provider,
414
+ "agent.model_name": agentConfig.model?.model,
415
+ "execution.pool_running": pool.runningJobCount,
416
+ "execution.pool_scale": pool.size,
417
+ });
418
+ const { triggers } = await availableRunner.run(prompt, { type: 'webhook', source: context.event });
419
+ span.setAttributes({
420
+ "execution.triggers_fired": triggers.length,
421
+ });
314
422
  if (triggers.length > 0) {
315
423
  dispatchTriggers(triggers, agentConfig.name, 0, schedulerCtx);
316
424
  }
317
425
  // Drain any events that queued while this webhook run was executing
318
- return drainWebhookQueue(agentConfig, schedulerCtx);
319
- }).catch((err) => {
426
+ await drainWebhookQueue(agentConfig, schedulerCtx);
427
+ }, {}, SpanKind.INTERNAL).catch((err) => {
320
428
  logger.error({ err }, `${agentConfig.name} webhook run failed`);
321
429
  });
322
430
  },
@@ -421,6 +529,16 @@ export async function startScheduler(projectPath, globalConfigOverride, statusTr
421
529
  await gateway.close();
422
530
  logger.info("Gateway server stopped");
423
531
  }
532
+ // Shutdown telemetry
533
+ if (telemetry) {
534
+ try {
535
+ await telemetry.shutdown();
536
+ logger.info("Telemetry shutdown completed");
537
+ }
538
+ catch (error) {
539
+ logger.warn({ error: error.message }, "Error during telemetry shutdown");
540
+ }
541
+ }
424
542
  logger.info("All cron jobs stopped");
425
543
  process.exit(0);
426
544
  };