@maiaos/cli 0.1.0-canary.44938d4.manual.1

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.
Files changed (75) hide show
  1. package/README.md +382 -0
  2. package/dist/bin/maia.NOTICES.txt +31 -0
  3. package/dist/bin/maia.cdx.json +138 -0
  4. package/dist/bin/maia.mjs +115 -0
  5. package/dist/command-line/arguments.d.ts +21 -0
  6. package/dist/command-line/arguments.js +99 -0
  7. package/dist/command-line/context.d.ts +112 -0
  8. package/dist/command-line/context.js +2 -0
  9. package/dist/command-line/help.d.ts +36 -0
  10. package/dist/command-line/help.js +267 -0
  11. package/dist/command-line/output.d.ts +2111 -0
  12. package/dist/command-line/output.js +643 -0
  13. package/dist/command-line/stdin.d.ts +7 -0
  14. package/dist/command-line/stdin.js +34 -0
  15. package/dist/command-receipt/command.d.ts +3 -0
  16. package/dist/command-receipt/command.js +63 -0
  17. package/dist/command-receipt/compact-list.d.ts +18 -0
  18. package/dist/command-receipt/compact-list.js +18 -0
  19. package/dist/context/client.d.ts +4 -0
  20. package/dist/context/client.js +19 -0
  21. package/dist/context/commands.d.ts +3 -0
  22. package/dist/context/commands.js +13 -0
  23. package/dist/index.d.ts +7 -0
  24. package/dist/index.js +202 -0
  25. package/dist/integration-authorization/client.d.ts +16 -0
  26. package/dist/integration-authorization/client.js +30 -0
  27. package/dist/integration-authorization/commands.d.ts +3 -0
  28. package/dist/integration-authorization/commands.js +92 -0
  29. package/dist/local-node/client.d.ts +31 -0
  30. package/dist/local-node/client.js +99 -0
  31. package/dist/orchestration/client.d.ts +59 -0
  32. package/dist/orchestration/client.js +66 -0
  33. package/dist/orchestration/commands.d.ts +3 -0
  34. package/dist/orchestration/commands.js +336 -0
  35. package/dist/orchestration/compact-aggregate.d.ts +123 -0
  36. package/dist/orchestration/compact-aggregate.js +110 -0
  37. package/dist/orchestration/compact-run-list.d.ts +19 -0
  38. package/dist/orchestration/compact-run-list.js +16 -0
  39. package/dist/project-workspace/client.d.ts +43 -0
  40. package/dist/project-workspace/client.js +54 -0
  41. package/dist/project-workspace/commands.d.ts +5 -0
  42. package/dist/project-workspace/commands.js +239 -0
  43. package/dist/runtime/client.d.ts +6 -0
  44. package/dist/runtime/client.js +10 -0
  45. package/dist/runtime/command.d.ts +3 -0
  46. package/dist/runtime/command.js +20 -0
  47. package/dist/session/client.d.ts +32 -0
  48. package/dist/session/client.js +30 -0
  49. package/dist/session/commands.d.ts +3 -0
  50. package/dist/session/commands.js +160 -0
  51. package/dist/status/client.d.ts +5 -0
  52. package/dist/status/client.js +15 -0
  53. package/dist/status/command.d.ts +3 -0
  54. package/dist/status/command.js +17 -0
  55. package/dist/status/compact.d.ts +31 -0
  56. package/dist/status/compact.js +46 -0
  57. package/dist/terminal/arguments.d.ts +12 -0
  58. package/dist/terminal/arguments.js +79 -0
  59. package/dist/terminal/client.d.ts +45 -0
  60. package/dist/terminal/client.js +48 -0
  61. package/dist/terminal/commands.d.ts +3 -0
  62. package/dist/terminal/commands.js +151 -0
  63. package/dist/terminal/compact-list.d.ts +148 -0
  64. package/dist/terminal/compact-list.js +152 -0
  65. package/dist/terminal/control-commands.d.ts +7 -0
  66. package/dist/terminal/control-commands.js +211 -0
  67. package/dist/turn/client.d.ts +17 -0
  68. package/dist/turn/client.js +23 -0
  69. package/dist/turn/commands.d.ts +3 -0
  70. package/dist/turn/commands.js +126 -0
  71. package/dist/turn/prompt.d.ts +2 -0
  72. package/dist/turn/prompt.js +9 -0
  73. package/guidance/maia-cli/SKILL.md +75 -0
  74. package/guidance/maia-orchestration/SKILL.md +54 -0
  75. package/package.json +50 -0
