@aexol/spectral 0.9.245 → 0.9.247

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cli.js +6 -0
  3. package/dist/commands/secret.d.ts +16 -0
  4. package/dist/commands/secret.d.ts.map +1 -0
  5. package/dist/commands/secret.js +153 -0
  6. package/dist/commands/serve.d.ts.map +1 -1
  7. package/dist/commands/serve.js +21 -0
  8. package/dist/extensions/list-secrets.d.ts +14 -0
  9. package/dist/extensions/list-secrets.d.ts.map +1 -0
  10. package/dist/extensions/list-secrets.js +63 -0
  11. package/dist/generated/zeus/const.d.ts.map +1 -1
  12. package/dist/generated/zeus/const.js +16 -0
  13. package/dist/generated/zeus/index.d.ts +73 -0
  14. package/dist/generated/zeus/index.d.ts.map +1 -1
  15. package/dist/relay/routing.d.ts +1 -1
  16. package/dist/relay/routing.d.ts.map +1 -1
  17. package/dist/relay/routing.js +93 -17
  18. package/dist/sdk/coding-agent/utils/shell.d.ts.map +1 -1
  19. package/dist/sdk/coding-agent/utils/shell.js +15 -1
  20. package/dist/secrets/index.d.ts +11 -0
  21. package/dist/secrets/index.d.ts.map +1 -0
  22. package/dist/secrets/index.js +10 -0
  23. package/dist/secrets/store.d.ts +109 -0
  24. package/dist/secrets/store.d.ts.map +1 -0
  25. package/dist/secrets/store.js +415 -0
  26. package/dist/server/agent-bridge.d.ts.map +1 -1
  27. package/dist/server/agent-bridge.js +20 -2
  28. package/dist/server/attachments/cleanup.d.ts +42 -0
  29. package/dist/server/attachments/cleanup.d.ts.map +1 -0
  30. package/dist/server/attachments/cleanup.js +100 -0
  31. package/dist/server/attachments/persist.d.ts +131 -0
  32. package/dist/server/attachments/persist.d.ts.map +1 -0
  33. package/dist/server/attachments/persist.js +406 -0
  34. package/dist/server/handlers/secrets.d.ts +40 -0
  35. package/dist/server/handlers/secrets.d.ts.map +1 -0
  36. package/dist/server/handlers/secrets.js +78 -0
  37. package/dist/server/session-stream.d.ts +5 -0
  38. package/dist/server/session-stream.d.ts.map +1 -1
  39. package/dist/server/session-stream.js +51 -1
  40. package/dist/server/storage.d.ts +6 -0
  41. package/dist/server/storage.d.ts.map +1 -1
  42. package/dist/server/storage.js +9 -0
  43. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to `@aexol/spectral` are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.9.247] - 2026-10-04
9
+
10
+ ### Added
11
+
12
+ - Added a public built-in model catalog: new `publicModelCatalog` GraphQL
13
+ query (`BuiltInModelCatalogEntry`) exposing built-in UserModels with credit
14
+ pricing per 1M tokens, measured average TPS (output tokens over measured
15
+ duration rows only), owner-configured fallback tok/s on BaseModel,
16
+ last-request time, 30-day request count, and status. The `/models` landing
17
+ page was rebuilt around `models-catalog-section.tsx`.
18
+ - Added `durationMs` capture on CreditUsageEvent in the backend generate and
19
+ refine flows, with database migrations `20261004122612` and
20
+ `20261004135152`.
21
+ - Added cli-node attachment support: persist and cleanup in
22
+ `src/server/attachments` with tests, plus serve, agent-bridge,
23
+ session-stream, and storage changes.
24
+ - Added a Fallback tok/s input to the admin base-models tab.
25
+
8
26
  ## [0.9.231] - 2026-09-23
9
27
 
10
28
  ### Added
