mcoda 0.1.76 → 0.1.79
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/CHANGELOG.md +4 -0
- package/README.md +15 -0
- package/dist/bin/McodaEntrypoint.d.ts.map +1 -1
- package/dist/bin/McodaEntrypoint.js +8 -2
- package/dist/commands/gpu/GpuCommands.d.ts +8 -0
- package/dist/commands/gpu/GpuCommands.d.ts.map +1 -0
- package/dist/commands/gpu/GpuCommands.js +382 -0
- package/dist/commands/jobs/JobsCommands.d.ts.map +1 -1
- package/dist/commands/jobs/JobsCommands.js +5 -0
- package/dist/commands/self-hosted/SelfHostedCommands.d.ts.map +1 -1
- package/dist/commands/self-hosted/SelfHostedCommands.js +16 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
- Initial npm packaging scaffold for the mcoda CLI.
|
|
5
5
|
- Added bundled mswarm consent terms plus guided `mcoda setup`/postinstall consent bootstrap for installed CLI packages.
|
|
6
6
|
|
|
7
|
+
## 0.1.78
|
|
8
|
+
- Added owner-local GPU job commands: `mcoda gpu list`, `mcoda gpu ops`, and GPU-aware `mcoda job artifact upload|run|status|logs|events|artifacts|cancel|retry`.
|
|
9
|
+
- Added README and usage docs for the generic GPU job connection flags and environment fallbacks.
|
|
10
|
+
|
|
7
11
|
## 0.1.76
|
|
8
12
|
- Added top-level help aliases: `mcoda help`, `mcoda --help`, `mcoda -h`, and `mcoda -H`.
|
|
9
13
|
- Release v0.1.76.
|
package/README.md
CHANGED
|
@@ -34,6 +34,8 @@ mcoda docs pdr generate --workspace-root . --project WEB --rfp-path docs/rfp/web
|
|
|
34
34
|
- Execution: `mcoda add-tests`, `mcoda work-on-tasks`, `mcoda code-review`, `mcoda qa-tasks`
|
|
35
35
|
- Backlog: `mcoda backlog`, `mcoda task`
|
|
36
36
|
- Jobs/telemetry: `mcoda jobs`, `mcoda tokens`, `mcoda telemetry`
|
|
37
|
+
- Owner-local GPU jobs: `mcoda gpu list`, `mcoda gpu ops`, `mcoda job artifact upload|run|status|logs|events|artifacts|cancel|retry`
|
|
38
|
+
- Self-hosted agents: `mcoda self-hosted agent list`, `mcoda self-hosted agent details`, `mcoda self-hosted agent sync`
|
|
37
39
|
- Agents: `mcoda test-agent`, `mcoda agent-run`
|
|
38
40
|
- Updates: `mcoda update --check`
|
|
39
41
|
|
|
@@ -45,9 +47,22 @@ If that sufficiency pass errors, create-tasks continues (fail-open) and records
|
|
|
45
47
|
Environment variables are optional overrides for workspace settings:
|
|
46
48
|
- `MCODA_DOCDEX_URL` to point at a docdex server.
|
|
47
49
|
- `MCODA_API_BASE_URL` or `MCODA_JOBS_API_URL` for job APIs.
|
|
50
|
+
- `MCODA_MSWARM_NODE_BASE_URL`, `MCODA_MSWARM_NODE_ID`, and `MCODA_MSWARM_NODE_SIGNING_SECRET` for owner-local generic GPU job commands.
|
|
48
51
|
- `MCODA_TELEMETRY` set to `off` to disable telemetry.
|
|
49
52
|
- `MCODA_STREAM_IO=1` to emit agent I/O lines to stderr.
|
|
50
53
|
|
|
54
|
+
## Self-hosted mswarm agents
|
|
55
|
+
|
|
56
|
+
`mcoda self-hosted agent list` reads direct self-hosted agents and opt-in
|
|
57
|
+
load-balanced aliases from mswarm when the configured API key allows it. Direct
|
|
58
|
+
entries stay pinned to one server. Load-balanced aliases are saved as auto
|
|
59
|
+
routes and let mswarm choose an eligible upgraded node for the requested model
|
|
60
|
+
or capability.
|
|
61
|
+
|
|
62
|
+
Use direct slugs for rollback or pinned-server workloads. Use auto aliases only
|
|
63
|
+
when the product should allow mswarm to route around busy, drained, stale, or
|
|
64
|
+
incompatible nodes.
|
|
65
|
+
|
|
51
66
|
## Programmatic usage
|
|
52
67
|
```ts
|
|
53
68
|
import { McodaEntrypoint } from "mcoda";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AAyDA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAwPxE"}
|
|
@@ -6,6 +6,7 @@ import { AgentsCommands } from '../commands/agents/AgentsCommands.js';
|
|
|
6
6
|
import { CloudCommands } from '../commands/cloud/CloudCommands.js';
|
|
7
7
|
import { SelfHostedCommands } from '../commands/self-hosted/SelfHostedCommands.js';
|
|
8
8
|
import { WorkersCommands } from '../commands/workers/WorkersCommands.js';
|
|
9
|
+
import { GpuCommands } from '../commands/gpu/GpuCommands.js';
|
|
9
10
|
import { ConfigCommands } from '../commands/config/ConfigCommands.js';
|
|
10
11
|
import { ConsentCommands } from '../commands/consent/ConsentCommands.js';
|
|
11
12
|
import { GatewayAgentCommand } from '../commands/agents/GatewayAgentCommand.js';
|
|
@@ -35,7 +36,7 @@ import { AgentRunCommand } from '../commands/agents/AgentRunCommand.js';
|
|
|
35
36
|
import { SetWorkspaceCommand } from '../commands/workspace/SetWorkspaceCommand.js';
|
|
36
37
|
import { ProjectGuidanceCommand } from '../commands/workspace/ProjectGuidanceCommand.js';
|
|
37
38
|
import { MswarmConfigStore } from '@mcoda/core';
|
|
38
|
-
const TOP_LEVEL_USAGE = 'Usage: mcoda <agent|cloud|cloud-agent|self-hosted|self-hosted-agent|workers|worker|config|consent|setup|gateway-agent|test-agent|agent-run|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|task-sufficiency-audit|sds-preflight|order-tasks|tasks|add-tests|work-on-tasks|gateway-trio|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|project-guidance|pdr|sds> [...args]\n' +
|
|
39
|
+
const TOP_LEVEL_USAGE = 'Usage: mcoda <agent|cloud|cloud-agent|self-hosted|self-hosted-agent|workers|worker|gpu|config|consent|setup|gateway-agent|test-agent|agent-run|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|task-sufficiency-audit|sds-preflight|order-tasks|tasks|add-tests|work-on-tasks|gateway-trio|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|project-guidance|pdr|sds> [...args]\n' +
|
|
39
40
|
'Setup: use `mcoda setup` after installation (or accept the postinstall prompt) to complete the mandatory mswarm telemetry consent flow.\n' +
|
|
40
41
|
'Config: use `mcoda config set mswarm-api-key <KEY>` to persist an encrypted mswarm API key in the resolved global mcoda config file.\n' +
|
|
41
42
|
'Consent: use `mcoda consent accept` before other commands if you need to complete consent outside the guided setup flow.\n' +
|
|
@@ -43,10 +44,11 @@ const TOP_LEVEL_USAGE = 'Usage: mcoda <agent|cloud|cloud-agent|self-hosted|self-
|
|
|
43
44
|
'Cloud agents: use `mcoda cloud agent list|details|sync` to discover and materialize mswarm-managed remote agents.\n' +
|
|
44
45
|
'Self-hosted agents: use `mcoda self-hosted agent list|details|sync` to discover and materialize owner-hosted mswarm agents.\n' +
|
|
45
46
|
'Workers: use `mcoda workers list|details|sync|run` to discover, materialize, and invoke mswarm Workers.\n' +
|
|
47
|
+
'GPU jobs: use `mcoda gpu list` and `mcoda job artifact upload|run|status|logs|events|artifacts|cancel` for owner-local generic GPU jobs.\n' +
|
|
46
48
|
'Expose this machine: install `@mcoda/mswarm`, then run `mswarm install <KEY>`.\n' +
|
|
47
49
|
'Aliases: `tasks order-by-deps` forwards to `order-tasks` (dependency-aware ordering), `task`/`task-detail` show a single task.\n' +
|
|
48
50
|
'Help: use `mcoda help`, `mcoda --help`, `mcoda -h`, or `mcoda -H` for this overview.\n' +
|
|
49
|
-
'Job commands (mcoda job --help for details): list|status|watch|logs|inspect|resume|cancel|tokens\n' +
|
|
51
|
+
'Job commands (mcoda job --help for details): list|status|watch|logs|inspect|resume|cancel|tokens plus GPU job artifact|run|events|artifacts with node options\n' +
|
|
50
52
|
'Jobs API required for job commands (set MCODA_API_BASE_URL/MCODA_JOBS_API_URL or workspace api.baseUrl). status/watch/logs exit non-zero on failed/cancelled jobs per SDS.';
|
|
51
53
|
const TOP_LEVEL_HELP_COMMANDS = new Set(['--help', '-h', '-H', 'help']);
|
|
52
54
|
export class McodaEntrypoint {
|
|
@@ -135,6 +137,10 @@ export class McodaEntrypoint {
|
|
|
135
137
|
await WorkersCommands.run(rest);
|
|
136
138
|
return;
|
|
137
139
|
}
|
|
140
|
+
if (command === 'gpu') {
|
|
141
|
+
await GpuCommands.run(rest);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
138
144
|
if (command === 'config') {
|
|
139
145
|
await ConfigCommands.run(rest);
|
|
140
146
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GpuCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/gpu/GpuCommands.ts"],"names":[],"mappings":"AAoSA,qBAAa,WAAW;WACT,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiChD;AAED,qBAAa,cAAc;IACzB,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO;WAQ/B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA8FhD"}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import YAML from "yaml";
|
|
5
|
+
import { MswarmApi } from "@mcoda/core";
|
|
6
|
+
const GPU_USAGE = `
|
|
7
|
+
Usage: mcoda gpu <list|ops> [options]
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
gpu list List owner-local GPU/job capability projection
|
|
11
|
+
gpu ops Show owner-local generic job queue, usage, quota, and audit summary
|
|
12
|
+
|
|
13
|
+
Connection options:
|
|
14
|
+
--node-base-url <URL> Owner-local node URL (or MCODA_MSWARM_NODE_BASE_URL)
|
|
15
|
+
--node-id <ID> Node id for signing capability requests
|
|
16
|
+
--signing-secret <KEY> Owner-local generic job signing secret
|
|
17
|
+
--token <TOKEN> Pre-signed capability or ops token
|
|
18
|
+
--timeout-ms <N> Request timeout
|
|
19
|
+
--audit-limit <N> Audit rows for gpu ops (default 50, max 250)
|
|
20
|
+
--audit-offset <N> Audit row offset for gpu ops
|
|
21
|
+
--json Emit JSON
|
|
22
|
+
`.trim();
|
|
23
|
+
const JOB_USAGE = `
|
|
24
|
+
Usage: mcoda job <artifact|run|status|logs|events|artifacts|cancel|retry> [options]
|
|
25
|
+
|
|
26
|
+
GPU job commands:
|
|
27
|
+
job artifact upload <FILE>
|
|
28
|
+
--job-id <ID> --request-id <ID> --node-id <ID> --job-type <TYPE>
|
|
29
|
+
[--artifact-path <PATH>] [--artifact-name <NAME>] [--content-type <TYPE>]
|
|
30
|
+
job run --job-file <FILE> [--wait] [--json]
|
|
31
|
+
job run --type <TYPE> --payload-file <FILE> [--wait] [--json]
|
|
32
|
+
job status <JOB_ID> [--job-file <FILE> | --node-id ... --request-id ... --job-type ...]
|
|
33
|
+
job logs <JOB_ID>
|
|
34
|
+
job events <JOB_ID>
|
|
35
|
+
job artifacts <JOB_ID>
|
|
36
|
+
job cancel <JOB_ID>
|
|
37
|
+
job retry <JOB_ID>
|
|
38
|
+
|
|
39
|
+
Connection options:
|
|
40
|
+
--node-base-url <URL> Owner-local node URL (or MCODA_MSWARM_NODE_BASE_URL)
|
|
41
|
+
--node-id <ID> Node id for signing requests
|
|
42
|
+
--signing-secret <KEY> Owner-local generic job signing secret
|
|
43
|
+
--token <TOKEN> Pre-signed generic job token
|
|
44
|
+
--timeout-ms <N> Request timeout
|
|
45
|
+
--json Emit JSON
|
|
46
|
+
`.trim();
|
|
47
|
+
const GPU_JOB_SUBCOMMANDS = new Set(["artifact", "run", "events", "artifacts"]);
|
|
48
|
+
const SHARED_JOB_SUBCOMMANDS = new Set(["status", "logs", "cancel", "retry"]);
|
|
49
|
+
const GPU_JOB_FLAGS = new Set([
|
|
50
|
+
"--gpu",
|
|
51
|
+
"--node-base-url",
|
|
52
|
+
"--node-id",
|
|
53
|
+
"--signing-secret",
|
|
54
|
+
"--token",
|
|
55
|
+
"--job-file",
|
|
56
|
+
"--payload-file",
|
|
57
|
+
"--job-type",
|
|
58
|
+
"--type",
|
|
59
|
+
"--schema-version",
|
|
60
|
+
"--request-id"
|
|
61
|
+
]);
|
|
62
|
+
const TERMINAL_STATES = new Set(["succeeded", "failed", "cancelled", "expired", "blocked"]);
|
|
63
|
+
const parseArgs = (argv) => {
|
|
64
|
+
const flags = {};
|
|
65
|
+
const positionals = [];
|
|
66
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
67
|
+
const arg = argv[index];
|
|
68
|
+
if (arg.startsWith("--")) {
|
|
69
|
+
const key = arg.replace(/^--/, "");
|
|
70
|
+
const next = argv[index + 1];
|
|
71
|
+
if (next && !next.startsWith("--")) {
|
|
72
|
+
const current = flags[key];
|
|
73
|
+
if (current === undefined)
|
|
74
|
+
flags[key] = next;
|
|
75
|
+
else if (Array.isArray(current))
|
|
76
|
+
flags[key] = [...current, next];
|
|
77
|
+
else if (typeof current === "string")
|
|
78
|
+
flags[key] = [current, next];
|
|
79
|
+
else
|
|
80
|
+
flags[key] = [next];
|
|
81
|
+
index += 1;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
flags[key] = true;
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
positionals.push(arg);
|
|
89
|
+
}
|
|
90
|
+
return { flags, positionals };
|
|
91
|
+
};
|
|
92
|
+
const resolveString = (value) => {
|
|
93
|
+
if (value === undefined || typeof value === "boolean")
|
|
94
|
+
return undefined;
|
|
95
|
+
return Array.isArray(value) ? value[value.length - 1] : value;
|
|
96
|
+
};
|
|
97
|
+
const resolvePositiveInt = (value, label) => {
|
|
98
|
+
const raw = resolveString(value);
|
|
99
|
+
if (raw === undefined)
|
|
100
|
+
return undefined;
|
|
101
|
+
const parsed = Number.parseInt(raw, 10);
|
|
102
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
103
|
+
throw new Error(`Invalid ${label}; expected a positive integer`);
|
|
104
|
+
}
|
|
105
|
+
return parsed;
|
|
106
|
+
};
|
|
107
|
+
const resolveNonNegativeInt = (value, label) => {
|
|
108
|
+
const raw = resolveString(value);
|
|
109
|
+
if (raw === undefined)
|
|
110
|
+
return undefined;
|
|
111
|
+
const parsed = Number.parseInt(raw, 10);
|
|
112
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
113
|
+
throw new Error(`Invalid ${label}; expected a non-negative integer`);
|
|
114
|
+
}
|
|
115
|
+
return parsed;
|
|
116
|
+
};
|
|
117
|
+
const nodeBaseUrl = (parsed) => resolveString(parsed.flags["node-base-url"]) || process.env.MCODA_MSWARM_NODE_BASE_URL;
|
|
118
|
+
const nodeId = (parsed) => resolveString(parsed.flags["node-id"]) || process.env.MCODA_MSWARM_NODE_ID || process.env.MSWARM_SELF_HOSTED_NODE_ID;
|
|
119
|
+
const signingSecret = (parsed) => resolveString(parsed.flags["signing-secret"]) ||
|
|
120
|
+
process.env.MCODA_MSWARM_NODE_SIGNING_SECRET ||
|
|
121
|
+
process.env.MSWARM_SELF_HOSTED_INVOCATION_SIGNING_SECRET;
|
|
122
|
+
const baseAuth = (parsed) => ({
|
|
123
|
+
nodeBaseUrl: nodeBaseUrl(parsed),
|
|
124
|
+
token: resolveString(parsed.flags.token),
|
|
125
|
+
signingSecret: signingSecret(parsed),
|
|
126
|
+
tokenTtlSeconds: resolvePositiveInt(parsed.flags["token-ttl-seconds"], "--token-ttl-seconds")
|
|
127
|
+
});
|
|
128
|
+
const createApi = async (parsed) => MswarmApi.create({
|
|
129
|
+
baseUrl: nodeBaseUrl(parsed),
|
|
130
|
+
apiKey: resolveString(parsed.flags["api-key"]),
|
|
131
|
+
timeoutMs: resolvePositiveInt(parsed.flags["timeout-ms"], "--timeout-ms")
|
|
132
|
+
});
|
|
133
|
+
const readStructuredFile = async (file) => {
|
|
134
|
+
const raw = await readFile(file, "utf8");
|
|
135
|
+
if (file.endsWith(".yaml") || file.endsWith(".yml")) {
|
|
136
|
+
return YAML.parse(raw);
|
|
137
|
+
}
|
|
138
|
+
return JSON.parse(raw);
|
|
139
|
+
};
|
|
140
|
+
const asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value)
|
|
141
|
+
? value
|
|
142
|
+
: {};
|
|
143
|
+
const readJobEnvelope = async (parsed) => {
|
|
144
|
+
const file = resolveString(parsed.flags["job-file"]) || resolveString(parsed.flags["payload-file"]);
|
|
145
|
+
if (!file) {
|
|
146
|
+
throw new Error("GPU job run requires --job-file or --payload-file");
|
|
147
|
+
}
|
|
148
|
+
const payload = asRecord(await readStructuredFile(file));
|
|
149
|
+
if (typeof payload.job_id === "string" && typeof payload.request_id === "string" && typeof payload.node_id === "string") {
|
|
150
|
+
return payload;
|
|
151
|
+
}
|
|
152
|
+
const schemaVersion = resolveString(parsed.flags["schema-version"]) ||
|
|
153
|
+
(typeof payload.schema_version === "string" ? payload.schema_version : "2026-06-14");
|
|
154
|
+
const jobType = resolveString(parsed.flags.type) ||
|
|
155
|
+
resolveString(parsed.flags["job-type"]) ||
|
|
156
|
+
(typeof payload.job_type === "string" ? payload.job_type : undefined);
|
|
157
|
+
if (!jobType) {
|
|
158
|
+
throw new Error("--job-file/--payload-file must contain job_type or use --type/--job-type");
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
job_id: resolveString(parsed.flags["job-id"]) || `job-${randomUUID()}`,
|
|
162
|
+
request_id: resolveString(parsed.flags["request-id"]) || `req-${randomUUID()}`,
|
|
163
|
+
node_id: requireText(nodeId(parsed), "--node-id"),
|
|
164
|
+
job: {
|
|
165
|
+
...payload,
|
|
166
|
+
schema_version: schemaVersion,
|
|
167
|
+
job_type: jobType
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
const referenceFromArgs = async (parsed, explicitJobId) => {
|
|
172
|
+
const jobFile = resolveString(parsed.flags["job-file"]) || resolveString(parsed.flags["payload-file"]);
|
|
173
|
+
if (jobFile) {
|
|
174
|
+
const job = await readJobEnvelope(parsed);
|
|
175
|
+
return {
|
|
176
|
+
...baseAuth(parsed),
|
|
177
|
+
jobId: explicitJobId || job.job_id,
|
|
178
|
+
nodeId: job.node_id,
|
|
179
|
+
requestId: job.request_id,
|
|
180
|
+
schemaVersion: job.job.schema_version,
|
|
181
|
+
jobType: job.job.job_type
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
...baseAuth(parsed),
|
|
186
|
+
jobId: requireText(explicitJobId || resolveString(parsed.flags["job-id"]), "JOB_ID"),
|
|
187
|
+
nodeId: nodeId(parsed),
|
|
188
|
+
requestId: resolveString(parsed.flags["request-id"]),
|
|
189
|
+
schemaVersion: resolveString(parsed.flags["schema-version"]) || "2026-06-14",
|
|
190
|
+
jobType: resolveString(parsed.flags["job-type"]) || resolveString(parsed.flags.type)
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
function requireText(value, label) {
|
|
194
|
+
if (!value || !value.trim()) {
|
|
195
|
+
throw new Error(`${label} is required`);
|
|
196
|
+
}
|
|
197
|
+
return value.trim();
|
|
198
|
+
}
|
|
199
|
+
const printJsonOrValue = (value, json) => {
|
|
200
|
+
// eslint-disable-next-line no-console
|
|
201
|
+
console.log(json ? JSON.stringify(value, null, 2) : formatValue(value));
|
|
202
|
+
};
|
|
203
|
+
const formatValue = (value) => {
|
|
204
|
+
if (typeof value === "string")
|
|
205
|
+
return value;
|
|
206
|
+
return JSON.stringify(value, null, 2);
|
|
207
|
+
};
|
|
208
|
+
const printSnapshot = (snapshot, json) => {
|
|
209
|
+
if (json) {
|
|
210
|
+
printJsonOrValue(snapshot, true);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const job = snapshot.job;
|
|
214
|
+
// eslint-disable-next-line no-console
|
|
215
|
+
console.log(`${job.job_id} ${job.state}`);
|
|
216
|
+
if (job.backpressure?.message) {
|
|
217
|
+
// eslint-disable-next-line no-console
|
|
218
|
+
console.log(job.backpressure.message);
|
|
219
|
+
}
|
|
220
|
+
if (job.result?.error?.message) {
|
|
221
|
+
// eslint-disable-next-line no-console
|
|
222
|
+
console.log(job.result.error.message);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
const formatOpsSummary = (summary) => {
|
|
226
|
+
const lines = [
|
|
227
|
+
`${summary.node.node_id} ${summary.node.generic_jobs_enabled ? "generic-jobs-enabled" : "generic-jobs-disabled"}`,
|
|
228
|
+
`queue active=${summary.queue.active_jobs} queued=${summary.queue.queued_jobs} terminal=${summary.queue.terminal_jobs}`,
|
|
229
|
+
`quota available=${summary.quota.available_slots}/${summary.quota.max_concurrent_jobs} production_enforced=${summary.quota.production_enforced}`,
|
|
230
|
+
`usage total=${summary.usage.total_jobs} succeeded=${summary.usage.succeeded_jobs} failed=${summary.usage.failed_jobs} cancelled=${summary.usage.cancelled_jobs} blocked=${summary.usage.blocked_jobs} gpu_seconds=${summary.usage.gpu_seconds}`,
|
|
231
|
+
];
|
|
232
|
+
if (summary.queue.jobs.length) {
|
|
233
|
+
lines.push("jobs:");
|
|
234
|
+
for (const job of summary.queue.jobs.slice(0, 10)) {
|
|
235
|
+
lines.push(` ${job.job_id} ${job.state} ${job.job_type} tenant=${job.tenant_id}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (summary.audit.events.length) {
|
|
239
|
+
lines.push(`audit offset=${summary.audit.offset} limit=${summary.audit.limit} total=${summary.audit.total}:`);
|
|
240
|
+
for (const event of summary.audit.events.slice(0, 10)) {
|
|
241
|
+
lines.push(` ${event.timestamp} ${event.action} ${event.job_id}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return lines.join("\n");
|
|
245
|
+
};
|
|
246
|
+
const waitForJob = async (api, reference, intervalMs) => {
|
|
247
|
+
let snapshot = await api.getGenericJob(reference);
|
|
248
|
+
while (!TERMINAL_STATES.has(snapshot.job.state)) {
|
|
249
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
250
|
+
snapshot = await api.getGenericJob(reference);
|
|
251
|
+
}
|
|
252
|
+
return snapshot;
|
|
253
|
+
};
|
|
254
|
+
export class GpuCommands {
|
|
255
|
+
static async run(argv) {
|
|
256
|
+
const [subcommand, ...rest] = argv;
|
|
257
|
+
if (!subcommand || argv.includes("--help") || argv.includes("-h")) {
|
|
258
|
+
// eslint-disable-next-line no-console
|
|
259
|
+
console.log(GPU_USAGE);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (subcommand !== "list" && subcommand !== "ops") {
|
|
263
|
+
throw new Error(`Unknown gpu subcommand: ${subcommand}`);
|
|
264
|
+
}
|
|
265
|
+
const parsed = parseArgs(rest);
|
|
266
|
+
const api = await createApi(parsed);
|
|
267
|
+
try {
|
|
268
|
+
if (subcommand === "list") {
|
|
269
|
+
const capabilities = await api.listGpuCapabilities({
|
|
270
|
+
...baseAuth(parsed),
|
|
271
|
+
nodeId: nodeId(parsed)
|
|
272
|
+
});
|
|
273
|
+
printJsonOrValue(capabilities, Boolean(parsed.flags.json));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const ops = await api.getGenericJobOps({
|
|
277
|
+
...baseAuth(parsed),
|
|
278
|
+
nodeId: nodeId(parsed),
|
|
279
|
+
auditLimit: resolvePositiveInt(parsed.flags["audit-limit"], "--audit-limit"),
|
|
280
|
+
auditOffset: resolveNonNegativeInt(parsed.flags["audit-offset"], "--audit-offset")
|
|
281
|
+
});
|
|
282
|
+
// eslint-disable-next-line no-console
|
|
283
|
+
console.log(parsed.flags.json ? JSON.stringify(ops, null, 2) : formatOpsSummary(ops));
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
await api.close();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
export class GpuJobCommands {
|
|
291
|
+
static shouldHandle(argv) {
|
|
292
|
+
const [subcommand] = argv;
|
|
293
|
+
if (!subcommand)
|
|
294
|
+
return false;
|
|
295
|
+
if (GPU_JOB_SUBCOMMANDS.has(subcommand))
|
|
296
|
+
return true;
|
|
297
|
+
if (!SHARED_JOB_SUBCOMMANDS.has(subcommand))
|
|
298
|
+
return false;
|
|
299
|
+
return argv.some((arg) => GPU_JOB_FLAGS.has(arg) || arg.startsWith("--node-base-url="));
|
|
300
|
+
}
|
|
301
|
+
static async run(argv) {
|
|
302
|
+
const [subcommand, ...rest] = argv;
|
|
303
|
+
if (!subcommand || argv.includes("--help") || argv.includes("-h")) {
|
|
304
|
+
// eslint-disable-next-line no-console
|
|
305
|
+
console.log(JOB_USAGE);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const parsed = parseArgs(rest);
|
|
309
|
+
const api = await createApi(parsed);
|
|
310
|
+
try {
|
|
311
|
+
switch (subcommand) {
|
|
312
|
+
case "artifact": {
|
|
313
|
+
const action = parsed.positionals[0];
|
|
314
|
+
const file = parsed.positionals[1];
|
|
315
|
+
if (action !== "upload" || !file) {
|
|
316
|
+
throw new Error("Usage: mcoda job artifact upload <FILE> [options]");
|
|
317
|
+
}
|
|
318
|
+
const content = await readFile(file);
|
|
319
|
+
const artifactPath = resolveString(parsed.flags["artifact-path"]) || basename(file);
|
|
320
|
+
const result = await api.uploadGenericJobArtifact({
|
|
321
|
+
...(await referenceFromArgs(parsed, resolveString(parsed.flags["job-id"]))),
|
|
322
|
+
name: resolveString(parsed.flags["artifact-name"]) || basename(file),
|
|
323
|
+
path: artifactPath,
|
|
324
|
+
contentBase64: content.toString("base64"),
|
|
325
|
+
contentType: resolveString(parsed.flags["content-type"]),
|
|
326
|
+
sha256: createHash("sha256").update(content).digest("hex"),
|
|
327
|
+
sizeBytes: content.length
|
|
328
|
+
});
|
|
329
|
+
printJsonOrValue(result, Boolean(parsed.flags.json));
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
case "run": {
|
|
333
|
+
const job = await readJobEnvelope(parsed);
|
|
334
|
+
const snapshot = await api.runGenericJob(job, baseAuth(parsed));
|
|
335
|
+
const finalSnapshot = parsed.flags.wait
|
|
336
|
+
? await waitForJob(api, await referenceFromArgs(parsed, job.job_id), resolvePositiveInt(parsed.flags["interval-ms"], "--interval-ms") || 1000)
|
|
337
|
+
: snapshot;
|
|
338
|
+
printSnapshot(finalSnapshot, Boolean(parsed.flags.json));
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
case "status": {
|
|
342
|
+
const snapshot = await api.getGenericJob(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
343
|
+
printSnapshot(snapshot, Boolean(parsed.flags.json));
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
case "logs": {
|
|
347
|
+
const result = await api.getGenericJobLogs(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
348
|
+
if (parsed.flags.json)
|
|
349
|
+
printJsonOrValue(result, true);
|
|
350
|
+
else
|
|
351
|
+
printJsonOrValue(result.logs.map((log) => log.message).join("\n"), false);
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
case "events": {
|
|
355
|
+
const result = await api.getGenericJobEvents(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
356
|
+
printJsonOrValue(result, Boolean(parsed.flags.json));
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
case "artifacts": {
|
|
360
|
+
const result = await api.getGenericJobArtifacts(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
361
|
+
printJsonOrValue(result, Boolean(parsed.flags.json));
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
case "cancel": {
|
|
365
|
+
const result = await api.cancelGenericJob(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
366
|
+
printSnapshot(result, Boolean(parsed.flags.json));
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
case "retry": {
|
|
370
|
+
const result = await api.retryGenericJob(await referenceFromArgs(parsed, parsed.positionals[0]));
|
|
371
|
+
printSnapshot(result, Boolean(parsed.flags.json));
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
default:
|
|
375
|
+
throw new Error(`Unknown GPU job subcommand: ${subcommand}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
await api.close();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JobsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/jobs/JobsCommands.ts"],"names":[],"mappings":"AACA,OAAO,EAAsE,aAAa,EAA0C,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"JobsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/jobs/JobsCommands.ts"],"names":[],"mappings":"AACA,OAAO,EAAsE,aAAa,EAA0C,MAAM,aAAa,CAAC;AAIxJ,KAAK,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvG,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,aAAa,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAuCD,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,EAAE,KAAG,aAyH7C,CAAC;AA8BF,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,GAAG,SAiBhF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,GAAG,SAsB/E,CAAC;AAaF,eAAO,MAAM,eAAe,GAAI,MAAM,aAAa,EAAE,KAAG,IA8CvD,CAAC;AAwJF,qBAAa,YAAY;WACV,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiPhD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { JobInsightsService, JobResumeService, JobService, TelemetryService, WorkspaceResolver } from "@mcoda/core";
|
|
3
|
+
import { GpuJobCommands } from "../gpu/GpuCommands.js";
|
|
3
4
|
const usage = `mcoda job <list|status|watch|logs|inspect|resume|cancel|tokens> ...
|
|
4
5
|
|
|
5
6
|
Commands:
|
|
@@ -401,6 +402,10 @@ const handleTokens = async (parsed, workspace) => {
|
|
|
401
402
|
};
|
|
402
403
|
export class JobsCommands {
|
|
403
404
|
static async run(argv) {
|
|
405
|
+
if (GpuJobCommands.shouldHandle(argv)) {
|
|
406
|
+
await GpuJobCommands.run(argv);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
404
409
|
const parsed = parseJobArgs(argv);
|
|
405
410
|
const workspace = await WorkspaceResolver.resolveWorkspace({
|
|
406
411
|
cwd: process.cwd(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelfHostedCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/self-hosted/SelfHostedCommands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SelfHostedCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/self-hosted/SelfHostedCommands.ts"],"names":[],"mappings":"AAyOA,qBAAa,kBAAkB;WAChB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAkGhD"}
|
|
@@ -7,6 +7,7 @@ Subcommands:
|
|
|
7
7
|
--provider <NAME> Filter by provider (mcoda|ollama)
|
|
8
8
|
--limit <N> Limit returned agents
|
|
9
9
|
--include-unreachable Include unreachable agents in the catalog result
|
|
10
|
+
--include-load-balanced Include auto-routed load-balanced self-hosted aliases
|
|
10
11
|
--max-cost-per-1m-token <N>
|
|
11
12
|
Exclude agents above the given cost_per_million
|
|
12
13
|
--sorted-by-catalog-rating
|
|
@@ -14,9 +15,11 @@ Subcommands:
|
|
|
14
15
|
--min-context <N> Require at least this context window
|
|
15
16
|
--min-reasoning <N> Require at least this reasoning rating
|
|
16
17
|
agent details <SLUG> Show a single mswarm self-hosted agent (supports --json)
|
|
18
|
+
--include-load-balanced Allow details for auto-routed aliases
|
|
17
19
|
agent sync Sync self-hosted agents into the local mcoda registry
|
|
18
20
|
--provider <NAME> Filter by provider before syncing
|
|
19
21
|
--include-unreachable Sync unreachable agents too
|
|
22
|
+
--include-load-balanced Sync auto-routed load-balanced aliases too
|
|
20
23
|
--limit <N> Limit synced agents
|
|
21
24
|
--prune Remove previously synced self-hosted agents missing from the current catalog result
|
|
22
25
|
--agent-slug-prefix <P> Override the local managed-agent slug prefix
|
|
@@ -104,6 +107,7 @@ const resolveNonNegativeNumber = (value, label) => {
|
|
|
104
107
|
const formatNumber = (value) => value === undefined || Number.isNaN(value) ? "-" : String(value);
|
|
105
108
|
const formatCapabilities = (capabilities) => capabilities && capabilities.length > 0 ? capabilities.join(",") : "-";
|
|
106
109
|
const formatBoolean = (value) => value === undefined ? "-" : value ? "yes" : "no";
|
|
110
|
+
const agentRoutingMode = (agent) => agent.load_balanced ? "auto" : "direct";
|
|
107
111
|
const pad = (value, width) => value.padEnd(width, " ");
|
|
108
112
|
const renderTable = (headers, rows) => {
|
|
109
113
|
const widths = headers.map((header, columnIndex) => Math.max(header.length, ...rows.map((row) => row[columnIndex]?.length ?? 0)));
|
|
@@ -122,6 +126,7 @@ const printAgentList = (agents) => {
|
|
|
122
126
|
}
|
|
123
127
|
const headers = [
|
|
124
128
|
"REMOTE SLUG",
|
|
129
|
+
"ROUTE",
|
|
125
130
|
"PROVIDER",
|
|
126
131
|
"ADAPTER",
|
|
127
132
|
"MODEL",
|
|
@@ -136,6 +141,7 @@ const printAgentList = (agents) => {
|
|
|
136
141
|
];
|
|
137
142
|
const rows = agents.map((agent) => [
|
|
138
143
|
agent.remote_slug ?? agent.slug,
|
|
144
|
+
agentRoutingMode(agent),
|
|
139
145
|
agent.provider,
|
|
140
146
|
agent.adapter ?? "-",
|
|
141
147
|
agent.default_model,
|
|
@@ -155,6 +161,8 @@ const printAgentDetails = (agent) => {
|
|
|
155
161
|
const entries = [
|
|
156
162
|
["Slug", agent.slug],
|
|
157
163
|
["Remote slug", agent.remote_slug ?? "-"],
|
|
164
|
+
["Route", agentRoutingMode(agent)],
|
|
165
|
+
["Load-balanced group", agent.load_balanced_group_id ?? "-"],
|
|
158
166
|
["Provider", agent.provider],
|
|
159
167
|
["Adapter", agent.adapter ?? "-"],
|
|
160
168
|
["Source agent", agent.source_agent_slug ?? "-"],
|
|
@@ -170,6 +178,7 @@ const printAgentDetails = (agent) => {
|
|
|
170
178
|
["Supports tools", formatBoolean(agent.supports_tools)],
|
|
171
179
|
["Supports reasoning", formatBoolean(agent.supports_reasoning)],
|
|
172
180
|
["Health", agent.health_status ?? "-"],
|
|
181
|
+
["Members", formatNumber(agent.member_count)],
|
|
173
182
|
["Capabilities", formatCapabilities(agent.capabilities)],
|
|
174
183
|
];
|
|
175
184
|
const labelWidth = Math.max(...entries.map(([label]) => label.length));
|
|
@@ -187,11 +196,12 @@ const printSyncSummary = (summary) => {
|
|
|
187
196
|
record.remoteSlug,
|
|
188
197
|
record.localSlug,
|
|
189
198
|
record.action,
|
|
199
|
+
record.routingMode ?? "-",
|
|
190
200
|
record.provider,
|
|
191
201
|
record.defaultModel,
|
|
192
202
|
]);
|
|
193
203
|
// eslint-disable-next-line no-console
|
|
194
|
-
console.log(renderTable(["REMOTE SLUG", "LOCAL SLUG", "ACTION", "PROVIDER", "MODEL"], rows));
|
|
204
|
+
console.log(renderTable(["REMOTE SLUG", "LOCAL SLUG", "ACTION", "ROUTE", "PROVIDER", "MODEL"], rows));
|
|
195
205
|
};
|
|
196
206
|
export class SelfHostedCommands {
|
|
197
207
|
static async run(argv) {
|
|
@@ -227,6 +237,7 @@ export class SelfHostedCommands {
|
|
|
227
237
|
provider: resolveString(parsed.flags.provider),
|
|
228
238
|
limit: resolvePositiveInt(parsed.flags.limit, "--limit"),
|
|
229
239
|
includeUnreachable: Boolean(parsed.flags["include-unreachable"]),
|
|
240
|
+
includeLoadBalanced: Boolean(parsed.flags["include-load-balanced"]),
|
|
230
241
|
maxCostPerMillion: resolveNonNegativeNumber(parsed.flags["max-cost-per-1m-token"], "--max-cost-per-1m-token"),
|
|
231
242
|
minContextWindow: resolvePositiveInt(parsed.flags["min-context"], "--min-context"),
|
|
232
243
|
minReasoningRating: resolveNonNegativeNumber(parsed.flags["min-reasoning"], "--min-reasoning"),
|
|
@@ -246,7 +257,9 @@ export class SelfHostedCommands {
|
|
|
246
257
|
if (!slug) {
|
|
247
258
|
throw new Error("Usage: mcoda self-hosted agent details <SLUG> [--json]");
|
|
248
259
|
}
|
|
249
|
-
const agent = await api.getSelfHostedAgent(slug
|
|
260
|
+
const agent = await api.getSelfHostedAgent(slug, {
|
|
261
|
+
includeLoadBalanced: Boolean(parsed.flags["include-load-balanced"]),
|
|
262
|
+
});
|
|
250
263
|
if (parsed.flags.json) {
|
|
251
264
|
// eslint-disable-next-line no-console
|
|
252
265
|
console.log(JSON.stringify(agent, null, 2));
|
|
@@ -261,6 +274,7 @@ export class SelfHostedCommands {
|
|
|
261
274
|
provider: resolveString(parsed.flags.provider),
|
|
262
275
|
limit: resolvePositiveInt(parsed.flags.limit, "--limit"),
|
|
263
276
|
includeUnreachable: Boolean(parsed.flags["include-unreachable"]),
|
|
277
|
+
includeLoadBalanced: Boolean(parsed.flags["include-load-balanced"]),
|
|
264
278
|
pruneMissing: Boolean(parsed.flags.prune),
|
|
265
279
|
});
|
|
266
280
|
if (parsed.flags.json) {
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './bin/McodaEntrypoint.js';
|
|
|
3
3
|
export * from './commands/cloud/CloudCommands.js';
|
|
4
4
|
export * from './commands/self-hosted/SelfHostedCommands.js';
|
|
5
5
|
export * from './commands/workers/WorkersCommands.js';
|
|
6
|
+
export * from './commands/gpu/GpuCommands.js';
|
|
6
7
|
export * from './commands/config/ConfigCommands.js';
|
|
7
8
|
export * from './commands/consent/ConsentCommands.js';
|
|
8
9
|
export * from './commands/docs/DocsCommands.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,cAAc,gDAAgD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,cAAc,gDAAgD,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from './bin/McodaEntrypoint.js';
|
|
|
3
3
|
export * from './commands/cloud/CloudCommands.js';
|
|
4
4
|
export * from './commands/self-hosted/SelfHostedCommands.js';
|
|
5
5
|
export * from './commands/workers/WorkersCommands.js';
|
|
6
|
+
export * from './commands/gpu/GpuCommands.js';
|
|
6
7
|
export * from './commands/config/ConfigCommands.js';
|
|
7
8
|
export * from './commands/consent/ConsentCommands.js';
|
|
8
9
|
export * from './commands/docs/DocsCommands.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcoda",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.79",
|
|
4
4
|
"description": "Local-first CLI for planning, documentation, and execution workflows with agent assistance.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"yaml": "^2.4.2",
|
|
50
|
-
"@mcoda/
|
|
51
|
-
"@mcoda/
|
|
50
|
+
"@mcoda/core": "0.1.79",
|
|
51
|
+
"@mcoda/shared": "0.1.79"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@mcoda/db": "0.1.
|
|
55
|
-
"@mcoda/integrations": "0.1.
|
|
54
|
+
"@mcoda/db": "0.1.79",
|
|
55
|
+
"@mcoda/integrations": "0.1.79"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsc -p tsconfig.json",
|