@nodeint/migent 0.1.5 → 0.1.7

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/program.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { Command } from "commander";
3
- import { ConfigurationError, DEFAULT_MAX_DISPATCHES } from "@nodeint/migent-kernel";
4
- import { dispatchAgent } from "./commands/agent.js";
3
+ import { ConfigurationError, DEFAULT_MAX_DISPATCHES, requireAgentSession } from "@nodeint/migent-kernel";
4
+ import { continueAgent, dispatchAgent } from "./commands/agent.js";
5
5
  import { runConfigModel, runConfigRole, runConfigShow } from "./commands/config.js";
6
6
  import { runDoctor } from "./commands/doctor.js";
7
7
  import { executeWorkflow } from "./commands/execute.js";
@@ -11,6 +11,7 @@ import { runInit } from "./commands/init.js";
11
11
  import { runSessionMetrics, runSessions } from "./commands/sessions.js";
12
12
  import { parsePort, runServiceStart, runServiceStatus, runServiceStop } from "./commands/service.js";
13
13
  import { installSkill, updateSkill } from "./commands/skill.js";
14
+ import { runProviderList } from "./commands/provider.js";
14
15
  import { runRegister, runRemove, runWorkspaceList } from "./commands/workspace-registry.js";
15
16
  import { printError } from "./display.js";
16
17
  import { LOOP_EXITS, STAGE_EXITS } from "./exits.js";
@@ -20,7 +21,7 @@ import { PACKAGE_VERSION } from "./version.js";
20
21
  import { findWorkspace, invocationCwdPath } from "./workspace.js";
21
22
  const PRIOR_HELP = "Completed session with the workflow id and decision named in requires. Checked before outputs are injected.";
22
23
  const PROGRESS_HELP = "Print each tool call when it finishes. The default prints one line when a stage starts and one when it finishes.";
