@rk0429/agentic-relay 21.2.3 → 22.0.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/dist/application/chat/chat-daemon-service.d.ts +81 -0
- package/dist/application/chat/chat-daemon-service.js +382 -0
- package/dist/application/chat/chat-daemon-service.js.map +1 -0
- package/dist/application/chat/chat-inbound-handler.d.ts +35 -0
- package/dist/application/chat/chat-inbound-handler.js +175 -0
- package/dist/application/chat/chat-inbound-handler.js.map +1 -0
- package/dist/application/chat/chat-logging.d.ts +8 -0
- package/dist/application/chat/chat-logging.js +16 -0
- package/dist/application/chat/chat-logging.js.map +1 -0
- package/dist/application/chat/chat-outbound-handler.d.ts +16 -0
- package/dist/application/chat/chat-outbound-handler.js +190 -0
- package/dist/application/chat/chat-outbound-handler.js.map +1 -0
- package/dist/application/chat/chat-question-service.d.ts +37 -0
- package/dist/application/chat/chat-question-service.js +135 -0
- package/dist/application/chat/chat-question-service.js.map +1 -0
- package/dist/application/chat/chat-setup-service.d.ts +27 -0
- package/dist/application/chat/chat-setup-service.js +183 -0
- package/dist/application/chat/chat-setup-service.js.map +1 -0
- package/dist/application/chat/message-queue-manager.d.ts +13 -0
- package/dist/application/chat/message-queue-manager.js +34 -0
- package/dist/application/chat/message-queue-manager.js.map +1 -0
- package/dist/application/routine-status-query-service.d.ts +17 -0
- package/dist/application/routine-status-query-service.js +111 -0
- package/dist/application/routine-status-query-service.js.map +1 -1
- package/dist/bin/relay.d.ts +9 -2
- package/dist/bin/relay.js +296 -18
- package/dist/bin/relay.js.map +1 -1
- package/dist/core/chat-types.d.ts +18 -0
- package/dist/core/chat-types.js +14 -0
- package/dist/core/chat-types.js.map +1 -0
- package/dist/core/types.d.ts +7 -0
- package/dist/domain/chat/message-cleaner.d.ts +11 -0
- package/dist/domain/chat/message-cleaner.js +45 -0
- package/dist/domain/chat/message-cleaner.js.map +1 -0
- package/dist/domain/chat/message-router.d.ts +8 -0
- package/dist/domain/chat/message-router.js +93 -0
- package/dist/domain/chat/message-router.js.map +1 -0
- package/dist/domain/chat/message-splitter.d.ts +3 -0
- package/dist/domain/chat/message-splitter.js +148 -0
- package/dist/domain/chat/message-splitter.js.map +1 -0
- package/dist/domain/chat/platform-connection.d.ts +31 -0
- package/dist/domain/chat/platform-connection.js +67 -0
- package/dist/domain/chat/platform-connection.js.map +1 -0
- package/dist/domain/chat/ports.d.ts +31 -0
- package/dist/domain/chat/ports.js +2 -0
- package/dist/domain/chat/ports.js.map +1 -0
- package/dist/domain/chat/session-bridge.d.ts +41 -0
- package/dist/domain/chat/session-bridge.js +93 -0
- package/dist/domain/chat/session-bridge.js.map +1 -0
- package/dist/domain/chat/types.d.ts +83 -0
- package/dist/domain/chat/types.js +2 -0
- package/dist/domain/chat/types.js.map +1 -0
- package/dist/domain/chat/user-question.d.ts +33 -0
- package/dist/domain/chat/user-question.js +73 -0
- package/dist/domain/chat/user-question.js.map +1 -0
- package/dist/domain/config.d.ts +3 -1
- package/dist/domain/config.js +9 -0
- package/dist/domain/config.js.map +1 -1
- package/dist/domain/routine-loader.d.ts +2 -0
- package/dist/domain/routine-loader.js +3 -0
- package/dist/domain/routine-loader.js.map +1 -1
- package/dist/infrastructure/chat/adapter-factory.d.ts +5 -0
- package/dist/infrastructure/chat/adapter-factory.js +15 -0
- package/dist/infrastructure/chat/adapter-factory.js.map +1 -0
- package/dist/infrastructure/chat/adapters/discord-adapter.d.ts +23 -0
- package/dist/infrastructure/chat/adapters/discord-adapter.js +199 -0
- package/dist/infrastructure/chat/adapters/discord-adapter.js.map +1 -0
- package/dist/infrastructure/chat/adapters/slack-adapter.d.ts +24 -0
- package/dist/infrastructure/chat/adapters/slack-adapter.js +155 -0
- package/dist/infrastructure/chat/adapters/slack-adapter.js.map +1 -0
- package/dist/infrastructure/chat/agent-gateway-impl.d.ts +21 -0
- package/dist/infrastructure/chat/agent-gateway-impl.js +101 -0
- package/dist/infrastructure/chat/agent-gateway-impl.js.map +1 -0
- package/dist/infrastructure/chat/chat-ipc-client.d.ts +33 -0
- package/dist/infrastructure/chat/chat-ipc-client.js +70 -0
- package/dist/infrastructure/chat/chat-ipc-client.js.map +1 -0
- package/dist/infrastructure/chat/chat-ipc-server.d.ts +19 -0
- package/dist/infrastructure/chat/chat-ipc-server.js +125 -0
- package/dist/infrastructure/chat/chat-ipc-server.js.map +1 -0
- package/dist/infrastructure/chat/chat-logger.d.ts +24 -0
- package/dist/infrastructure/chat/chat-logger.js +86 -0
- package/dist/infrastructure/chat/chat-logger.js.map +1 -0
- package/dist/infrastructure/chat/credentials-repository.d.ts +8 -0
- package/dist/infrastructure/chat/credentials-repository.js +84 -0
- package/dist/infrastructure/chat/credentials-repository.js.map +1 -0
- package/dist/infrastructure/chat/session-bridge-repository.d.ts +13 -0
- package/dist/infrastructure/chat/session-bridge-repository.js +120 -0
- package/dist/infrastructure/chat/session-bridge-repository.js.map +1 -0
- package/dist/infrastructure/chat/token-masking.d.ts +3 -0
- package/dist/infrastructure/chat/token-masking.js +22 -0
- package/dist/infrastructure/chat/token-masking.js.map +1 -0
- package/dist/infrastructure/store/relay-store.js +3 -1
- package/dist/infrastructure/store/relay-store.js.map +1 -1
- package/dist/interfaces/cli/chat-cli.d.ts +34 -0
- package/dist/interfaces/cli/chat-cli.js +68 -0
- package/dist/interfaces/cli/chat-cli.js.map +1 -0
- package/dist/interfaces/cli/relay-cli-args.d.ts +16 -1
- package/dist/interfaces/cli/relay-cli-args.js +135 -2
- package/dist/interfaces/cli/relay-cli-args.js.map +1 -1
- package/dist/interfaces/mcp/chat-tools.d.ts +33 -0
- package/dist/interfaces/mcp/chat-tools.js +129 -0
- package/dist/interfaces/mcp/chat-tools.js.map +1 -0
- package/dist/interfaces/mcp/relay-mcp-server.d.ts +2 -0
- package/dist/interfaces/mcp/relay-mcp-server.js +194 -1
- package/dist/interfaces/mcp/relay-mcp-server.js.map +1 -1
- package/package.json +3 -1
package/dist/bin/relay.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --disable-warning=ExperimentalWarning
|
|
2
|
-
import { fork } from "node:child_process";
|
|
2
|
+
import { execFile, fork } from "node:child_process";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { access, readFile, realpath, rm } from "node:fs/promises";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { promisify } from "node:util";
|
|
10
|
+
import { ChatDaemonService, } from "../application/chat/chat-daemon-service.js";
|
|
11
|
+
import { ChatInboundHandler } from "../application/chat/chat-inbound-handler.js";
|
|
12
|
+
import { ChatOutboundHandler } from "../application/chat/chat-outbound-handler.js";
|
|
13
|
+
import { ChatQuestionService, InMemoryUserQuestionRepository, } from "../application/chat/chat-question-service.js";
|
|
14
|
+
import { ChatSetupService } from "../application/chat/chat-setup-service.js";
|
|
15
|
+
import { MessageQueueManager } from "../application/chat/message-queue-manager.js";
|
|
9
16
|
import { CoreManagementService, } from "../application/core-management-service.js";
|
|
10
17
|
import { LoopEventLogSink } from "../application/event-log-sink.js";
|
|
11
18
|
import { isProcessAlive, reconcileAbandonedRunningTaskSessions, runStartupHousekeeping, } from "../application/housekeeping.js";
|
|
@@ -28,6 +35,12 @@ import { resolveRole } from "../domain/role.js";
|
|
|
28
35
|
import { resolveBackend, validateRoutingRules } from "../domain/routing.js";
|
|
29
36
|
import { loadRoutine } from "../domain/routine-loader.js";
|
|
30
37
|
import { BackendRegistry } from "../infrastructure/backends/backend-registry.js";
|
|
38
|
+
import { AdapterFactory } from "../infrastructure/chat/adapter-factory.js";
|
|
39
|
+
import { AgentGatewayImpl } from "../infrastructure/chat/agent-gateway-impl.js";
|
|
40
|
+
import { ChatIpcServer } from "../infrastructure/chat/chat-ipc-server.js";
|
|
41
|
+
import { ChatLogger } from "../infrastructure/chat/chat-logger.js";
|
|
42
|
+
import { CredentialsFileRepository } from "../infrastructure/chat/credentials-repository.js";
|
|
43
|
+
import { SessionBridgeFileRepository } from "../infrastructure/chat/session-bridge-repository.js";
|
|
31
44
|
import { CommandExecutionGateway } from "../infrastructure/command-execution-gateway.js";
|
|
32
45
|
import { CliBackendExecutor } from "../infrastructure/backends/cli-backend-executor.js";
|
|
33
46
|
import { ChildProcessExecutor, ChildProcessInteractiveRunner, } from "../infrastructure/process/process-executor.js";
|
|
@@ -37,12 +50,28 @@ import { isMissingFileError } from "../infrastructure/store/file-utils.js";
|
|
|
37
50
|
import { RoutineExecutionLeaseRepository } from "../infrastructure/store/routine-execution-lease-repository.js";
|
|
38
51
|
import { RoutineRuntimeProjectionRepository } from "../infrastructure/store/routine-runtime-projection-repository.js";
|
|
39
52
|
import { RoutineStateRepository } from "../infrastructure/store/routine-state-repository.js";
|
|
53
|
+
import { handleChatCommand, } from "../interfaces/cli/chat-cli.js";
|
|
40
54
|
import { parseRelayCliArgs, } from "../interfaces/cli/relay-cli-args.js";
|
|
41
55
|
import { createLoopProgressReporter } from "../interfaces/cli/loop-progress-shell.js";
|
|
42
56
|
import { runRelayInteractiveShell } from "../interfaces/cli/relay-shell.js";
|
|
43
57
|
import { renderVisualization } from "../interfaces/cli/visualization-renderer.js";
|
|
44
58
|
import { createRelayMcpServer, serveRelayMcpServer, } from "../interfaces/mcp/relay-mcp-server.js";
|
|
59
|
+
const execFileAsync = promisify(execFile);
|
|
45
60
|
export const AGENTIC_SETUP_PROMPT = "ワークスペースのエージェント基盤をセットアップしてください。 .agents/skills/agentic-setup/SKILL.md の手順に従って実行してください。";
|
|
61
|
+
export function buildRoutineStatusQueryService(options) {
|
|
62
|
+
return new RoutineStatusQueryService({
|
|
63
|
+
catalogService: new RoutineCatalogService({
|
|
64
|
+
configDir: options.configDir ?? options.store.routinesDir(),
|
|
65
|
+
workflowRepo: options.workflowRepo,
|
|
66
|
+
}),
|
|
67
|
+
stateRepo: new RoutineStateRepository(options.store),
|
|
68
|
+
runtimeRepo: new RoutineRuntimeProjectionRepository(options.store),
|
|
69
|
+
store: options.store,
|
|
70
|
+
leaseRepo: new RoutineExecutionLeaseRepository(options.store),
|
|
71
|
+
loopStateFiles: () => options.store.listLoopStateFiles(),
|
|
72
|
+
deleteLoopState: (filename) => options.store.deleteLoopState(filename),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
46
75
|
async function main() {
|
|
47
76
|
const command = parseRelayCliArgs(process.argv.slice(2));
|
|
48
77
|
const cwd = process.cwd();
|
|
@@ -168,18 +197,62 @@ async function main() {
|
|
|
168
197
|
onRoutineEvent,
|
|
169
198
|
});
|
|
170
199
|
};
|
|
171
|
-
const createRoutineStatusQueryService = ({ configDir }) =>
|
|
172
|
-
catalogService: new RoutineCatalogService({
|
|
173
|
-
configDir,
|
|
174
|
-
workflowRepo,
|
|
175
|
-
}),
|
|
176
|
-
stateRepo: new RoutineStateRepository(store),
|
|
177
|
-
runtimeRepo: new RoutineRuntimeProjectionRepository(store),
|
|
200
|
+
const createRoutineStatusQueryService = ({ configDir }) => buildRoutineStatusQueryService({
|
|
178
201
|
store,
|
|
202
|
+
workflowRepo,
|
|
203
|
+
configDir,
|
|
179
204
|
});
|
|
205
|
+
const createChatSetupService = () => new ChatSetupService({
|
|
206
|
+
credentialsRepository: new CredentialsFileRepository(store.rootDir),
|
|
207
|
+
prompt: promptFromStdin,
|
|
208
|
+
confirm: confirmFromStdin,
|
|
209
|
+
openUrl: openUrlInBrowser,
|
|
210
|
+
logger: (message) => writeLine(process.stderr, message),
|
|
211
|
+
});
|
|
212
|
+
const createChatDaemonService = () => {
|
|
213
|
+
const credentialsRepository = new CredentialsFileRepository(store.rootDir);
|
|
214
|
+
const sessionBridgeRepository = new SessionBridgeFileRepository(store.rootDir);
|
|
215
|
+
const outboundHandler = new ChatOutboundHandler();
|
|
216
|
+
const questionService = new ChatQuestionService({
|
|
217
|
+
userQuestionRepository: new InMemoryUserQuestionRepository(),
|
|
218
|
+
});
|
|
219
|
+
const spawnService = new SpawnAgentsService({
|
|
220
|
+
backendRegistry,
|
|
221
|
+
backendExecutor,
|
|
222
|
+
store,
|
|
223
|
+
taskService,
|
|
224
|
+
cwd,
|
|
225
|
+
env: process.env,
|
|
226
|
+
});
|
|
227
|
+
const inboundHandler = new ChatInboundHandler({
|
|
228
|
+
agentGateway: new AgentGatewayImpl(spawnService, taskService, store, backendRegistry),
|
|
229
|
+
sessionBridgeRepository,
|
|
230
|
+
outboundHandler,
|
|
231
|
+
questionService,
|
|
232
|
+
messageQueueManager: new MessageQueueManager(),
|
|
233
|
+
logger: (message) => writeLine(process.stderr, message),
|
|
234
|
+
});
|
|
235
|
+
const ipcServer = new ChatIpcServer({
|
|
236
|
+
rootDir: store.rootDir,
|
|
237
|
+
outboundHandler,
|
|
238
|
+
questionService,
|
|
239
|
+
});
|
|
240
|
+
return new ChatDaemonService({
|
|
241
|
+
store,
|
|
242
|
+
credentialsRepository,
|
|
243
|
+
sessionBridgeRepository,
|
|
244
|
+
adapterFactory: new AdapterFactory(),
|
|
245
|
+
outboundHandler,
|
|
246
|
+
questionService,
|
|
247
|
+
inboundHandler,
|
|
248
|
+
ipcServer,
|
|
249
|
+
createLogger: (options) => new ChatLogger(options),
|
|
250
|
+
});
|
|
251
|
+
};
|
|
180
252
|
if (command.kind === "routine-run" ||
|
|
181
253
|
command.kind === "routine-start" ||
|
|
182
254
|
command.kind === "routine-stop" ||
|
|
255
|
+
command.kind === "routine-cleanup" ||
|
|
183
256
|
command.kind === "routine-list" ||
|
|
184
257
|
command.kind === "routine-status") {
|
|
185
258
|
const exitCode = await handleRoutineCommand(command, {
|
|
@@ -210,6 +283,26 @@ async function main() {
|
|
|
210
283
|
}
|
|
211
284
|
return;
|
|
212
285
|
}
|
|
286
|
+
if (command.kind === "chat-setup" ||
|
|
287
|
+
command.kind === "chat-start" ||
|
|
288
|
+
command.kind === "chat-stop" ||
|
|
289
|
+
command.kind === "chat-status") {
|
|
290
|
+
const exitCode = await handleChatCommand(command, {
|
|
291
|
+
cwd,
|
|
292
|
+
argv: process.argv.slice(2),
|
|
293
|
+
scriptPath: process.argv[1] ?? fileURLToPath(import.meta.url),
|
|
294
|
+
env: process.env,
|
|
295
|
+
stdout: process.stdout,
|
|
296
|
+
stderr: process.stderr,
|
|
297
|
+
createSetupService: createChatSetupService,
|
|
298
|
+
createDaemonService: createChatDaemonService,
|
|
299
|
+
forkProcess: (modulePath, args, options) => fork(modulePath, args, options),
|
|
300
|
+
});
|
|
301
|
+
if (exitCode !== undefined) {
|
|
302
|
+
process.exitCode = exitCode;
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
213
306
|
if (command.kind === "mcp") {
|
|
214
307
|
const installed = await backendRegistry.detectInstalled();
|
|
215
308
|
if (installed.length === 0) {
|
|
@@ -236,6 +329,11 @@ async function main() {
|
|
|
236
329
|
service,
|
|
237
330
|
taskService,
|
|
238
331
|
store,
|
|
332
|
+
routineStatusQueryService: buildRoutineStatusQueryService({
|
|
333
|
+
store,
|
|
334
|
+
workflowRepo,
|
|
335
|
+
configDir: command.configDir,
|
|
336
|
+
}),
|
|
239
337
|
allowSpawnAgents: process.env.RELAY_ALLOW_SPAWN_AGENTS !== "0",
|
|
240
338
|
shutdownSignal: shutdownController.signal,
|
|
241
339
|
});
|
|
@@ -340,9 +438,9 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
340
438
|
const placeholderTime = new Date().toISOString();
|
|
341
439
|
warnOnBuiltInRoutineVarOverrides(command.vars, dependencies.stderr);
|
|
342
440
|
const routineVars = buildRoutineLoadVars(command.vars, placeholderTime);
|
|
343
|
-
await dependencies.runStartupHousekeeping(dependencies.store, {
|
|
441
|
+
await suppressLoopStateWarnings(() => dependencies.runStartupHousekeeping(dependencies.store, {
|
|
344
442
|
protectedLoopStateFile: command.resumeStateFile,
|
|
345
|
-
});
|
|
443
|
+
}));
|
|
346
444
|
await dependencies.reconcileAbandonedRunningTaskSessions(dependencies.store, dependencies.taskService);
|
|
347
445
|
const loadedRoutine = await dependencies.loadRoutine(workflowPath, dependencies.workflowRepo, routineVars);
|
|
348
446
|
warnOnBuiltInRoutineYamlVarOverrides(loadedRoutine.rawYamlVarKeys, dependencies.stderr);
|
|
@@ -364,7 +462,7 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
364
462
|
vars: command.vars ?? {},
|
|
365
463
|
})
|
|
366
464
|
: undefined;
|
|
367
|
-
dependencies.stdout.write(renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight));
|
|
465
|
+
dependencies.stdout.write(renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight, command.vars, loadedRoutine.rawYamlVars));
|
|
368
466
|
return 0;
|
|
369
467
|
}
|
|
370
468
|
enforceAllowCommandRun(workflowPath, loadedRoutine.capabilitySummary, command.allowCommandRun ?? false);
|
|
@@ -470,6 +568,26 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
470
568
|
await stopRoutineDaemon(dependencies);
|
|
471
569
|
return 0;
|
|
472
570
|
}
|
|
571
|
+
case "routine-cleanup": {
|
|
572
|
+
const service = dependencies.createRoutineStatusQueryService({
|
|
573
|
+
configDir: resolveRoutineConfigDir(command.configDir, dependencies.store, dependencies.cwd),
|
|
574
|
+
});
|
|
575
|
+
const result = await service.cleanup(command.dryRun ?? false);
|
|
576
|
+
if (result.targets.length === 0) {
|
|
577
|
+
dependencies.stderr.write("No cleanup targets found.\n");
|
|
578
|
+
return 0;
|
|
579
|
+
}
|
|
580
|
+
if (command.dryRun) {
|
|
581
|
+
dependencies.stderr.write("Cleanup targets (dry-run):\n");
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
dependencies.stderr.write(`Cleaned up ${result.deleted} file(s):\n`);
|
|
585
|
+
}
|
|
586
|
+
for (const target of result.targets) {
|
|
587
|
+
dependencies.stderr.write(` ${target.kind}: ${target.filePath} — ${target.reason}\n`);
|
|
588
|
+
}
|
|
589
|
+
return 0;
|
|
590
|
+
}
|
|
473
591
|
case "routine-list": {
|
|
474
592
|
const service = dependencies.createRoutineStatusQueryService({
|
|
475
593
|
configDir: resolveRoutineConfigDir(command.configDir, dependencies.store, dependencies.cwd),
|
|
@@ -490,11 +608,31 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
490
608
|
}
|
|
491
609
|
}
|
|
492
610
|
}
|
|
611
|
+
async function suppressLoopStateWarnings(fn) {
|
|
612
|
+
const origWarn = console.warn;
|
|
613
|
+
console.warn = (...args) => {
|
|
614
|
+
const msg = typeof args[0] === "string" ? args[0] : "";
|
|
615
|
+
if (msg.startsWith("Ignoring invalid loop state file")) {
|
|
616
|
+
console.debug(...args);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
origWarn.apply(console, args);
|
|
620
|
+
};
|
|
621
|
+
try {
|
|
622
|
+
return await fn();
|
|
623
|
+
}
|
|
624
|
+
finally {
|
|
625
|
+
console.warn = origWarn;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
493
628
|
export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(import.meta.url))) {
|
|
494
629
|
if (topic) {
|
|
495
630
|
if (isRoutineHelpTopic(topic)) {
|
|
496
631
|
return renderRoutineHelp(topic, scriptName);
|
|
497
632
|
}
|
|
633
|
+
if (isChatHelpTopic(topic)) {
|
|
634
|
+
return renderChatHelp(topic, scriptName);
|
|
635
|
+
}
|
|
498
636
|
return renderCoreSubcommandHelp(topic, scriptName);
|
|
499
637
|
}
|
|
500
638
|
const commandName = path.parse(scriptName).name;
|
|
@@ -503,8 +641,13 @@ export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(i
|
|
|
503
641
|
` ${scriptName} routine run <path> [--config <dir>] [--var key=value ...] [--dry-run] [--resume-state <file>] [--force-resume] [--allow-command-run]`,
|
|
504
642
|
` ${scriptName} routine start [--config <dir>] [--daemon] [--allow-command-run]`,
|
|
505
643
|
` ${scriptName} routine stop`,
|
|
644
|
+
` ${scriptName} routine cleanup [--config <dir>] [--dry-run]`,
|
|
506
645
|
` ${scriptName} routine list [--config <dir>] [--format <table|tsv|json>]`,
|
|
507
646
|
` ${scriptName} routine status [name] [--config <dir>] [--format <table|tsv|json>] [--limit <n>]`,
|
|
647
|
+
` ${scriptName} chat setup (--slack | --discord)`,
|
|
648
|
+
` ${scriptName} chat start [--foreground]`,
|
|
649
|
+
` ${scriptName} chat stop`,
|
|
650
|
+
` ${scriptName} chat status`,
|
|
508
651
|
` ${scriptName} core <setup|update|remove> [options]`,
|
|
509
652
|
` ${scriptName} setup-vscode [--target <code|code-insiders|cursor>] [--uninstall]`,
|
|
510
653
|
` ${scriptName} visualize`,
|
|
@@ -516,8 +659,13 @@ export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(i
|
|
|
516
659
|
` ${commandName} routine run [options] Run one routine YAML immediately`,
|
|
517
660
|
` ${commandName} routine start [options] Start the routine daemon`,
|
|
518
661
|
` ${commandName} routine stop Stop the routine daemon`,
|
|
662
|
+
` ${commandName} routine cleanup [options] Remove stale routine metadata`,
|
|
519
663
|
` ${commandName} routine list [options] List known routines`,
|
|
520
664
|
` ${commandName} routine status [options] Show routine status details`,
|
|
665
|
+
` ${commandName} chat setup [options] Configure Slack or Discord integration`,
|
|
666
|
+
` ${commandName} chat start [options] Start the chat daemon`,
|
|
667
|
+
` ${commandName} chat stop Stop the chat daemon`,
|
|
668
|
+
` ${commandName} chat status Show chat daemon status`,
|
|
521
669
|
` ${commandName} core setup [options] Setup .agents/ from agentic-core dist`,
|
|
522
670
|
` ${commandName} core update [options] Update .agents/ from latest dist`,
|
|
523
671
|
` ${commandName} core remove [options] Remove relay core managed files`,
|
|
@@ -573,6 +721,82 @@ function renderCoreSubcommandHelp(topic, scriptName) {
|
|
|
573
721
|
function isRoutineHelpTopic(topic) {
|
|
574
722
|
return topic.startsWith("routine");
|
|
575
723
|
}
|
|
724
|
+
function isChatHelpTopic(topic) {
|
|
725
|
+
return topic.startsWith("chat");
|
|
726
|
+
}
|
|
727
|
+
function renderChatHelp(topic, scriptName) {
|
|
728
|
+
if (topic === "chat") {
|
|
729
|
+
return [
|
|
730
|
+
`Usage: ${scriptName} chat setup (--slack | --discord)`,
|
|
731
|
+
` ${scriptName} chat start [--foreground]`,
|
|
732
|
+
` ${scriptName} chat stop`,
|
|
733
|
+
` ${scriptName} chat status`,
|
|
734
|
+
"",
|
|
735
|
+
"Chat commands:",
|
|
736
|
+
" setup Configure Slack or Discord credentials",
|
|
737
|
+
" start Start the chat daemon",
|
|
738
|
+
" stop Stop the chat daemon",
|
|
739
|
+
" status Show chat daemon status",
|
|
740
|
+
"",
|
|
741
|
+
"Options:",
|
|
742
|
+
" --slack Setup Slack integration",
|
|
743
|
+
" --discord Setup Discord integration",
|
|
744
|
+
" --foreground Run the chat daemon in the foreground",
|
|
745
|
+
" -h, --help Show this help",
|
|
746
|
+
].join("\n");
|
|
747
|
+
}
|
|
748
|
+
const commandName = path.parse(scriptName).name;
|
|
749
|
+
const allSubcommandsReference = `See '${commandName} chat --help' for all subcommands.`;
|
|
750
|
+
switch (topic) {
|
|
751
|
+
case "chat-setup":
|
|
752
|
+
return [
|
|
753
|
+
`Usage: ${scriptName} chat setup (--slack | --discord)`,
|
|
754
|
+
"",
|
|
755
|
+
"Configure Slack or Discord credentials for the chat daemon.",
|
|
756
|
+
"",
|
|
757
|
+
"Options:",
|
|
758
|
+
" --slack Configure Slack",
|
|
759
|
+
" --discord Configure Discord",
|
|
760
|
+
" -h, --help Show this help",
|
|
761
|
+
"",
|
|
762
|
+
allSubcommandsReference,
|
|
763
|
+
].join("\n");
|
|
764
|
+
case "chat-start":
|
|
765
|
+
return [
|
|
766
|
+
`Usage: ${scriptName} chat start [--foreground]`,
|
|
767
|
+
"",
|
|
768
|
+
"Start the chat daemon.",
|
|
769
|
+
"",
|
|
770
|
+
"Options:",
|
|
771
|
+
" --foreground Run in the foreground for debugging",
|
|
772
|
+
" -h, --help Show this help",
|
|
773
|
+
"",
|
|
774
|
+
allSubcommandsReference,
|
|
775
|
+
].join("\n");
|
|
776
|
+
case "chat-stop":
|
|
777
|
+
return [
|
|
778
|
+
`Usage: ${scriptName} chat stop`,
|
|
779
|
+
"",
|
|
780
|
+
"Stop the chat daemon.",
|
|
781
|
+
"",
|
|
782
|
+
"Options:",
|
|
783
|
+
" -h, --help Show this help",
|
|
784
|
+
"",
|
|
785
|
+
allSubcommandsReference,
|
|
786
|
+
].join("\n");
|
|
787
|
+
case "chat-status":
|
|
788
|
+
return [
|
|
789
|
+
`Usage: ${scriptName} chat status`,
|
|
790
|
+
"",
|
|
791
|
+
"Show chat daemon status.",
|
|
792
|
+
"",
|
|
793
|
+
"Options:",
|
|
794
|
+
" -h, --help Show this help",
|
|
795
|
+
"",
|
|
796
|
+
allSubcommandsReference,
|
|
797
|
+
].join("\n");
|
|
798
|
+
}
|
|
799
|
+
}
|
|
576
800
|
function renderRoutineHelp(topic, scriptName) {
|
|
577
801
|
if (topic === "routine") {
|
|
578
802
|
return renderRoutineAggregateHelp(scriptName);
|
|
@@ -622,6 +846,19 @@ function renderRoutineHelp(topic, scriptName) {
|
|
|
622
846
|
"",
|
|
623
847
|
allSubcommandsReference,
|
|
624
848
|
].join("\n");
|
|
849
|
+
case "routine-cleanup":
|
|
850
|
+
return [
|
|
851
|
+
`Usage: ${scriptName} routine cleanup [options]`,
|
|
852
|
+
"",
|
|
853
|
+
"Remove stale routine metadata files.",
|
|
854
|
+
"",
|
|
855
|
+
"Options:",
|
|
856
|
+
" --config <dir> Override the routine config directory",
|
|
857
|
+
" --dry-run Show cleanup targets without deleting them",
|
|
858
|
+
" -h, --help Show this help",
|
|
859
|
+
"",
|
|
860
|
+
allSubcommandsReference,
|
|
861
|
+
].join("\n");
|
|
625
862
|
case "routine-list":
|
|
626
863
|
return [
|
|
627
864
|
`Usage: ${scriptName} routine list [options]`,
|
|
@@ -644,7 +881,7 @@ function renderRoutineHelp(topic, scriptName) {
|
|
|
644
881
|
"Options:",
|
|
645
882
|
" --config <dir> Override the routine config directory",
|
|
646
883
|
" --format <fmt> Output format (table, tsv, json)",
|
|
647
|
-
" --limit <n> Limit the number of status log entries",
|
|
884
|
+
" --limit <n> Limit the number of status log entries (default: 10)",
|
|
648
885
|
" -h, --help Show this help",
|
|
649
886
|
"",
|
|
650
887
|
allSubcommandsReference,
|
|
@@ -656,6 +893,7 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
656
893
|
`Usage: ${scriptName} routine run <workflow.yaml> [options]`,
|
|
657
894
|
` ${scriptName} routine start [options]`,
|
|
658
895
|
` ${scriptName} routine stop`,
|
|
896
|
+
` ${scriptName} routine cleanup [options]`,
|
|
659
897
|
` ${scriptName} routine list [options]`,
|
|
660
898
|
` ${scriptName} routine status [name] [options]`,
|
|
661
899
|
"",
|
|
@@ -663,6 +901,7 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
663
901
|
" run Run one routine YAML immediately",
|
|
664
902
|
" start Start the routine daemon",
|
|
665
903
|
" stop Stop the routine daemon",
|
|
904
|
+
" cleanup Remove stale routine metadata",
|
|
666
905
|
" list List known routines",
|
|
667
906
|
" status Show routine status details",
|
|
668
907
|
"",
|
|
@@ -673,9 +912,9 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
673
912
|
" --allow-command-run Allow trusted workflows that declare command.run",
|
|
674
913
|
" --resume-state <file> Resume a loop-capable routine from checkpoint state",
|
|
675
914
|
" --force-resume Override workflow digest mismatch during resume",
|
|
676
|
-
" --dry-run Render routine structure without executing
|
|
915
|
+
" --dry-run Render routine structure or cleanup targets without executing deletion",
|
|
677
916
|
" --var key=value Set template variables for one routine run",
|
|
678
|
-
" --limit <n> Limit the number of status log entries",
|
|
917
|
+
" --limit <n> Limit the number of status log entries (default: 10)",
|
|
679
918
|
" -h, --help Show this help",
|
|
680
919
|
].join("\n");
|
|
681
920
|
}
|
|
@@ -942,6 +1181,9 @@ function printRoutineRunResult(result, writer = process.stderr) {
|
|
|
942
1181
|
writeLine(writer, lines.join("\n"));
|
|
943
1182
|
}
|
|
944
1183
|
const BUILT_IN_ROUTINE_VAR_KEYS = ["scheduled_time", "trigger_time"];
|
|
1184
|
+
function isBuiltInRoutineVarKey(key) {
|
|
1185
|
+
return BUILT_IN_ROUTINE_VAR_KEYS.includes(key);
|
|
1186
|
+
}
|
|
945
1187
|
function buildRoutineLoadVars(vars, placeholderValue) {
|
|
946
1188
|
return {
|
|
947
1189
|
...(vars ?? {}),
|
|
@@ -1023,7 +1265,18 @@ async function validateRoutineDryRunResumeState(options) {
|
|
|
1023
1265
|
});
|
|
1024
1266
|
}
|
|
1025
1267
|
}
|
|
1026
|
-
function renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight) {
|
|
1268
|
+
function renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight, vars, yamlVars) {
|
|
1269
|
+
const cliVarKeys = new Set(Object.keys(vars ?? {}));
|
|
1270
|
+
const emptyVarWarnings = [
|
|
1271
|
+
...Object.entries(vars ?? {})
|
|
1272
|
+
.filter(([key, value]) => value === "" && !isBuiltInRoutineVarKey(key))
|
|
1273
|
+
.map(([key]) => key),
|
|
1274
|
+
...Object.entries(yamlVars ?? {})
|
|
1275
|
+
.filter(([key, value]) => value === "" &&
|
|
1276
|
+
!isBuiltInRoutineVarKey(key) &&
|
|
1277
|
+
!cliVarKeys.has(key))
|
|
1278
|
+
.map(([key]) => key),
|
|
1279
|
+
].map((key) => ` - Template variable "{{${key}}}" resolved to empty string.`);
|
|
1027
1280
|
const lines = [
|
|
1028
1281
|
`Routine: ${loadedRoutine.routineDefinition.name.value}`,
|
|
1029
1282
|
...(loadedRoutine.routineDefinition.description
|
|
@@ -1047,6 +1300,7 @@ function renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight) {
|
|
|
1047
1300
|
: []),
|
|
1048
1301
|
]
|
|
1049
1302
|
: []),
|
|
1303
|
+
...(emptyVarWarnings.length > 0 ? ["Warnings:", ...emptyVarWarnings] : []),
|
|
1050
1304
|
"",
|
|
1051
1305
|
renderDryRun(loadedRoutine.routineDefinition.workflow, workflowPath),
|
|
1052
1306
|
];
|
|
@@ -1076,7 +1330,7 @@ function renderRoutineList(result, format = "table") {
|
|
|
1076
1330
|
formatOptionalTimestamp(entry.nextScheduledAt),
|
|
1077
1331
|
formatRoutineStatusWithOrphan(entry.status, entry.orphan),
|
|
1078
1332
|
].join("\t")),
|
|
1079
|
-
...invalid.map((entry) => `#
|
|
1333
|
+
...invalid.map((entry) => `# ${path.basename(entry.yamlPath)}: ${firstLine(stripYamlPathPrefix(entry.yamlPath, entry.error))}`),
|
|
1080
1334
|
];
|
|
1081
1335
|
return `${lines.join("\n")}\n`;
|
|
1082
1336
|
}
|
|
@@ -1106,10 +1360,14 @@ function renderRoutineList(result, format = "table") {
|
|
|
1106
1360
|
}
|
|
1107
1361
|
function renderInvalidRoutineFiles(invalid) {
|
|
1108
1362
|
return [
|
|
1109
|
-
`Skipped ${invalid.length}
|
|
1110
|
-
...invalid.map((entry) => ` - ${path.basename(entry.yamlPath)}: ${firstLine(entry.error)}`),
|
|
1363
|
+
`Skipped (${invalid.length}):`,
|
|
1364
|
+
...invalid.map((entry) => ` - ${path.basename(entry.yamlPath)}: ${firstLine(stripYamlPathPrefix(entry.yamlPath, entry.error))}`),
|
|
1111
1365
|
].join("\n");
|
|
1112
1366
|
}
|
|
1367
|
+
function stripYamlPathPrefix(yamlPath, error) {
|
|
1368
|
+
const prefix = `${yamlPath}: `;
|
|
1369
|
+
return error.startsWith(prefix) ? error.slice(prefix.length) : error;
|
|
1370
|
+
}
|
|
1113
1371
|
function firstLine(value) {
|
|
1114
1372
|
return value.split(/\r?\n/u, 1)[0] ?? "";
|
|
1115
1373
|
}
|
|
@@ -1435,6 +1693,26 @@ function confirmFromStdin(message) {
|
|
|
1435
1693
|
});
|
|
1436
1694
|
});
|
|
1437
1695
|
}
|
|
1696
|
+
function promptFromStdin(message) {
|
|
1697
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1698
|
+
return new Promise((resolve) => {
|
|
1699
|
+
rl.question(message, (answer) => {
|
|
1700
|
+
rl.close();
|
|
1701
|
+
resolve(answer);
|
|
1702
|
+
});
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
async function openUrlInBrowser(url) {
|
|
1706
|
+
if (process.platform === "darwin") {
|
|
1707
|
+
await execFileAsync("open", [url]);
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
if (process.platform === "win32") {
|
|
1711
|
+
await execFileAsync("cmd", ["/c", "start", "", url]);
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
await execFileAsync("xdg-open", [url]);
|
|
1715
|
+
}
|
|
1438
1716
|
async function isExecutedAsScript(metaUrl) {
|
|
1439
1717
|
const entryPath = process.argv[1];
|
|
1440
1718
|
if (!entryPath) {
|