@rk0429/agentic-relay 21.3.0 → 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 +4 -2
- package/dist/bin/relay.js +278 -11
- 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.js +43 -6
- 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,11 +50,13 @@ 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 の手順に従って実行してください。";
|
|
46
61
|
export function buildRoutineStatusQueryService(options) {
|
|
47
62
|
return new RoutineStatusQueryService({
|
|
@@ -52,6 +67,9 @@ export function buildRoutineStatusQueryService(options) {
|
|
|
52
67
|
stateRepo: new RoutineStateRepository(options.store),
|
|
53
68
|
runtimeRepo: new RoutineRuntimeProjectionRepository(options.store),
|
|
54
69
|
store: options.store,
|
|
70
|
+
leaseRepo: new RoutineExecutionLeaseRepository(options.store),
|
|
71
|
+
loopStateFiles: () => options.store.listLoopStateFiles(),
|
|
72
|
+
deleteLoopState: (filename) => options.store.deleteLoopState(filename),
|
|
55
73
|
});
|
|
56
74
|
}
|
|
57
75
|
async function main() {
|
|
@@ -184,9 +202,57 @@ async function main() {
|
|
|
184
202
|
workflowRepo,
|
|
185
203
|
configDir,
|
|
186
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
|
+
};
|
|
187
252
|
if (command.kind === "routine-run" ||
|
|
188
253
|
command.kind === "routine-start" ||
|
|
189
254
|
command.kind === "routine-stop" ||
|
|
255
|
+
command.kind === "routine-cleanup" ||
|
|
190
256
|
command.kind === "routine-list" ||
|
|
191
257
|
command.kind === "routine-status") {
|
|
192
258
|
const exitCode = await handleRoutineCommand(command, {
|
|
@@ -217,6 +283,26 @@ async function main() {
|
|
|
217
283
|
}
|
|
218
284
|
return;
|
|
219
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
|
+
}
|
|
220
306
|
if (command.kind === "mcp") {
|
|
221
307
|
const installed = await backendRegistry.detectInstalled();
|
|
222
308
|
if (installed.length === 0) {
|
|
@@ -246,6 +332,7 @@ async function main() {
|
|
|
246
332
|
routineStatusQueryService: buildRoutineStatusQueryService({
|
|
247
333
|
store,
|
|
248
334
|
workflowRepo,
|
|
335
|
+
configDir: command.configDir,
|
|
249
336
|
}),
|
|
250
337
|
allowSpawnAgents: process.env.RELAY_ALLOW_SPAWN_AGENTS !== "0",
|
|
251
338
|
shutdownSignal: shutdownController.signal,
|
|
@@ -351,9 +438,9 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
351
438
|
const placeholderTime = new Date().toISOString();
|
|
352
439
|
warnOnBuiltInRoutineVarOverrides(command.vars, dependencies.stderr);
|
|
353
440
|
const routineVars = buildRoutineLoadVars(command.vars, placeholderTime);
|
|
354
|
-
await dependencies.runStartupHousekeeping(dependencies.store, {
|
|
441
|
+
await suppressLoopStateWarnings(() => dependencies.runStartupHousekeeping(dependencies.store, {
|
|
355
442
|
protectedLoopStateFile: command.resumeStateFile,
|
|
356
|
-
});
|
|
443
|
+
}));
|
|
357
444
|
await dependencies.reconcileAbandonedRunningTaskSessions(dependencies.store, dependencies.taskService);
|
|
358
445
|
const loadedRoutine = await dependencies.loadRoutine(workflowPath, dependencies.workflowRepo, routineVars);
|
|
359
446
|
warnOnBuiltInRoutineYamlVarOverrides(loadedRoutine.rawYamlVarKeys, dependencies.stderr);
|
|
@@ -375,7 +462,7 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
375
462
|
vars: command.vars ?? {},
|
|
376
463
|
})
|
|
377
464
|
: undefined;
|
|
378
|
-
dependencies.stdout.write(renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight));
|
|
465
|
+
dependencies.stdout.write(renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight, command.vars, loadedRoutine.rawYamlVars));
|
|
379
466
|
return 0;
|
|
380
467
|
}
|
|
381
468
|
enforceAllowCommandRun(workflowPath, loadedRoutine.capabilitySummary, command.allowCommandRun ?? false);
|
|
@@ -481,6 +568,26 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
481
568
|
await stopRoutineDaemon(dependencies);
|
|
482
569
|
return 0;
|
|
483
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
|
+
}
|
|
484
591
|
case "routine-list": {
|
|
485
592
|
const service = dependencies.createRoutineStatusQueryService({
|
|
486
593
|
configDir: resolveRoutineConfigDir(command.configDir, dependencies.store, dependencies.cwd),
|
|
@@ -501,11 +608,31 @@ export async function handleRoutineCommand(command, dependencies) {
|
|
|
501
608
|
}
|
|
502
609
|
}
|
|
503
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
|
+
}
|
|
504
628
|
export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(import.meta.url))) {
|
|
505
629
|
if (topic) {
|
|
506
630
|
if (isRoutineHelpTopic(topic)) {
|
|
507
631
|
return renderRoutineHelp(topic, scriptName);
|
|
508
632
|
}
|
|
633
|
+
if (isChatHelpTopic(topic)) {
|
|
634
|
+
return renderChatHelp(topic, scriptName);
|
|
635
|
+
}
|
|
509
636
|
return renderCoreSubcommandHelp(topic, scriptName);
|
|
510
637
|
}
|
|
511
638
|
const commandName = path.parse(scriptName).name;
|
|
@@ -514,8 +641,13 @@ export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(i
|
|
|
514
641
|
` ${scriptName} routine run <path> [--config <dir>] [--var key=value ...] [--dry-run] [--resume-state <file>] [--force-resume] [--allow-command-run]`,
|
|
515
642
|
` ${scriptName} routine start [--config <dir>] [--daemon] [--allow-command-run]`,
|
|
516
643
|
` ${scriptName} routine stop`,
|
|
644
|
+
` ${scriptName} routine cleanup [--config <dir>] [--dry-run]`,
|
|
517
645
|
` ${scriptName} routine list [--config <dir>] [--format <table|tsv|json>]`,
|
|
518
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`,
|
|
519
651
|
` ${scriptName} core <setup|update|remove> [options]`,
|
|
520
652
|
` ${scriptName} setup-vscode [--target <code|code-insiders|cursor>] [--uninstall]`,
|
|
521
653
|
` ${scriptName} visualize`,
|
|
@@ -527,8 +659,13 @@ export function renderHelpText(topic, scriptName = path.basename(fileURLToPath(i
|
|
|
527
659
|
` ${commandName} routine run [options] Run one routine YAML immediately`,
|
|
528
660
|
` ${commandName} routine start [options] Start the routine daemon`,
|
|
529
661
|
` ${commandName} routine stop Stop the routine daemon`,
|
|
662
|
+
` ${commandName} routine cleanup [options] Remove stale routine metadata`,
|
|
530
663
|
` ${commandName} routine list [options] List known routines`,
|
|
531
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`,
|
|
532
669
|
` ${commandName} core setup [options] Setup .agents/ from agentic-core dist`,
|
|
533
670
|
` ${commandName} core update [options] Update .agents/ from latest dist`,
|
|
534
671
|
` ${commandName} core remove [options] Remove relay core managed files`,
|
|
@@ -584,6 +721,82 @@ function renderCoreSubcommandHelp(topic, scriptName) {
|
|
|
584
721
|
function isRoutineHelpTopic(topic) {
|
|
585
722
|
return topic.startsWith("routine");
|
|
586
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
|
+
}
|
|
587
800
|
function renderRoutineHelp(topic, scriptName) {
|
|
588
801
|
if (topic === "routine") {
|
|
589
802
|
return renderRoutineAggregateHelp(scriptName);
|
|
@@ -633,6 +846,19 @@ function renderRoutineHelp(topic, scriptName) {
|
|
|
633
846
|
"",
|
|
634
847
|
allSubcommandsReference,
|
|
635
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");
|
|
636
862
|
case "routine-list":
|
|
637
863
|
return [
|
|
638
864
|
`Usage: ${scriptName} routine list [options]`,
|
|
@@ -655,7 +881,7 @@ function renderRoutineHelp(topic, scriptName) {
|
|
|
655
881
|
"Options:",
|
|
656
882
|
" --config <dir> Override the routine config directory",
|
|
657
883
|
" --format <fmt> Output format (table, tsv, json)",
|
|
658
|
-
" --limit <n> Limit the number of status log entries",
|
|
884
|
+
" --limit <n> Limit the number of status log entries (default: 10)",
|
|
659
885
|
" -h, --help Show this help",
|
|
660
886
|
"",
|
|
661
887
|
allSubcommandsReference,
|
|
@@ -667,6 +893,7 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
667
893
|
`Usage: ${scriptName} routine run <workflow.yaml> [options]`,
|
|
668
894
|
` ${scriptName} routine start [options]`,
|
|
669
895
|
` ${scriptName} routine stop`,
|
|
896
|
+
` ${scriptName} routine cleanup [options]`,
|
|
670
897
|
` ${scriptName} routine list [options]`,
|
|
671
898
|
` ${scriptName} routine status [name] [options]`,
|
|
672
899
|
"",
|
|
@@ -674,6 +901,7 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
674
901
|
" run Run one routine YAML immediately",
|
|
675
902
|
" start Start the routine daemon",
|
|
676
903
|
" stop Stop the routine daemon",
|
|
904
|
+
" cleanup Remove stale routine metadata",
|
|
677
905
|
" list List known routines",
|
|
678
906
|
" status Show routine status details",
|
|
679
907
|
"",
|
|
@@ -684,9 +912,9 @@ function renderRoutineAggregateHelp(scriptName) {
|
|
|
684
912
|
" --allow-command-run Allow trusted workflows that declare command.run",
|
|
685
913
|
" --resume-state <file> Resume a loop-capable routine from checkpoint state",
|
|
686
914
|
" --force-resume Override workflow digest mismatch during resume",
|
|
687
|
-
" --dry-run Render routine structure without executing
|
|
915
|
+
" --dry-run Render routine structure or cleanup targets without executing deletion",
|
|
688
916
|
" --var key=value Set template variables for one routine run",
|
|
689
|
-
" --limit <n> Limit the number of status log entries",
|
|
917
|
+
" --limit <n> Limit the number of status log entries (default: 10)",
|
|
690
918
|
" -h, --help Show this help",
|
|
691
919
|
].join("\n");
|
|
692
920
|
}
|
|
@@ -953,6 +1181,9 @@ function printRoutineRunResult(result, writer = process.stderr) {
|
|
|
953
1181
|
writeLine(writer, lines.join("\n"));
|
|
954
1182
|
}
|
|
955
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
|
+
}
|
|
956
1187
|
function buildRoutineLoadVars(vars, placeholderValue) {
|
|
957
1188
|
return {
|
|
958
1189
|
...(vars ?? {}),
|
|
@@ -1034,7 +1265,18 @@ async function validateRoutineDryRunResumeState(options) {
|
|
|
1034
1265
|
});
|
|
1035
1266
|
}
|
|
1036
1267
|
}
|
|
1037
|
-
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.`);
|
|
1038
1280
|
const lines = [
|
|
1039
1281
|
`Routine: ${loadedRoutine.routineDefinition.name.value}`,
|
|
1040
1282
|
...(loadedRoutine.routineDefinition.description
|
|
@@ -1058,6 +1300,7 @@ function renderRoutineDryRun(loadedRoutine, workflowPath, resumePreflight) {
|
|
|
1058
1300
|
: []),
|
|
1059
1301
|
]
|
|
1060
1302
|
: []),
|
|
1303
|
+
...(emptyVarWarnings.length > 0 ? ["Warnings:", ...emptyVarWarnings] : []),
|
|
1061
1304
|
"",
|
|
1062
1305
|
renderDryRun(loadedRoutine.routineDefinition.workflow, workflowPath),
|
|
1063
1306
|
];
|
|
@@ -1087,7 +1330,7 @@ function renderRoutineList(result, format = "table") {
|
|
|
1087
1330
|
formatOptionalTimestamp(entry.nextScheduledAt),
|
|
1088
1331
|
formatRoutineStatusWithOrphan(entry.status, entry.orphan),
|
|
1089
1332
|
].join("\t")),
|
|
1090
|
-
...invalid.map((entry) => `#
|
|
1333
|
+
...invalid.map((entry) => `# ${path.basename(entry.yamlPath)}: ${firstLine(stripYamlPathPrefix(entry.yamlPath, entry.error))}`),
|
|
1091
1334
|
];
|
|
1092
1335
|
return `${lines.join("\n")}\n`;
|
|
1093
1336
|
}
|
|
@@ -1117,10 +1360,14 @@ function renderRoutineList(result, format = "table") {
|
|
|
1117
1360
|
}
|
|
1118
1361
|
function renderInvalidRoutineFiles(invalid) {
|
|
1119
1362
|
return [
|
|
1120
|
-
`Skipped ${invalid.length}
|
|
1121
|
-
...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))}`),
|
|
1122
1365
|
].join("\n");
|
|
1123
1366
|
}
|
|
1367
|
+
function stripYamlPathPrefix(yamlPath, error) {
|
|
1368
|
+
const prefix = `${yamlPath}: `;
|
|
1369
|
+
return error.startsWith(prefix) ? error.slice(prefix.length) : error;
|
|
1370
|
+
}
|
|
1124
1371
|
function firstLine(value) {
|
|
1125
1372
|
return value.split(/\r?\n/u, 1)[0] ?? "";
|
|
1126
1373
|
}
|
|
@@ -1446,6 +1693,26 @@ function confirmFromStdin(message) {
|
|
|
1446
1693
|
});
|
|
1447
1694
|
});
|
|
1448
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
|
+
}
|
|
1449
1716
|
async function isExecutedAsScript(metaUrl) {
|
|
1450
1717
|
const entryPath = process.argv[1];
|
|
1451
1718
|
if (!entryPath) {
|