@stndrds/cli 1.0.0-alpha.294 → 1.0.0-alpha.296
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/LICENSE +111 -0
- package/README.md +4 -0
- package/dist/bin.mjs +146 -173
- package/package.json +7 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
STANDARDS SDK LICENSE
|
|
2
|
+
Version 1.0, September 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2025-2026 AND YOU CREATE SAS. All rights reserved.
|
|
5
|
+
|
|
6
|
+
AND YOU CREATE, a French société par actions simplifiée with a share capital
|
|
7
|
+
of EUR 500, registered with the Paris Trade and Companies Register under
|
|
8
|
+
number 940 190 614, having its registered office at 60 rue François Ier,
|
|
9
|
+
75008 Paris, France (VAT FR34940190614) ("AYC", "we"), is the sole owner of
|
|
10
|
+
the software distributed under this license (the "SDK"): the source code,
|
|
11
|
+
compiled code, type declarations, documentation and any accompanying files
|
|
12
|
+
published in this package.
|
|
13
|
+
|
|
14
|
+
This is not an open source license. The SDK is made available so that you
|
|
15
|
+
can build software that communicates with the Standards platform operated by
|
|
16
|
+
AYC ("Standards"). Reading the source is permitted; everything else is
|
|
17
|
+
governed by the terms below. By installing, copying or using the SDK you
|
|
18
|
+
("you", the "Licensee") accept them. If you do not accept them, do not use
|
|
19
|
+
the SDK.
|
|
20
|
+
|
|
21
|
+
1. LICENSE GRANT
|
|
22
|
+
AYC grants you a limited, non-exclusive, non-transferable, non-sublicensable,
|
|
23
|
+
revocable license to:
|
|
24
|
+
(a) install and use the SDK, in unmodified form, solely to develop, test
|
|
25
|
+
and run applications that communicate with a Standards tenant, workspace
|
|
26
|
+
or API that you are authorised to access under a valid agreement with
|
|
27
|
+
AYC or with an AYC customer; and
|
|
28
|
+
(b) make the copies of the SDK reasonably necessary for that purpose,
|
|
29
|
+
including copies produced by your build tooling and bundlers.
|
|
30
|
+
|
|
31
|
+
2. RESTRICTIONS
|
|
32
|
+
Except as expressly permitted in Section 1, you shall not, and shall not
|
|
33
|
+
permit any third party to:
|
|
34
|
+
(a) modify, translate, adapt or create derivative works of the SDK;
|
|
35
|
+
(b) reverse engineer, decompile or disassemble the SDK, or otherwise attempt
|
|
36
|
+
to derive its design or internal structure, except to the extent that
|
|
37
|
+
applicable law expressly permits it despite this restriction (Articles
|
|
38
|
+
L.122-6-1 III and IV of the French Intellectual Property Code), in which
|
|
39
|
+
case you shall first request the information from AYC;
|
|
40
|
+
(c) distribute, sell, rent, lease, lend, sublicense, publish or otherwise
|
|
41
|
+
make the SDK, or any part of it, available to any third party, other
|
|
42
|
+
than as bundled inside an application described in Section 1(a);
|
|
43
|
+
(d) use the SDK, or any knowledge of its interfaces, formats, protocols or
|
|
44
|
+
schemas obtained through it, to build, train or improve a product or
|
|
45
|
+
service that competes with Standards, or to access Standards other than
|
|
46
|
+
through the interfaces AYC documents;
|
|
47
|
+
(e) use the SDK to interact with any Standards instance, tenant or API that
|
|
48
|
+
you are not authorised to access, or to circumvent any authentication,
|
|
49
|
+
authorisation, rate limit, licence key or other technical measure;
|
|
50
|
+
(f) remove, alter or obscure any copyright, trademark, licence or other
|
|
51
|
+
proprietary notice in the SDK; or
|
|
52
|
+
(g) use AYC's or Standards' names, logos or trademarks except to state
|
|
53
|
+
truthfully that your application uses the Standards SDK.
|
|
54
|
+
|
|
55
|
+
3. OWNERSHIP
|
|
56
|
+
The SDK is licensed, not sold. AYC and its licensors retain all right, title
|
|
57
|
+
and interest in and to the SDK, including all intellectual property rights.
|
|
58
|
+
No right is granted by implication, estoppel or otherwise. Any feedback or
|
|
59
|
+
suggestion you provide about the SDK may be used by AYC without restriction
|
|
60
|
+
or obligation.
|
|
61
|
+
|
|
62
|
+
4. THIRD-PARTY COMPONENTS
|
|
63
|
+
The SDK may include or depend on third-party open source components. Those
|
|
64
|
+
components are governed by their own licences, which are identified in the
|
|
65
|
+
package metadata and prevail over this license for those components only.
|
|
66
|
+
|
|
67
|
+
5. UPDATES
|
|
68
|
+
AYC may publish new versions of the SDK at any time. This license applies to
|
|
69
|
+
each version you obtain unless that version is accompanied by a different
|
|
70
|
+
licence. AYC has no obligation to maintain, support or update the SDK.
|
|
71
|
+
|
|
72
|
+
6. TERM AND TERMINATION
|
|
73
|
+
This license is effective until terminated. It terminates automatically,
|
|
74
|
+
without notice, if you breach any of its terms. AYC may also terminate it on
|
|
75
|
+
written notice if your agreement with AYC or with the AYC customer whose
|
|
76
|
+
tenant you access ends. Upon termination you shall stop using the SDK and
|
|
77
|
+
destroy every copy in your possession or control. Sections 2, 3, 7, 8 and 9
|
|
78
|
+
survive termination.
|
|
79
|
+
|
|
80
|
+
7. NO WARRANTY
|
|
81
|
+
THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT WARRANTY OF ANY KIND,
|
|
82
|
+
EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
83
|
+
PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, TO THE FULLEST EXTENT
|
|
84
|
+
PERMITTED BY APPLICABLE LAW. AYC does not warrant that the SDK will be
|
|
85
|
+
error-free or uninterrupted.
|
|
86
|
+
|
|
87
|
+
8. LIMITATION OF LIABILITY
|
|
88
|
+
TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, AYC SHALL NOT BE LIABLE
|
|
89
|
+
FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, OR
|
|
90
|
+
FOR ANY LOSS OF PROFITS, REVENUE, DATA OR GOODWILL, ARISING OUT OF OR IN
|
|
91
|
+
CONNECTION WITH THE SDK OR THIS LICENSE. AYC'S TOTAL AGGREGATE LIABILITY
|
|
92
|
+
UNDER THIS LICENSE SHALL NOT EXCEED ONE HUNDRED EUROS (EUR 100). Nothing in
|
|
93
|
+
this license excludes or limits liability that cannot be excluded or limited
|
|
94
|
+
under applicable law, including liability for gross negligence, wilful
|
|
95
|
+
misconduct or death or personal injury caused by negligence.
|
|
96
|
+
|
|
97
|
+
9. GOVERNING LAW AND JURISDICTION
|
|
98
|
+
This license is governed by the laws of France. Any dispute arising out of or
|
|
99
|
+
in connection with it shall be submitted to the exclusive jurisdiction of the
|
|
100
|
+
courts of Paris, France, subject to any mandatory rule granting jurisdiction
|
|
101
|
+
to another court.
|
|
102
|
+
|
|
103
|
+
10. GENERAL
|
|
104
|
+
If any provision of this license is held unenforceable, the remaining
|
|
105
|
+
provisions remain in force. AYC's failure to enforce a provision is not a
|
|
106
|
+
waiver of it. This license is the entire agreement between you and AYC about
|
|
107
|
+
the SDK and supersedes any prior understanding about it, without prejudice to
|
|
108
|
+
any separate agreement governing your access to Standards.
|
|
109
|
+
|
|
110
|
+
To obtain a different licence, or for any question about this one, contact
|
|
111
|
+
AND YOU CREATE SAS, 60 rue François Ier, 75008 Paris, France.
|
package/README.md
CHANGED
|
@@ -32,3 +32,7 @@ claude -p "Summarize the failing tests"
|
|
|
32
32
|
|
|
33
33
|
Every agent command targeting a device requires explicit user approval. Calls to `exec_command`
|
|
34
34
|
without a `deviceId` continue to use the agent sandbox.
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
Licensed under the Standards SDK License 1.0 — see `LICENSE`. This package is not open source: it is provided to build applications that communicate with Standards.
|
package/dist/bin.mjs
CHANGED
|
@@ -1,170 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
2
3
|
|
|
3
4
|
// src/program.ts
|
|
4
5
|
import chalk10 from "chalk";
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
|
|
7
8
|
// src/client.ts
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
super(message);
|
|
11
|
-
this.statusCode = statusCode;
|
|
12
|
-
this.name = "ApiClientError";
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
function buildUrl(base, path, params) {
|
|
16
|
-
const normalizedBase = base.endsWith("/") ? base : `${base}/`;
|
|
17
|
-
const normalizedPath = path.replace(/^\/+/, "");
|
|
18
|
-
const url = new URL(normalizedPath, normalizedBase);
|
|
19
|
-
if (params) {
|
|
20
|
-
for (const [key, value] of Object.entries(params)) {
|
|
21
|
-
if (value !== void 0 && value !== null) {
|
|
22
|
-
url.searchParams.set(key, String(value));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return url.toString();
|
|
27
|
-
}
|
|
9
|
+
import { StandardsRequestError, createTransport } from "@stndrds/client";
|
|
10
|
+
var ApiClientError = StandardsRequestError;
|
|
28
11
|
function createClient(config) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
...tenantId ? { "X-Tenant-ID": tenantId } : {}
|
|
34
|
-
};
|
|
35
|
-
async function sendRequest(url, init) {
|
|
36
|
-
let response;
|
|
37
|
-
try {
|
|
38
|
-
response = await fetch(url, { ...init, signal: AbortSignal.timeout(3e4) });
|
|
39
|
-
} catch (error) {
|
|
40
|
-
if (error instanceof TypeError || error instanceof DOMException && error.name === "TimeoutError") {
|
|
41
|
-
throw new ApiClientError(0, `Could not connect to ${apiUrl}. Is the server running?`);
|
|
42
|
-
}
|
|
43
|
-
throw error;
|
|
44
|
-
}
|
|
45
|
-
if (response.status === 204) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
const data = await response.json();
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
const message = data.message ?? `Request failed with status ${response.status}`;
|
|
51
|
-
throw new ApiClientError(response.status, message);
|
|
52
|
-
}
|
|
53
|
-
return data;
|
|
54
|
-
}
|
|
55
|
-
function request(method, path, options) {
|
|
56
|
-
const url = buildUrl(apiUrl, path, options?.params);
|
|
57
|
-
return sendRequest(url, {
|
|
58
|
-
method,
|
|
59
|
-
headers,
|
|
60
|
-
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
async function getText(path, params) {
|
|
64
|
-
const url = buildUrl(apiUrl, path, params);
|
|
65
|
-
let response;
|
|
66
|
-
try {
|
|
67
|
-
response = await fetch(url, { method: "GET", headers, signal: AbortSignal.timeout(3e4) });
|
|
68
|
-
} catch (error) {
|
|
69
|
-
if (error instanceof TypeError || error instanceof DOMException && error.name === "TimeoutError") {
|
|
70
|
-
throw new ApiClientError(0, `Could not connect to ${apiUrl}. Is the server running?`);
|
|
71
|
-
}
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
const text = await response.text();
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
let message = `Request failed with status ${response.status}`;
|
|
77
|
-
try {
|
|
78
|
-
message = JSON.parse(text).message ?? message;
|
|
79
|
-
} catch {
|
|
80
|
-
if (text) message = text;
|
|
81
|
-
}
|
|
82
|
-
throw new ApiClientError(response.status, message);
|
|
83
|
-
}
|
|
84
|
-
return text;
|
|
85
|
-
}
|
|
86
|
-
function postMultipart(path, form) {
|
|
87
|
-
const url = buildUrl(apiUrl, path);
|
|
88
|
-
const { "Content-Type": _ct, ...multipartHeaders } = headers;
|
|
89
|
-
return sendRequest(url, { method: "POST", headers: multipartHeaders, body: form });
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
get(path, params) {
|
|
93
|
-
return request("GET", path, { params });
|
|
94
|
-
},
|
|
95
|
-
post(path, body) {
|
|
96
|
-
return request("POST", path, { body });
|
|
97
|
-
},
|
|
98
|
-
patch(path, body) {
|
|
99
|
-
return request("PATCH", path, { body });
|
|
100
|
-
},
|
|
101
|
-
put(path, body) {
|
|
102
|
-
return request("PUT", path, { body });
|
|
103
|
-
},
|
|
104
|
-
delete(path) {
|
|
105
|
-
return request("DELETE", path);
|
|
106
|
-
},
|
|
107
|
-
getText,
|
|
108
|
-
postMultipart
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// src/commands/auth.ts
|
|
113
|
-
import chalk from "chalk";
|
|
114
|
-
|
|
115
|
-
// src/commands/common.ts
|
|
116
|
-
function getGlobalOptions(cmd) {
|
|
117
|
-
return cmd.optsWithGlobals();
|
|
118
|
-
}
|
|
119
|
-
function getFormat(cmd) {
|
|
120
|
-
return getGlobalOptions(cmd).format;
|
|
121
|
-
}
|
|
122
|
-
function parseCsvList(value) {
|
|
123
|
-
return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
124
|
-
}
|
|
125
|
-
function getClientFromCommand(cmd) {
|
|
126
|
-
const root = getGlobalOptions(cmd);
|
|
127
|
-
if (!(root.apiUrl && root.apiKey)) {
|
|
128
|
-
throw new Error('No Standards instance configured. Run "standards login" or pass --api-key.');
|
|
129
|
-
}
|
|
130
|
-
return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey, tenantId: root.tenant });
|
|
131
|
-
}
|
|
132
|
-
function requireTenant(cmd, message) {
|
|
133
|
-
const { tenant } = getGlobalOptions(cmd);
|
|
134
|
-
if (!tenant) {
|
|
135
|
-
throw new Error(message);
|
|
136
|
-
}
|
|
137
|
-
return tenant;
|
|
138
|
-
}
|
|
139
|
-
function messageOf(error) {
|
|
140
|
-
return error instanceof Error ? error.message : String(error);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// src/commands/auth.ts
|
|
144
|
-
function registerAuthCommand(program) {
|
|
145
|
-
const auth = program.command("auth").description("Inspect CLI authentication");
|
|
146
|
-
auth.command("whoami").description("Show current configuration and validate API key").action(async (_opts, cmd) => {
|
|
147
|
-
const root = getGlobalOptions(cmd);
|
|
148
|
-
const client = getClientFromCommand(cmd);
|
|
149
|
-
const write = (msg) => process.stdout.write(`${msg}
|
|
150
|
-
`);
|
|
151
|
-
write(chalk.bold("Standards CLI Configuration"));
|
|
152
|
-
write(` API URL: ${root.apiUrl}`);
|
|
153
|
-
write(` API Key: ${root.apiKey ? `${root.apiKey.slice(0, 8)}...` : chalk.red("not set")}`);
|
|
154
|
-
write("");
|
|
155
|
-
const keys = await client.get("/api-keys");
|
|
156
|
-
write(chalk.green("\u2713 API key is valid"));
|
|
157
|
-
if (Array.isArray(keys) && keys.length > 0) {
|
|
158
|
-
const activeKeys = keys.filter(
|
|
159
|
-
(key) => typeof key === "object" && key !== null && !("revokedAt" in key && key.revokedAt)
|
|
160
|
-
);
|
|
161
|
-
write(` Active keys: ${activeKeys.length}`);
|
|
162
|
-
}
|
|
12
|
+
return createTransport({
|
|
13
|
+
baseUrl: config.apiUrl,
|
|
14
|
+
apiKey: config.apiKey,
|
|
15
|
+
tenantId: config.tenantId
|
|
163
16
|
});
|
|
164
17
|
}
|
|
165
18
|
|
|
19
|
+
// src/commands/ai.ts
|
|
20
|
+
import { ValidationError } from "@stndrds/schema";
|
|
21
|
+
|
|
166
22
|
// src/output.ts
|
|
167
|
-
import
|
|
23
|
+
import chalk from "chalk";
|
|
168
24
|
import Table from "cli-table3";
|
|
169
25
|
var MAX_CELL_WIDTH = 50;
|
|
170
26
|
function truncate(value, maxLength) {
|
|
@@ -193,7 +49,7 @@ function formatTable(items) {
|
|
|
193
49
|
if (items.length === 0) return "No results.";
|
|
194
50
|
const headers = Object.keys(items[0]);
|
|
195
51
|
const table = new Table({
|
|
196
|
-
head: headers.map((h) =>
|
|
52
|
+
head: headers.map((h) => chalk.bold(h)),
|
|
197
53
|
style: { head: [], border: [] }
|
|
198
54
|
});
|
|
199
55
|
for (const item of items) {
|
|
@@ -223,6 +79,90 @@ function formatOutput(data, format) {
|
|
|
223
79
|
`);
|
|
224
80
|
}
|
|
225
81
|
|
|
82
|
+
// src/commands/common.ts
|
|
83
|
+
function getGlobalOptions(cmd) {
|
|
84
|
+
return cmd.optsWithGlobals();
|
|
85
|
+
}
|
|
86
|
+
function getFormat(cmd) {
|
|
87
|
+
return getGlobalOptions(cmd).format;
|
|
88
|
+
}
|
|
89
|
+
function parseCsvList(value) {
|
|
90
|
+
return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
91
|
+
}
|
|
92
|
+
function getClientFromCommand(cmd) {
|
|
93
|
+
const root = getGlobalOptions(cmd);
|
|
94
|
+
if (!(root.apiUrl && root.apiKey)) {
|
|
95
|
+
throw new Error('No Standards instance configured. Run "standards login" or pass --api-key.');
|
|
96
|
+
}
|
|
97
|
+
return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey, tenantId: root.tenant });
|
|
98
|
+
}
|
|
99
|
+
function requireTenant(cmd, message) {
|
|
100
|
+
const { tenant } = getGlobalOptions(cmd);
|
|
101
|
+
if (!tenant) {
|
|
102
|
+
throw new Error(message);
|
|
103
|
+
}
|
|
104
|
+
return tenant;
|
|
105
|
+
}
|
|
106
|
+
function messageOf(error) {
|
|
107
|
+
return error instanceof Error ? error.message : String(error);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/commands/ai.ts
|
|
111
|
+
var SCOPES = ["me", "workspace"];
|
|
112
|
+
var ISO_DAY = /^\d{4}-\d{2}-\d{2}$/u;
|
|
113
|
+
function parseDay(flag, value) {
|
|
114
|
+
if (!ISO_DAY.test(value)) {
|
|
115
|
+
throw new ValidationError(`${flag} must be a YYYY-MM-DD date`, []);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
function parseScope(scope) {
|
|
120
|
+
if (SCOPES.includes(scope)) return scope;
|
|
121
|
+
throw new ValidationError(`--scope must be one of: ${SCOPES.join(", ")}`, []);
|
|
122
|
+
}
|
|
123
|
+
function registerAiCommand(program) {
|
|
124
|
+
const ai = program.command("ai").description("Inspect AI usage and credit state");
|
|
125
|
+
ai.command("usage").description("Aggregate the AI journal over an inclusive UTC day window").requiredOption("--from <day>", "first day of the window (YYYY-MM-DD)").requiredOption("--to <day>", "last day of the window, inclusive (YYYY-MM-DD)").option("--scope <scope>", "me or workspace", "me").action(async (opts, cmd) => {
|
|
126
|
+
const params = {
|
|
127
|
+
from: parseDay("--from", opts.from),
|
|
128
|
+
to: parseDay("--to", opts.to),
|
|
129
|
+
scope: parseScope(opts.scope ?? "me")
|
|
130
|
+
};
|
|
131
|
+
const client = getClientFromCommand(cmd);
|
|
132
|
+
const result = await client.get("/ai/usage", params);
|
|
133
|
+
formatOutput(result, getFormat(cmd));
|
|
134
|
+
});
|
|
135
|
+
ai.command("wallet").description("Show the tenant's billing mode and AI credit state").action(async (_opts, cmd) => {
|
|
136
|
+
const client = getClientFromCommand(cmd);
|
|
137
|
+
const result = await client.get("/ai/wallet");
|
|
138
|
+
formatOutput(result, getFormat(cmd));
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/commands/auth.ts
|
|
143
|
+
import chalk2 from "chalk";
|
|
144
|
+
function registerAuthCommand(program) {
|
|
145
|
+
const auth = program.command("auth").description("Inspect CLI authentication");
|
|
146
|
+
auth.command("whoami").description("Show current configuration and validate API key").action(async (_opts, cmd) => {
|
|
147
|
+
const root = getGlobalOptions(cmd);
|
|
148
|
+
const client = getClientFromCommand(cmd);
|
|
149
|
+
const write = (msg) => process.stdout.write(`${msg}
|
|
150
|
+
`);
|
|
151
|
+
write(chalk2.bold("Standards CLI Configuration"));
|
|
152
|
+
write(` API URL: ${root.apiUrl}`);
|
|
153
|
+
write(` API Key: ${root.apiKey ? `${root.apiKey.slice(0, 8)}...` : chalk2.red("not set")}`);
|
|
154
|
+
write("");
|
|
155
|
+
const keys = await client.get("/api-keys");
|
|
156
|
+
write(chalk2.green("\u2713 API key is valid"));
|
|
157
|
+
if (Array.isArray(keys) && keys.length > 0) {
|
|
158
|
+
const activeKeys = keys.filter(
|
|
159
|
+
(key) => typeof key === "object" && key !== null && !("revokedAt" in key && key.revokedAt)
|
|
160
|
+
);
|
|
161
|
+
write(` Active keys: ${activeKeys.length}`);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
226
166
|
// src/commands/bundles.ts
|
|
227
167
|
function registerBundlesCommand(program) {
|
|
228
168
|
const bundles = program.command("bundles").description("Manage system bundles assigned to the current tenant (admin)");
|
|
@@ -257,7 +197,7 @@ function registerBundlesCommand(program) {
|
|
|
257
197
|
}
|
|
258
198
|
|
|
259
199
|
// src/commands/connectors.ts
|
|
260
|
-
import { ValidationError } from "@stndrds/schema";
|
|
200
|
+
import { ValidationError as ValidationError2 } from "@stndrds/schema";
|
|
261
201
|
import chalk3 from "chalk";
|
|
262
202
|
var PROVIDER_IDS = {
|
|
263
203
|
gmail: true,
|
|
@@ -288,7 +228,7 @@ function registerConnectorsCommand(program) {
|
|
|
288
228
|
`connector provider (${PROVIDERS.join(", ")}); run "connectors providers" for the ones this deployment configured`
|
|
289
229
|
).option("--scope <scope>", "connection scope (tenant or actor)", "tenant").action(async (opts, cmd) => {
|
|
290
230
|
if (!PROVIDERS.includes(opts.provider)) {
|
|
291
|
-
throw new
|
|
231
|
+
throw new ValidationError2(`--provider must be one of: ${PROVIDERS.join(", ")}`, []);
|
|
292
232
|
}
|
|
293
233
|
const client = getClientFromCommand(cmd);
|
|
294
234
|
const result = await client.post("/connectors/auth/start", {
|
|
@@ -1295,19 +1235,19 @@ function registerKeysCommand(program) {
|
|
|
1295
1235
|
}
|
|
1296
1236
|
|
|
1297
1237
|
// src/commands/mcp.ts
|
|
1298
|
-
import { RESOURCE_VISIBILITIES, ValidationError as
|
|
1238
|
+
import { RESOURCE_VISIBILITIES, ValidationError as ValidationError3 } from "@stndrds/schema";
|
|
1299
1239
|
import chalk6 from "chalk";
|
|
1300
1240
|
var AUTH_TYPES = ["none", "header"];
|
|
1301
1241
|
function buildAuth(opts) {
|
|
1302
1242
|
const type = opts.authType ?? "none";
|
|
1303
1243
|
if (!AUTH_TYPES.includes(type)) {
|
|
1304
|
-
throw new
|
|
1244
|
+
throw new ValidationError3(`--auth-type must be one of: ${AUTH_TYPES.join(", ")}`, []);
|
|
1305
1245
|
}
|
|
1306
1246
|
if (type === "none") {
|
|
1307
1247
|
return { type: "none" };
|
|
1308
1248
|
}
|
|
1309
1249
|
if (!(opts.headerName && opts.secret)) {
|
|
1310
|
-
throw new
|
|
1250
|
+
throw new ValidationError3('--auth-type "header" requires both --header-name and --secret.', []);
|
|
1311
1251
|
}
|
|
1312
1252
|
return { type: "header", headerName: opts.headerName, secret: opts.secret };
|
|
1313
1253
|
}
|
|
@@ -1316,7 +1256,7 @@ function resolveVisibility(visibility) {
|
|
|
1316
1256
|
return "workspace";
|
|
1317
1257
|
}
|
|
1318
1258
|
if (!RESOURCE_VISIBILITIES.includes(visibility)) {
|
|
1319
|
-
throw new
|
|
1259
|
+
throw new ValidationError3(
|
|
1320
1260
|
`--visibility must be one of: ${RESOURCE_VISIBILITIES.join(", ")}`,
|
|
1321
1261
|
[]
|
|
1322
1262
|
);
|
|
@@ -1365,7 +1305,7 @@ function registerMcpCommand(program) {
|
|
|
1365
1305
|
});
|
|
1366
1306
|
mcp.command("disconnect").description("Disconnect (delete) an MCP server").argument("<id>", "MCP server ID").option("--yes", "disconnect without confirmation").action(async (id, opts, cmd) => {
|
|
1367
1307
|
if (!opts.yes) {
|
|
1368
|
-
throw new
|
|
1308
|
+
throw new ValidationError3(
|
|
1369
1309
|
'Disconnecting an MCP server is explicit. Re-run with "--yes" to confirm.',
|
|
1370
1310
|
[]
|
|
1371
1311
|
);
|
|
@@ -1382,17 +1322,17 @@ import { createHmac } from "crypto";
|
|
|
1382
1322
|
import {
|
|
1383
1323
|
FAKE_MEETING_BOT_SIGNATURE_HEADER,
|
|
1384
1324
|
RECORDING_OVERRIDES,
|
|
1385
|
-
ValidationError as
|
|
1325
|
+
ValidationError as ValidationError4
|
|
1386
1326
|
} from "@stndrds/schema";
|
|
1387
1327
|
var ORDERS = ["asc", "desc"];
|
|
1388
1328
|
function parseOrder(order) {
|
|
1389
1329
|
if (ORDERS.includes(order)) return order;
|
|
1390
|
-
throw new
|
|
1330
|
+
throw new ValidationError4(`--order must be one of: ${ORDERS.join(", ")}`, []);
|
|
1391
1331
|
}
|
|
1392
1332
|
function parseCount(flag, value) {
|
|
1393
1333
|
const parsed = Number(value);
|
|
1394
1334
|
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
1395
|
-
throw new
|
|
1335
|
+
throw new ValidationError4(`${flag} must be a non-negative integer`, []);
|
|
1396
1336
|
}
|
|
1397
1337
|
return parsed;
|
|
1398
1338
|
}
|
|
@@ -1414,7 +1354,7 @@ function parseOverride(opts) {
|
|
|
1414
1354
|
);
|
|
1415
1355
|
if (opts.auto) chosen.push(null);
|
|
1416
1356
|
if (chosen.length !== 1) {
|
|
1417
|
-
throw new
|
|
1357
|
+
throw new ValidationError4("record needs exactly one of --force, --skip or --auto", []);
|
|
1418
1358
|
}
|
|
1419
1359
|
return chosen[0] ?? null;
|
|
1420
1360
|
}
|
|
@@ -1499,15 +1439,15 @@ function registerMeetingsCommand(program) {
|
|
|
1499
1439
|
).action(async (id, opts, cmd) => {
|
|
1500
1440
|
const secret = process.env.MEETING_BOT_FAKE_SECRET;
|
|
1501
1441
|
if (!secret) {
|
|
1502
|
-
throw new
|
|
1442
|
+
throw new ValidationError4("MEETING_BOT_FAKE_SECRET is not set in this shell", []);
|
|
1503
1443
|
}
|
|
1504
1444
|
const lines = parseCount("--lines", opts.lines);
|
|
1505
|
-
if (lines < 1) throw new
|
|
1445
|
+
if (lines < 1) throw new ValidationError4("--lines must be at least 1", []);
|
|
1506
1446
|
const client = getClientFromCommand(cmd);
|
|
1507
1447
|
const meeting = await client.get(`/meetings/${id}`);
|
|
1508
1448
|
const { status, botId } = meeting.recording;
|
|
1509
1449
|
if (status !== "scheduled" && status !== "recording" || botId === null) {
|
|
1510
|
-
throw new
|
|
1450
|
+
throw new ValidationError4(`Meeting ${id} has no bot to complete (status: ${status})`, []);
|
|
1511
1451
|
}
|
|
1512
1452
|
const segments = buildSimulatedSegments(simulatedSpeakers(meeting), lines);
|
|
1513
1453
|
const startedAt = meeting.startsAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1536,7 +1476,7 @@ function registerMeetingsCommand(program) {
|
|
|
1536
1476
|
}
|
|
1537
1477
|
);
|
|
1538
1478
|
if (!response.ok) {
|
|
1539
|
-
throw new
|
|
1479
|
+
throw new ValidationError4(`webhook answered ${response.status}`, []);
|
|
1540
1480
|
}
|
|
1541
1481
|
formatOutput({ botId, segments: segments.length }, getFormat(cmd));
|
|
1542
1482
|
});
|
|
@@ -1688,6 +1628,16 @@ function registerPullCommand(program) {
|
|
|
1688
1628
|
});
|
|
1689
1629
|
}
|
|
1690
1630
|
|
|
1631
|
+
// src/commands/quotas.ts
|
|
1632
|
+
function registerQuotasCommand(program) {
|
|
1633
|
+
const quotas = program.command("quotas").description("Inspect the tenant's remaining capacity");
|
|
1634
|
+
quotas.command("list").description("List one state per quota key (limit is null when nothing is enforced)").action(async (_opts, cmd) => {
|
|
1635
|
+
const client = getClientFromCommand(cmd);
|
|
1636
|
+
const result = await client.get("/quotas");
|
|
1637
|
+
formatOutput(result, getFormat(cmd));
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1691
1641
|
// src/commands/records.ts
|
|
1692
1642
|
import { readFile as readFile3 } from "fs/promises";
|
|
1693
1643
|
import { basename } from "path";
|
|
@@ -1867,6 +1817,26 @@ function registerSearchCommand(program) {
|
|
|
1867
1817
|
});
|
|
1868
1818
|
}
|
|
1869
1819
|
|
|
1820
|
+
// src/commands/sources.ts
|
|
1821
|
+
function registerSourcesCommand(program) {
|
|
1822
|
+
const sources = program.command("sources").description("Inspect and remove remote schema sources on the current tenant");
|
|
1823
|
+
sources.command("list").description("List remote schema sources: id, hash, last apply, object names").action(async (_opts, cmd) => {
|
|
1824
|
+
const client = getClientFromCommand(cmd);
|
|
1825
|
+
const result = await client.get("/schema/sources");
|
|
1826
|
+
formatOutput(result, getFormat(cmd));
|
|
1827
|
+
});
|
|
1828
|
+
sources.command("remove").description(
|
|
1829
|
+
"Remove a remote schema source: its objects are demoted to custom, records are kept"
|
|
1830
|
+
).argument("<sourceId>", "source id declared in code").option("--yes", "remove without confirmation").action(async (sourceId, opts, cmd) => {
|
|
1831
|
+
if (!opts.yes) {
|
|
1832
|
+
throw new Error('Removing a schema source is explicit. Re-run with "--yes" to confirm.');
|
|
1833
|
+
}
|
|
1834
|
+
const client = getClientFromCommand(cmd);
|
|
1835
|
+
await client.delete(`/schema/sources/${sourceId}`);
|
|
1836
|
+
formatOutput({ removed: sourceId }, getFormat(cmd));
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1870
1840
|
// src/program.ts
|
|
1871
1841
|
var PUBLIC_COMMANDS = /* @__PURE__ */ new Set(["login", "use", "instances", "current", "logout", "help"]);
|
|
1872
1842
|
function isPublicCommand(actionCommand) {
|
|
@@ -1886,11 +1856,14 @@ function createProgram() {
|
|
|
1886
1856
|
registerKeysCommand(program);
|
|
1887
1857
|
registerAuthCommand(program);
|
|
1888
1858
|
registerBundlesCommand(program);
|
|
1859
|
+
registerSourcesCommand(program);
|
|
1889
1860
|
registerConnectorsCommand(program);
|
|
1890
1861
|
registerMcpCommand(program);
|
|
1891
1862
|
registerMeetingsCommand(program);
|
|
1892
1863
|
registerSearchCommand(program);
|
|
1893
1864
|
registerEmbeddingsCommand(program);
|
|
1865
|
+
registerAiCommand(program);
|
|
1866
|
+
registerQuotasCommand(program);
|
|
1894
1867
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
1895
1868
|
const raw = program.opts();
|
|
1896
1869
|
const resolved = await resolveCliConfig({
|
|
@@ -1917,8 +1890,8 @@ async function runProgram(argv = process.argv) {
|
|
|
1917
1890
|
const program = createProgram();
|
|
1918
1891
|
await program.parseAsync(argv).catch((error) => {
|
|
1919
1892
|
if (error instanceof ApiClientError) {
|
|
1920
|
-
if (error.
|
|
1921
|
-
console.error(chalk10.red(`\u2717 Error (${error.
|
|
1893
|
+
if (error.status > 0) {
|
|
1894
|
+
console.error(chalk10.red(`\u2717 Error (${error.status}): ${error.message}`));
|
|
1922
1895
|
} else {
|
|
1923
1896
|
console.error(chalk10.red(`\u2717 Error: ${error.message}`));
|
|
1924
1897
|
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stndrds/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.296",
|
|
4
4
|
"description": "CLI tool to interact with Standards API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"standards": "./dist/bin.mjs"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"README.md"
|
|
11
13
|
],
|
|
12
14
|
"dependencies": {
|
|
13
15
|
"chalk": "^5.4.1",
|
|
14
16
|
"cli-table3": "^0.6.5",
|
|
15
17
|
"commander": "^13.1.0",
|
|
16
|
-
"@stndrds/
|
|
18
|
+
"@stndrds/client": "1.0.0-alpha.296",
|
|
19
|
+
"@stndrds/schema": "1.0.0-alpha.296"
|
|
17
20
|
},
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"@types/node": "^25.6.0",
|
|
@@ -30,7 +33,7 @@
|
|
|
30
33
|
"url": "https://github.com/andyoucreate/standards.git",
|
|
31
34
|
"directory": "packages/cli"
|
|
32
35
|
},
|
|
33
|
-
"license": "
|
|
36
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
34
37
|
"author": "AndYouCreate",
|
|
35
38
|
"bugs": {
|
|
36
39
|
"url": "https://github.com/andyoucreate/standards/issues"
|