package/dist/cli.js CHANGED
@@ -39,6 +39,7 @@ function printHeader() {
39
39
  " spectral desktop Start the agent in the background and open the UI",
40
40
  " spectral bind Link this directory to an Aexol Studio project",
41
41
  " spectral unbind Remove the Aexol Studio project binding",
42
+ " spectral secret Manage local secrets (set/list/rm)",
42
43
  " spectral update Check for and install the latest Spectral version",
43
44
  " spectral ports Diagnose port collisions across local projects",
44
45
  " spectral --version Print version and exit",
@@ -135,6 +136,11 @@ async function main() {
135
136
  await runUnbind();
136
137
  process.exit(0);
137
138
  }
139
+ if (first === "secret") {
140
+ const { runSecret } = await import("./commands/secret.js");
141
+ await runSecret(args.slice(1));
142
+ process.exit(0);
143
+ }
138
144
  if (first === "update") {
139
145
  const { runUpdate } = await import("./commands/update.js");
140
146
  await runUpdate(args.slice(1));
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `spectral secret` — manage the local encrypted secret store.
3
+ *
4
+ * Usage:
5
+ * spectral secret set NAME create/update a secret; value is read from
6
+ * STDIN (piped or hidden interactive prompt) and
7
+ * is NEVER passed as a command-line argument
8
+ * spectral secret list list names + timestamps — values are never shown
9
+ * spectral secret rm NAME delete a secret
10
+ *
11
+ * Shares the exact same store as the /api/secrets relay API and the
12
+ * `list_secrets` agent tool. Secrets set here are injected as env vars into
13
+ * the agent's bash tool (see src/secrets/store.ts).
14
+ */
15
+ export declare function runSecret(args: string[]): Promise<void>;
16
+ //# sourceMappingURL=secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../src/commands/secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAsEH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyG7D"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * `spectral secret` — manage the local encrypted secret store.
3
+ *
4
+ * Usage:
5
+ * spectral secret set NAME create/update a secret; value is read from
6
+ * STDIN (piped or hidden interactive prompt) and
7
+ * is NEVER passed as a command-line argument
8
+ * spectral secret list list names + timestamps — values are never shown
9
+ * spectral secret rm NAME delete a secret
10
+ *
11
+ * Shares the exact same store as the /api/secrets relay API and the
12
+ * `list_secrets` agent tool. Secrets set here are injected as env vars into
13
+ * the agent's bash tool (see src/secrets/store.ts).
14
+ */
15
+ import { createInterface } from "node:readline";
16
+ import { Writable } from "node:stream";
17
+ import pc from "picocolors";
18
+ import { SecretNameError, SecretStoreCorruptError, SecretValueError, deleteSecret, listSecrets, setSecret, } from "../secrets/index.js";
19
+ /**
20
+ * Read the secret value from STDIN. Never from argv — argv is visible in
21
+ * shell history and the process table.
22
+ *
23
+ * - Piped input: the entire stdin is consumed; a single trailing newline
24
+ * (from `echo "value" | …`) is stripped, everything else is preserved.
25
+ * - Interactive TTY: a single line is read with the typed characters hidden
26
+ * (readline with a swallowing output stream).
27
+ */
28
+ function readValueFromStdin(name) {
29
+ return new Promise((resolve, reject) => {
30
+ if (process.stdin.isTTY) {
31
+ // Hide input: swallow every echoed chunk; the prompt goes to real stdout.
32
+ const muted = new Writable({
33
+ write(_chunk, _enc, cb) {
34
+ cb();
35
+ },
36
+ });
37
+ const rl = createInterface({ input: process.stdin, output: muted, terminal: true });
38
+ process.stdout.write(`Enter value for ${name} (input hidden): `);
39
+ rl.question("", (answer) => {
40
+ rl.close();
41
+ process.stdout.write("\n");
42
+ resolve(answer);
43
+ });
44
+ rl.on("error", reject);
45
+ return;
46
+ }
47
+ const chunks = [];
48
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
49
+ process.stdin.on("error", reject);
50
+ process.stdin.on("end", () => {
51
+ const raw = Buffer.concat(chunks).toString("utf8");
52
+ // Strip exactly one trailing newline/CR from `echo`-style pipes; keep
53
+ // any other whitespace — the value is preserved verbatim otherwise.
54
+ const value = raw.replace(/\r?\n$/, "");
55
+ resolve(value);
56
+ });
57
+ });
58
+ }
59
+ function fail(err) {
60
+ if (err instanceof SecretNameError ||
61
+ err instanceof SecretValueError ||
62
+ err instanceof SecretStoreCorruptError) {
63
+ process.stderr.write(pc.red(`${err.message}\n`));
64
+ process.exit(1);
65
+ }
66
+ process.stderr.write(pc.red(`Secret operation failed: ${err instanceof Error ? err.message : String(err)}\n`));
67
+ process.exit(1);
68
+ }
69
+ export async function runSecret(args) {
70
+ const sub = args[0];
71
+ if (sub === "set") {
72
+ const nameArg = args[1];
73
+ if (!nameArg || nameArg.trim() === "") {
74
+ process.stderr.write(pc.red('Usage: spectral secret set NAME (value is read from STDIN, e.g. `echo -n "value" | spectral secret set NAME`)\n'));
75
+ process.exit(1);
76
+ }
77
+ let value;
78
+ try {
79
+ value = await readValueFromStdin(nameArg.trim());
80
+ }
81
+ catch (err) {
82
+ fail(err);
83
+ }
84
+ if (value.length === 0) {
85
+ process.stderr.write(pc.red("Secret value is empty — pipe a non-empty value on STDIN, e.g. `echo -n \"value\" | spectral secret set NAME`\n"));
86
+ process.exit(1);
87
+ }
88
+ try {
89
+ const meta = setSecret(nameArg.trim(), value);
90
+ process.stdout.write(pc.green(`✓ Secret ${meta.name} stored (encrypted at rest, injected as env var into the agent bash tool)\n`));
91
+ }
92
+ catch (err) {
93
+ fail(err);
94
+ }
95
+ return;
96
+ }
97
+ if (sub === "list") {
98
+ try {
99
+ const secrets = listSecrets();
100
+ if (secrets.length === 0) {
101
+ process.stdout.write("No secrets stored.\n");
102
+ return;
103
+ }
104
+ const nameW = Math.max(5, ...secrets.map((s) => s.name.length));
105
+ process.stdout.write([
106
+ `${secrets.length} stored secret(s) (values are never shown):`,
107
+ "",
108
+ `${"NAME".padEnd(nameW)} Created Updated`,
109
+ `${"─".repeat(nameW)} ${"─".repeat(19)} ${"─".repeat(19)}`,
110
+ ...secrets.map((s) => `${s.name.padEnd(nameW)} ${s.createdAt.padEnd(19)} ${s.updatedAt}`),
111
+ ].join("\n") + "\n");
112
+ }
113
+ catch (err) {
114
+ fail(err);
115
+ }
116
+ return;
117
+ }
118
+ if (sub === "rm") {
119
+ const nameArg = args[1];
120
+ if (!nameArg || nameArg.trim() === "") {
121
+ process.stderr.write(pc.red("Usage: spectral secret rm NAME\n"));
122
+ process.exit(1);
123
+ }
124
+ try {
125
+ const deleted = deleteSecret(nameArg.trim());
126
+ if (!deleted) {
127
+ process.stderr.write(pc.red(`Secret ${nameArg.trim().toUpperCase()} not found\n`));
128
+ process.exit(1);
129
+ }
130
+ process.stdout.write(pc.green(`✓ Secret ${nameArg.trim().toUpperCase()} removed\n`));
131
+ }
132
+ catch (err) {
133
+ fail(err);
134
+ }
135
+ return;
136
+ }
137
+ if (sub === "--help" || sub === "-h") {
138
+ process.stdout.write([
139
+ "Usage:",
140
+ " spectral secret set NAME create/update a secret (value read from STDIN, never argv)",
141
+ " spectral secret list list names + timestamps (values are never shown)",
142
+ " spectral secret rm NAME delete a secret",
143
+ "",
144
+ "Stored secrets are encrypted at rest (AES-256-GCM) and injected as env vars",
145
+ "into the agent's bash tool. Manage them remotely via the /api/secrets API.",
146
+ "",
147
+ ].join("\n"));
148
+ process.exit(0);
149
+ }
150
+ process.stderr.write(pc.red(`Unknown secret subcommand: ${sub ?? ""}\n`) +
151
+ pc.dim("Use `spectral secret --help` for usage.\n"));
152
+ process.exit(1);
153
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAwBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AAclE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA6B9D;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC9E;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4CAA4C;IAC5C,KAAK,EAAE,WAAW,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoqBlF;AAmFD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAsB5E"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAwBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AAgBlE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA6B9D;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC9E;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4CAA4C;IAC5C,KAAK,EAAE,WAAW,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAurBlF;AAmFD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAsB5E"}
@@ -43,6 +43,8 @@ import { getFanoutManager } from "../server/fanout/fanout-manager.js";
43
43
  import { detachAllSubscribers, handleAutoOptimizeFrame, handleAutoResearchFrame, handleCancelTurn, handleClientMessage, handleRestRequest, handleStopToolCall, handleSubscribe, } from "../relay/dispatcher.js";
44
44
  import { ensureMachineRegistered } from "../relay/registration.js";
45
45
  import { saveMachine } from "../relay/machine-store.js";
46
+ import { sweepAttachments } from "../server/attachments/cleanup.js";
47
+ import { attachmentsRootFor } from "../server/attachments/persist.js";
46
48
  import { SessionStreamManager } from "../server/session-stream.js";
47
49
  import { gracefulShutdown } from "../server/shutdown.js";
48
50
  import { getLiveMcpState } from "../mcp/state-getter.js";
@@ -175,6 +177,25 @@ export async function runServe(opts = {}) {
175
177
  // Best-effort.
176
178
  }
177
179
  });
