@sensigo/realm-cli 0.1.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/README.md +109 -0
- package/dist/agent/agent-utils.d.ts +27 -0
- package/dist/agent/agent-utils.d.ts.map +1 -0
- package/dist/agent/agent-utils.js +79 -0
- package/dist/agent/agent-utils.js.map +1 -0
- package/dist/agent/anthropic-provider.d.ts +23 -0
- package/dist/agent/anthropic-provider.d.ts.map +1 -0
- package/dist/agent/anthropic-provider.js +245 -0
- package/dist/agent/anthropic-provider.js.map +1 -0
- package/dist/agent/gate/slack-gate-notifier.d.ts +80 -0
- package/dist/agent/gate/slack-gate-notifier.d.ts.map +1 -0
- package/dist/agent/gate/slack-gate-notifier.js +315 -0
- package/dist/agent/gate/slack-gate-notifier.js.map +1 -0
- package/dist/agent/gate/slack-gate-server.d.ts +30 -0
- package/dist/agent/gate/slack-gate-server.d.ts.map +1 -0
- package/dist/agent/gate/slack-gate-server.js +99 -0
- package/dist/agent/gate/slack-gate-server.js.map +1 -0
- package/dist/agent/gate/slack-socket-client.d.ts +20 -0
- package/dist/agent/gate/slack-socket-client.d.ts.map +1 -0
- package/dist/agent/gate/slack-socket-client.js +141 -0
- package/dist/agent/gate/slack-socket-client.js.map +1 -0
- package/dist/agent/gate-intent-interpreter.d.ts +29 -0
- package/dist/agent/gate-intent-interpreter.d.ts.map +1 -0
- package/dist/agent/gate-intent-interpreter.js +33 -0
- package/dist/agent/gate-intent-interpreter.js.map +1 -0
- package/dist/agent/index.d.ts +4 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +4 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/llm-provider.d.ts +46 -0
- package/dist/agent/llm-provider.d.ts.map +1 -0
- package/dist/agent/llm-provider.js +55 -0
- package/dist/agent/llm-provider.js.map +1 -0
- package/dist/agent/mcp/mcp-client.d.ts +18 -0
- package/dist/agent/mcp/mcp-client.d.ts.map +1 -0
- package/dist/agent/mcp/mcp-client.js +108 -0
- package/dist/agent/mcp/mcp-client.js.map +1 -0
- package/dist/agent/mcp/mcp-extensions.d.ts +40 -0
- package/dist/agent/mcp/mcp-extensions.d.ts.map +1 -0
- package/dist/agent/mcp/mcp-extensions.js +2 -0
- package/dist/agent/mcp/mcp-extensions.js.map +1 -0
- package/dist/agent/mcp-client.d.ts +18 -0
- package/dist/agent/mcp-client.d.ts.map +1 -0
- package/dist/agent/mcp-client.js +108 -0
- package/dist/agent/mcp-client.js.map +1 -0
- package/dist/agent/mcp-types.d.ts +40 -0
- package/dist/agent/mcp-types.d.ts.map +1 -0
- package/dist/agent/mcp-types.js +2 -0
- package/dist/agent/mcp-types.js.map +1 -0
- package/dist/agent/openai-provider.d.ts +30 -0
- package/dist/agent/openai-provider.d.ts.map +1 -0
- package/dist/agent/openai-provider.js +253 -0
- package/dist/agent/openai-provider.js.map +1 -0
- package/dist/agent/openai-reasoning-provider.d.ts +18 -0
- package/dist/agent/openai-reasoning-provider.d.ts.map +1 -0
- package/dist/agent/openai-reasoning-provider.js +76 -0
- package/dist/agent/openai-reasoning-provider.js.map +1 -0
- package/dist/agent/preflight.d.ts +36 -0
- package/dist/agent/preflight.d.ts.map +1 -0
- package/dist/agent/preflight.js +81 -0
- package/dist/agent/preflight.js.map +1 -0
- package/dist/agent/providers/agent-utils.d.ts +27 -0
- package/dist/agent/providers/agent-utils.d.ts.map +1 -0
- package/dist/agent/providers/agent-utils.js +79 -0
- package/dist/agent/providers/agent-utils.js.map +1 -0
- package/dist/agent/providers/anthropic-provider.d.ts +23 -0
- package/dist/agent/providers/anthropic-provider.d.ts.map +1 -0
- package/dist/agent/providers/anthropic-provider.js +257 -0
- package/dist/agent/providers/anthropic-provider.js.map +1 -0
- package/dist/agent/providers/llm-provider.d.ts +46 -0
- package/dist/agent/providers/llm-provider.d.ts.map +1 -0
- package/dist/agent/providers/llm-provider.js +56 -0
- package/dist/agent/providers/llm-provider.js.map +1 -0
- package/dist/agent/providers/openai-provider.d.ts +30 -0
- package/dist/agent/providers/openai-provider.d.ts.map +1 -0
- package/dist/agent/providers/openai-provider.js +253 -0
- package/dist/agent/providers/openai-provider.js.map +1 -0
- package/dist/agent/providers/openai-reasoning-provider.d.ts +19 -0
- package/dist/agent/providers/openai-reasoning-provider.d.ts.map +1 -0
- package/dist/agent/providers/openai-reasoning-provider.js +89 -0
- package/dist/agent/providers/openai-reasoning-provider.js.map +1 -0
- package/dist/agent/run-agent.d.ts +50 -0
- package/dist/agent/run-agent.d.ts.map +1 -0
- package/dist/agent/run-agent.js +327 -0
- package/dist/agent/run-agent.js.map +1 -0
- package/dist/agent/slack-gate-notifier.d.ts +80 -0
- package/dist/agent/slack-gate-notifier.d.ts.map +1 -0
- package/dist/agent/slack-gate-notifier.js +315 -0
- package/dist/agent/slack-gate-notifier.js.map +1 -0
- package/dist/agent/slack-gate-poller.d.ts +28 -0
- package/dist/agent/slack-gate-poller.d.ts.map +1 -0
- package/dist/agent/slack-gate-poller.js +66 -0
- package/dist/agent/slack-gate-poller.js.map +1 -0
- package/dist/agent/slack-gate-server.d.ts +30 -0
- package/dist/agent/slack-gate-server.d.ts.map +1 -0
- package/dist/agent/slack-gate-server.js +99 -0
- package/dist/agent/slack-gate-server.js.map +1 -0
- package/dist/agent/slack-socket-client.d.ts +20 -0
- package/dist/agent/slack-socket-client.d.ts.map +1 -0
- package/dist/agent/slack-socket-client.js +141 -0
- package/dist/agent/slack-socket-client.js.map +1 -0
- package/dist/commands/agent.d.ts +3 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +183 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/cleanup.d.ts +16 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +79 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/diff.d.ts +41 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +203 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +97 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect.d.ts +14 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +224 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/list.d.ts +18 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +88 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/mcp.d.ts +8 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +22 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +42 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/register.d.ts +6 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +51 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/replay-format.d.ts +3 -0
- package/dist/commands/replay-format.d.ts.map +1 -0
- package/dist/commands/replay-format.js +10 -0
- package/dist/commands/replay-format.js.map +1 -0
- package/dist/commands/replay.d.ts +38 -0
- package/dist/commands/replay.d.ts.map +1 -0
- package/dist/commands/replay.js +173 -0
- package/dist/commands/replay.js.map +1 -0
- package/dist/commands/respond.d.ts +20 -0
- package/dist/commands/respond.d.ts.map +1 -0
- package/dist/commands/respond.js +49 -0
- package/dist/commands/respond.js.map +1 -0
- package/dist/commands/resume.d.ts +15 -0
- package/dist/commands/resume.d.ts.map +1 -0
- package/dist/commands/resume.js +63 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +127 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/serve.d.ts +33 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +144 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/test.d.ts +12 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +58 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +35 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/watch.d.ts +18 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +112 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/webhook.d.ts +51 -0
- package/dist/commands/webhook.d.ts.map +1 -0
- package/dist/commands/webhook.js +227 -0
- package/dist/commands/webhook.js.map +1 -0
- package/dist/commands-registry.d.ts +7 -0
- package/dist/commands-registry.d.ts.map +1 -0
- package/dist/commands-registry.js +44 -0
- package/dist/commands-registry.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/store/replay-store.d.ts +29 -0
- package/dist/store/replay-store.d.ts.map +1 -0
- package/dist/store/replay-store.js +31 -0
- package/dist/store/replay-store.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opens a Slack Socket Mode WebSocket connection and begins delivering gate thread events.
|
|
3
|
+
* Handles reconnection transparently on drops or Slack-requested refreshes.
|
|
4
|
+
* Returns a handle to close the connection immediately.
|
|
5
|
+
*/
|
|
6
|
+
export function connectSocketMode(config) {
|
|
7
|
+
const { appToken, threadTs, onEvent, signal } = config;
|
|
8
|
+
let stopped = false;
|
|
9
|
+
let currentWs;
|
|
10
|
+
let backoffMs = 1000;
|
|
11
|
+
const stop = () => {
|
|
12
|
+
stopped = true;
|
|
13
|
+
currentWs?.close();
|
|
14
|
+
};
|
|
15
|
+
const connect = async () => {
|
|
16
|
+
if (stopped || signal?.aborted)
|
|
17
|
+
return;
|
|
18
|
+
// Step 1 — obtain the WebSocket URL from Slack.
|
|
19
|
+
let wsUrl;
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch('https://slack.com/api/apps.connections.open', {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: {
|
|
24
|
+
'Content-Type': 'application/json',
|
|
25
|
+
Authorization: `Bearer ${appToken}`,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const data = (await response.json());
|
|
29
|
+
if (!data.ok || data.url === undefined) {
|
|
30
|
+
const delay = backoffMs;
|
|
31
|
+
backoffMs = Math.min(backoffMs * 2, 30_000);
|
|
32
|
+
console.warn(` ⚠ Socket Mode: apps.connections.open failed (${data.error ?? 'unknown'}) — retrying in ${delay}ms.`);
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
if (!stopped && !signal?.aborted) {
|
|
35
|
+
void connect();
|
|
36
|
+
}
|
|
37
|
+
}, delay);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
wsUrl = data.url;
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const delay = backoffMs;
|
|
44
|
+
backoffMs = Math.min(backoffMs * 2, 30_000);
|
|
45
|
+
console.warn(` ⚠ Socket Mode: failed to obtain WebSocket URL — ${err instanceof Error ? err.message : String(err)}. Retrying in ${delay}ms.`);
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
if (!stopped && !signal?.aborted) {
|
|
48
|
+
void connect();
|
|
49
|
+
}
|
|
50
|
+
}, delay);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (stopped || signal?.aborted)
|
|
54
|
+
return;
|
|
55
|
+
// Step 2 — open the WebSocket connection.
|
|
56
|
+
const ws = new WebSocket(wsUrl);
|
|
57
|
+
currentWs = ws;
|
|
58
|
+
// Tracks deliberate closes (disconnect message) to skip backoff on the close event.
|
|
59
|
+
let intentionalClose = false;
|
|
60
|
+
ws.addEventListener('message', (event) => {
|
|
61
|
+
// A successful message indicates a live connection — reset backoff.
|
|
62
|
+
backoffMs = 1000;
|
|
63
|
+
let msg;
|
|
64
|
+
try {
|
|
65
|
+
msg = JSON.parse(event.data);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const type = msg['type'];
|
|
71
|
+
if (type === 'hello') {
|
|
72
|
+
console.log(' ℹ Socket Mode connected.');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Slack requesting a reconnect — close and reconnect immediately, no backoff.
|
|
76
|
+
if (type === 'disconnect') {
|
|
77
|
+
intentionalClose = true;
|
|
78
|
+
ws.close();
|
|
79
|
+
if (!stopped && !signal?.aborted) {
|
|
80
|
+
void connect();
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (type === 'events_api') {
|
|
85
|
+
const envelopeId = msg['envelope_id'];
|
|
86
|
+
// ACK immediately (within 3 s as required by Slack).
|
|
87
|
+
if (envelopeId !== undefined) {
|
|
88
|
+
ws.send(JSON.stringify({ envelope_id: envelopeId }));
|
|
89
|
+
}
|
|
90
|
+
const payload = msg['payload'];
|
|
91
|
+
if (payload === undefined)
|
|
92
|
+
return;
|
|
93
|
+
const msgEvent = payload['event'];
|
|
94
|
+
if (msgEvent === undefined)
|
|
95
|
+
return;
|
|
96
|
+
// Use envelope_id as the dedup event_id (outer envelope is the authoritative key).
|
|
97
|
+
const eventId = envelopeId ?? payload['event_id'];
|
|
98
|
+
if (!eventId)
|
|
99
|
+
return;
|
|
100
|
+
// Apply all required filters before forwarding to onEvent.
|
|
101
|
+
if (msgEvent['type'] !== 'message')
|
|
102
|
+
return;
|
|
103
|
+
if (msgEvent['bot_id'] !== undefined)
|
|
104
|
+
return;
|
|
105
|
+
if (msgEvent['subtype'] === 'bot_message')
|
|
106
|
+
return;
|
|
107
|
+
if (msgEvent['thread_ts'] !== threadTs)
|
|
108
|
+
return;
|
|
109
|
+
const user = msgEvent['user'];
|
|
110
|
+
if (!user)
|
|
111
|
+
return;
|
|
112
|
+
const text = msgEvent['text'];
|
|
113
|
+
if (!text)
|
|
114
|
+
return;
|
|
115
|
+
const ts = msgEvent['ts'];
|
|
116
|
+
if (!ts)
|
|
117
|
+
return;
|
|
118
|
+
onEvent({ event_id: eventId, thread_ts: threadTs, user, text, ts });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
ws.addEventListener('close', () => {
|
|
122
|
+
if (stopped || signal?.aborted || intentionalClose)
|
|
123
|
+
return;
|
|
124
|
+
// Unexpected close — reconnect with exponential backoff (max 30 s).
|
|
125
|
+
const delay = backoffMs;
|
|
126
|
+
backoffMs = Math.min(backoffMs * 2, 30_000);
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
if (!stopped && !signal?.aborted) {
|
|
129
|
+
void connect();
|
|
130
|
+
}
|
|
131
|
+
}, delay);
|
|
132
|
+
});
|
|
133
|
+
signal?.addEventListener('abort', () => {
|
|
134
|
+
stopped = true;
|
|
135
|
+
ws.close();
|
|
136
|
+
}, { once: true });
|
|
137
|
+
};
|
|
138
|
+
void connect();
|
|
139
|
+
return { close: stop };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=slack-socket-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-socket-client.js","sourceRoot":"","sources":["../../src/agent/slack-socket-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,eAAO,MAAM,YAAY,SA0OtB,CAAC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// realm agent — autonomous CLI command that drives a workflow using an LLM provider.
|
|
2
|
+
// Core loop logic lives in packages/cli/src/agent/run-agent.ts for testability.
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
import { loadWorkflowFromFile, JsonFileStore, JsonWorkflowStore, createDefaultRegistry, GitHubAdapter, SlackAdapter, } from '@sensigo/realm';
|
|
7
|
+
import { LlmProvider, resolveProvider } from '../agent/providers/llm-provider.js';
|
|
8
|
+
import { runAgent } from '../agent/run-agent.js';
|
|
9
|
+
import { createSlackGateHandler } from '../agent/gate/slack-gate-notifier.js';
|
|
10
|
+
import { checkAdapterPrerequisites, formatPreflightError, checkSlackBidirectionalConfig, } from '../agent/preflight.js';
|
|
11
|
+
export const agentCommand = new Command('agent')
|
|
12
|
+
.description('Run a workflow autonomously using an LLM provider')
|
|
13
|
+
.option('--workflow <path>', 'Path to workflow directory or workflow.yaml file')
|
|
14
|
+
.option('--run-id <id>', 'Attach to an existing run instead of creating a new one')
|
|
15
|
+
.option('--params <json>', 'Initial run parameters as JSON string', '{}')
|
|
16
|
+
.option('--provider <provider>', 'LLM provider: openai or anthropic (auto-detected from env)')
|
|
17
|
+
.option('--model <model>', 'Model name override (default: gpt-4o / claude-sonnet-4-5)')
|
|
18
|
+
.option('--base-url <url>', 'Base URL for OpenAI-compatible endpoints (e.g. DeepSeek, Qwen, Groq)')
|
|
19
|
+
.option('--provider-module <path>', 'Path to a custom LlmProvider module (default export must be an instance extending LlmProvider)')
|
|
20
|
+
.option('--register', 'Persist the workflow definition to ~/.realm/workflows/ (same as realm workflow register)')
|
|
21
|
+
.action(async (opts) => {
|
|
22
|
+
if (!opts.workflow && !opts.runId) {
|
|
23
|
+
console.error('Error: one of --workflow or --run-id is required');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
if (opts.workflow && opts.runId) {
|
|
27
|
+
console.error('Error: --workflow and --run-id are mutually exclusive');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (opts.params !== '{}' && opts.runId) {
|
|
31
|
+
console.error('Error: --params cannot be used with --run-id; the run already has params from creation time');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const workflowStore = new JsonWorkflowStore();
|
|
36
|
+
const store = new JsonFileStore();
|
|
37
|
+
let provider;
|
|
38
|
+
if (opts.providerModule !== undefined) {
|
|
39
|
+
if (opts.provider !== undefined ||
|
|
40
|
+
opts.model !== undefined ||
|
|
41
|
+
opts.baseUrl !== undefined) {
|
|
42
|
+
console.error('Error: --provider-module cannot be combined with --provider, --model, or --base-url');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const modulePath = resolve(opts.providerModule);
|
|
46
|
+
const moduleUrl = pathToFileURL(modulePath).href;
|
|
47
|
+
let mod;
|
|
48
|
+
try {
|
|
49
|
+
mod = (await import(moduleUrl));
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.error(`Error: failed to import provider module '${opts.providerModule}': ${err instanceof Error ? err.message : String(err)}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
if (!(mod.default instanceof LlmProvider)) {
|
|
56
|
+
console.error(`Error: provider module default export must be an instance extending LlmProvider.\n` +
|
|
57
|
+
`Import LlmProvider from '@sensigo/realm-cli/agent' and export 'export default new MyProvider()'.`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
provider = mod.default;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
provider = await resolveProvider(opts.provider, opts.model, opts.baseUrl);
|
|
64
|
+
}
|
|
65
|
+
const registry = createDefaultRegistry();
|
|
66
|
+
if (process.env['GITHUB_TOKEN'] !== undefined)
|
|
67
|
+
registry.register('adapter', 'github', new GitHubAdapter('github', { auth: { token: process.env['GITHUB_TOKEN'] } }));
|
|
68
|
+
if (process.env['SLACK_WEBHOOK_URL'] !== undefined)
|
|
69
|
+
registry.register('adapter', 'slack', new SlackAdapter('slack', { webhook_url: process.env['SLACK_WEBHOOK_URL'] }));
|
|
70
|
+
let result;
|
|
71
|
+
if (opts.runId !== undefined) {
|
|
72
|
+
// --run-id path: attach to existing run, load definition from store.
|
|
73
|
+
const runRecord = await store.get(opts.runId);
|
|
74
|
+
const definition = await workflowStore.get(runRecord.workflow_id);
|
|
75
|
+
const hasSlack = process.env['SLACK_BOT_TOKEN'] !== undefined ||
|
|
76
|
+
process.env['SLACK_WEBHOOK_URL'] !== undefined;
|
|
77
|
+
const slackConfig = {
|
|
78
|
+
store,
|
|
79
|
+
definition,
|
|
80
|
+
provider,
|
|
81
|
+
...(process.env['SLACK_WEBHOOK_URL'] !== undefined && {
|
|
82
|
+
webhookUrl: process.env['SLACK_WEBHOOK_URL'],
|
|
83
|
+
}),
|
|
84
|
+
...(process.env['SLACK_BOT_TOKEN'] !== undefined && {
|
|
85
|
+
botToken: process.env['SLACK_BOT_TOKEN'],
|
|
86
|
+
}),
|
|
87
|
+
...(process.env['SLACK_CHANNEL_ID'] !== undefined && {
|
|
88
|
+
channelId: process.env['SLACK_CHANNEL_ID'],
|
|
89
|
+
}),
|
|
90
|
+
...(process.env['SLACK_SIGNING_SECRET'] !== undefined && {
|
|
91
|
+
signingSecret: process.env['SLACK_SIGNING_SECRET'],
|
|
92
|
+
}),
|
|
93
|
+
...(process.env['SLACK_EVENTS_PORT'] !== undefined && {
|
|
94
|
+
eventsPort: parseInt(process.env['SLACK_EVENTS_PORT'], 10),
|
|
95
|
+
}),
|
|
96
|
+
...(process.env['SLACK_APP_TOKEN'] !== undefined && {
|
|
97
|
+
appToken: process.env['SLACK_APP_TOKEN'],
|
|
98
|
+
}),
|
|
99
|
+
...(process.env['SLACK_GATE_REMINDER_INTERVAL_MS'] !== undefined && {
|
|
100
|
+
reminderIntervalMs: parseInt(process.env['SLACK_GATE_REMINDER_INTERVAL_MS'], 10),
|
|
101
|
+
}),
|
|
102
|
+
...(process.env['SLACK_GATE_ESCALATION_THRESHOLD_MS'] !== undefined && {
|
|
103
|
+
escalationThresholdMs: parseInt(process.env['SLACK_GATE_ESCALATION_THRESHOLD_MS'], 10),
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
const gateHandler = hasSlack ? createSlackGateHandler(slackConfig) : undefined;
|
|
107
|
+
result = await runAgent({ store, workflowStore, provider, registry, ...(gateHandler ? { gateHandler } : {}) }, {
|
|
108
|
+
existingRunId: opts.runId,
|
|
109
|
+
definition,
|
|
110
|
+
params: {},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const params = JSON.parse(opts.params);
|
|
115
|
+
// Resolve and load workflow definition before starting a run.
|
|
116
|
+
const inputPath = opts.workflow;
|
|
117
|
+
const filePath = inputPath.endsWith('.yaml') || inputPath.endsWith('.yml')
|
|
118
|
+
? inputPath
|
|
119
|
+
: join(inputPath, 'workflow.yaml');
|
|
120
|
+
const definition = loadWorkflowFromFile(filePath);
|
|
121
|
+
// Fail fast if required adapter env vars are missing.
|
|
122
|
+
const preflightFindings = checkAdapterPrerequisites(definition);
|
|
123
|
+
if (preflightFindings.length > 0) {
|
|
124
|
+
console.error(formatPreflightError(preflightFindings));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
// Print advisory warnings for incomplete Slack bidirectional config.
|
|
128
|
+
const slackWarnings = checkSlackBidirectionalConfig();
|
|
129
|
+
for (const warning of slackWarnings) {
|
|
130
|
+
console.warn(` ⚠ ${warning.message}`);
|
|
131
|
+
}
|
|
132
|
+
const hasSlack2 = process.env['SLACK_BOT_TOKEN'] !== undefined ||
|
|
133
|
+
process.env['SLACK_WEBHOOK_URL'] !== undefined;
|
|
134
|
+
const slackConfig2 = {
|
|
135
|
+
store,
|
|
136
|
+
definition,
|
|
137
|
+
provider,
|
|
138
|
+
...(process.env['SLACK_WEBHOOK_URL'] !== undefined && {
|
|
139
|
+
webhookUrl: process.env['SLACK_WEBHOOK_URL'],
|
|
140
|
+
}),
|
|
141
|
+
...(process.env['SLACK_BOT_TOKEN'] !== undefined && {
|
|
142
|
+
botToken: process.env['SLACK_BOT_TOKEN'],
|
|
143
|
+
}),
|
|
144
|
+
...(process.env['SLACK_CHANNEL_ID'] !== undefined && {
|
|
145
|
+
channelId: process.env['SLACK_CHANNEL_ID'],
|
|
146
|
+
}),
|
|
147
|
+
...(process.env['SLACK_SIGNING_SECRET'] !== undefined && {
|
|
148
|
+
signingSecret: process.env['SLACK_SIGNING_SECRET'],
|
|
149
|
+
}),
|
|
150
|
+
...(process.env['SLACK_EVENTS_PORT'] !== undefined && {
|
|
151
|
+
eventsPort: parseInt(process.env['SLACK_EVENTS_PORT'], 10),
|
|
152
|
+
}),
|
|
153
|
+
...(process.env['SLACK_APP_TOKEN'] !== undefined && {
|
|
154
|
+
appToken: process.env['SLACK_APP_TOKEN'],
|
|
155
|
+
}),
|
|
156
|
+
...(process.env['SLACK_GATE_REMINDER_INTERVAL_MS'] !== undefined && {
|
|
157
|
+
reminderIntervalMs: parseInt(process.env['SLACK_GATE_REMINDER_INTERVAL_MS'], 10),
|
|
158
|
+
}),
|
|
159
|
+
...(process.env['SLACK_GATE_ESCALATION_THRESHOLD_MS'] !== undefined && {
|
|
160
|
+
escalationThresholdMs: parseInt(process.env['SLACK_GATE_ESCALATION_THRESHOLD_MS'], 10),
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
163
|
+
const gateHandler2 = hasSlack2 ? createSlackGateHandler(slackConfig2) : undefined;
|
|
164
|
+
result = await runAgent({
|
|
165
|
+
store,
|
|
166
|
+
workflowStore,
|
|
167
|
+
provider,
|
|
168
|
+
registry,
|
|
169
|
+
...(gateHandler2 ? { gateHandler: gateHandler2 } : {}),
|
|
170
|
+
}, {
|
|
171
|
+
definition,
|
|
172
|
+
params,
|
|
173
|
+
register: opts.register === true,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
process.exit(result === 'completed' ? 0 : 1);
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { RunStore, RunRecord } from '@sensigo/realm';
|
|
3
|
+
/**
|
|
4
|
+
* List all non-terminal runs idle for longer than `olderThan` and mark them abandoned.
|
|
5
|
+
* @param options `olderThan` is a duration string; `dryRun` skips writes.
|
|
6
|
+
* @param runStore Store holding run records.
|
|
7
|
+
* @returns The list of affected runs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function cleanupRuns(options: {
|
|
10
|
+
olderThan: string;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
}, runStore: RunStore): Promise<{
|
|
13
|
+
affected: RunRecord[];
|
|
14
|
+
}>;
|
|
15
|
+
export declare const cleanupCommand: Command;
|
|
16
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAyB1D;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAChD,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CA+BpC;AAED,eAAO,MAAM,cAAc,SAsBvB,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// cleanup command — marks idle non-terminal runs as abandoned.
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { WorkflowError, WAITING_PHASES } from '@sensigo/realm';
|
|
4
|
+
/**
|
|
5
|
+
* Parses a duration string such as "30d", "6h", or "10m" into milliseconds.
|
|
6
|
+
*/
|
|
7
|
+
function parseDuration(s) {
|
|
8
|
+
const match = /^(\d+)(d|h|m)$/.exec(s);
|
|
9
|
+
if (match === null) {
|
|
10
|
+
throw new WorkflowError(`Invalid duration '${s}'. Use format: <number>(d|h|m), e.g. 30d, 6h, 10m`, {
|
|
11
|
+
code: 'VALIDATION_INPUT_SCHEMA',
|
|
12
|
+
category: 'VALIDATION',
|
|
13
|
+
agentAction: 'provide_input',
|
|
14
|
+
retryable: false,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const value = parseInt(match[1], 10);
|
|
18
|
+
const unit = match[2];
|
|
19
|
+
const multipliers = { d: 86_400_000, h: 3_600_000, m: 60_000 };
|
|
20
|
+
return value * multipliers[unit];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* List all non-terminal runs idle for longer than `olderThan` and mark them abandoned.
|
|
24
|
+
* @param options `olderThan` is a duration string; `dryRun` skips writes.
|
|
25
|
+
* @param runStore Store holding run records.
|
|
26
|
+
* @returns The list of affected runs.
|
|
27
|
+
*/
|
|
28
|
+
export async function cleanupRuns(options, runStore) {
|
|
29
|
+
const threshold = parseDuration(options.olderThan);
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
const all = await runStore.list();
|
|
32
|
+
const affected = [];
|
|
33
|
+
for (const run of all) {
|
|
34
|
+
if (run.terminal_state) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (WAITING_PHASES.has(run.run_phase)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const idleMs = now - new Date(run.updated_at).getTime();
|
|
41
|
+
if (idleMs >= threshold) {
|
|
42
|
+
affected.push(run);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!(options.dryRun ?? false)) {
|
|
46
|
+
for (const run of affected) {
|
|
47
|
+
await runStore.update({
|
|
48
|
+
...run,
|
|
49
|
+
run_phase: 'abandoned',
|
|
50
|
+
terminal_state: true,
|
|
51
|
+
terminal_reason: 'Marked abandoned by realm cleanup',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { affected };
|
|
56
|
+
}
|
|
57
|
+
export const cleanupCommand = new Command('cleanup')
|
|
58
|
+
.description('Mark idle non-terminal runs as abandoned')
|
|
59
|
+
.requiredOption('--older-than <duration>', 'Abandon runs idle longer than this duration (e.g. 30d, 6h, 10m)')
|
|
60
|
+
.option('--dry-run', 'Preview which runs would be abandoned without modifying them')
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
const { JsonFileStore } = await import('@sensigo/realm');
|
|
63
|
+
const runStore = new JsonFileStore();
|
|
64
|
+
try {
|
|
65
|
+
const { affected } = await cleanupRuns(opts, runStore);
|
|
66
|
+
const n = affected.length;
|
|
67
|
+
if (opts.dryRun ?? false) {
|
|
68
|
+
console.log(`Would mark ${n} run(s) as abandoned.`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(`Marked ${n} run(s) as abandoned.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { RunRecord } from '@sensigo/realm';
|
|
3
|
+
import type { ReplayRecord } from '../store/replay-store.js';
|
|
4
|
+
/** Returns true when the given ID is a replay ID (starts with "rpl_"). */
|
|
5
|
+
export declare function isReplayId(id: string): boolean;
|
|
6
|
+
export interface ReplayDiffRow {
|
|
7
|
+
step_id: string;
|
|
8
|
+
/** Precondition column for replay A. */
|
|
9
|
+
precond_a: string;
|
|
10
|
+
/** Precondition column for replay B. */
|
|
11
|
+
precond_b: string;
|
|
12
|
+
/** Whether the two replay outcomes differ for this step. */
|
|
13
|
+
differs: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Compares step-level precondition results from two replay records.
|
|
17
|
+
* @param recordA First replay record.
|
|
18
|
+
* @param recordB Second replay record.
|
|
19
|
+
*/
|
|
20
|
+
export declare function diffReplays(recordA: ReplayRecord, recordB: ReplayRecord): ReplayDiffRow[];
|
|
21
|
+
export interface DiffStepRow {
|
|
22
|
+
step_id: string;
|
|
23
|
+
status_a: string;
|
|
24
|
+
status_b: string;
|
|
25
|
+
hash_a: string;
|
|
26
|
+
hash_b: string;
|
|
27
|
+
duration_a_ms: number;
|
|
28
|
+
duration_b_ms: number;
|
|
29
|
+
/** True when both runs have the step and produce the same evidence hash. */
|
|
30
|
+
same_output: boolean;
|
|
31
|
+
/** True when both runs have the same step status (including 'missing'). */
|
|
32
|
+
same_status: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Compares evidence chains of two runs, producing a row per unique step.
|
|
36
|
+
* @param runA First run to compare.
|
|
37
|
+
* @param runB Second run to compare.
|
|
38
|
+
*/
|
|
39
|
+
export declare function diffRuns(runA: RunRecord, runB: RunRecord): DiffStepRow[];
|
|
40
|
+
export declare const diffCommand: Command;
|
|
41
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;CAClB;AAgBD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,GAAG,aAAa,EAAE,CAezF;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB,2EAA2E;IAC3E,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,EAAE,CAqCxE;AAuBD,eAAO,MAAM,WAAW,SAsHpB,CAAC"}
|