@w6w/cli 0.9.15 → 0.9.23
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/README.md +29 -14
- package/dist/bin/w6w.js +4 -0
- package/dist/bin/w6w.js.map +1 -1
- package/dist/mod.d.ts +20 -2
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +25 -13
- package/dist/mod.js.map +1 -1
- package/dist/src/args.d.ts +8 -1
- package/dist/src/args.d.ts.map +1 -1
- package/dist/src/args.js +15 -3
- package/dist/src/args.js.map +1 -1
- package/dist/src/client.d.ts +51 -4
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +83 -30
- package/dist/src/client.js.map +1 -1
- package/dist/src/commands/agents-studio.d.ts +24 -0
- package/dist/src/commands/agents-studio.d.ts.map +1 -0
- package/dist/src/commands/agents-studio.js +431 -0
- package/dist/src/commands/agents-studio.js.map +1 -0
- package/dist/src/commands/assets.d.ts +47 -0
- package/dist/src/commands/assets.d.ts.map +1 -0
- package/dist/src/commands/assets.js +412 -0
- package/dist/src/commands/assets.js.map +1 -0
- package/dist/src/commands/auth.d.ts +24 -0
- package/dist/src/commands/auth.d.ts.map +1 -0
- package/dist/src/commands/auth.js +112 -0
- package/dist/src/commands/auth.js.map +1 -0
- package/dist/src/commands/config.d.ts +21 -0
- package/dist/src/commands/config.d.ts.map +1 -0
- package/dist/src/commands/config.js +73 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/connections.d.ts +1 -1
- package/dist/src/commands/connections.d.ts.map +1 -1
- package/dist/src/commands/connections.js +27 -2
- package/dist/src/commands/connections.js.map +1 -1
- package/dist/src/commands/index.d.ts +6 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +18 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/ls.d.ts +21 -0
- package/dist/src/commands/ls.d.ts.map +1 -0
- package/dist/src/commands/ls.js +53 -0
- package/dist/src/commands/ls.js.map +1 -0
- package/dist/src/commands/models.d.ts +16 -0
- package/dist/src/commands/models.d.ts.map +1 -0
- package/dist/src/commands/models.js +126 -0
- package/dist/src/commands/models.js.map +1 -0
- package/dist/src/commands/vars.d.ts.map +1 -1
- package/dist/src/commands/vars.js +2 -2
- package/dist/src/commands/vars.js.map +1 -1
- package/dist/src/config-store.d.ts +86 -0
- package/dist/src/config-store.d.ts.map +1 -0
- package/dist/src/config-store.js +129 -0
- package/dist/src/config-store.js.map +1 -0
- package/dist/src/help.generated.d.ts.map +1 -1
- package/dist/src/help.generated.js +2723 -105
- package/dist/src/help.generated.js.map +1 -1
- package/dist/src/store-fs.d.ts +34 -0
- package/dist/src/store-fs.d.ts.map +1 -0
- package/dist/src/store-fs.js +151 -0
- package/dist/src/store-fs.js.map +1 -0
- package/package.json +2 -2
package/dist/src/client.js
CHANGED
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
* has a flag which outranks the environment variable.
|
|
10
10
|
*
|
|
11
11
|
* ```
|
|
12
|
-
* CLI flag (--base-url
|
|
12
|
+
* base URL CLI flag (--base-url) > W6W_BASE_URL > stored `baseUrl` > DEFAULT_BASE_URL
|
|
13
|
+
* token CLI flag (--token) > W6W_TOKEN > the stored token for the resolved base URL
|
|
13
14
|
* ```
|
|
14
15
|
*
|
|
16
|
+
* The stored tier is the per-user config `w6w auth login` writes (see
|
|
17
|
+
* `src/config-store.ts`). A stored token is **bound to the base URL it was saved
|
|
18
|
+
* for**: it is looked up by the canonical resolved base URL, exact match only, so
|
|
19
|
+
* pointing `--base-url` or `W6W_BASE_URL` at another host can never send it
|
|
20
|
+
* there. That is the trust boundary of this module.
|
|
21
|
+
*
|
|
15
22
|
* The resolved values are passed to the SDK **explicitly**, and the SDK is never
|
|
16
23
|
* left to read the environment on the CLI's behalf. That is a mechanism choice,
|
|
17
24
|
* not a stylistic one: the CLI has to be able to say *which* source it was
|
|
@@ -23,7 +30,10 @@
|
|
|
23
30
|
*
|
|
24
31
|
* @module
|
|
25
32
|
*/
|
|
26
|
-
import { ConfigError, W6WClient } from "@w6w/sdk";
|
|
33
|
+
import { ConfigError, joinBaseUrl, W6WClient } from "@w6w/sdk";
|
|
34
|
+
import { NO_CONFIG } from "./config-store.js";
|
|
35
|
+
/** The API every command targets unless told otherwise. Equals endpoints.json `defaultBaseUrl`. */
|
|
36
|
+
export const DEFAULT_BASE_URL = "https://api.w6w.io";
|
|
27
37
|
/** Environment variable holding the server **origin**. Falls behind `--base-url`. */
|
|
28
38
|
export const ENV_BASE_URL = "W6W_BASE_URL";
|
|
29
39
|
/** Environment variable holding the bearer token. Falls behind `--token`. */
|
|
@@ -34,8 +44,8 @@ export const NO_ENV = () => undefined;
|
|
|
34
44
|
* Read an environment variable, treating a blank value as **absent**.
|
|
35
45
|
*
|
|
36
46
|
* `W6W_BASE_URL=`, `W6W_BASE_URL=" "` and an unset `W6W_BASE_URL` are the same
|
|
37
|
-
* thing: all three fall through the precedence chain to the next source
|
|
38
|
-
*
|
|
47
|
+
* thing: all three fall through the precedence chain to the next source (the
|
|
48
|
+
* stored base URL, then the default).
|
|
39
49
|
*
|
|
40
50
|
* The check is a trim-and-emptiness test and deliberately **not** a nullish
|
|
41
51
|
* coalesce. `??` does not convert `""`, so a set-but-empty variable would
|
|
@@ -60,21 +70,6 @@ export function envValue(env, name) {
|
|
|
60
70
|
return undefined;
|
|
61
71
|
return value;
|
|
62
72
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Apply the precedence rule to one setting.
|
|
65
|
-
*
|
|
66
|
-
* A flag that was **given** wins outright, even when what it was given is empty:
|
|
67
|
-
* that is a value the user typed, and quietly consulting the environment behind
|
|
68
|
-
* an explicit `--token=` would be the CLI second-guessing them. (It still does
|
|
69
|
-
* not produce a usable value — an empty flag reaches the same error — but it
|
|
70
|
-
* gets there without a detour through the environment.) Only an **absent** flag
|
|
71
|
-
* falls through.
|
|
72
|
-
*/
|
|
73
|
-
function resolve(flag, env, name) {
|
|
74
|
-
if (flag !== undefined)
|
|
75
|
-
return flag;
|
|
76
|
-
return envValue(env, name);
|
|
77
|
-
}
|
|
78
73
|
/**
|
|
79
74
|
* A value the CLI cannot work with, phrased as a usage error.
|
|
80
75
|
*
|
|
@@ -123,7 +118,7 @@ function requireAbsolute(baseUrl) {
|
|
|
123
118
|
* the header builder and comes back as a bare `TypeError` from outside anyone's
|
|
124
119
|
* error model: a stack trace, for a typo.
|
|
125
120
|
*/
|
|
126
|
-
function isUnsendable(token) {
|
|
121
|
+
export function isUnsendable(token) {
|
|
127
122
|
for (const character of token) {
|
|
128
123
|
const code = character.codePointAt(0) ?? 0;
|
|
129
124
|
if (code < 0x20 || code === 0x7f || code > 0xff)
|
|
@@ -138,6 +133,67 @@ function requireSendableToken(token) {
|
|
|
138
133
|
throw configError("The w6w API token contains a character that cannot be sent in an HTTP header " +
|
|
139
134
|
"(a control character, such as a newline).", "--token", ENV_TOKEN, "A token read out of a file usually carries a trailing newline — strip it.");
|
|
140
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* The one resolver. `createClient` and every `auth` command use it, so what
|
|
138
|
+
* `auth status` reports is what a command will do.
|
|
139
|
+
*
|
|
140
|
+
* Base URL: flag (given, even empty) > env (blank = absent) > stored `baseUrl` >
|
|
141
|
+
* {@linkcode DEFAULT_BASE_URL}, validated, then canonicalised once. Token: flag >
|
|
142
|
+
* env > `stored.hosts[<canonical base URL>]` — exact key only.
|
|
143
|
+
*
|
|
144
|
+
* @throws {ConfigError} When the base URL is blank-by-flag, relative, or not http(s),
|
|
145
|
+
* or a resolved token cannot be sent in a header. A *missing* token is not an
|
|
146
|
+
* error here; `createClient` raises that.
|
|
147
|
+
*/
|
|
148
|
+
export function resolveSettings(globals, env = NO_ENV, stored = NO_CONFIG) {
|
|
149
|
+
let raw;
|
|
150
|
+
let baseUrlSource;
|
|
151
|
+
if (globals.baseUrl !== undefined) {
|
|
152
|
+
raw = globals.baseUrl;
|
|
153
|
+
baseUrlSource = "flag";
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const fromEnv = envValue(env, ENV_BASE_URL);
|
|
157
|
+
if (fromEnv !== undefined) {
|
|
158
|
+
raw = fromEnv;
|
|
159
|
+
baseUrlSource = "env";
|
|
160
|
+
}
|
|
161
|
+
else if (stored.baseUrl.trim().length > 0) {
|
|
162
|
+
raw = stored.baseUrl;
|
|
163
|
+
baseUrlSource = "config";
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
raw = DEFAULT_BASE_URL;
|
|
167
|
+
baseUrlSource = "default";
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (raw.trim().length === 0) {
|
|
171
|
+
throw configError("No w6w base URL is configured.", "--base-url", ENV_BASE_URL, "It holds the server's origin, like `https://api.example.com`; the API is served at its root, so no path is appended.");
|
|
172
|
+
}
|
|
173
|
+
// Validate for the CLI's own message, then canonicalise with the SDK's join —
|
|
174
|
+
// the single key used both to look a token up and to build the client.
|
|
175
|
+
const baseUrl = joinBaseUrl(requireAbsolute(raw.trim()));
|
|
176
|
+
let token;
|
|
177
|
+
let tokenSource;
|
|
178
|
+
if (globals.token !== undefined) {
|
|
179
|
+
token = globals.token;
|
|
180
|
+
tokenSource = "flag";
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const fromEnv = envValue(env, ENV_TOKEN);
|
|
184
|
+
if (fromEnv !== undefined) {
|
|
185
|
+
token = fromEnv;
|
|
186
|
+
tokenSource = "env";
|
|
187
|
+
}
|
|
188
|
+
else if (Object.hasOwn(stored.hosts, baseUrl)) {
|
|
189
|
+
token = stored.hosts[baseUrl].token;
|
|
190
|
+
tokenSource = "config";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (token === undefined || token.trim().length === 0)
|
|
194
|
+
return { baseUrl, baseUrlSource };
|
|
195
|
+
return { baseUrl, baseUrlSource, token: requireSendableToken(token), tokenSource };
|
|
196
|
+
}
|
|
141
197
|
/**
|
|
142
198
|
* Build the API client for one invocation.
|
|
143
199
|
*
|
|
@@ -147,25 +203,22 @@ function requireSendableToken(token) {
|
|
|
147
203
|
*
|
|
148
204
|
* @param globals - The parsed global flags.
|
|
149
205
|
* @param env - The environment seam. Defaults to an empty environment.
|
|
150
|
-
* @param options - Transport and
|
|
206
|
+
* @param options - Transport, default project and the stored config.
|
|
151
207
|
* @returns A configured client.
|
|
152
208
|
* @throws {ConfigError} When the base URL or token is missing or unusable — a usage error.
|
|
153
209
|
*/
|
|
154
210
|
export function createClient(globals, env = NO_ENV, options = {}) {
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
throw configError(
|
|
158
|
-
|
|
159
|
-
const token = resolve(globals.token, env, ENV_TOKEN);
|
|
160
|
-
if (token === undefined || token.trim().length === 0) {
|
|
161
|
-
throw configError("No w6w API token is configured.", "--token", ENV_TOKEN, "Every w6w API command is authenticated.");
|
|
211
|
+
const settings = resolveSettings(globals, env, options.stored);
|
|
212
|
+
if (settings.token === undefined) {
|
|
213
|
+
throw configError(`No w6w API token is configured for ${settings.baseUrl}.`, "--token", ENV_TOKEN, "Or save one with `w6w auth login` (a saved token only applies to the base URL it was saved for). " +
|
|
214
|
+
"Every w6w API command is authenticated.");
|
|
162
215
|
}
|
|
163
216
|
// The join rule (origin in, base path appended, never doubled) belongs to the
|
|
164
217
|
// SDK and is applied by the constructor. Nothing here re-derives it — read it
|
|
165
218
|
// back off `client.config.baseUrl` if you need to know where a request went.
|
|
166
219
|
return new W6WClient({
|
|
167
|
-
baseUrl:
|
|
168
|
-
token:
|
|
220
|
+
baseUrl: settings.baseUrl,
|
|
221
|
+
token: settings.token,
|
|
169
222
|
project: options.project,
|
|
170
223
|
fetch: options.fetch,
|
|
171
224
|
});
|
package/dist/src/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `w6w skills|context|agents …` — the agent-authoring surface at the command line.
|
|
3
|
+
*
|
|
4
|
+
* Seventeen commands, **one SDK call each**. Skill upload is deliberately not
|
|
5
|
+
* here: it is `w6w assets upload --purpose skill`.
|
|
6
|
+
*
|
|
7
|
+
* Two write paths carry optimistic concurrency — `agents update` and
|
|
8
|
+
* `context entries-update`. Both send the body `revision` and, when given, the
|
|
9
|
+
* `--if-unmodified-since` precondition. A `409` is re-thrown as an `ApiError`
|
|
10
|
+
* with a message naming the **current revision** and what to do next; a `428`
|
|
11
|
+
* says the precondition is required. Both keep their status, so the exit code is
|
|
12
|
+
* the API-error code and a script can tell the write was refused. A uniform
|
|
13
|
+
* `404` needs no handling at all: `main()` prints the server's one-line message
|
|
14
|
+
* and exits, never a stack trace.
|
|
15
|
+
*
|
|
16
|
+
* Only flags the user typed reach the wire, so an omitted `--description` leaves
|
|
17
|
+
* the field alone and `--description ""` clears it.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import type { CommandRegistry } from "../../mod.ts";
|
|
22
|
+
/** Keys are the help tree's command paths (`naming.cli`). */
|
|
23
|
+
export declare const AGENT_STUDIO_COMMANDS: CommandRegistry;
|
|
24
|
+
//# sourceMappingURL=agents-studio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-studio.d.ts","sourceRoot":"","sources":["../../../src/commands/agents-studio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAkC,eAAe,EAAE,MAAM,cAAc,CAAC;AA+hBpF,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,EAAE,eAyBnC,CAAC"}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `w6w skills|context|agents …` — the agent-authoring surface at the command line.
|
|
3
|
+
*
|
|
4
|
+
* Seventeen commands, **one SDK call each**. Skill upload is deliberately not
|
|
5
|
+
* here: it is `w6w assets upload --purpose skill`.
|
|
6
|
+
*
|
|
7
|
+
* Two write paths carry optimistic concurrency — `agents update` and
|
|
8
|
+
* `context entries-update`. Both send the body `revision` and, when given, the
|
|
9
|
+
* `--if-unmodified-since` precondition. A `409` is re-thrown as an `ApiError`
|
|
10
|
+
* with a message naming the **current revision** and what to do next; a `428`
|
|
11
|
+
* says the precondition is required. Both keep their status, so the exit code is
|
|
12
|
+
* the API-error code and a script can tell the write was refused. A uniform
|
|
13
|
+
* `404` needs no handling at all: `main()` prints the server's one-line message
|
|
14
|
+
* and exits, never a stack trace.
|
|
15
|
+
*
|
|
16
|
+
* Only flags the user typed reach the wire, so an omitted `--description` leaves
|
|
17
|
+
* the field alone and `--description ""` clears it.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { ApiError } from "@w6w/sdk";
|
|
22
|
+
import { argument, noExtraArguments, requiredFlag, table, textFlag, usageError } from "./shared.js";
|
|
23
|
+
/** A positive-integer flag, or `undefined` when absent. */
|
|
24
|
+
function count(context, name) {
|
|
25
|
+
const value = textFlag(context, name);
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (!/^[0-9]+$/.test(value) || Number(value) < 1) {
|
|
29
|
+
throw usageError(context, `\`--${name}\` must be a positive integer.`);
|
|
30
|
+
}
|
|
31
|
+
return Number(value);
|
|
32
|
+
}
|
|
33
|
+
/** A non-negative integer flag that must be present (a revision may be `0`). */
|
|
34
|
+
function revision(context) {
|
|
35
|
+
const value = requiredFlag(context, "revision", "--revision <n>");
|
|
36
|
+
if (!/^[0-9]+$/.test(value)) {
|
|
37
|
+
throw usageError(context, "`--revision` must be a non-negative integer.");
|
|
38
|
+
}
|
|
39
|
+
return Number(value);
|
|
40
|
+
}
|
|
41
|
+
function includeArchived(context) {
|
|
42
|
+
return context.invocation.options.includeArchived === true ? { includeArchived: true } : {};
|
|
43
|
+
}
|
|
44
|
+
function tags(context) {
|
|
45
|
+
const value = textFlag(context, "tags");
|
|
46
|
+
if (value === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
return value.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
49
|
+
}
|
|
50
|
+
/** A flag whose value is a JSON array of pins. */
|
|
51
|
+
function jsonList(context, name) {
|
|
52
|
+
const value = textFlag(context, name);
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
let parsed;
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(value);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw usageError(context, `\`--${name}\` must be valid JSON (an array).`);
|
|
61
|
+
}
|
|
62
|
+
if (!Array.isArray(parsed))
|
|
63
|
+
throw usageError(context, `\`--${name}\` must be a JSON array.`);
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
function visibility(context) {
|
|
67
|
+
const value = textFlag(context, "visibility");
|
|
68
|
+
if (value === undefined)
|
|
69
|
+
return undefined;
|
|
70
|
+
if (value !== "private" && value !== "project" && value !== "account") {
|
|
71
|
+
throw usageError(context, "`--visibility` must be private, project or account.");
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
const cell = (value) => value === null || value === undefined || value === "" ? "-" : String(value);
|
|
76
|
+
/**
|
|
77
|
+
* Run a precondition write, turning a 409 / 428 into an actionable message.
|
|
78
|
+
*
|
|
79
|
+
* The thrown error is still an `ApiError` with the original status, code and
|
|
80
|
+
* body, so the exit code and `--json` consumers are unchanged; only the sentence
|
|
81
|
+
* a human reads is replaced.
|
|
82
|
+
*/
|
|
83
|
+
async function guarded(what, refetch, run) {
|
|
84
|
+
try {
|
|
85
|
+
return await run();
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
89
|
+
const current = err.raw?.error
|
|
90
|
+
?.currentRevision;
|
|
91
|
+
const at = current === undefined ? "" : ` (current revision: ${current})`;
|
|
92
|
+
throw new ApiError(409, err.code, `Conflict: ${what} changed since you read it${at}. ` +
|
|
93
|
+
`Re-read it with \`${refetch}\` and retry with the new revision.`, err.raw);
|
|
94
|
+
}
|
|
95
|
+
if (err instanceof ApiError && err.status === 428) {
|
|
96
|
+
throw new ApiError(428, err.code, `Precondition required: ${what} can only be updated with a precondition. ` +
|
|
97
|
+
`Pass \`--if-unmodified-since <ts>\` (the updatedAt you read).`, err.raw);
|
|
98
|
+
}
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const precondition = (context) => ({
|
|
103
|
+
ifUnmodifiedSince: textFlag(context, "ifUnmodifiedSince"),
|
|
104
|
+
});
|
|
105
|
+
// ---------------------------------------------------------------- skills
|
|
106
|
+
const skillRow = (s) => [s.id, s.name, cell(s.activeVersionId), cell(s.archivedAt)];
|
|
107
|
+
const skillsList = async (context) => {
|
|
108
|
+
noExtraArguments(context, 0);
|
|
109
|
+
const rows = await context.client().skills.list({
|
|
110
|
+
...includeArchived(context),
|
|
111
|
+
limit: count(context, "limit"),
|
|
112
|
+
});
|
|
113
|
+
context.out.emit(rows, (styles) => rows.length === 0
|
|
114
|
+
? styles.dim("No skills.")
|
|
115
|
+
: table(["ID", "NAME", "ACTIVE VERSION", "ARCHIVED"], rows.map(skillRow), styles));
|
|
116
|
+
};
|
|
117
|
+
const skillsGet = async (context) => {
|
|
118
|
+
const id = argument(context, 0, "a skill id (see: `w6w skills list`)");
|
|
119
|
+
noExtraArguments(context, 1);
|
|
120
|
+
const skill = await context.client().skills.get(id);
|
|
121
|
+
context.out.emit(skill, (styles) => table(["ID", "NAME", "ACTIVE VERSION", "ARCHIVED"], [skillRow(skill)], styles));
|
|
122
|
+
};
|
|
123
|
+
const skillsVersions = async (context) => {
|
|
124
|
+
const id = argument(context, 0, "a skill id (see: `w6w skills list`)");
|
|
125
|
+
noExtraArguments(context, 1);
|
|
126
|
+
const rows = await context.client().skills.versions(id);
|
|
127
|
+
const row = (v) => {
|
|
128
|
+
const r = v;
|
|
129
|
+
return [cell(r.id), cell(r.version), cell(r.createdAt)];
|
|
130
|
+
};
|
|
131
|
+
context.out.emit(rows, (styles) => rows.length === 0
|
|
132
|
+
? styles.dim("No versions.")
|
|
133
|
+
: table(["ID", "VERSION", "CREATED"], rows.map(row), styles));
|
|
134
|
+
};
|
|
135
|
+
const skillsArchive = async (context) => {
|
|
136
|
+
const id = argument(context, 0, "a skill id (see: `w6w skills list`)");
|
|
137
|
+
noExtraArguments(context, 1);
|
|
138
|
+
const skill = await context.client().skills.archive(id);
|
|
139
|
+
context.out.emit(skill, (styles) => `Archived ${styles.bold(skill.name)} ${styles.dim(`(${id})`)}`);
|
|
140
|
+
};
|
|
141
|
+
// --------------------------------------------------------------- context
|
|
142
|
+
const collectionRow = (c) => [
|
|
143
|
+
c.id,
|
|
144
|
+
c.name,
|
|
145
|
+
c.tags.join(",") || "-",
|
|
146
|
+
c.visibility,
|
|
147
|
+
cell(c.archivedAt),
|
|
148
|
+
];
|
|
149
|
+
const COLLECTION_HEAD = ["ID", "NAME", "TAGS", "VISIBILITY", "ARCHIVED"];
|
|
150
|
+
const contextList = async (context) => {
|
|
151
|
+
noExtraArguments(context, 0);
|
|
152
|
+
const rows = await context.client().context.list({
|
|
153
|
+
...includeArchived(context),
|
|
154
|
+
limit: count(context, "limit"),
|
|
155
|
+
});
|
|
156
|
+
context.out.emit(rows, (styles) => rows.length === 0
|
|
157
|
+
? styles.dim("No context collections.")
|
|
158
|
+
: table(COLLECTION_HEAD, rows.map(collectionRow), styles));
|
|
159
|
+
};
|
|
160
|
+
const contextCreate = async (context) => {
|
|
161
|
+
const name = argument(context, 0, "a collection name");
|
|
162
|
+
noExtraArguments(context, 1);
|
|
163
|
+
const created = await context.client().context.create({
|
|
164
|
+
name,
|
|
165
|
+
description: textFlag(context, "description"),
|
|
166
|
+
tags: tags(context),
|
|
167
|
+
visibility: visibility(context),
|
|
168
|
+
});
|
|
169
|
+
context.out.emit(created, (styles) => `Created ${styles.bold(created.name)} ${styles.dim(`(${created.id})`)}`);
|
|
170
|
+
};
|
|
171
|
+
const contextGet = async (context) => {
|
|
172
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
173
|
+
noExtraArguments(context, 1);
|
|
174
|
+
const found = await context.client().context.get(id);
|
|
175
|
+
context.out.emit(found, (styles) => table(COLLECTION_HEAD, [collectionRow(found)], styles));
|
|
176
|
+
};
|
|
177
|
+
/** A patch: only the typed flags are sent (collection edits are last-write-wins). */
|
|
178
|
+
const contextUpdate = async (context) => {
|
|
179
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
180
|
+
noExtraArguments(context, 1);
|
|
181
|
+
const patch = {};
|
|
182
|
+
const name = textFlag(context, "name");
|
|
183
|
+
if (name !== undefined)
|
|
184
|
+
patch.name = name;
|
|
185
|
+
const description = textFlag(context, "description");
|
|
186
|
+
if (description !== undefined)
|
|
187
|
+
patch.description = description;
|
|
188
|
+
const tagList = tags(context);
|
|
189
|
+
if (tagList !== undefined)
|
|
190
|
+
patch.tags = tagList;
|
|
191
|
+
const updated = await context.client().context.update(id, patch);
|
|
192
|
+
context.out.emit(updated, (styles) => `Updated ${styles.bold(updated.name)} ${styles.dim(`(${id})`)}`);
|
|
193
|
+
};
|
|
194
|
+
const contextArchive = async (context) => {
|
|
195
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
196
|
+
noExtraArguments(context, 1);
|
|
197
|
+
const archived = await context.client().context.archive(id);
|
|
198
|
+
context.out.emit(archived, (styles) => `Archived ${styles.bold(archived.name)} ${styles.dim(`(${id})`)}`);
|
|
199
|
+
};
|
|
200
|
+
const entryRow = (e) => [
|
|
201
|
+
e.id,
|
|
202
|
+
e.name,
|
|
203
|
+
e.mediaType,
|
|
204
|
+
cell(e.revision),
|
|
205
|
+
cell(e.archivedAt),
|
|
206
|
+
];
|
|
207
|
+
const ENTRY_HEAD = ["ID", "NAME", "TYPE", "REVISION", "ARCHIVED"];
|
|
208
|
+
const entriesList = async (context) => {
|
|
209
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
210
|
+
noExtraArguments(context, 1);
|
|
211
|
+
const rows = await context.client().context.entries.list(id, includeArchived(context));
|
|
212
|
+
context.out.emit(rows, (styles) => rows.length === 0 ? styles.dim("No entries.") : table(ENTRY_HEAD, rows.map(entryRow), styles));
|
|
213
|
+
};
|
|
214
|
+
const entriesCreate = async (context) => {
|
|
215
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
216
|
+
const name = argument(context, 1, "an entry name");
|
|
217
|
+
noExtraArguments(context, 2);
|
|
218
|
+
const entry = await context.client().context.entries.create(id, {
|
|
219
|
+
name,
|
|
220
|
+
text: requiredFlag(context, "text", "--text <text>"),
|
|
221
|
+
});
|
|
222
|
+
context.out.emit(entry, (styles) => `Created ${styles.bold(entry.name)} ${styles.dim(`(${entry.id}, revision ${entry.revision})`)}`);
|
|
223
|
+
};
|
|
224
|
+
const entriesUpdate = async (context) => {
|
|
225
|
+
const id = argument(context, 0, "a collection id (see: `w6w context list`)");
|
|
226
|
+
const entryId = argument(context, 1, "an entry id (see: `w6w context entries-list`)");
|
|
227
|
+
noExtraArguments(context, 2);
|
|
228
|
+
const text = requiredFlag(context, "text", "--text <text>");
|
|
229
|
+
const rev = revision(context);
|
|
230
|
+
const entry = await guarded("the entry", `w6w context entries-list ${id}`, () => context.client().context.entries.update(id, entryId, { text, revision: rev }, precondition(context)));
|
|
231
|
+
context.out.emit(entry, (styles) => `Updated ${styles.bold(entry.name)} ${styles.dim(`(${entry.id}, revision ${entry.revision})`)}`);
|
|
232
|
+
};
|
|
233
|
+
// ------------------------------------------------------- context-entries
|
|
234
|
+
const topEntryRow = (e) => [
|
|
235
|
+
e.id,
|
|
236
|
+
e.name,
|
|
237
|
+
cell(e.mediaType),
|
|
238
|
+
cell(e.revision),
|
|
239
|
+
];
|
|
240
|
+
const TOP_ENTRY_HEAD = ["ID", "NAME", "TYPE", "REVISION"];
|
|
241
|
+
const ceList = async (context) => {
|
|
242
|
+
noExtraArguments(context, 0);
|
|
243
|
+
const rows = await context.client().contextEntries.list({
|
|
244
|
+
...includeArchived(context),
|
|
245
|
+
collectionId: textFlag(context, "collectionId"),
|
|
246
|
+
project: textFlag(context, "project"),
|
|
247
|
+
});
|
|
248
|
+
context.out.emit(rows, (styles) => rows.length === 0
|
|
249
|
+
? styles.dim("No context entries.")
|
|
250
|
+
: table(TOP_ENTRY_HEAD, rows.map(topEntryRow), styles));
|
|
251
|
+
};
|
|
252
|
+
const ceCreate = async (context) => {
|
|
253
|
+
const name = argument(context, 0, "an entry name");
|
|
254
|
+
noExtraArguments(context, 1);
|
|
255
|
+
const ids = textFlag(context, "collectionId");
|
|
256
|
+
const collectionIds = ids === undefined
|
|
257
|
+
? undefined
|
|
258
|
+
: ids.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
259
|
+
const entry = await context.client().contextEntries.create({
|
|
260
|
+
name,
|
|
261
|
+
text: requiredFlag(context, "text", "--text <text>"),
|
|
262
|
+
visibility: visibility(context),
|
|
263
|
+
...(collectionIds ? { collectionIds } : {}),
|
|
264
|
+
});
|
|
265
|
+
context.out.emit(entry, (styles) => `Created ${styles.bold(entry.name)} ${styles.dim(`(${entry.id}, revision ${entry.revision})`)}`);
|
|
266
|
+
};
|
|
267
|
+
const ceGet = async (context) => {
|
|
268
|
+
const id = argument(context, 0, "an entry id (see: `w6w context-entries list`)");
|
|
269
|
+
noExtraArguments(context, 1);
|
|
270
|
+
const entry = await context.client().contextEntries.get(id);
|
|
271
|
+
context.out.emit(entry, (styles) => table(TOP_ENTRY_HEAD, [topEntryRow(entry)], styles));
|
|
272
|
+
};
|
|
273
|
+
const ceUpdate = async (context) => {
|
|
274
|
+
const id = argument(context, 0, "an entry id (see: `w6w context-entries list`)");
|
|
275
|
+
noExtraArguments(context, 1);
|
|
276
|
+
const text = requiredFlag(context, "text", "--text <text>");
|
|
277
|
+
const rev = revision(context);
|
|
278
|
+
const entry = await guarded("the entry", `w6w context-entries get ${id}`, () => context.client().contextEntries.update(id, { text, revision: rev }, precondition(context)));
|
|
279
|
+
context.out.emit(entry, (styles) => `Updated ${styles.bold(entry.name)} ${styles.dim(`(${entry.id}, revision ${entry.revision})`)}`);
|
|
280
|
+
};
|
|
281
|
+
const ceArchive = async (context) => {
|
|
282
|
+
const id = argument(context, 0, "an entry id (see: `w6w context-entries list`)");
|
|
283
|
+
noExtraArguments(context, 1);
|
|
284
|
+
const entry = await context.client().contextEntries.archive(id);
|
|
285
|
+
context.out.emit(entry, (styles) => `Archived ${styles.bold(entry.name)} ${styles.dim(`(${id})`)}`);
|
|
286
|
+
};
|
|
287
|
+
const ceAdd = async (context) => {
|
|
288
|
+
const id = argument(context, 0, "an entry id (see: `w6w context-entries list`)");
|
|
289
|
+
const collection = argument(context, 1, "a collection id (see: `w6w context list`)");
|
|
290
|
+
noExtraArguments(context, 2);
|
|
291
|
+
const entry = await context.client().contextEntries.addToCollection(id, collection);
|
|
292
|
+
context.out.emit(entry, (styles) => `Added ${styles.bold(entry.name)} to ${styles.dim(collection)}`);
|
|
293
|
+
};
|
|
294
|
+
const ceRemove = async (context) => {
|
|
295
|
+
const id = argument(context, 0, "an entry id (see: `w6w context-entries list`)");
|
|
296
|
+
const collection = argument(context, 1, "a collection id (see: `w6w context list`)");
|
|
297
|
+
noExtraArguments(context, 2);
|
|
298
|
+
const entry = await context.client().contextEntries.removeFromCollection(id, collection);
|
|
299
|
+
context.out.emit(entry, (styles) => `Removed ${styles.bold(entry.name)} from ${styles.dim(collection)}`);
|
|
300
|
+
};
|
|
301
|
+
// ---------------------------------------------------------------- agents
|
|
302
|
+
const agentRow = (a) => [
|
|
303
|
+
a.id,
|
|
304
|
+
cell(a.name),
|
|
305
|
+
cell(a.modelRouteId),
|
|
306
|
+
String(a.revision),
|
|
307
|
+
a.archived ? "yes" : "no",
|
|
308
|
+
"no",
|
|
309
|
+
];
|
|
310
|
+
const AGENT_HEAD = ["ID", "NAME", "MODEL ROUTE", "REVISION", "ARCHIVED", "RUNNABLE"];
|
|
311
|
+
const agentsList = async (context) => {
|
|
312
|
+
noExtraArguments(context, 0);
|
|
313
|
+
const rows = await context.client().agents.list(includeArchived(context));
|
|
314
|
+
context.out.emit(rows, (styles) => rows.length === 0 ? styles.dim("No agents.") : table(AGENT_HEAD, rows.map(agentRow), styles));
|
|
315
|
+
};
|
|
316
|
+
/** The fields `agents create|update` share, only those typed. */
|
|
317
|
+
function agentFields(context) {
|
|
318
|
+
const fields = {};
|
|
319
|
+
const name = textFlag(context, "name");
|
|
320
|
+
if (name !== undefined)
|
|
321
|
+
fields.name = name;
|
|
322
|
+
const instructions = textFlag(context, "instructions");
|
|
323
|
+
if (instructions !== undefined)
|
|
324
|
+
fields.instructions = instructions;
|
|
325
|
+
const route = textFlag(context, "modelRouteId");
|
|
326
|
+
if (route !== undefined)
|
|
327
|
+
fields.modelRouteId = route;
|
|
328
|
+
const skills = jsonList(context, "skills");
|
|
329
|
+
if (skills !== undefined)
|
|
330
|
+
fields.skills = skills;
|
|
331
|
+
const pins = jsonList(context, "context");
|
|
332
|
+
if (pins !== undefined)
|
|
333
|
+
fields.context = pins;
|
|
334
|
+
const vis = visibility(context);
|
|
335
|
+
if (vis !== undefined)
|
|
336
|
+
fields.visibility = vis;
|
|
337
|
+
const project = textFlag(context, "project");
|
|
338
|
+
if (project !== undefined)
|
|
339
|
+
fields.project = project;
|
|
340
|
+
const modelOptions = modelOptionFlags(context);
|
|
341
|
+
if (modelOptions !== undefined)
|
|
342
|
+
fields.modelOptions = modelOptions;
|
|
343
|
+
return fields;
|
|
344
|
+
}
|
|
345
|
+
/** `--temperature`, `--top-p`, `--max-output-tokens` and the repeatable `--stop`. */
|
|
346
|
+
function modelOptionFlags(context) {
|
|
347
|
+
const options = {};
|
|
348
|
+
const number = (name, min, max, integer) => {
|
|
349
|
+
const raw = textFlag(context, name);
|
|
350
|
+
if (raw === undefined)
|
|
351
|
+
return undefined;
|
|
352
|
+
const value = Number(raw);
|
|
353
|
+
if (raw.trim() === "" || !Number.isFinite(value) || value < min || value > max ||
|
|
354
|
+
(integer && !Number.isInteger(value))) {
|
|
355
|
+
throw usageError(context, `\`--${name}\` must be ${integer ? "an integer" : "a number"} from ${min} to ${max}.`);
|
|
356
|
+
}
|
|
357
|
+
return value;
|
|
358
|
+
};
|
|
359
|
+
const temperature = number("temperature", 0, 2, false);
|
|
360
|
+
if (temperature !== undefined)
|
|
361
|
+
options.temperature = temperature;
|
|
362
|
+
const topP = number("topP", 0, 1, false);
|
|
363
|
+
if (topP !== undefined)
|
|
364
|
+
options.topP = topP;
|
|
365
|
+
const max = number("maxOutputTokens", 1, 1_000_000, true);
|
|
366
|
+
if (max !== undefined)
|
|
367
|
+
options.maxOutputTokens = max;
|
|
368
|
+
const stop = context.invocation.lists?.stop;
|
|
369
|
+
if (stop !== undefined)
|
|
370
|
+
options.stop = stop;
|
|
371
|
+
return Object.keys(options).length > 0 ? options : undefined;
|
|
372
|
+
}
|
|
373
|
+
const agentsCreate = async (context) => {
|
|
374
|
+
noExtraArguments(context, 0);
|
|
375
|
+
const agent = await context.client().agents.create(agentFields(context));
|
|
376
|
+
context.out.emit(agent, (styles) => `Created ${styles.bold(cell(agent.name))} ${styles.dim(`(${agent.id}, revision ${agent.revision})`)}`);
|
|
377
|
+
};
|
|
378
|
+
const agentsGet = async (context) => {
|
|
379
|
+
const id = argument(context, 0, "an agent id (see: `w6w agents list`)");
|
|
380
|
+
noExtraArguments(context, 1);
|
|
381
|
+
const agent = await context.client().agents.get(id);
|
|
382
|
+
context.out.emit(agent, (styles) => {
|
|
383
|
+
const issues = agent.validation.map((v) => ` ! ${JSON.stringify(v)}`);
|
|
384
|
+
return [
|
|
385
|
+
table(AGENT_HEAD, [agentRow(agent)], styles),
|
|
386
|
+
...(agent.instructions.length > 0 ? ["", agent.instructions] : []),
|
|
387
|
+
...(issues.length > 0 ? ["", "Validation:", ...issues] : []),
|
|
388
|
+
].join("\n");
|
|
389
|
+
});
|
|
390
|
+
};
|
|
391
|
+
const agentsUpdate = async (context) => {
|
|
392
|
+
const id = argument(context, 0, "an agent id (see: `w6w agents list`)");
|
|
393
|
+
noExtraArguments(context, 1);
|
|
394
|
+
const patch = { ...agentFields(context), revision: revision(context) };
|
|
395
|
+
const agent = await guarded("the agent", `w6w agents get ${id}`, () => context.client().agents.update(id, patch, precondition(context)));
|
|
396
|
+
context.out.emit(agent, (styles) => `Updated ${styles.bold(cell(agent.name))} ${styles.dim(`(${id}, revision ${agent.revision})`)}`);
|
|
397
|
+
};
|
|
398
|
+
const agentsArchive = async (context) => {
|
|
399
|
+
const id = argument(context, 0, "an agent id (see: `w6w agents list`)");
|
|
400
|
+
noExtraArguments(context, 1);
|
|
401
|
+
const agent = await context.client().agents.archive(id);
|
|
402
|
+
context.out.emit(agent, (styles) => `Archived ${styles.bold(cell(agent.name))} ${styles.dim(`(${id})`)}`);
|
|
403
|
+
};
|
|
404
|
+
/** Keys are the help tree's command paths (`naming.cli`). */
|
|
405
|
+
export const AGENT_STUDIO_COMMANDS = {
|
|
406
|
+
"skills list": skillsList,
|
|
407
|
+
"skills get": skillsGet,
|
|
408
|
+
"skills versions": skillsVersions,
|
|
409
|
+
"skills archive": skillsArchive,
|
|
410
|
+
"context list": contextList,
|
|
411
|
+
"context create": contextCreate,
|
|
412
|
+
"context get": contextGet,
|
|
413
|
+
"context update": contextUpdate,
|
|
414
|
+
"context archive": contextArchive,
|
|
415
|
+
"context entries-list": entriesList,
|
|
416
|
+
"context entries-create": entriesCreate,
|
|
417
|
+
"context entries-update": entriesUpdate,
|
|
418
|
+
"context-entries list": ceList,
|
|
419
|
+
"context-entries create": ceCreate,
|
|
420
|
+
"context-entries get": ceGet,
|
|
421
|
+
"context-entries update": ceUpdate,
|
|
422
|
+
"context-entries archive": ceArchive,
|
|
423
|
+
"context-entries add-to-collection": ceAdd,
|
|
424
|
+
"context-entries remove-from-collection": ceRemove,
|
|
425
|
+
"agents list": agentsList,
|
|
426
|
+
"agents create": agentsCreate,
|
|
427
|
+
"agents get": agentsGet,
|
|
428
|
+
"agents update": agentsUpdate,
|
|
429
|
+
"agents archive": agentsArchive,
|
|
430
|
+
};
|
|
431
|
+
//# sourceMappingURL=agents-studio.js.map
|