@@ -0,0 +1,63 @@
1
+ import { DEFAULT_RECEIPT_LIST_PAGE_SIZE, } from "@maiaos/sdk";
2
+ import { CliArgumentError, parseOptions, requirePositionals, } from "../command-line/arguments.js";
3
+ import { writeNodeResult } from "../command-line/output.js";
4
+ import { projectReceiptListResult } from "./compact-list.js";
5
+ const RECEIPT_LIST_USAGE = "maia [--json] receipt list [--limit <1..32>] [--after <cursor>] [--actor <actor-id>] [--method <method>] [--since <recorded-at>] [--until <recorded-at>]";
6
+ const RECEIPT_SHOW_USAGE = "maia receipt show <command-id>";
7
+ const readReceiptListPageSize = (value) => {
8
+ if (value === undefined)
9
+ return DEFAULT_RECEIPT_LIST_PAGE_SIZE;
10
+ if (!/^(?:[1-9]|[12]\d|3[0-2])$/u.test(value)) {
11
+ throw new CliArgumentError("Option '--limit' must be an integer from 1 to 32.");
12
+ }
13
+ return Number(value);
14
+ };
15
+ const optionalListFilter = (options, flag, key) => {
16
+ const value = options.get(flag);
17
+ return value === undefined ? {} : { [key]: value };
18
+ };
19
+ const readReceiptListParameters = (tokens) => {
20
+ const parsed = parseOptions(tokens, new Set([
21
+ "--actor",
22
+ "--after",
23
+ "--limit",
24
+ "--method",
25
+ "--since",
26
+ "--until",
27
+ ]));
28
+ requirePositionals(parsed.positionals, 0, RECEIPT_LIST_USAGE);
29
+ return {
30
+ limit: readReceiptListPageSize(parsed.options.get("--limit")),
31
+ ...optionalListFilter(parsed.options, "--actor", "actor"),
32
+ ...optionalListFilter(parsed.options, "--after", "afterCursor"),
33
+ ...optionalListFilter(parsed.options, "--method", "method"),
34
+ ...optionalListFilter(parsed.options, "--since", "since"),
35
+ ...optionalListFilter(parsed.options, "--until", "until"),
36
+ };
37
+ };
38
+ const runReceiptList = async (tokens, context) => {
39
+ const result = await context.dependencies.listReceipts(readReceiptListParameters(tokens));
40
+ return writeNodeResult(result, context, projectReceiptListResult);
41
+ };
42
+ const runReceiptShow = async (tokens, context) => {
43
+ const parsed = parseOptions(tokens, new Set());
44
+ requirePositionals(parsed.positionals, 1, RECEIPT_SHOW_USAGE);
45
+ const commandId = parsed.positionals[0];
46
+ if (commandId === undefined) {
47
+ throw new CliArgumentError("The command identifier is missing.");
48
+ }
49
+ const result = await context.dependencies.getReceipt(commandId);
50
+ return writeNodeResult(result, context, (value) => ({
51
+ command: "receipt.show",
52
+ result: value,
53
+ }));
54
+ };
55
+ export const runReceiptCommand = async (tokens, context) => {
56
+ const [subcommand, ...rest] = tokens;
57
+ if (subcommand === "list")
58
+ return runReceiptList(rest, context);
59
+ if (subcommand === "show")
60
+ return runReceiptShow(rest, context);
61
+ throw new CliArgumentError(`Usage: ${RECEIPT_LIST_USAGE} | ${RECEIPT_SHOW_USAGE}`);
62
+ };
63
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1,18 @@
1
+ import type { ReceiptListResult } from "@maiaos/sdk";
2
+ export type CliReceiptListItem = {
3
+ readonly commandId: ReceiptListResult["items"][number]["commandId"];
4
+ readonly createdAt: ReceiptListResult["items"][number]["createdAt"];
5
+ readonly method: ReceiptListResult["items"][number]["method"];
6
+ readonly receiptId: ReceiptListResult["items"][number]["receiptId"];
7
+ readonly state: ReceiptListResult["items"][number]["state"];
8
+ readonly target: ReceiptListResult["items"][number]["target"];
9
+ };
10
+ export type CliReceiptListResult = {
11
+ readonly command: "receipt.list";
12
+ readonly count: number;
13
+ readonly items: readonly CliReceiptListItem[];
14
+ readonly nextCursor?: ReceiptListResult["nextCursor"];
15
+ };
16
+ export declare const projectReceiptListItem: (item: ReceiptListResult["items"][number]) => CliReceiptListItem;
17
+ export declare const projectReceiptListResult: (value: ReceiptListResult) => CliReceiptListResult;
18
+ //# sourceMappingURL=compact-list.d.ts.map
@@ -0,0 +1,18 @@
1
+ export const projectReceiptListItem = (item) => ({
2
+ commandId: item.commandId,
3
+ createdAt: item.createdAt,
4
+ method: item.method,
5
+ receiptId: item.receiptId,
6
+ state: item.state,
7
+ target: {
8
+ id: item.target.id,
9
+ type: item.target.type,
10
+ },
11
+ });
12
+ export const projectReceiptListResult = (value) => ({
13
+ command: "receipt.list",
14
+ count: value.items.length,
15
+ items: value.items.map(projectReceiptListItem),
16
+ ...(value.nextCursor === undefined ? {} : { nextCursor: value.nextCursor }),
17
+ });
18
+ //# sourceMappingURL=compact-list.js.map
@@ -0,0 +1,4 @@
1
+ import type { InvocationContextShowResult } from "@maiaos/sdk";
2
+ import { type CliNodeResult } from "../local-node/client.js";
3
+ export declare const showCurrentContext: () => Promise<CliNodeResult<InvocationContextShowResult>>;
4
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { INVOCATION_CONTEXT_ERROR_NODE_UNAVAILABLE, invocationContextShowParametersSchema, } from "@maiaos/sdk";
2
+ import { runValidatedNodeOperation, } from "../local-node/client.js";
3
+ const nodeContextUnavailable = () => Promise.resolve({
4
+ error: {
5
+ code: INVOCATION_CONTEXT_ERROR_NODE_UNAVAILABLE,
6
+ message: "The authenticated Maia node is unavailable.",
7
+ retryable: true,
8
+ },
9
+ ok: false,
10
+ });
11
+ export const showCurrentContext = () => {
12
+ return runValidatedNodeOperation({}, invocationContextShowParametersSchema, (client, parameters, options) => client.showCurrentContext(parameters, options)).then((result) => {
13
+ if (!result.ok && result.error.code === "node_unavailable") {
14
+ return nodeContextUnavailable();
15
+ }
16
+ return result;
17
+ });
18
+ };
19
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,3 @@
1
+ import type { CommandContext } from "../command-line/context.js";
2
+ export declare const runContextCommand: (tokens: readonly string[], context: CommandContext) => Promise<number>;
3
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { CliArgumentError, requireNoArguments, } from "../command-line/arguments.js";
2
+ import { writeCurrentContextResult } from "../command-line/output.js";
3
+ export const runContextCommand = (tokens, context) => {
4
+ const [subcommand, ...rest] = tokens;
5
+ if (subcommand !== "show") {
6
+ throw new CliArgumentError("Usage: maia context show");
7
+ }
8
+ requireNoArguments(rest, "Context show");
9
+ return context.dependencies
10
+ .showCurrentContext()
11
+ .then((result) => writeCurrentContextResult(result, context));
12
+ };
13
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1,7 @@
1
+ import type { CliDependencies } from "./command-line/context.js";
2
+ import { type CliIo } from "./command-line/output.js";
3
+ export type { CliDependencies } from "./command-line/context.js";
4
+ export type { CliErrorOutput, CliHelpResult, CliIo, CliStatusResult, CliSuccessOutput, CliSuccessResult, CliVersionResult, } from "./command-line/output.js";
5
+ export declare const makeCli: (dependencies: CliDependencies) => (arguments_: readonly string[], version: string, io: CliIo) => Promise<number>;
6
+ export declare const runCli: (arguments_: readonly string[], version: string, io: CliIo) => Promise<number>;
7
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,202 @@
1
+ import { argumentsAreBounded, CliArgumentError, parseArguments, requireNoArguments, } from "./command-line/arguments.js";
2
+ import { createHelpResult } from "./command-line/help.js";
3
+ import { reportError, writeNodeResult, writeSuccess, } from "./command-line/output.js";
4
+ import { runReceiptCommand } from "./command-receipt/command.js";
5
+ import { runContextCommand } from "./context/commands.js";
6
+ import { runIntegrationCommand } from "./integration-authorization/commands.js";
7
+ import { runOrchestrationCommand } from "./orchestration/commands.js";
8
+ import { runExecutionCommand, runProjectCommand, runWorkspaceCommand, } from "./project-workspace/commands.js";
9
+ import { runRuntimeCommand } from "./runtime/command.js";
10
+ import { runSessionCommand } from "./session/commands.js";
11
+ import { runStatusCommand } from "./status/command.js";
12
+ import { runTerminalCommand } from "./terminal/commands.js";
13
+ import { runTurnCommand } from "./turn/commands.js";
14
+ const HELP_ALIASES = new Set(["help", "--help", "-h"]);
15
+ const VERSION_ALIASES = new Set(["version", "--version", "-v"]);
16
+ const createArgumentError = (message) => ({
17
+ code: "invalid_argument",
18
+ message,
19
+ retryable: false,
20
+ });
21
+ const runHelpCommand = (rest, context) => {
22
+ writeSuccess(createHelpResult(context.version, rest), context.json, context.io);
23
+ return Promise.resolve(0);
24
+ };
25
+ const runVersionCommand = (rest, context) => {
26
+ requireNoArguments(rest, "Version");
27
+ writeSuccess({ command: "version", name: "maia", version: context.version }, context.json, context.io);
28
+ return Promise.resolve(0);
29
+ };
30
+ const runMonitorCommand = (rest, context) => {
31
+ requireNoArguments(rest, "Monitor");
32
+ return (context.dependencies.createMonitorBootstrap?.().then((result) => writeNodeResult(result, context, (value) => ({
33
+ command: "monitor",
34
+ result: value,
35
+ }))) ?? Promise.reject(new Error("No monitor.")));
36
+ };
37
+ const PRODUCT_COMMANDS = {
38
+ context: runContextCommand,
39
+ execution: runExecutionCommand,
40
+ integration: runIntegrationCommand,
41
+ project: runProjectCommand,
42
+ receipt: runReceiptCommand,
43
+ run: runOrchestrationCommand,
44
+ runtime: runRuntimeCommand,
45
+ session: runSessionCommand,
46
+ terminal: runTerminalCommand,
47
+ turn: runTurnCommand,
48
+ workspace: runWorkspaceCommand,
49
+ };
50
+ const runCommand = (tokens, context) => {
51
+ const [command, ...rest] = tokens;
52
+ if (command === undefined || HELP_ALIASES.has(command))
53
+ return runHelpCommand(rest, context);
54
+ if (VERSION_ALIASES.has(command))
55
+ return runVersionCommand(rest, context);
56
+ if (command === "status") {
57
+ requireNoArguments(rest, "Status");
58
+ return runStatusCommand(context);
59
+ }
60
+ if (command === "monitor")
61
+ return runMonitorCommand(rest, context);
62
+ const product = PRODUCT_COMMANDS[command];
63
+ if (product !== undefined)
64
+ return product(rest, context);
65
+ if (command.startsWith("-"))
66
+ throw new CliArgumentError("Command has an unknown option.");
67
+ return Promise.resolve(reportError({
68
+ code: "command_not_implemented",
69
+ message: "Command not implemented.",
70
+ retryable: false,
71
+ }, context));
72
+ };
73
+ const parseInvocation = (input) => {
74
+ if (!argumentsAreBounded(input.arguments_)) {
75
+ return {
76
+ exitCode: reportError(createArgumentError("Command arguments exceed the limit."), { io: input.io, json: input.arguments_.includes("--json") }),
77
+ ok: false,
78
+ };
79
+ }
80
+ const parsed = parseArguments(input.arguments_);
81
+ if (parsed.jsonFlagCount > 1) {
82
+ return {
83
+ exitCode: reportError(createArgumentError("Option '--json' may be used only once."), { io: input.io, json: true }),
84
+ ok: false,
85
+ };
86
+ }
87
+ return { ok: true, parsed };
88
+ };
89
+ const executeCli = async (input) => {
90
+ const invocation = parseInvocation(input);
91
+ if (!invocation.ok)
92
+ return invocation.exitCode;
93
+ const context = {
94
+ dependencies: input.dependencies,
95
+ io: input.io,
96
+ json: invocation.parsed.json,
97
+ version: input.version,
98
+ };
99
+ try {
100
+ return await runCommand(invocation.parsed.tokens, context);
101
+ }
102
+ catch (error) {
103
+ return error instanceof CliArgumentError
104
+ ? reportError(createArgumentError(error.message), context)
105
+ : reportError({
106
+ code: "internal_error",
107
+ message: "Maia CLI command failed.",
108
+ retryable: false,
109
+ }, context);
110
+ }
111
+ };
112
+ export const makeCli = (dependencies) => (arguments_, version, io) => executeCli({
113
+ arguments_,
114
+ dependencies,
115
+ io,
116
+ version,
117
+ });
118
+ const readStatus = async () => {
119
+ const { readLocalNodeStatus } = await import("./status/client.js");
120
+ return readLocalNodeStatus();
121
+ };
122
+ const loadIntegrationAuthorization = () => import("./integration-authorization/client.js");
123
+ const loadProjectWorkspace = () => import("./project-workspace/client.js");
124
+ const loadOrchestration = () => import("./orchestration/client.js");
125
+ const loadSession = () => import("./session/client.js");
126
+ const loadTerminal = () => import("./terminal/client.js");
127
+ const loadTurn = () => import("./turn/client.js");
128
+ const loadStatus = () => import("./status/client.js");
129
+ const loadRuntime = () => import("./runtime/client.js");
130
+ const loadContext = () => import("./context/client.js");
131
+ const lazyDependencies = (load, names) => Object.fromEntries(names.map((name) => [
132
+ name,
133
+ (...arguments_) => load().then((module) => {
134
+ const operation = module[name];
135
+ return operation(...arguments_);
136
+ }),
137
+ ]));
138
+ const defaultCliDependencies = {
139
+ ...lazyDependencies(loadIntegrationAuthorization, [
140
+ "applyIntegration",
141
+ "planIntegration",
142
+ "removeIntegration",
143
+ "statusIntegration",
144
+ ]),
145
+ ...lazyDependencies(loadProjectWorkspace, [
146
+ "attachWorkspaceRepository",
147
+ "configureWorkspaceExecution",
148
+ "getReceipt",
149
+ "listProjects",
150
+ "listReceipts",
151
+ "listWorkspaces",
152
+ "readExecutionCatalog",
153
+ "registerProject",
154
+ "showProject",
155
+ "showWorkspace",
156
+ "showWorkspaceExecution",
157
+ ]),
158
+ ...lazyDependencies(loadOrchestration, [
159
+ "acknowledgeRunDelivery",
160
+ "cancelRunQuestion",
161
+ "checkRunInbox",
162
+ "createRun",
163
+ "listRuns",
164
+ "listTasks",
165
+ "openRunQuestion",
166
+ "replyRunQuestion",
167
+ "settleRunDispatchTerminal",
168
+ "showDispatch",
169
+ "showRun",
170
+ "showTask",
171
+ ]),
172
+ ...lazyDependencies(loadSession, [
173
+ "createSession",
174
+ "listSessionEvents",
175
+ "listSessions",
176
+ "showSession",
177
+ "startSession",
178
+ ]),
179
+ ...lazyDependencies(loadTerminal, [
180
+ "acquireTerminalController",
181
+ "closeTerminal",
182
+ "createTerminal",
183
+ "listTerminalEvents",
184
+ "listTerminals",
185
+ "readTerminal",
186
+ "releaseTerminalController",
187
+ "requestTerminalController",
188
+ "resizeTerminal",
189
+ "showTerminal",
190
+ "showTerminalControllerRequest",
191
+ "signalTerminal",
192
+ "writeTerminalInput",
193
+ ]),
194
+ ...lazyDependencies(loadTurn, ["interruptTurn", "sendTurn", "showTurn"]),
195
+ ...lazyDependencies(loadRuntime, ["listInstalledHarnesses"]),
196
+ ...lazyDependencies(loadContext, ["showCurrentContext"]),
197
+ ...lazyDependencies(loadStatus, ["createMonitorBootstrap"]),
198
+ probeRuntime: (runtime = "codex") => loadRuntime().then((module) => module.probeRuntime(runtime)),
199
+ readStatus,
200
+ };
201
+ export const runCli = makeCli(defaultCliDependencies);
202
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ import type { IntegrationApplyCodexResult, IntegrationApplyPiRpcResult, IntegrationPlanCodexResult, IntegrationPlanPiRpcResult, IntegrationRemoveCodexResult, IntegrationRemovePiRpcResult, IntegrationStatusCodexResult, IntegrationStatusPiRpcResult } from "@maiaos/sdk";
2
+ import { type CliNodeResult } from "../local-node/client.js";
3
+ export type IntegrationTarget = "codex" | "pi-rpc";
4
+ export declare const planIntegration: (integration: IntegrationTarget) => Promise<CliNodeResult<IntegrationPlanCodexResult | IntegrationPlanPiRpcResult>>;
5
+ type ApplyIntegrationInput = {
6
+ readonly commandId?: string;
7
+ readonly planId: string;
8
+ };
9
+ export declare const applyIntegration: (integration: IntegrationTarget, input: ApplyIntegrationInput) => Promise<CliNodeResult<IntegrationApplyCodexResult | IntegrationApplyPiRpcResult>>;
10
+ export declare const statusIntegration: (integration: IntegrationTarget) => Promise<CliNodeResult<IntegrationStatusCodexResult | IntegrationStatusPiRpcResult>>;
11
+ type RemoveIntegrationInput = {
12
+ readonly commandId?: string;
13
+ };
14
+ export declare const removeIntegration: (integration: IntegrationTarget, input: RemoveIntegrationInput) => Promise<CliNodeResult<IntegrationRemoveCodexResult | IntegrationRemovePiRpcResult>>;
15
+ export {};
16
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,30 @@
1
+ import { integrationApplyCodexParametersSchema, integrationApplyPiRpcParametersSchema, integrationPlanCodexParametersSchema, integrationPlanPiRpcParametersSchema, integrationRemoveCodexParametersSchema, integrationRemovePiRpcParametersSchema, integrationStatusCodexParametersSchema, integrationStatusPiRpcParametersSchema, } from "@maiaos/sdk";
2
+ import { newCliIdentifier, runValidatedNodeOperation, } from "../local-node/client.js";
3
+ const commandId = (requested) => requested ?? newCliIdentifier("command");
4
+ export const planIntegration = (integration) => {
5
+ if (integration === "codex") {
6
+ return runValidatedNodeOperation({ integration }, integrationPlanCodexParametersSchema, (client, parameters, options) => client.planCodexIntegration(parameters, options));
7
+ }
8
+ return runValidatedNodeOperation({ integration }, integrationPlanPiRpcParametersSchema, (client, parameters, options) => client.planPiRpcIntegration(parameters, options));
9
+ };
10
+ export const applyIntegration = (integration, input) => {
11
+ const selectedCommandId = commandId(input.commandId);
12
+ if (integration === "codex") {
13
+ return runValidatedNodeOperation({ commandId: selectedCommandId, planId: input.planId }, integrationApplyCodexParametersSchema, (client, parameters, options) => client.applyCodexIntegration(parameters, options), { commandId: selectedCommandId });
14
+ }
15
+ return runValidatedNodeOperation({ commandId: selectedCommandId, planId: input.planId }, integrationApplyPiRpcParametersSchema, (client, parameters, options) => client.applyPiRpcIntegration(parameters, options), { commandId: selectedCommandId });
16
+ };
17
+ export const statusIntegration = (integration) => {
18
+ if (integration === "codex") {
19
+ return runValidatedNodeOperation({ integration }, integrationStatusCodexParametersSchema, (client, parameters, options) => client.statusCodexIntegration(parameters, options));
20
+ }
21
+ return runValidatedNodeOperation({ integration }, integrationStatusPiRpcParametersSchema, (client, parameters, options) => client.statusPiRpcIntegration(parameters, options));
22
+ };
23
+ export const removeIntegration = (integration, input) => {
24
+ const selectedCommandId = commandId(input.commandId);
25
+ if (integration === "codex") {
26
+ return runValidatedNodeOperation({ commandId: selectedCommandId, integration }, integrationRemoveCodexParametersSchema, (client, parameters, options) => client.removeCodexIntegration(parameters, options), { commandId: selectedCommandId });
27
+ }
28
+ return runValidatedNodeOperation({ commandId: selectedCommandId, integration }, integrationRemovePiRpcParametersSchema, (client, parameters, options) => client.removePiRpcIntegration(parameters, options), { commandId: selectedCommandId });
29
+ };
30
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,3 @@
1
+ import type { CommandContext } from "../command-line/context.js";
2
+ export declare const runIntegrationCommand: (tokens: readonly string[], context: CommandContext) => Promise<number>;
3
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1,92 @@
1
+ import { CliArgumentError, parseOptions, requirePositionals, } from "../command-line/arguments.js";
2
+ import { writeIntegrationApplyResult, writeIntegrationPlanResult, writeIntegrationRemoveResult, writeIntegrationStatusResult, } from "../command-line/output.js";
3
+ const EXIT_OUTCOME_UNKNOWN = 76;
4
+ const integrationUsage = (tail) => `maia integration ${tail}`;
5
+ const PLAN_USAGE = integrationUsage("plan <codex|pi-rpc>");
6
+ const APPLY_USAGE = integrationUsage("apply <plan-id> [--integration <codex|pi-rpc>] [--command-id <id>]");
7
+ const STATUS_USAGE = integrationUsage("status <codex|pi-rpc>");
8
+ const REMOVE_USAGE = integrationUsage("remove <codex|pi-rpc> [--command-id <id>]");
9
+ const INTEGRATION_USAGE = [
10
+ PLAN_USAGE,
11
+ APPLY_USAGE,
12
+ STATUS_USAGE,
13
+ REMOVE_USAGE,
14
+ ].join(" | ");
15
+ const requireIntegrationTarget = (value) => {
16
+ if (value === "codex" || value === "pi-rpc")
17
+ return value;
18
+ throw new CliArgumentError(`Usage: ${INTEGRATION_USAGE}`);
19
+ };
20
+ const applyIntegrationTarget = (options) => {
21
+ const requested = options.get("--integration");
22
+ return requested === undefined
23
+ ? "codex"
24
+ : requireIntegrationTarget(requested);
25
+ };
26
+ const runPlan = (tokens, context) => {
27
+ const parsed = parseOptions(tokens, new Set());
28
+ requirePositionals(parsed.positionals, 1, PLAN_USAGE);
29
+ const integration = requireIntegrationTarget(parsed.positionals[0]);
30
+ const operation = context.dependencies.planIntegration;
31
+ if (operation === undefined)
32
+ throw new Error("Missing integration client.");
33
+ return operation(integration).then((result) => writeIntegrationPlanResult(result, context));
34
+ };
35
+ const runApply = (tokens, context) => {
36
+ const parsed = parseOptions(tokens, new Set(["--command-id", "--integration"]));
37
+ requirePositionals(parsed.positionals, 1, APPLY_USAGE);
38
+ const planId = parsed.positionals[0];
39
+ if (planId === undefined)
40
+ throw new CliArgumentError("The integration plan identifier is missing.");
41
+ const integration = applyIntegrationTarget(parsed.options);
42
+ const operation = context.dependencies.applyIntegration;
43
+ if (operation === undefined)
44
+ throw new Error("Missing integration client.");
45
+ const requestedCommandId = parsed.options.get("--command-id");
46
+ return operation(integration, {
47
+ planId,
48
+ ...(requestedCommandId === undefined
49
+ ? {}
50
+ : { commandId: requestedCommandId }),
51
+ }).then((result) => writeIntegrationApplyResult(result, context));
52
+ };
53
+ const runStatus = (tokens, context) => {
54
+ const parsed = parseOptions(tokens, new Set());
55
+ requirePositionals(parsed.positionals, 1, STATUS_USAGE);
56
+ const integration = requireIntegrationTarget(parsed.positionals[0]);
57
+ const operation = context.dependencies.statusIntegration;
58
+ if (operation === undefined)
59
+ throw new Error("Missing integration client.");
60
+ return operation(integration).then((result) => writeIntegrationStatusResult(result, context));
61
+ };
62
+ const runRemove = async (tokens, context) => {
63
+ const parsed = parseOptions(tokens, new Set(["--command-id"]));
64
+ requirePositionals(parsed.positionals, 1, REMOVE_USAGE);
65
+ const integration = requireIntegrationTarget(parsed.positionals[0]);
66
+ const operation = context.dependencies.removeIntegration;
67
+ if (operation === undefined)
68
+ throw new Error("Missing integration client.");
69
+ const requestedCommandId = parsed.options.get("--command-id");
70
+ const result = await operation(integration, {
71
+ ...(requestedCommandId === undefined
72
+ ? {}
73
+ : { commandId: requestedCommandId }),
74
+ });
75
+ const exitCode = writeIntegrationRemoveResult(result, context);
76
+ return result.ok && result.value.outcome === "cleanup_unknown"
77
+ ? EXIT_OUTCOME_UNKNOWN
78
+ : exitCode;
79
+ };
80
+ export const runIntegrationCommand = (tokens, context) => {
81
+ const [subcommand, ...rest] = tokens;
82
+ if (subcommand === "plan")
83
+ return runPlan(rest, context);
84
+ if (subcommand === "apply")
85
+ return runApply(rest, context);
86
+ if (subcommand === "status")
87
+ return runStatus(rest, context);
88
+ if (subcommand === "remove")
89
+ return runRemove(rest, context);
90
+ throw new CliArgumentError(`Usage: ${INTEGRATION_USAGE}`);
91
+ };
92
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1,31 @@
1
+ import type { LocalNodeClient, LocalNodeRequestOptions, ProtocolError } from "@maiaos/sdk";
2
+ import { type LocalNodeConnection, type LocalNodeDiscoveryOptions } from "@maiaos/sdk/node";
3
+ export type CliMutationRecovery = {
4
+ readonly commandId: string;
5
+ };
6
+ export type CliNodeResult<TValue> = {
7
+ readonly error: ProtocolError;
8
+ readonly ok: false;
9
+ readonly recovery?: CliMutationRecovery;
10
+ } | {
11
+ readonly ok: true;
12
+ readonly value: TValue;
13
+ };
14
+ export declare const newCliIdentifier: (prefix: "command" | "request") => string;
15
+ export declare const resolveCliDiscoveryOptions: () => LocalNodeDiscoveryOptions;
16
+ export declare const connectCliLocalNode: (signal: AbortSignal) => Promise<LocalNodeConnection>;
17
+ export declare const outcomeCanBeAmbiguous: (error: unknown) => boolean;
18
+ export declare const invalidNodeInput: <TValue>() => Promise<CliNodeResult<TValue>>;
19
+ export declare const runNodeOperation: <TValue>(operation: (signal: AbortSignal) => Promise<TValue>, recovery?: CliMutationRecovery) => Promise<CliNodeResult<TValue>>;
20
+ export declare const runNodeClientOperation: <TValue>(operation: (client: LocalNodeClient, options: LocalNodeRequestOptions) => Promise<TValue>, recovery?: CliMutationRecovery) => Promise<CliNodeResult<TValue>>;
21
+ type ParameterSchema<TParameters> = {
22
+ readonly safeParse: (input: unknown) => {
23
+ readonly data: TParameters;
24
+ readonly success: true;
25
+ } | {
26
+ readonly success: false;
27
+ };
28
+ };
29
+ export declare const runValidatedNodeOperation: <TParameters, TValue>(...[input, schema, operation, recovery]: readonly [input: unknown, schema: ParameterSchema<TParameters>, operation: (client: LocalNodeClient, parameters: TParameters, options: LocalNodeRequestOptions) => Promise<TValue>, recovery?: CliMutationRecovery]) => Promise<CliNodeResult<TValue>>;
30
+ export {};
31
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,99 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { MaiaClientError, protocolErrorSchema } from "@maiaos/sdk";
3
+ import { connectLocalNode, } from "@maiaos/sdk/node";
4
+ import * as Effect from "effect/Effect";
5
+ export const newCliIdentifier = (prefix) => `${prefix}_${randomUUID().replaceAll("-", "")}`;
6
+ export const resolveCliDiscoveryOptions = () => {
7
+ if (process.env.MAIA_CLI_TEST_MODE !== "1")
8
+ return {};
9
+ const runtimeRootOverride = process.env.MAIA_CLI_TEST_RUNTIME_ROOT;
10
+ if (runtimeRootOverride === undefined) {
11
+ throw new Error("The CLI test runtime root is missing.");
12
+ }
13
+ return { runtimeRootOverride };
14
+ };
15
+ export const connectCliLocalNode = (signal) => connectLocalNode({ ...resolveCliDiscoveryOptions(), signal });
16
+ const LOCAL_DEADLINE_ERROR = {
17
+ code: "deadline_exceeded",
18
+ message: "Local request expired before dispatch.",
19
+ retryable: true,
20
+ };
21
+ const LOCAL_OUTCOME_UNKNOWN_ERROR = {
22
+ code: "outcome_unknown",
23
+ message: "Local request outcome unknown.",
24
+ retryable: false,
25
+ };
26
+ const LOCAL_SATURATED_ERROR = {
27
+ code: "saturated",
28
+ message: "Local node saturated.",
29
+ retryable: true,
30
+ };
31
+ const localOperationError = (error) => {
32
+ if (error.code === "deadline_exceeded")
33
+ return LOCAL_DEADLINE_ERROR;
34
+ if (error.code === "outcome_unknown")
35
+ return LOCAL_OUTCOME_UNKNOWN_ERROR;
36
+ if (error.code === "saturated")
37
+ return LOCAL_SATURATED_ERROR;
38
+ };
39
+ const operationError = (error) => {
40
+ const remoteError = error instanceof Error && "remoteError" in error
41
+ ? error.remoteError
42
+ : undefined;
43
+ const parsed = protocolErrorSchema.safeParse(remoteError);
44
+ if (parsed.success)
45
+ return parsed.data;
46
+ if (error instanceof MaiaClientError) {
47
+ if (error.code === "invalid_request") {
48
+ return {
49
+ code: "invalid_argument",
50
+ message: "Command input is invalid.",
51
+ retryable: false,
52
+ };
53
+ }
54
+ const local = localOperationError(error);
55
+ if (local !== undefined)
56
+ return local;
57
+ }
58
+ return {
59
+ code: "node_unavailable",
60
+ message: "Local Maia node unavailable.",
61
+ retryable: true,
62
+ };
63
+ };
64
+ export const outcomeCanBeAmbiguous = (error) => !(error instanceof MaiaClientError) ||
65
+ (error.code !== "deadline_exceeded" &&
66
+ error.code !== "invalid_request" &&
67
+ error.code !== "saturated");
68
+ export const invalidNodeInput = () => Promise.resolve({
69
+ error: {
70
+ code: "invalid_argument",
71
+ message: "The command input is invalid.",
72
+ retryable: false,
73
+ },
74
+ ok: false,
75
+ });
76
+ export const runNodeOperation = (operation, recovery) => Effect.runPromise(Effect.tryPromise({
77
+ catch: (cause) => ({ cause, error: operationError(cause) }),
78
+ try: operation,
79
+ }).pipe(Effect.map((value) => ({ ok: true, value })), Effect.catch(({ cause, error }) => Effect.succeed({
80
+ error,
81
+ ok: false,
82
+ ...(recovery !== undefined && outcomeCanBeAmbiguous(cause)
83
+ ? { recovery }
84
+ : {}),
85
+ }))));
86
+ export const runNodeClientOperation = (operation, recovery) => runNodeOperation(async (signal) => {
87
+ const connection = await connectCliLocalNode(signal);
88
+ return operation(connection.client, {
89
+ messageId: newCliIdentifier("request"),
90
+ signal,
91
+ });
92
+ }, recovery);
93
+ export const runValidatedNodeOperation = (...[input, schema, operation, recovery]) => {
94
+ const parameters = schema.safeParse(input);
95
+ if (!parameters.success)
96
+ return invalidNodeInput();
97
+ return runNodeClientOperation((client, options) => operation(client, parameters.data, options), recovery);
98
+ };
99
+ //# sourceMappingURL=client.js.map