180
+ // GC for stale persisted chat attachments (`.spectral/attachments/<id>/`).
181
+ // Fire-and-forget like the offload sweep: never blocks server startup and
182
+ // never takes down serving. Sweeps every known project root (attachments
183
+ // live under the session's project cwd) plus the fallback cwd.
184
+ setImmediate(() => {
185
+ try {
186
+ const activeSessionIds = new Set(store.listAllSessionIds());
187
+ const roots = new Set([attachmentsRootFor(cwd)]);
188
+ for (const project of store.listProjects()) {
189
+ roots.add(attachmentsRootFor(project.path));
190
+ }
191
+ for (const root of roots) {
192
+ sweepAttachments({ root, activeSessionIds });
193
+ }
194
+ }
195
+ catch {
196
+ // Best-effort.
197
+ }
198
+ });
178
199
  // Mutable holder for the meta-event publisher. Bound below once we
179
200
  // have both `relay` (the send target) and `registration.record.machineId`
180
201
  // (the canonical machineId the backend uses to fan out). The manager
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `list_secrets` tool extension.
3
+ *
4
+ * Lets the agent see which local secrets are stored (names + timestamps) so it
5
+ * can reason about what env vars will be injected into its bash tool.
6
+ *
7
+ * SECURITY: this tool returns ONLY names and timestamps. Secret values are
8
+ * never returned by this tool, by the relay GET API, or by anything else —
9
+ * values exist solely as env vars injected into the agent's bash environment
10
+ * (see src/secrets/store.ts `getSecretEnvVars`).
11
+ */
12
+ import type { ExtensionAPI } from "../sdk/coding-agent/index.js";
13
+ export default function listSecretsExtension(ext: ExtensionAPI): void;
14
+ //# sourceMappingURL=list-secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-secrets.d.ts","sourceRoot":"","sources":["../../src/extensions/list-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,8BAA8B,CAAC;AAGnF,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CA4DpE"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * `list_secrets` tool extension.
3
+ *
4
+ * Lets the agent see which local secrets are stored (names + timestamps) so it
5
+ * can reason about what env vars will be injected into its bash tool.
6
+ *
7
+ * SECURITY: this tool returns ONLY names and timestamps. Secret values are
8
+ * never returned by this tool, by the relay GET API, or by anything else —
9
+ * values exist solely as env vars injected into the agent's bash environment
10
+ * (see src/secrets/store.ts `getSecretEnvVars`).
11
+ */
12
+ import { getSecretEnvVars, listSecrets } from "../secrets/index.js";
13
+ export default function listSecretsExtension(ext) {
14
+ ext.registerTool({
15
+ name: "list_secrets",
16
+ label: "List Secrets",
17
+ description: "List the locally stored secret env vars that will be injected into your bash tool environment " +
18
+ "(e.g. GITHUB_TOKEN). Returns ONLY names and timestamps — secret values are never returned by " +
19
+ "this tool or any other; they exist solely as environment variables in your bash sessions. " +
20
+ "Manage secrets with the `spectral secret` CLI command or the /api/secrets relay API.",
21
+ parameters: {
22
+ type: "object",
23
+ properties: {},
24
+ },
25
+ async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
26
+ try {
27
+ const secrets = listSecrets();
28
+ if (secrets.length === 0) {
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: "No secrets stored. Add one with `spectral secret set NAME` (value read from STDIN) " +
34
+ "or POST /api/secrets. Stored secrets are injected as env vars into your bash tool.",
35
+ },
36
+ ],
37
+ details: { isError: false },
38
+ };
39
+ }
40
+ const envNames = Object.keys(getSecretEnvVars());
41
+ const lines = [
42
+ `${secrets.length} stored secret(s) (values are never returned — they are injected as env vars):`,
43
+ "",
44
+ ...secrets.map((s) => ` ${s.name} created ${s.createdAt} updated ${s.updatedAt}` +
45
+ (envNames.includes(s.name) ? "" : " (not injected: reserved name)")),
46
+ "",
47
+ "These are available as environment variables in your bash tool sessions.",
48
+ ];
49
+ return {
50
+ content: [{ type: "text", text: lines.join("\n") }],
51
+ details: { isError: false },
52
+ };
53
+ }
54
+ catch (err) {
55
+ const msg = err instanceof Error ? err.message : String(err);
56
+ return {
57
+ content: [{ type: "text", text: `Error reading secrets: ${msg}` }],
58
+ details: { isError: true },
59
+ };
60
+ }
61
+ },
62
+ });
63
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../../src/generated/zeus/const.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAy0B5C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAqoC1C,CAAA;AAED,eAAO,MAAM,GAAG;;;;CAIf,CAAA"}
1
+ {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../../src/generated/zeus/const.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAy0B5C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAqpC1C,CAAA;AAED,eAAO,MAAM,GAAG;;;;CAIf,CAAA"}
@@ -1018,6 +1018,7 @@ export const ReturnTypes = {
1018
1018
  subscriptionCompatibleModels: "UserModel",
1019
1019
  baseModelCatalog: "CatalogModel",
1020
1020
  availableModels: "AvailableModel",
1021
+ publicModelCatalog: "BuiltInModelCatalogEntry",
1021
1022
  availablePlans: "PlanInfo",
1022
1023
  availableCreditPacks: "CreditPack",
1023
1024
  teamSubscription: "BillingSubscription",
@@ -1524,6 +1525,20 @@ export const ReturnTypes = {
1524
1525
  supportsImages: "Boolean",
1525
1526
  supportsReasoning: "Boolean"
1526
1527
  },
1528
+ BuiltInModelCatalogEntry: {
1529
+ slug: "String",
1530
+ name: "String",
1531
+ baseModel: "String",
1532
+ contextWindow: "Int",
1533
+ creditInputPer1M: "Int",
1534
+ creditOutputPer1M: "Int",
1535
+ visibleInStudio: "Boolean",
1536
+ agentEnabled: "Boolean",
1537
+ lastRequestAt: "DateTime",
1538
+ avgTps: "Float",
1539
+ fallbackTps: "Float",
1540
+ requestCount30d: "Int"
1541
+ },
1527
1542
  AvailableModel: {
1528
1543
  name: "String",
1529
1544
  provider: "String",
@@ -1561,6 +1576,7 @@ export const ReturnTypes = {
1561
1576
  creditCacheWritePer1M: "Int",
1562
1577
  creditPerImage: "Float",
1563
1578
  creditPerVideoSecond: "Float",
1579
+ fallbackTps: "Float",
1564
1580
  capabilities: "JSON",
1565
1581
  family: "String",
1566
1582
  enabled: "Boolean",
@@ -1246,6 +1246,7 @@ export type ValueTypes = {
1246
1246
  scope?: ValueTypes["ModelScope"] | undefined | null | Variable<any, string>;
1247
1247
  teamId?: ValueTypes["ID"] | undefined | null | Variable<any, string>;
1248
1248
  }, ValueTypes["AvailableModel"]];
1249
+ publicModelCatalog?: ValueTypes["BuiltInModelCatalogEntry"];
1249
1250
  availablePlans?: ValueTypes["PlanInfo"];
1250
1251
  availableCreditPacks?: ValueTypes["CreditPack"];
1251
1252
  teamSubscription?: [{
@@ -2460,6 +2461,22 @@ export type ValueTypes = {
2460
2461
  __typename?: boolean | `@${string}`;
2461
2462
  ['...on CatalogModel']?: Omit<ValueTypes["CatalogModel"], "...on CatalogModel">;
2462
2463
  }>;
2464
+ ["BuiltInModelCatalogEntry"]: AliasType<{
2465
+ slug?: boolean | `@${string}`;
2466
+ name?: boolean | `@${string}`;
2467
+ baseModel?: boolean | `@${string}`;
2468
+ contextWindow?: boolean | `@${string}`;
2469
+ creditInputPer1M?: boolean | `@${string}`;
2470
+ creditOutputPer1M?: boolean | `@${string}`;
2471
+ visibleInStudio?: boolean | `@${string}`;
2472
+ agentEnabled?: boolean | `@${string}`;
2473
+ lastRequestAt?: boolean | `@${string}`;
2474
+ avgTps?: boolean | `@${string}`;
2475
+ fallbackTps?: boolean | `@${string}`;
2476
+ requestCount30d?: boolean | `@${string}`;
2477
+ __typename?: boolean | `@${string}`;
2478
+ ['...on BuiltInModelCatalogEntry']?: Omit<ValueTypes["BuiltInModelCatalogEntry"], "...on BuiltInModelCatalogEntry">;
2479
+ }>;
2463
2480
  ["AvailableModel"]: AliasType<{
2464
2481
  name?: boolean | `@${string}`;
2465
2482
  provider?: boolean | `@${string}`;
@@ -2499,6 +2516,7 @@ export type ValueTypes = {
2499
2516
  creditCacheWritePer1M?: boolean | `@${string}`;
2500
2517
  creditPerImage?: boolean | `@${string}`;
2501
2518
  creditPerVideoSecond?: boolean | `@${string}`;
2519
+ fallbackTps?: boolean | `@${string}`;
2502
2520
  capabilities?: boolean | `@${string}`;
2503
2521
  family?: boolean | `@${string}`;
2504
2522
  enabled?: boolean | `@${string}`;
@@ -2534,6 +2552,7 @@ export type ValueTypes = {
2534
2552
  creditCacheWritePer1M?: number | undefined | null | Variable<any, string>;
2535
2553
  creditPerImage?: number | undefined | null | Variable<any, string>;
2536
2554
  creditPerVideoSecond?: number | undefined | null | Variable<any, string>;
2555
+ fallbackTps?: number | undefined | null | Variable<any, string>;
2537
2556
  family?: string | undefined | null | Variable<any, string>;
2538
2557
  isDefault?: boolean | undefined | null | Variable<any, string>;
2539
2558
  isVisionDefault?: boolean | undefined | null | Variable<any, string>;
@@ -3597,6 +3616,7 @@ export type ResolverInputTypes = {
3597
3616
  scope?: ResolverInputTypes["ModelScope"] | undefined | null;
3598
3617
  teamId?: ResolverInputTypes["ID"] | undefined | null;
3599
3618
  }, ResolverInputTypes["AvailableModel"]];
3619
+ publicModelCatalog?: ResolverInputTypes["BuiltInModelCatalogEntry"];
3600
3620
  availablePlans?: ResolverInputTypes["PlanInfo"];
3601
3621
  availableCreditPacks?: ResolverInputTypes["CreditPack"];
3602
3622
  teamSubscription?: [{
@@ -4783,6 +4803,21 @@ export type ResolverInputTypes = {
4783
4803
  supportsReasoning?: boolean | `@${string}`;
4784
4804
  __typename?: boolean | `@${string}`;
4785
4805
  }>;
4806
+ ["BuiltInModelCatalogEntry"]: AliasType<{
4807
+ slug?: boolean | `@${string}`;
4808
+ name?: boolean | `@${string}`;
4809
+ baseModel?: boolean | `@${string}`;
4810
+ contextWindow?: boolean | `@${string}`;
4811
+ creditInputPer1M?: boolean | `@${string}`;
4812
+ creditOutputPer1M?: boolean | `@${string}`;
4813
+ visibleInStudio?: boolean | `@${string}`;
4814
+ agentEnabled?: boolean | `@${string}`;
4815
+ lastRequestAt?: boolean | `@${string}`;
4816
+ avgTps?: boolean | `@${string}`;
4817
+ fallbackTps?: boolean | `@${string}`;
4818
+ requestCount30d?: boolean | `@${string}`;
4819
+ __typename?: boolean | `@${string}`;
4820
+ }>;
4786
4821
  ["AvailableModel"]: AliasType<{
4787
4822
  name?: boolean | `@${string}`;
4788
4823
  provider?: boolean | `@${string}`;
@@ -4821,6 +4856,7 @@ export type ResolverInputTypes = {
4821
4856
  creditCacheWritePer1M?: boolean | `@${string}`;
4822
4857
  creditPerImage?: boolean | `@${string}`;
4823
4858
  creditPerVideoSecond?: boolean | `@${string}`;
4859
+ fallbackTps?: boolean | `@${string}`;
4824
4860
  capabilities?: boolean | `@${string}`;
4825
4861
  family?: boolean | `@${string}`;
4826
4862
  enabled?: boolean | `@${string}`;
@@ -4854,6 +4890,7 @@ export type ResolverInputTypes = {
4854
4890
  creditCacheWritePer1M?: number | undefined | null;
4855
4891
  creditPerImage?: number | undefined | null;
4856
4892
  creditPerVideoSecond?: number | undefined | null;
4893
+ fallbackTps?: number | undefined | null;
4857
4894
  family?: string | undefined | null;
4858
4895
  isDefault?: boolean | undefined | null;
4859
4896
  isVisionDefault?: boolean | undefined | null;
@@ -5774,6 +5811,7 @@ export type ModelTypes = {
5774
5811
  subscriptionCompatibleModels: Array<ModelTypes["UserModel"]>;
5775
5812
  baseModelCatalog: Array<ModelTypes["CatalogModel"]>;
5776
5813
  availableModels: Array<ModelTypes["AvailableModel"]>;
5814
+ publicModelCatalog: Array<ModelTypes["BuiltInModelCatalogEntry"]>;
5777
5815
  availablePlans: Array<ModelTypes["PlanInfo"]>;
5778
5816
  availableCreditPacks: Array<ModelTypes["CreditPack"]>;
5779
5817
  teamSubscription?: ModelTypes["BillingSubscription"] | undefined | null;
@@ -6432,6 +6470,20 @@ export type ModelTypes = {
6432
6470
  supportsImages?: boolean | undefined | null;
6433
6471
  supportsReasoning?: boolean | undefined | null;
6434
6472
  };
6473
+ ["BuiltInModelCatalogEntry"]: {
6474
+ slug: string;
6475
+ name: string;
6476
+ baseModel: string;
6477
+ contextWindow?: number | undefined | null;
6478
+ creditInputPer1M?: number | undefined | null;
6479
+ creditOutputPer1M?: number | undefined | null;
6480
+ visibleInStudio: boolean;
6481
+ agentEnabled: boolean;
6482
+ lastRequestAt?: ModelTypes["DateTime"] | undefined | null;
6483
+ avgTps?: number | undefined | null;
6484
+ fallbackTps?: number | undefined | null;
6485
+ requestCount30d: number;
6486
+ };
6435
6487
  ["AvailableModel"]: {
6436
6488
  name: string;
6437
6489
  provider: string;
@@ -6469,6 +6521,7 @@ export type ModelTypes = {
6469
6521
  creditCacheWritePer1M?: number | undefined | null;
6470
6522
  creditPerImage?: number | undefined | null;
6471
6523
  creditPerVideoSecond?: number | undefined | null;
6524
+ fallbackTps?: number | undefined | null;
6472
6525
  capabilities?: ModelTypes["JSON"] | undefined | null;
6473
6526
  family?: string | undefined | null;
6474
6527
  enabled: boolean;
@@ -6500,6 +6553,7 @@ export type ModelTypes = {
6500
6553
  creditCacheWritePer1M?: number | undefined | null;
6501
6554
  creditPerImage?: number | undefined | null;
6502
6555
  creditPerVideoSecond?: number | undefined | null;
6556
+ fallbackTps?: number | undefined | null;
6503
6557
  family?: string | undefined | null;
6504
6558
  isDefault?: boolean | undefined | null;
6505
6559
  isVisionDefault?: boolean | undefined | null;
@@ -7518,6 +7572,7 @@ export type GraphQLTypes = {
7518
7572
  subscriptionCompatibleModels: Array<GraphQLTypes["UserModel"]>;
7519
7573
  baseModelCatalog: Array<GraphQLTypes["CatalogModel"]>;
7520
7574
  availableModels: Array<GraphQLTypes["AvailableModel"]>;
7575
+ publicModelCatalog: Array<GraphQLTypes["BuiltInModelCatalogEntry"]>;
7521
7576
  availablePlans: Array<GraphQLTypes["PlanInfo"]>;
7522
7577
  availableCreditPacks: Array<GraphQLTypes["CreditPack"]>;
7523
7578
  teamSubscription?: GraphQLTypes["BillingSubscription"] | undefined | null;
@@ -8237,6 +8292,22 @@ export type GraphQLTypes = {
8237
8292
  supportsReasoning?: boolean | undefined | null;
8238
8293
  ['...on CatalogModel']: Omit<GraphQLTypes["CatalogModel"], "...on CatalogModel">;
8239
8294
  };
8295
+ ["BuiltInModelCatalogEntry"]: {
8296
+ __typename: "BuiltInModelCatalogEntry";
8297
+ slug: string;
8298
+ name: string;
8299
+ baseModel: string;
8300
+ contextWindow?: number | undefined | null;
8301
+ creditInputPer1M?: number | undefined | null;
8302
+ creditOutputPer1M?: number | undefined | null;
8303
+ visibleInStudio: boolean;
8304
+ agentEnabled: boolean;
8305
+ lastRequestAt?: GraphQLTypes["DateTime"] | undefined | null;
8306
+ avgTps?: number | undefined | null;
8307
+ fallbackTps?: number | undefined | null;
8308
+ requestCount30d: number;
8309
+ ['...on BuiltInModelCatalogEntry']: Omit<GraphQLTypes["BuiltInModelCatalogEntry"], "...on BuiltInModelCatalogEntry">;
8310
+ };
8240
8311
  ["AvailableModel"]: {
8241
8312
  __typename: "AvailableModel";
8242
8313
  name: string;
@@ -8277,6 +8348,7 @@ export type GraphQLTypes = {
8277
8348
  creditCacheWritePer1M?: number | undefined | null;
8278
8349
  creditPerImage?: number | undefined | null;
8279
8350
  creditPerVideoSecond?: number | undefined | null;
8351
+ fallbackTps?: number | undefined | null;
8280
8352
  capabilities?: GraphQLTypes["JSON"] | undefined | null;
8281
8353
  family?: string | undefined | null;
8282
8354
  enabled: boolean;
@@ -8311,6 +8383,7 @@ export type GraphQLTypes = {
8311
8383
  creditCacheWritePer1M?: number | undefined | null;
8312
8384
  creditPerImage?: number | undefined | null;
8313
8385
  creditPerVideoSecond?: number | undefined | null;
8386
+ fallbackTps?: number | undefined | null;
8314
8387
  family?: string | undefined | null;
8315
8388
  isDefault?: boolean | undefined | null;
8316
8389
  isVisionDefault?: boolean | undefined | null;