23
- const VERBOSE_HELP = "Include every stage and its response text in the result JSON.";
24
+ const VERBOSE_HELP = "Accepted for compatibility. Stage lines already include the attempt and the time. The response stays in the execution directory.";
24
25
  export function createProgram(status) {
25
26
  const program = new Command();
26
27
  program
@@ -127,6 +128,18 @@ export function createProgram(status) {
127
128
  .option("--json", "Print the checks as one JSON object.")
128
129
  .addHelpText("after", exitText(["Exit 0 when every check passes.", "Exit 1 when a check fails."]))
129
130
  .action((options) => settle(status, () => runDoctor(findWorkspace(invocationCwdPath()), { asJson: options.json === true })));
131
+ const provider = program.command("provider").description("List registered provider providers and their models.");
132
+ provider
133
+ .command("list")
134
+ .description("List each registered provider, whether its CLI is on PATH, and the models it reports.")
135
+ .option("--json", "Print the provider list as one JSON object.")
136
+ .addHelpText("after", exitText([
137
+ "Exit 0 when the command ran and at least one provider returned models.",
138
+ "Exit 1 when no provider returned any models.",
139
+ "A missing optional CLI is not an error.",
140
+ ]))
141
+ .action((options) => settle(status, () => runProviderList({ asJson: options.json === true })));
142
+ showHelpWhenBare(status, provider);
130
143
  program
131
144
  .command("migrate")
132
145
  .description("Upgrade config and workflows to the current schema version.")
@@ -195,10 +208,11 @@ export function createProgram(status) {
195
208
  return program;
196
209
  }
197
210
  const ROLE_EXITS = [
198
- "Exit 0 when the outcome is complete.",
211
+ "Exit 0 when the outcome is complete, or the role session is already completed.",
199
212
  "Exit 1 when the outcome is not complete.",
200
213
  "Exit 2 on a configuration error.",
201
- "Exit 130 when cancelled. A later run of this session resumes that execution.",
214
+ "Exit 6 when a cancelled role session reopened more than one execution and one exhausted verify.",
215
+ "Exit 130 when cancelled. session continue resumes that execution.",
202
216
  ];
203
217
  const RUN_SPLIT = "Pass --workflow for a workflow run, or --role for an agent run.";
204
218
  function registerSessionCommand(program, status) {
@@ -218,26 +232,26 @@ function registerSessionCommand(program, status) {
218
232
  .option("--prompt <prompt>", "Prompt text for a role run.")
219
233
  .option("--file <file>", "Read the role prompt from this file.")
220
234
  .option("--stdin", "Read the role prompt from stdin.")
221
- .option("--json", "Print the role result as one JSON object. A workflow run is already JSON.")
222
- .addHelpText("after", `With --workflow:\n${exitText(LOOP_EXITS)}With --workflow and --once:\n${exitText(STAGE_EXITS)}Without --workflow:\n${exitText(ROLE_EXITS)}Examples:\n migent session run --workflow plan --task "<one line>"\n migent session run --session wave-3 --workflow plan\n migent session run --role reviewer --prompt "<prompt>"\n`)
235
+ .option("--json", "Print the role result as one JSON object.")
236
+ .addHelpText("after", `With --workflow:\n${exitText(LOOP_EXITS)}With --workflow and --once:\n${exitText(STAGE_EXITS)}Without --workflow:\n${exitText(ROLE_EXITS)}Examples:\n migent session run --workflow plan --task "<one line>"\n migent session run --session <session> --workflow plan\n migent session run --role reviewer --prompt "<prompt>"\n`)
223
237
  .action((options) => settle(status, () => runSessionCommand(options)));
224
238
  session
225
239
  .command("prepare")
226
240
  .description("Create a prepared session and exit. Write task.md, then session run --session <id> --workflow <workflow>.")
227
- .argument("<id>", "Session id: a lowercase slug such as wave-3.")
241
+ .argument("<title>", "Session title shown in the list, such as \"some task title\". The session id is a UUID.")
228
242
  .requiredOption("--workflow <workflow>", "Workflow id, or a path to a workflow file.")
229
243
  .option("--prior <session>", PRIOR_HELP)
230
- .addHelpText("after", `${exitText(["Exit 0 when the session is prepared.", "Exit 2 on a configuration error."])}Examples:\n migent session prepare wave-3 --workflow plan\n`)
244
+ .addHelpText("after", `${exitText(["Exit 0 when the session is prepared.", "Exit 2 on a configuration error."])}Examples:\n migent session prepare "some task title" --workflow plan\n`)
231
245
  .action((id, options) => settle(status, () => prepareWorkflowSession(findWorkspace(invocationCwdPath()), id, String(options.workflow), optionalText(options.prior))));
232
246
  const continueCommand = session
233
247
  .command("continue")
234
- .description("Resume an active or blocked workflow session until it stops. Resets revision counts. --once dispatches one stage and does not reset them.")
248
+ .description("Resume a stopped workflow or role session. A workflow session runs until it stops and resets revision counts. --once dispatches one workflow stage and does not reset them.")
235
249
  .argument("<session>", "Session to resume.");
236
250
  addDispatchOptions(continueCommand, "Dispatch the next eligible stage once and do not reset revision counts. Without --once, continue resets them.");
237
251
  continueCommand
238
252
  .option("--reply <text>", "Reply for the blocked stage. The new execution prompt body is this text.")
239
253
  .option("--reply-file <file>", "Read the blocked stage's reply from this file.")
240
- .addHelpText("after", `${exitText(LOOP_EXITS)}With --once:\n${exitText(STAGE_EXITS)}Examples:\n migent session continue <session> --once\n migent session continue <session> --reply "<reply>"\n migent session continue <session> --stage plan --reply-file answer.md\n`)
254
+ .addHelpText("after", `Workflow session:\n${exitText(LOOP_EXITS)}With --once:\n${exitText(STAGE_EXITS)}Role session:\n${exitText(ROLE_EXITS)}Examples:\n migent session continue <session>\n migent session continue <session> --once\n migent session continue <session> --reply "<reply>"\n migent session continue <session> --stage plan --reply-file answer.md\n`)
241
255
  .action((id, options) => settle(status, () => continueSession(id, options)));
242
256
  session
243
257
  .command("repair")
@@ -290,15 +304,15 @@ function registerSessionCommand(program, status) {
290
304
  })));
291
305
  session
292
306
  .command("metrics")
293
- .description("Print derived usage, time, and revision counts.")
294
- .argument("[session]", "Session to measure. Omit to list sessions.")
307
+ .description("Print usage, time, and revision counts recorded for a completed workflow session.")
308
+ .argument("[session]", "Workflow session to read. Omit to list sessions that have metrics.")
295
309
  .option("--json", "Print one JSON object, or one object per line for a list.")
296
310
  .option("--workflow <id>", "With a list, keep sessions for this workflow.")
297
311
  .option("--status <status>", "With a list, keep sessions in this status.")
298
312
  .option("--limit <n>", "With a list, keep the newest n sessions.")
299
313
  .addHelpText("after", `${exitText([
300
314
  "Exit 0 after one session object, or one object per line. An empty list prints nothing.",
301
- "Exit 2 when --json is missing, the session has no events.jsonl, or a list flag is invalid.",
315
+ "Exit 2 when --json is missing, the session has no metrics.json, that file is corrupt, or a list flag is invalid.",
302
316
  ])}Examples:\n migent session metrics <session> --json\n migent session metrics --json --workflow <id> --status completed --limit 10\n`)
303
317
  .action((id, options) => settle(status, () => runSessionMetrics(findWorkspace(invocationCwdPath()), id, {
304
318
  asJson: options.json === true,
@@ -393,7 +407,6 @@ function workflowFlagsPresent(options) {
393
407
  return (options.once === true ||
394
408
  options.stage !== undefined ||
395
409
  options.prior !== undefined ||
396
- options.attempts !== undefined ||
397
410
  options.maxDispatches !== undefined ||
398
411
  options.unlimitedDispatches === true ||
399
412
  options.progress === true ||
@@ -418,7 +431,6 @@ function runWorkflowCommand(args) {
418
431
  sessionId,
419
432
  startPrepared: args.prepared,
420
433
  priorSessionId: optionalText(args.options.prior),
421
- maxAttempts: attemptsOf(args.options),
422
434
  maxDispatches: ceiling,
423
435
  refreshWorkflow: args.options.refreshWorkflow === true,
424
436
  ...outputFlags(args.options),
@@ -432,7 +444,6 @@ function runWorkflowCommand(args) {
432
444
  stageId,
433
445
  startPrepared: args.prepared,
434
446
  priorSessionId: optionalText(args.options.prior),
435
- maxAttempts: null,
436
447
  maxDispatches: null,
437
448
  refreshWorkflow: args.options.refreshWorkflow === true,
438
449
  ...outputFlags(args.options),
@@ -443,6 +454,9 @@ function continueSession(session, options) {
443
454
  printError("--stage is empty.");
444
455
  return 2;
445
456
  }
457
+ const workspace = findWorkspace(invocationCwdPath());
458
+ if (isAgentSession(workspace, session))
459
+ return continueRoleSession(workspace, session, options);
446
460
  if (rejectOnce(options))
447
461
  return 2;
448
462
  const reply = readReply(options);
@@ -455,8 +469,8 @@ function continueSession(session, options) {
455
469
  sessionId: session,
456
470
  stageId,
457
471
  priorSessionId: optionalText(options.prior),
458
- maxAttempts: null,
459
472
  maxDispatches: null,
473
+ continueFailed: true,
460
474
  refreshWorkflow: options.refreshWorkflow === true,
461
475
  reply,
462
476
  ...outputFlags(options),
@@ -469,13 +483,57 @@ function continueSession(session, options) {
469
483
  action: "continue",
470
484
  sessionId: session,
471
485
  priorSessionId: optionalText(options.prior),
472
- maxAttempts: attemptsOf(options),
473
486
  maxDispatches: ceiling,
487
+ continueFailed: true,
474
488
  refreshWorkflow: options.refreshWorkflow === true,
475
489
  reply,
476
490
  ...outputFlags(options),
477
491
  });
478
492
  }
493
+ function isAgentSession(workspace, sessionId) {
494
+ try {
495
+ requireAgentSession(workspace, sessionId);
496
+ return true;
497
+ }
498
+ catch (error) {
499
+ if (!(error instanceof ConfigurationError))
500
+ throw error;
501
+ if (error.message === `Session not found: ${sessionId}.`)
502
+ return false;
503
+ if (error.message === `Session ${sessionId} was not created by agent.`)
504
+ return false;
505
+ if (error.message.startsWith("Session status file is corrupt:"))
506
+ return false;
507
+ throw error;
508
+ }
509
+ }
510
+ function continueRoleSession(workspace, sessionId, options) {
511
+ const flags = [];
512
+ if (options.once === true)
513
+ flags.push("--once");
514
+ if (options.stage !== undefined)
515
+ flags.push("--stage");
516
+ if (options.prior !== undefined)
517
+ flags.push("--prior");
518
+ if (options.maxDispatches !== undefined)
519
+ flags.push("--max-dispatches");
520
+ if (options.unlimitedDispatches === true)
521
+ flags.push("--unlimited-dispatches");
522
+ if (options.progress === true)
523
+ flags.push("--progress");
524
+ if (options.verbose === true)
525
+ flags.push("--verbose");
526
+ if (options.refreshWorkflow === true)
527
+ flags.push("--refresh-workflow");
528
+ if (flags.length > 0) {
529
+ printError(`Session ${sessionId} is a role session. Omit ${flags.join(", ")}.`);
530
+ return 2;
531
+ }
532
+ const reply = readReply(options);
533
+ if (reply === "invalid")
534
+ return 2;
535
+ return continueAgent(workspace, { sessionId, reply });
536
+ }
479
537
  function readReply(options) {
480
538
  const hasReply = options.reply !== undefined;
481
539
  const hasFile = options.replyFile !== undefined;
@@ -518,7 +576,6 @@ function addDispatchOptions(command, onceDescription) {
518
576
  .option("--once", onceDescription)
519
577
  .option("--stage <stage>", "Dispatch this ready stage once. It does not have to be the first ready stage.")
520
578
  .option("--prior <session>", PRIOR_HELP)
521
- .option("--attempts <count>", "Failed executions allowed for one stage. Default: 3.")
522
579
  .option("--max-dispatches <count>", `Stage dispatches allowed in this command. Default: ${DEFAULT_MAX_DISPATCHES}. Pass --unlimited-dispatches to remove the ceiling.`)
523
580
  .option("--unlimited-dispatches", "Remove the dispatch ceiling for this command.")
524
581
  .option("--progress", PROGRESS_HELP)
@@ -526,7 +583,7 @@ function addDispatchOptions(command, onceDescription) {
526
583
  .option("--refresh-workflow", "Use the current workflow, models, and role instructions for this session. Requires an existing session that has a frozen workflow.");
527
584
  }
528
585
  function outputFlags(options) {
529
- return { verbose: options.verbose === true, itemProgress: options.progress === true };
586
+ return { itemProgress: options.progress === true };
530
587
  }
531
588
  function showHelpWhenBare(status, command) {
532
589
  command.action(() => {
@@ -590,10 +647,6 @@ function rejectOnce(options) {
590
647
  if (options.once !== true && options.stage === undefined)
591
648
  return false;
592
649
  const flag = options.once === true ? "--once" : "--stage";
593
- if (options.attempts !== undefined) {
594
- printError(`${flag} cannot be combined with --attempts.`);
595
- return true;
596
- }
597
650
  if (options.maxDispatches !== undefined) {
598
651
  printError(`${flag} cannot be combined with --max-dispatches.`);
599
652
  return true;
@@ -617,12 +670,6 @@ function dispatchCeiling(options) {
617
670
  return DEFAULT_MAX_DISPATCHES;
618
671
  return integerFlag(maxDispatches, "--max-dispatches");
619
672
  }
620
- function attemptsOf(options) {
621
- const raw = optionalText(options.attempts);
622
- if (raw === null)
623
- return 3;
624
- return integerFlag(raw, "--attempts");
625
- }
626
673
  function integerFlag(raw, flag) {
627
674
  if (!/^[0-9]+$/.test(raw) || Number(raw) < 1) {
628
675
  throw new ConfigurationError(`${flag} must be at least 1.`);
@@ -1,23 +1,25 @@
1
1
  import { ModelCatalog } from "@nodeint/migent-adapters";
2
- import { type AgentAdapter, type ProviderOption } from "@nodeint/migent-kernel";
3
- export interface CatalogAdapter extends AgentAdapter {
2
+ import { type Provider, type ProviderOption } from "@nodeint/migent-kernel";
3
+ export interface CatalogProvider extends Provider {
4
4
  modelCatalogCommand(): string[];
5
+ /** Written to the catalog command's stdin when the CLI reads its request there. */
6
+ modelCatalogInput?(): string;
5
7
  parseModelCatalog(stdout: string): ModelCatalog;
6
8
  optionValuesCommand(name: string, model: string): string[] | null;
7
9
  parseOptionValues(name: string, text: string, model?: string): readonly string[];
8
10
  providerOptions(): readonly ProviderOption[];
9
11
  }
10
12
  export type Which = (command: string) => string | null;
11
- export type RunCommand = (argv: string[]) => string | Promise<string>;
13
+ export type RunCommand = (argv: string[], input?: string) => string | Promise<string>;
12
14
  export declare class ProviderCommandFailed extends Error {
13
15
  }
14
- export declare function adapterMap(): Record<string, AgentAdapter>;
15
- export declare function asCatalog(adapter: AgentAdapter): CatalogAdapter;
16
- export declare function requireAdapter(adapters: Record<string, AgentAdapter>, provider: string): AgentAdapter;
17
- export declare function detected(adapters: Record<string, AgentAdapter>, which: Which): Array<[string, string | null, AgentAdapter]>;
18
- export declare function loadCatalog(adapter: AgentAdapter, which: Which, runCommand: RunCommand): Promise<ModelCatalog>;
16
+ export declare function providerMap(): Record<string, Provider>;
17
+ export declare function asCatalog(provider: Provider): CatalogProvider;
18
+ export declare function requireProvider(providers: Record<string, Provider>, provider: string): Provider;
19
+ export declare function detected(providers: Record<string, Provider>, which: Which): Array<[string, string | null, Provider]>;
20
+ export declare function loadCatalog(provider: Provider, which: Which, runCommand: RunCommand): Promise<ModelCatalog>;
19
21
  export declare function knownModel(model: string, catalog: ModelCatalog): string;
20
22
  export declare function parseOptions(pairs: readonly string[]): Record<string, string>;
21
- export declare function loadOptionValues(adapter: AgentAdapter, name: string, model: string, catalog: ModelCatalog, which: Which, runCommand: RunCommand): Promise<readonly string[] | null>;
22
- export declare function acceptedOptions(adapter: AgentAdapter, model: string, catalog: ModelCatalog, which: Which, runCommand: RunCommand, options: Readonly<Record<string, string>>): Promise<Record<string, string>>;
23
- export declare function runProviderCommand(argv: string[]): string;
23
+ export declare function loadOptionValues(provider: Provider, name: string, model: string, catalog: ModelCatalog, which: Which, runCommand: RunCommand): Promise<readonly string[] | null>;
24
+ export declare function acceptedOptions(provider: Provider, model: string, catalog: ModelCatalog, which: Which, runCommand: RunCommand, options: Readonly<Record<string, string>>): Promise<Record<string, string>>;
25
+ export declare function runProviderCommand(argv: string[], input?: string): string;
package/dist/provider.js CHANGED
@@ -1,27 +1,27 @@
1
- import { ModelCatalog, defaultAdapters } from "@nodeint/migent-adapters";
1
+ import { ModelCatalog, defaultProviders } from "@nodeint/migent-adapters";
2
2
  import { spawnProviderSync } from "@nodeint/migent-kernel";
3
3
  export class ProviderCommandFailed extends Error {
4
4
  }
5
- export function adapterMap() {
6
- return defaultAdapters();
5
+ export function providerMap() {
6
+ return defaultProviders();
7
7
  }
8
- export function asCatalog(adapter) {
9
- const candidate = adapter;
8
+ export function asCatalog(provider) {
9
+ const candidate = provider;
10
10
  if (typeof candidate.modelCatalogCommand !== "function" || typeof candidate.parseModelCatalog !== "function") {
11
- throw new ProviderCommandFailed(`${adapter.command} does not list models.`);
11
+ throw new ProviderCommandFailed(`${provider.command} does not list models.`);
12
12
  }
13
13
  return candidate;
14
14
  }
15
- export function requireAdapter(adapters, provider) {
16
- const adapter = adapters[provider];
17
- if (adapter === undefined) {
18
- const supported = Object.keys(adapters).sort().join(", ");
15
+ export function requireProvider(providers, provider) {
16
+ const impl = providers[provider];
17
+ if (impl === undefined) {
18
+ const supported = Object.keys(providers).sort().join(", ");
19
19
  throw new ProviderCommandFailed(`Unknown provider: ${provider}. Supported: ${supported}.`);
20
20
  }
21
- return adapter;
21
+ return impl;
22
22
  }
23
- export function detected(adapters, which) {
24
- const rows = Object.entries(adapters).map(([name, adapter]) => [name, which(adapter.command), adapter]);
23
+ export function detected(providers, which) {
24
+ const rows = Object.entries(providers).filter(([, provider]) => provider.requiresClient !== true).map(([name, provider]) => [name, which(provider.command), provider]);
25
25
  rows.sort((left, right) => {
26
26
  const leftMissing = left[1] === null ? 1 : 0;
27
27
  const rightMissing = right[1] === null ? 1 : 0;
@@ -35,24 +35,24 @@ export function detected(adapters, which) {
35
35
  });
36
36
  return rows;
37
37
  }
38
- export async function loadCatalog(adapter, which, runCommand) {
39
- if (which(adapter.command) === null) {
40
- throw new ProviderCommandFailed(`${adapter.command} is not on PATH, so its models could not be listed.`);
38
+ export async function loadCatalog(provider, which, runCommand) {
39
+ if (which(provider.command) === null) {
40
+ throw new ProviderCommandFailed(`${provider.command} is not on PATH, so its models could not be listed.`);
41
41
  }
42
- const catalogAdapter = asCatalog(adapter);
42
+ const catalogProvider = asCatalog(provider);
43
43
  let stdout;
44
44
  try {
45
- stdout = await runCommand(catalogAdapter.modelCatalogCommand());
45
+ stdout = await runCommand(catalogProvider.modelCatalogCommand(), catalogProvider.modelCatalogInput?.());
46
46
  }
47
47
  catch (error) {
48
48
  if (error instanceof ProviderCommandFailed)
49
49
  throw error;
50
50
  const reason = error instanceof Error ? error.message : String(error);
51
- throw new ProviderCommandFailed(`Could not list ${adapter.command} models: ${reason}`);
51
+ throw new ProviderCommandFailed(`Could not list ${provider.command} models: ${reason}`);
52
52
  }
53
- const catalog = catalogAdapter.parseModelCatalog(stdout);
53
+ const catalog = catalogProvider.parseModelCatalog(stdout);
54
54
  if (catalog.ids.length === 0)
55
- throw new ProviderCommandFailed(`${adapter.command} returned no models.`);
55
+ throw new ProviderCommandFailed(`${provider.command} returned no models.`);
56
56
  return catalog;
57
57
  }
58
58
  export function knownModel(model, catalog) {
@@ -75,16 +75,16 @@ export function parseOptions(pairs) {
75
75
  }
76
76
  return parsed;
77
77
  }
78
- export async function loadOptionValues(adapter, name, model, catalog, which, runCommand) {
78
+ export async function loadOptionValues(provider, name, model, catalog, which, runCommand) {
79
79
  const found = catalog.valuesFor(model, name);
80
80
  if (found !== null)
81
81
  return found;
82
- const catalogAdapter = asCatalog(adapter);
83
- const argv = catalogAdapter.optionValuesCommand(name, model);
82
+ const catalogProvider = asCatalog(provider);
83
+ const argv = catalogProvider.optionValuesCommand(name, model);
84
84
  if (argv === null)
85
85
  return null;
86
- if (which(adapter.command) === null) {
87
- throw new ProviderCommandFailed(`${adapter.command} is not on PATH, so its ${name} values could not be listed.`);
86
+ if (which(provider.command) === null) {
87
+ throw new ProviderCommandFailed(`${provider.command} is not on PATH, so its ${name} values could not be listed.`);
88
88
  }
89
89
  let text;
90
90
  try {
@@ -95,18 +95,18 @@ export async function loadOptionValues(adapter, name, model, catalog, which, run
95
95
  text = error.message;
96
96
  else {
97
97
  const reason = error instanceof Error ? error.message : String(error);
98
- throw new ProviderCommandFailed(`Could not list ${adapter.command} ${name} values for ${model}: ${reason}`);
98
+ throw new ProviderCommandFailed(`Could not list ${provider.command} ${name} values for ${model}: ${reason}`);
99
99
  }
100
100
  }
101
- return catalogAdapter.parseOptionValues(name, text, model);
101
+ return catalogProvider.parseOptionValues(name, text, model);
102
102
  }
103
- export async function acceptedOptions(adapter, model, catalog, which, runCommand, options) {
103
+ export async function acceptedOptions(provider, model, catalog, which, runCommand, options) {
104
104
  if (Object.keys(options).length === 0)
105
105
  return {};
106
- adapter.validateOptions(options);
106
+ provider.validateOptions(options);
107
107
  const stored = {};
108
108
  for (const [name, value] of Object.entries(options)) {
109
- const values = await loadOptionValues(adapter, name, model, catalog, which, runCommand);
109
+ const values = await loadOptionValues(provider, name, model, catalog, which, runCommand);
110
110
  if (values === null) {
111
111
  stored[name] = value;
112
112
  continue;
@@ -120,11 +120,16 @@ export async function acceptedOptions(adapter, model, catalog, which, runCommand
120
120
  }
121
121
  return stored;
122
122
  }
123
- export function runProviderCommand(argv) {
123
+ export function runProviderCommand(argv, input) {
124
124
  const [command, ...args] = argv;
125
125
  if (command === undefined)
126
126
  throw new ProviderCommandFailed("Provider command is empty.");
127
- const completed = spawnProviderSync(command, args, { encoding: "utf8", timeout: 60_000, windowsHide: true });
127
+ const completed = spawnProviderSync(command, args, {
128
+ encoding: "utf8",
129
+ timeout: 60_000,
130
+ windowsHide: true,
131
+ ...(input === undefined ? {} : { input }),
132
+ });
128
133
  if (completed.error) {
129
134
  throw new Error(completed.error.message);
130
135
  }
@@ -7,9 +7,11 @@ export declare const SESSION_COLUMN: {
7
7
  readonly decision: 5;
8
8
  readonly outputs: 6;
9
9
  readonly task: 7;
10
+ readonly title: 8;
10
11
  };
11
12
  export interface SessionFields {
12
13
  session: string;
14
+ title: string;
13
15
  workflow: string;
14
16
  status: string;
15
17
  execution: string;
@@ -7,10 +7,12 @@ export const SESSION_COLUMN = {
7
7
  decision: 5,
8
8
  outputs: 6,
9
9
  task: 7,
10
+ title: 8,
10
11
  };
11
12
  export function sessionFields(row) {
12
13
  return {
13
14
  session: row[SESSION_COLUMN.session] ?? "",
15
+ title: row[SESSION_COLUMN.title] ?? "",
14
16
  workflow: row[SESSION_COLUMN.workflow] ?? "",
15
17
  status: row[SESSION_COLUMN.status] ?? "",
16
18
  execution: row[SESSION_COLUMN.execution] ?? "",