@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.
- package/AGENTS.md +17 -6
- package/README.md +8 -4
- package/dist/agents/container-entry.d.ts.map +1 -1
- package/dist/agents/container-entry.js +37 -0
- package/dist/agents/container-entry.js.map +1 -1
- package/dist/agents/container-runner.d.ts +4 -0
- package/dist/agents/container-runner.d.ts.map +1 -1
- package/dist/agents/container-runner.js +82 -5
- package/dist/agents/container-runner.js.map +1 -1
- package/dist/agents/execution-engine.d.ts +2 -0
- package/dist/agents/execution-engine.d.ts.map +1 -1
- package/dist/agents/execution-engine.js +5 -1
- package/dist/agents/execution-engine.js.map +1 -1
- package/dist/agents/runner.d.ts +3 -0
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js +45 -2
- package/dist/agents/runner.js.map +1 -1
- package/dist/cli/commands/chat.d.ts +5 -2
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +240 -23
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/commands/cloud-deploy.d.ts.map +1 -1
- package/dist/cli/commands/cloud-deploy.js +5 -47
- package/dist/cli/commands/cloud-deploy.js.map +1 -1
- package/dist/cli/commands/cloud-setup.d.ts.map +1 -1
- package/dist/cli/commands/cloud-setup.js +20 -33
- package/dist/cli/commands/cloud-setup.js.map +1 -1
- package/dist/cli/commands/cloud-teardown.d.ts.map +1 -1
- package/dist/cli/commands/cloud-teardown.js +6 -126
- package/dist/cli/commands/cloud-teardown.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +0 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +19 -14
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/kill.d.ts +1 -1
- package/dist/cli/commands/kill.d.ts.map +1 -1
- package/dist/cli/commands/kill.js +17 -6
- package/dist/cli/commands/kill.js.map +1 -1
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/commands/logs.js +104 -58
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/pause.d.ts +1 -1
- package/dist/cli/commands/pause.d.ts.map +1 -1
- package/dist/cli/commands/pause.js +9 -6
- package/dist/cli/commands/pause.js.map +1 -1
- package/dist/cli/commands/resume.d.ts +1 -1
- package/dist/cli/commands/resume.d.ts.map +1 -1
- package/dist/cli/commands/resume.js +9 -6
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +12 -54
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +22 -39
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/gateway-client.d.ts +12 -0
- package/dist/cli/gateway-client.d.ts.map +1 -0
- package/dist/cli/gateway-client.js +27 -0
- package/dist/cli/gateway-client.js.map +1 -0
- package/dist/cli/main.js +49 -14
- package/dist/cli/main.js.map +1 -1
- package/dist/{shared/aws-constants.d.ts → cloud/aws/constants.d.ts} +3 -34
- package/dist/cloud/aws/constants.d.ts.map +1 -0
- package/dist/{shared/aws-constants.js → cloud/aws/constants.js} +3 -34
- package/dist/cloud/aws/constants.js.map +1 -0
- package/dist/cloud/{deploy-apprunner.d.ts → aws/deploy.d.ts} +6 -6
- package/dist/cloud/aws/deploy.d.ts.map +1 -0
- package/dist/cloud/{deploy-apprunner.js → aws/deploy.js} +2 -2
- package/dist/cloud/aws/deploy.js.map +1 -0
- package/dist/cloud/aws/iam.d.ts +37 -0
- package/dist/cloud/aws/iam.d.ts.map +1 -0
- package/dist/{cli/commands/cloud-iam.js → cloud/aws/iam.js} +30 -179
- package/dist/cloud/aws/iam.js.map +1 -0
- package/dist/cloud/aws/provider.d.ts +69 -0
- package/dist/cloud/aws/provider.d.ts.map +1 -0
- package/dist/cloud/aws/provider.js +173 -0
- package/dist/cloud/aws/provider.js.map +1 -0
- package/dist/cloud/aws/provision.d.ts +9 -0
- package/dist/cloud/aws/provision.d.ts.map +1 -0
- package/dist/{cli/commands/cloud-setup-ecs.js → cloud/aws/provision.js} +10 -9
- package/dist/cloud/aws/provision.js.map +1 -0
- package/dist/cloud/aws/teardown.d.ts +15 -0
- package/dist/cloud/aws/teardown.d.ts.map +1 -0
- package/dist/cloud/aws/teardown.js +74 -0
- package/dist/cloud/aws/teardown.js.map +1 -0
- package/dist/cloud/gcp/constants.d.ts +16 -0
- package/dist/cloud/gcp/constants.d.ts.map +1 -0
- package/dist/cloud/gcp/constants.js +16 -0
- package/dist/cloud/gcp/constants.js.map +1 -0
- package/dist/cloud/{deploy-cloudrun.d.ts → gcp/deploy.d.ts} +6 -6
- package/dist/cloud/gcp/deploy.d.ts.map +1 -0
- package/dist/cloud/{deploy-cloudrun.js → gcp/deploy.js} +7 -7
- package/dist/cloud/gcp/deploy.js.map +1 -0
- package/dist/cloud/gcp/iam.d.ts +20 -0
- package/dist/cloud/gcp/iam.d.ts.map +1 -0
- package/dist/cloud/gcp/iam.js +179 -0
- package/dist/cloud/gcp/iam.js.map +1 -0
- package/dist/cloud/gcp/provider.d.ts +28 -0
- package/dist/cloud/gcp/provider.d.ts.map +1 -0
- package/dist/cloud/gcp/provider.js +84 -0
- package/dist/cloud/gcp/provider.js.map +1 -0
- package/dist/cloud/gcp/provision.d.ts +14 -0
- package/dist/cloud/gcp/provision.d.ts.map +1 -0
- package/dist/cloud/gcp/provision.js +37 -0
- package/dist/cloud/gcp/provision.js.map +1 -0
- package/dist/cloud/gcp/teardown.d.ts +12 -0
- package/dist/cloud/gcp/teardown.d.ts.map +1 -0
- package/dist/cloud/gcp/teardown.js +67 -0
- package/dist/cloud/gcp/teardown.js.map +1 -0
- package/dist/cloud/image-builder.d.ts.map +1 -1
- package/dist/cloud/image-builder.js +115 -18
- package/dist/cloud/image-builder.js.map +1 -1
- package/dist/cloud/provider.d.ts +57 -0
- package/dist/cloud/provider.d.ts.map +1 -0
- package/dist/cloud/provider.js +21 -0
- package/dist/cloud/provider.js.map +1 -0
- package/dist/cloud/scheduler-image.d.ts.map +1 -1
- package/dist/cloud/scheduler-image.js +16 -3
- package/dist/cloud/scheduler-image.js.map +1 -1
- package/dist/cloud/state.d.ts +17 -0
- package/dist/cloud/state.d.ts.map +1 -0
- package/dist/cloud/state.js +48 -0
- package/dist/cloud/state.js.map +1 -0
- package/dist/docker/aws-shared.d.ts +6 -4
- package/dist/docker/aws-shared.d.ts.map +1 -1
- package/dist/docker/aws-shared.js +405 -23
- package/dist/docker/aws-shared.js.map +1 -1
- package/dist/docker/cloud-run-runtime.d.ts.map +1 -1
- package/dist/docker/cloud-run-runtime.js +10 -9
- package/dist/docker/cloud-run-runtime.js.map +1 -1
- package/dist/docker/ecs-runtime.d.ts +3 -1
- package/dist/docker/ecs-runtime.d.ts.map +1 -1
- package/dist/docker/ecs-runtime.js +78 -29
- package/dist/docker/ecs-runtime.js.map +1 -1
- package/dist/docker/image.d.ts +7 -0
- package/dist/docker/image.d.ts.map +1 -1
- package/dist/docker/image.js +31 -4
- package/dist/docker/image.js.map +1 -1
- package/dist/docker/lambda-runtime.js +1 -1
- package/dist/docker/lambda-runtime.js.map +1 -1
- package/dist/docker/local-runtime.js +4 -4
- package/dist/docker/local-runtime.js.map +1 -1
- package/dist/docker/network.d.ts.map +1 -1
- package/dist/docker/network.js +2 -2
- package/dist/docker/network.js.map +1 -1
- package/dist/docker/runtime.d.ts +23 -0
- package/dist/docker/runtime.d.ts.map +1 -1
- package/dist/gateway/api-key.d.ts +10 -0
- package/dist/gateway/api-key.d.ts.map +1 -0
- package/dist/gateway/api-key.js +19 -0
- package/dist/gateway/api-key.js.map +1 -0
- package/dist/gateway/auth.d.ts +16 -0
- package/dist/gateway/auth.d.ts.map +1 -0
- package/dist/gateway/auth.js +60 -0
- package/dist/gateway/auth.js.map +1 -0
- package/dist/gateway/index.d.ts +1 -0
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +33 -2
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/routes/control.d.ts +6 -0
- package/dist/gateway/routes/control.d.ts.map +1 -1
- package/dist/gateway/routes/control.js +117 -0
- package/dist/gateway/routes/control.js.map +1 -1
- package/dist/gateway/routes/dashboard.d.ts +1 -1
- package/dist/gateway/routes/dashboard.d.ts.map +1 -1
- package/dist/gateway/routes/dashboard.js +144 -53
- package/dist/gateway/routes/dashboard.js.map +1 -1
- package/dist/gateway/views/dashboard-page.d.ts.map +1 -1
- package/dist/gateway/views/dashboard-page.js +93 -20
- package/dist/gateway/views/dashboard-page.js.map +1 -1
- package/dist/gateway/views/login-page.d.ts +2 -0
- package/dist/gateway/views/login-page.d.ts.map +1 -0
- package/dist/gateway/views/login-page.js +54 -0
- package/dist/gateway/views/login-page.js.map +1 -0
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +154 -36
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/runner-pool.d.ts +5 -0
- package/dist/scheduler/runner-pool.d.ts.map +1 -1
- package/dist/scheduler/runner-pool.js +14 -0
- package/dist/scheduler/runner-pool.js.map +1 -1
- package/dist/scheduler/runtime-factory.d.ts +2 -0
- package/dist/scheduler/runtime-factory.d.ts.map +1 -1
- package/dist/scheduler/runtime-factory.js +35 -65
- package/dist/scheduler/runtime-factory.js.map +1 -1
- package/dist/setup/scaffold.d.ts.map +1 -1
- package/dist/setup/scaffold.js +25 -0
- package/dist/setup/scaffold.js.map +1 -1
- package/dist/shared/asm-backend.d.ts.map +1 -1
- package/dist/shared/asm-backend.js +2 -2
- package/dist/shared/asm-backend.js.map +1 -1
- package/dist/shared/config.d.ts +28 -13
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +40 -4
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/constants.d.ts +34 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +34 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/credential-backend.d.ts +1 -1
- package/dist/shared/filesystem-backend.d.ts +1 -1
- package/dist/shared/filesystem-backend.js +1 -1
- package/dist/shared/gsm-backend.d.ts.map +1 -1
- package/dist/shared/gsm-backend.js +2 -2
- package/dist/shared/gsm-backend.js.map +1 -1
- package/dist/shared/paths.d.ts +2 -0
- package/dist/shared/paths.d.ts.map +1 -1
- package/dist/shared/paths.js +3 -1
- package/dist/shared/paths.js.map +1 -1
- package/dist/shared/remote.d.ts +1 -0
- package/dist/shared/remote.d.ts.map +1 -1
- package/dist/shared/remote.js +4 -16
- package/dist/shared/remote.js.map +1 -1
- package/dist/shared/usage.d.ts +22 -0
- package/dist/shared/usage.d.ts.map +1 -0
- package/dist/shared/usage.js +43 -0
- package/dist/shared/usage.js.map +1 -0
- package/dist/telemetry/index.d.ts +57 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +189 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/providers/otel.d.ts +15 -0
- package/dist/telemetry/providers/otel.d.ts.map +1 -0
- package/dist/telemetry/providers/otel.js +77 -0
- package/dist/telemetry/providers/otel.js.map +1 -0
- package/dist/telemetry/providers/xray.d.ts +13 -0
- package/dist/telemetry/providers/xray.d.ts.map +1 -0
- package/dist/telemetry/providers/xray.js +33 -0
- package/dist/telemetry/providers/xray.js.map +1 -0
- package/dist/telemetry/types.d.ts +59 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +2 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +2 -0
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/plain-logger.d.ts.map +1 -1
- package/dist/tui/plain-logger.js +8 -2
- package/dist/tui/plain-logger.js.map +1 -1
- package/dist/tui/status-tracker.d.ts +4 -1
- package/dist/tui/status-tracker.d.ts.map +1 -1
- package/dist/tui/status-tracker.js +11 -1
- package/dist/tui/status-tracker.js.map +1 -1
- package/docker/adot-collector-config.yaml +57 -0
- package/package.json +9 -1
- package/dist/cli/commands/cloud-iam.d.ts +0 -17
- package/dist/cli/commands/cloud-iam.d.ts.map +0 -1
- package/dist/cli/commands/cloud-iam.js.map +0 -1
- package/dist/cli/commands/cloud-setup-ecs.d.ts +0 -9
- package/dist/cli/commands/cloud-setup-ecs.d.ts.map +0 -1
- package/dist/cli/commands/cloud-setup-ecs.js.map +0 -1
- package/dist/cloud/deploy-apprunner.d.ts.map +0 -1
- package/dist/cloud/deploy-apprunner.js.map +0 -1
- package/dist/cloud/deploy-cloudrun.d.ts.map +0 -1
- package/dist/cloud/deploy-cloudrun.js.map +0 -1
- package/dist/shared/aws-constants.d.ts.map +0 -1
- 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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
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="
|
|
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
|
|
252
|
-
|
|
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":"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,OAAO;
|
|
1
|
+
{"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../../../src/gateway/views/dashboard-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -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, "&")
|
|
4
|
+
.replace(/</g, "<")
|
|
5
|
+
.replace(/>/g, ">")
|
|
6
|
+
.replace(/"/g, """);
|
|
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;
|
|
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"}
|
package/dist/scheduler/index.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
133
|
-
if (cloudMode && globalConfig.cloud
|
|
134
|
-
logger.info("Validating
|
|
135
|
-
const {
|
|
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
|
|
138
|
-
|
|
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("
|
|
142
|
-
throw new Error(`❌
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
};
|