@01.software/cli 0.10.3 → 0.10.5
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/index.js +256 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-VSMPWKVX.js → chunk-2EPYMNHW.js} +256 -221
- package/dist/mcp/chunk-2EPYMNHW.js.map +1 -0
- package/dist/mcp/http.js +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +255 -220
- package/package.json +2 -2
- package/dist/mcp/chunk-VSMPWKVX.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { Command } from "commander";
|
|
|
8
8
|
import {
|
|
9
9
|
CollectionClient,
|
|
10
10
|
ServerCommerceClient
|
|
11
|
-
} from "@01.software/sdk";
|
|
11
|
+
} from "@01.software/sdk/server";
|
|
12
12
|
|
|
13
13
|
// src/lib/credentials.ts
|
|
14
14
|
import {
|
|
@@ -166,6 +166,9 @@ function classifyError(err) {
|
|
|
166
166
|
if (isPermissionCode(code)) {
|
|
167
167
|
return { type: "permission", code };
|
|
168
168
|
}
|
|
169
|
+
if (code === "auth_error" || code === "permission_error") {
|
|
170
|
+
return { type: "permission", code: "credential_invalid" };
|
|
171
|
+
}
|
|
169
172
|
if (isDegradedCode(code)) {
|
|
170
173
|
const out = { type: "degraded", code };
|
|
171
174
|
if (typeof obj.retryAfter === "number") {
|
|
@@ -187,7 +190,7 @@ function classifyError(err) {
|
|
|
187
190
|
}
|
|
188
191
|
const name = typeof obj.name === "string" ? obj.name : void 0;
|
|
189
192
|
const status = typeof obj.status === "number" ? obj.status : void 0;
|
|
190
|
-
if (name === "ConfigError" || status === 401) {
|
|
193
|
+
if (name === "ConfigError" || name === "AuthError" || name === "PermissionError" || status === 401 || status === 403) {
|
|
191
194
|
return { type: "permission", code: "credential_invalid" };
|
|
192
195
|
}
|
|
193
196
|
if (name === "NetworkError" || name === "TimeoutError" || status === 408 || status === 503) {
|
|
@@ -440,7 +443,14 @@ function exitWithError(error, options = {}) {
|
|
|
440
443
|
function isValidBearerToken(secret) {
|
|
441
444
|
return secret.startsWith("sk01_") || secret.startsWith("pat01_");
|
|
442
445
|
}
|
|
443
|
-
function
|
|
446
|
+
function credentialError(detail) {
|
|
447
|
+
return {
|
|
448
|
+
type: "permission",
|
|
449
|
+
code: "credential_invalid",
|
|
450
|
+
detail
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function resolveClientCredentials(apiKeyFlag) {
|
|
444
454
|
let publishableKey = process.env.SOFTWARE_PUBLISHABLE_KEY;
|
|
445
455
|
let secretKey = apiKeyFlag ?? process.env.SOFTWARE_SECRET_KEY;
|
|
446
456
|
if (!publishableKey || !secretKey) {
|
|
@@ -458,29 +468,25 @@ function resolveClient(apiKeyFlag) {
|
|
|
458
468
|
}
|
|
459
469
|
}
|
|
460
470
|
if (!publishableKey || !secretKey) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
t("PassApiKey"),
|
|
469
|
-
t("SetEnvVars")
|
|
470
|
-
]
|
|
471
|
-
}
|
|
471
|
+
throw credentialError({
|
|
472
|
+
message: t("AuthenticationRequired"),
|
|
473
|
+
steps: [
|
|
474
|
+
t("RunLoginToAuthenticate"),
|
|
475
|
+
t("PassApiKey"),
|
|
476
|
+
t("SetEnvVars")
|
|
477
|
+
]
|
|
472
478
|
});
|
|
473
479
|
}
|
|
474
480
|
if (!isValidBearerToken(secretKey)) {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
detail: {
|
|
479
|
-
message: t("InvalidApiKeyFormat"),
|
|
480
|
-
suggestion: t("RetiredHexCredentialsRejected")
|
|
481
|
-
}
|
|
481
|
+
throw credentialError({
|
|
482
|
+
message: t("InvalidApiKeyFormat"),
|
|
483
|
+
suggestion: t("RetiredHexCredentialsRejected")
|
|
482
484
|
});
|
|
483
485
|
}
|
|
486
|
+
return { publishableKey, secretKey };
|
|
487
|
+
}
|
|
488
|
+
function resolveClientOrThrow(apiKeyFlag) {
|
|
489
|
+
const { publishableKey, secretKey } = resolveClientCredentials(apiKeyFlag);
|
|
484
490
|
const serverOptions = { publishableKey, secretKey };
|
|
485
491
|
return {
|
|
486
492
|
collections: new CollectionClient(
|
|
@@ -495,11 +501,37 @@ function resolveClient(apiKeyFlag) {
|
|
|
495
501
|
secretKey
|
|
496
502
|
};
|
|
497
503
|
}
|
|
504
|
+
function resolveClient(apiKeyFlag) {
|
|
505
|
+
try {
|
|
506
|
+
return resolveClientOrThrow(apiKeyFlag);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
exitWithError(error);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
498
511
|
|
|
499
512
|
// src/commands/crud.ts
|
|
500
513
|
import { readFileSync as readFileSync2 } from "fs";
|
|
501
514
|
import { basename } from "path";
|
|
515
|
+
|
|
516
|
+
// src/lib/collections.ts
|
|
502
517
|
import { COLLECTIONS } from "@01.software/sdk";
|
|
518
|
+
function validateCollection(name) {
|
|
519
|
+
if (COLLECTIONS.includes(name)) {
|
|
520
|
+
return name;
|
|
521
|
+
}
|
|
522
|
+
const normalized = name.replace(/-/g, "").toLowerCase();
|
|
523
|
+
const suggestions = COLLECTIONS.filter((collection) => {
|
|
524
|
+
const candidate = collection.replace(/-/g, "").toLowerCase();
|
|
525
|
+
return candidate.startsWith(normalized) || normalized.startsWith(candidate) || normalized.length >= 3 && candidate.includes(normalized);
|
|
526
|
+
}).slice(0, 5);
|
|
527
|
+
const hint = suggestions.length > 0 ? `Did you mean: ${suggestions.join(", ")}?` : 'Run "01 --help" for available collections.';
|
|
528
|
+
throw new Error(`Unknown collection "${name}". ${hint}`);
|
|
529
|
+
}
|
|
530
|
+
function parseSelect(input) {
|
|
531
|
+
return Object.fromEntries(
|
|
532
|
+
input.split(",").map((field) => field.trim()).map((field) => [field, true])
|
|
533
|
+
);
|
|
534
|
+
}
|
|
503
535
|
|
|
504
536
|
// src/lib/parse.ts
|
|
505
537
|
function failArg(label, value, expectedKind) {
|
|
@@ -581,21 +613,6 @@ function readFileAsBlob(filePath) {
|
|
|
581
613
|
const buffer = readFileSync2(filePath);
|
|
582
614
|
return { blob: new Blob([buffer]), filename: basename(filePath) };
|
|
583
615
|
}
|
|
584
|
-
function validateCollection(name) {
|
|
585
|
-
if (!COLLECTIONS.includes(name)) {
|
|
586
|
-
const normalized = name.replace(/-/g, "").toLowerCase();
|
|
587
|
-
const suggestions = COLLECTIONS.filter((c) => {
|
|
588
|
-
const cn = c.replace(/-/g, "").toLowerCase();
|
|
589
|
-
return cn.startsWith(normalized) || normalized.startsWith(cn) || normalized.length >= 3 && cn.includes(normalized);
|
|
590
|
-
}).slice(0, 5);
|
|
591
|
-
const hint = suggestions.length > 0 ? `Did you mean: ${suggestions.join(", ")}?` : 'Run "01 --help" for available collections.';
|
|
592
|
-
throw new Error(`Unknown collection "${name}". ${hint}`);
|
|
593
|
-
}
|
|
594
|
-
return name;
|
|
595
|
-
}
|
|
596
|
-
function parseSelect(input) {
|
|
597
|
-
return Object.fromEntries(input.split(",").map((f) => [f.trim(), true]));
|
|
598
|
-
}
|
|
599
616
|
function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
600
617
|
program2.command("query <collection>").description("Query documents from a collection").option("--where <json>", "Filter conditions (JSON)").option("--limit <n>", "Max results", (v) => parseInt(v, 10)).option("--page <n>", "Page number", (v) => parseInt(v, 10)).option("--sort <field>", "Sort field (prefix with - for descending)").option(
|
|
601
618
|
"--depth <n>",
|
|
@@ -1850,6 +1867,207 @@ Prerequisites:
|
|
|
1850
1867
|
});
|
|
1851
1868
|
}
|
|
1852
1869
|
|
|
1870
|
+
// src/commands/agent.ts
|
|
1871
|
+
import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
|
|
1872
|
+
|
|
1873
|
+
// src/lib/agent-output.ts
|
|
1874
|
+
function stringifyAgentJson(data, options = {}) {
|
|
1875
|
+
return options.pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
1876
|
+
}
|
|
1877
|
+
function asRecord(value) {
|
|
1878
|
+
return value && typeof value === "object" ? value : null;
|
|
1879
|
+
}
|
|
1880
|
+
function errorMessage(error) {
|
|
1881
|
+
const raw = asRecord(error);
|
|
1882
|
+
if (raw) {
|
|
1883
|
+
if (typeof raw.message === "string" && raw.message.length > 0) {
|
|
1884
|
+
return raw.message;
|
|
1885
|
+
}
|
|
1886
|
+
if (raw.detail && typeof raw.detail === "object" && typeof raw.detail.message === "string") {
|
|
1887
|
+
return String(raw.detail.message);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
if (error instanceof Error && error.message.length > 0) {
|
|
1891
|
+
return error.message;
|
|
1892
|
+
}
|
|
1893
|
+
if (typeof error === "string" && error.length > 0) {
|
|
1894
|
+
return error;
|
|
1895
|
+
}
|
|
1896
|
+
return "Internal error";
|
|
1897
|
+
}
|
|
1898
|
+
function isRawNotFound(error) {
|
|
1899
|
+
const raw = asRecord(error);
|
|
1900
|
+
return raw?.status === 404 || raw?.code === "not_found" || raw?.name === "GoneError";
|
|
1901
|
+
}
|
|
1902
|
+
function agentErrorExitCode(code) {
|
|
1903
|
+
switch (code) {
|
|
1904
|
+
case "INVALID_INPUT":
|
|
1905
|
+
return 2;
|
|
1906
|
+
case "AUTH_FAILED":
|
|
1907
|
+
return 3;
|
|
1908
|
+
case "NOT_FOUND":
|
|
1909
|
+
return 4;
|
|
1910
|
+
case "INTERNAL":
|
|
1911
|
+
return 1;
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
function classifyAgentError(error) {
|
|
1915
|
+
const adminError = classifyError(error);
|
|
1916
|
+
const message = errorMessage(error);
|
|
1917
|
+
if (isRawNotFound(error) || adminError.code === "not_found") {
|
|
1918
|
+
return { error: { code: "NOT_FOUND", message } };
|
|
1919
|
+
}
|
|
1920
|
+
if (adminError.type === "permission") {
|
|
1921
|
+
return { error: { code: "AUTH_FAILED", message } };
|
|
1922
|
+
}
|
|
1923
|
+
if (adminError.type === "validation" && adminError.code !== "unknown") {
|
|
1924
|
+
return { error: { code: "INVALID_INPUT", message } };
|
|
1925
|
+
}
|
|
1926
|
+
return { error: { code: "INTERNAL", message } };
|
|
1927
|
+
}
|
|
1928
|
+
function printAgentSuccess(data, options = {}) {
|
|
1929
|
+
console.log(stringifyAgentJson(data, options));
|
|
1930
|
+
}
|
|
1931
|
+
function printAgentError(error, options = {}) {
|
|
1932
|
+
const envelope = classifyAgentError(error);
|
|
1933
|
+
console.log(stringifyAgentJson(envelope, options));
|
|
1934
|
+
return envelope;
|
|
1935
|
+
}
|
|
1936
|
+
function exitWithAgentError(error, options = {}) {
|
|
1937
|
+
const envelope = printAgentError(error, options);
|
|
1938
|
+
process.exit(agentErrorExitCode(envelope.error.code));
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// src/commands/agent.ts
|
|
1942
|
+
var AGENT_PROTOCOL_VERSION = "1";
|
|
1943
|
+
function buildStableAgentFields() {
|
|
1944
|
+
return {
|
|
1945
|
+
id: { type: "string", queryable: true },
|
|
1946
|
+
createdAt: { type: "string", queryable: true },
|
|
1947
|
+
updatedAt: { type: "string", queryable: true }
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1950
|
+
function invalidInput(message, field, value) {
|
|
1951
|
+
const error = new Error(message);
|
|
1952
|
+
Object.assign(error, {
|
|
1953
|
+
type: "validation",
|
|
1954
|
+
code: "invalid_argument",
|
|
1955
|
+
field,
|
|
1956
|
+
detail: { message, value, field }
|
|
1957
|
+
});
|
|
1958
|
+
return error;
|
|
1959
|
+
}
|
|
1960
|
+
function parsePositiveInteger(value, field) {
|
|
1961
|
+
if (value == null) return void 0;
|
|
1962
|
+
if (/^[1-9]\d*$/.test(value)) return Number(value);
|
|
1963
|
+
throw invalidInput(`--${field} must be a positive integer`, field, value);
|
|
1964
|
+
}
|
|
1965
|
+
function handleCommanderError(error) {
|
|
1966
|
+
if (error.code === "commander.helpDisplayed") {
|
|
1967
|
+
process.exit(error.exitCode);
|
|
1968
|
+
}
|
|
1969
|
+
exitWithAgentError(invalidInput(error.message, "command"));
|
|
1970
|
+
}
|
|
1971
|
+
function configureAgentParser(command) {
|
|
1972
|
+
command.configureOutput({
|
|
1973
|
+
writeErr: () => {
|
|
1974
|
+
},
|
|
1975
|
+
writeOut: (str) => {
|
|
1976
|
+
process.stdout.write(str);
|
|
1977
|
+
}
|
|
1978
|
+
});
|
|
1979
|
+
command.exitOverride(handleCommanderError);
|
|
1980
|
+
return command;
|
|
1981
|
+
}
|
|
1982
|
+
function parseWhere(value) {
|
|
1983
|
+
if (value == null) return void 0;
|
|
1984
|
+
try {
|
|
1985
|
+
const parsed = JSON.parse(value);
|
|
1986
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1987
|
+
return parsed;
|
|
1988
|
+
}
|
|
1989
|
+
} catch {
|
|
1990
|
+
throw invalidInput("--where must be a JSON object", "where", value);
|
|
1991
|
+
}
|
|
1992
|
+
throw invalidInput("--where must be a JSON object", "where", value);
|
|
1993
|
+
}
|
|
1994
|
+
function buildAgentManifest() {
|
|
1995
|
+
const collections = {};
|
|
1996
|
+
for (const collection of COLLECTIONS3) {
|
|
1997
|
+
collections[collection] = {
|
|
1998
|
+
operations: ["query", "get"],
|
|
1999
|
+
fields: buildStableAgentFields()
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
return {
|
|
2003
|
+
version: AGENT_PROTOCOL_VERSION,
|
|
2004
|
+
collections
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
function validateAgentCollection(collection) {
|
|
2008
|
+
try {
|
|
2009
|
+
return validateCollection(collection);
|
|
2010
|
+
} catch (error) {
|
|
2011
|
+
const message = error instanceof Error ? error.message : `Unknown collection "${collection}".`;
|
|
2012
|
+
throw invalidInput(message, "collection", collection);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function registerAgentCommands(program2, getClient2) {
|
|
2016
|
+
const agent = configureAgentParser(
|
|
2017
|
+
program2.command("agent").description("Machine-stable CLI namespace for coding agents").addHelpText(
|
|
2018
|
+
"after",
|
|
2019
|
+
"\nContract: docs/agent-cli-contract.md\nJSON only on stdout; no TTY effects."
|
|
2020
|
+
)
|
|
2021
|
+
);
|
|
2022
|
+
configureAgentParser(
|
|
2023
|
+
agent.command("manifest").description("Print the Agent CLI protocol manifest").option("--pretty", "Print 2-space indented JSON").action((opts) => {
|
|
2024
|
+
printAgentSuccess(buildAgentManifest(), { pretty: Boolean(opts.pretty) });
|
|
2025
|
+
})
|
|
2026
|
+
);
|
|
2027
|
+
configureAgentParser(
|
|
2028
|
+
agent.command("query <collection>").description("Query documents from a collection").option("--where <json>", "Filter conditions as a JSON object").option("--limit <n>", "Max results").option("--page <n>", "Page number").option("--sort <field>", "Sort field; prefix with - for descending").option("--select <fields>", "Comma-separated fields to select").option("--pretty", "Print 2-space indented JSON").action(
|
|
2029
|
+
async (collection, opts) => {
|
|
2030
|
+
try {
|
|
2031
|
+
const col = validateAgentCollection(collection);
|
|
2032
|
+
const options = {};
|
|
2033
|
+
const where = parseWhere(opts.where);
|
|
2034
|
+
const limit = parsePositiveInteger(opts.limit, "limit");
|
|
2035
|
+
const page = parsePositiveInteger(opts.page, "page");
|
|
2036
|
+
if (where) options.where = where;
|
|
2037
|
+
if (limit != null) options.limit = limit;
|
|
2038
|
+
if (page != null) options.page = page;
|
|
2039
|
+
if (opts.sort) options.sort = opts.sort;
|
|
2040
|
+
if (opts.select) options.select = parseSelect(opts.select);
|
|
2041
|
+
const client = getClient2();
|
|
2042
|
+
const result = await client.collections.from(col).find(options);
|
|
2043
|
+
printAgentSuccess(result, { pretty: Boolean(opts.pretty) });
|
|
2044
|
+
} catch (error) {
|
|
2045
|
+
exitWithAgentError(error, { pretty: Boolean(opts.pretty) });
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
)
|
|
2049
|
+
);
|
|
2050
|
+
configureAgentParser(
|
|
2051
|
+
agent.command("get <collection> [id]").description("Get a document by ID").option("--select <fields>", "Comma-separated fields to select").option("--pretty", "Print 2-space indented JSON").action(
|
|
2052
|
+
async (collection, id, opts) => {
|
|
2053
|
+
try {
|
|
2054
|
+
const col = validateAgentCollection(collection);
|
|
2055
|
+
if (!id) {
|
|
2056
|
+
throw invalidInput("Missing required argument: id", "id");
|
|
2057
|
+
}
|
|
2058
|
+
const options = {};
|
|
2059
|
+
if (opts.select) options.select = parseSelect(opts.select);
|
|
2060
|
+
const client = getClient2();
|
|
2061
|
+
const result = await client.collections.from(col).findById(id, options);
|
|
2062
|
+
printAgentSuccess(result, { pretty: Boolean(opts.pretty) });
|
|
2063
|
+
} catch (error) {
|
|
2064
|
+
exitWithAgentError(error, { pretty: Boolean(opts.pretty) });
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
)
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
1853
2071
|
// src/index.ts
|
|
1854
2072
|
var require2 = createRequire(import.meta.url);
|
|
1855
2073
|
var { version } = require2("../package.json");
|
|
@@ -1865,6 +2083,8 @@ process.on("unhandledRejection", (err) => {
|
|
|
1865
2083
|
exitWithError(err, { format: getFormat() });
|
|
1866
2084
|
});
|
|
1867
2085
|
var getClient = () => resolveClient(program.opts().apiKey);
|
|
2086
|
+
var getAgentClient = () => resolveClientOrThrow(program.opts().apiKey);
|
|
2087
|
+
registerAgentCommands(program, getAgentClient);
|
|
1868
2088
|
registerCrudCommands(program, getClient, getFormat);
|
|
1869
2089
|
registerOrderCommands(program, getClient, getFormat);
|
|
1870
2090
|
registerReturnCommands(program, getClient, getFormat);
|