@sequenceholdings/studio-cli 0.1.13 → 0.1.21

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 (63) hide show
  1. package/README.md +258 -38
  2. package/dist/agents/apply-chunks.d.ts +13 -0
  3. package/dist/agents/apply-chunks.js +43 -0
  4. package/dist/agents/commands.d.ts +10 -0
  5. package/dist/agents/commands.js +218 -0
  6. package/dist/agents/scaffold.d.ts +2 -0
  7. package/dist/agents/scaffold.js +77 -0
  8. package/dist/agents/source.d.ts +18 -0
  9. package/dist/agents/source.js +121 -0
  10. package/dist/artifact/delegate.d.ts +2 -2
  11. package/dist/artifact/delegate.js +31 -73
  12. package/dist/atlas-client.js +52 -37
  13. package/dist/auth-cmds/commands.d.ts +1 -1
  14. package/dist/auth-cmds/commands.js +12 -7
  15. package/dist/auth.d.ts +104 -24
  16. package/dist/auth.js +456 -94
  17. package/dist/config.d.ts +3 -3
  18. package/dist/config.js +18 -13
  19. package/dist/env-catalog.js +13 -3
  20. package/dist/env-flags.d.ts +2 -0
  21. package/dist/env-flags.js +2 -0
  22. package/dist/env-registry.d.ts +27 -0
  23. package/dist/env-registry.js +204 -0
  24. package/dist/envs/commands.d.ts +1 -1
  25. package/dist/envs/commands.js +41 -3
  26. package/dist/file-lock.d.ts +5 -0
  27. package/dist/file-lock.js +187 -0
  28. package/dist/functions/commands.d.ts +10 -10
  29. package/dist/functions/commands.js +87 -53
  30. package/dist/functions/manifest.d.ts +1 -0
  31. package/dist/functions/manifest.js +36 -0
  32. package/dist/functions/source-selection.d.ts +24 -0
  33. package/dist/functions/source-selection.js +67 -0
  34. package/dist/login.d.ts +8 -3
  35. package/dist/login.js +46 -34
  36. package/dist/main.d.ts +3 -1
  37. package/dist/main.js +41 -12
  38. package/dist/orm/delegate.js +25 -7
  39. package/dist/pat-hints.js +2 -2
  40. package/dist/pipeline/commands.d.ts +58 -0
  41. package/dist/pipeline/commands.js +330 -0
  42. package/dist/pipeline/lifecycle.d.ts +58 -0
  43. package/dist/pipeline/lifecycle.js +348 -0
  44. package/dist/pipeline/pinning.d.ts +5 -0
  45. package/dist/pipeline/pinning.js +9 -0
  46. package/dist/pipeline/templates.d.ts +11 -0
  47. package/dist/pipeline/templates.js +166 -0
  48. package/dist/process/build.d.ts +4 -0
  49. package/dist/process/build.js +33 -2
  50. package/dist/process/codegen.js +19 -1
  51. package/dist/process/commands.js +97 -47
  52. package/dist/process/compiler-subprocess.d.ts +29 -0
  53. package/dist/process/compiler-subprocess.js +99 -0
  54. package/dist/process/compiler-worker.d.ts +1 -0
  55. package/dist/process/compiler-worker.js +38 -0
  56. package/dist/process/lint.d.ts +8 -0
  57. package/dist/process/lint.js +84 -29
  58. package/dist/process/repo-install.js +18 -2
  59. package/dist/repos/commands.d.ts +1 -1
  60. package/dist/repos/commands.js +17 -12
  61. package/dist/secrets/commands.d.ts +1 -1
  62. package/dist/secrets/commands.js +18 -18
  63. package/package.json +12 -5
@@ -11,9 +11,10 @@
11
11
  */
12
12
  import { execFileSync } from 'node:child_process';
13
13
  import { existsSync } from 'node:fs';
14
- import { mkdtemp, rm, writeFile } from 'node:fs/promises';
14
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
15
15
  import { homedir, tmpdir } from 'node:os';
16
16
  import { join } from 'node:path';
17
+ import { createScrubbedChildEnv } from '@sequenceholdings/artifact-studio/child-environment';
17
18
  import { ARTIFACT_BUILD_PNPM, buildControlledArtifactNpmrc, } from '@sequenceholdings/artifact-studio/prepare-build';
18
19
  import { stripInstallControlFiles } from '@sequenceholdings/artifact-studio/sanitize-remote-tree';
19
20
  import { ArtifactInstallTrustError, assertTrustedArtifactInstallTree, } from '@sequenceholdings/artifact-studio/trusted-install';
@@ -52,14 +53,27 @@ export async function prepareProcessBuildRoot(dir) {
52
53
  await rm(join(dir, 'node_modules'), { recursive: true, force: true });
53
54
  const configDir = await mkdtemp(join(tmpdir(), 'process-pnpm-'));
54
55
  const controlledNpmrc = join(configDir, '.npmrc');
56
+ const homeDir = join(configDir, 'home');
57
+ // Keep package-manager writes scoped to this install. A persistent cache
58
+ // would be writable by the untrusted source install and could poison later
59
+ // process builds that run under the same uid.
60
+ const npmCache = join(configDir, 'npm-cache');
61
+ const pnpmStore = join(configDir, 'pnpm-store');
55
62
  const userNpmrcPath = process.env.npm_config_userconfig ?? join(homedir(), '.npmrc');
56
63
  console.log(`[seq-studio] installing process dependencies (frozen lockfile, prod only) via ${ARTIFACT_BUILD_PNPM}…`);
57
64
  try {
65
+ await mkdir(homeDir, { recursive: true });
58
66
  await writeFile(controlledNpmrc, buildControlledArtifactNpmrc(userNpmrcPath), { mode: 0o600 });
59
67
  const spawnOpts = {
60
68
  cwd: configDir,
61
69
  stdio: 'inherit',
62
- env: { ...process.env, npm_config_userconfig: controlledNpmrc },
70
+ env: createScrubbedChildEnv({
71
+ homeDir,
72
+ additionalEnv: {
73
+ npm_config_userconfig: controlledNpmrc,
74
+ npm_config_cache: npmCache,
75
+ },
76
+ }),
63
77
  };
64
78
  execFileSync('npx', [
65
79
  '--yes',
@@ -70,6 +84,8 @@ export async function prepareProcessBuildRoot(dir) {
70
84
  '--frozen-lockfile',
71
85
  '--ignore-scripts',
72
86
  '--prod',
87
+ '--store-dir',
88
+ pnpmStore,
73
89
  ], spawnOpts);
74
90
  }
75
91
  catch (error) {
@@ -45,5 +45,5 @@ export declare function reposCloneCommand(args: ParsedArgs, deps?: {
45
45
  */
46
46
  export declare function normalizeCloneUrl(raw: string, env: ResolvedEnv): string;
47
47
  export declare function reposDeleteCommand(args: ParsedArgs): Promise<number>;
48
- export declare const REPOS_USAGE = "usage:\n seq-studio repos list [-e env] [--namespace <slug>] [--mine] repos visible on the environment\n seq-studio repos namespaces [create <slug>] [-e env] list or create namespaces\n seq-studio repos show <ns>/<name> [-e env] repo detail (branches, clone URL)\n seq-studio repos create <ns>/<name> [-e env] [--default-branch b] create an empty repo\n seq-studio repos clone <ns>/<name> [-e env] [--ref r] [--out dir] [--force]\n seq-studio repos clone --url <https://\u2026/repos/<id>/git> [-e env] [--ref r] [--out dir]\n seq-studio repos clone --id <uuid> [-e env] [--ref r] [--out dir]\n smart-HTTP when ATLAS_GIT_PAT is set;\n otherwise JSON materialize (<ns>/<name>)\n seq-studio repos pull <ns>/<name> [-e env] [--ref r] [--out dir] [--force]\n materialize the tree at a ref (JSON API)\n seq-studio repos delete <ns>/<name> [-e env] [--yes] delete a repo (confirm prompt)\n\n Flags: -e/--env <env> (see: seq-studio envs list)\n\n clone prefers real git clone (PAT via askpass \u2014 never written into the remote\n URL). Without ATLAS_GIT_PAT, <ns>/<name> falls back to the JSON API and prints\n how to get a PAT (seq-studio or Atlas UI /settings/tokens).\n PAT without Auth0 login: use --url from Repositories \u2192 Clone (or --id <uuid>).\n --ref accepts a branch, tag, or commit SHA (SHA \u2192 clone then checkout).\n\n Authenticate JSON API calls with: seq-studio login\n Authenticate git clone/push with: ATLAS_GIT_PAT (from Atlas Settings \u2192 Tokens)\n";
48
+ export declare const REPOS_USAGE = "usage:\n seq-studio repos list -e <env> [--namespace <slug>] [--mine] repos visible on the environment\n seq-studio repos namespaces [create <slug>] -e <env> list or create namespaces\n seq-studio repos show <ns>/<name> -e <env> repo detail (branches, clone URL)\n seq-studio repos create <ns>/<name> -e <env> [--default-branch b] create an empty repo\n seq-studio repos clone <ns>/<name> -e <env> [--ref r] [--out dir] [--force]\n seq-studio repos clone --url <https://\u2026/repos/<id>/git> -e <env> [--ref r] [--out dir]\n seq-studio repos clone --id <uuid> -e <env> [--ref r] [--out dir]\n smart-HTTP when ATLAS_GIT_PAT is set;\n otherwise JSON materialize (<ns>/<name>)\n seq-studio repos pull <ns>/<name> -e <env> [--ref r] [--out dir] [--force]\n materialize the tree at a ref (JSON API)\n seq-studio repos delete <ns>/<name> -e <env> [--yes] delete a repo (confirm prompt)\n\n Flags: -e/--env <env> (required; see: seq-studio envs list)\n\n clone prefers real git clone (PAT via askpass \u2014 never written into the remote\n URL). Without ATLAS_GIT_PAT, <ns>/<name> falls back to the JSON API and prints\n how to get a PAT (seq-studio or Atlas UI /settings/tokens).\n PAT without Auth0 login: use --url from Repositories \u2192 Clone (or --id <uuid>).\n --ref accepts a branch, tag, or commit SHA (SHA \u2192 clone then checkout).\n\n Authenticate JSON API calls with: seq-studio login\n Authenticate git clone/push with: ATLAS_GIT_PAT (from Atlas Settings \u2192 Tokens)\n";
49
49
  export declare function runReposCommand(sub: string | undefined, args: ParsedArgs): Promise<number>;
@@ -25,6 +25,7 @@ import { resolveGitPatFromEnv, runGitClone, } from './git-clone.js';
25
25
  import { formatPatSetupHint } from '../pat-hints.js';
26
26
  import { tryGetAccessToken } from '../auth.js';
27
27
  import { resolveEnvWithDiscovery } from '../config.js';
28
+ import { REQUIRE_EXPLICIT_ENV_MESSAGE } from '../env-flags.js';
28
29
  const PAGE_SIZE = 200;
29
30
  // ---------------------------------------------------------------------------
30
31
  // Helpers
@@ -158,7 +159,7 @@ export async function reposNamespacesCommand(args) {
158
159
  const ctx = await reposContext(args);
159
160
  if (action === 'create') {
160
161
  if (!slug) {
161
- console.error('usage: seq-studio repos namespaces create <slug> [-e env]');
162
+ console.error('usage: seq-studio repos namespaces create <slug> -e <env>');
162
163
  return 1;
163
164
  }
164
165
  const created = await postJson({
@@ -358,7 +359,7 @@ export async function reposCloneCommand(args, deps = {}) {
358
359
  // <ns>/<name> path — needs Auth0 for resolveRepo (JSON API) whether or not
359
360
  // we then use smart-HTTP. Without Auth0, point users at --url from the UI.
360
361
  if (!positional) {
361
- console.error('usage: seq-studio repos clone <ns>/<name> | --url <clone-url> | --id <uuid> [-e env] [--ref r] [--out dir]');
362
+ console.error('usage: seq-studio repos clone <ns>/<name> | --url <clone-url> | --id <uuid> -e <env> [--ref r] [--out dir]');
362
363
  return 1;
363
364
  }
364
365
  const { namespace, name } = parseRepoPath(positional);
@@ -418,6 +419,10 @@ async function resolveEnvOnly(args) {
418
419
  }
419
420
  const requested = (typeof args.flags.env === 'string' ? args.flags.env : undefined) ??
420
421
  (typeof args.flags.e === 'string' ? args.flags.e : undefined);
422
+ // Same contract as buildContext: never silently fall back to `local`.
423
+ if (!requested) {
424
+ throw new Error(REQUIRE_EXPLICIT_ENV_MESSAGE);
425
+ }
421
426
  return resolveEnvWithDiscovery({ requested });
422
427
  }
423
428
  /**
@@ -488,20 +493,20 @@ export async function reposDeleteCommand(args) {
488
493
  // Router
489
494
  // ---------------------------------------------------------------------------
490
495
  export const REPOS_USAGE = `usage:
491
- seq-studio repos list [-e env] [--namespace <slug>] [--mine] repos visible on the environment
492
- seq-studio repos namespaces [create <slug>] [-e env] list or create namespaces
493
- seq-studio repos show <ns>/<name> [-e env] repo detail (branches, clone URL)
494
- seq-studio repos create <ns>/<name> [-e env] [--default-branch b] create an empty repo
495
- seq-studio repos clone <ns>/<name> [-e env] [--ref r] [--out dir] [--force]
496
- seq-studio repos clone --url <https://…/repos/<id>/git> [-e env] [--ref r] [--out dir]
497
- seq-studio repos clone --id <uuid> [-e env] [--ref r] [--out dir]
496
+ seq-studio repos list -e <env> [--namespace <slug>] [--mine] repos visible on the environment
497
+ seq-studio repos namespaces [create <slug>] -e <env> list or create namespaces
498
+ seq-studio repos show <ns>/<name> -e <env> repo detail (branches, clone URL)
499
+ seq-studio repos create <ns>/<name> -e <env> [--default-branch b] create an empty repo
500
+ seq-studio repos clone <ns>/<name> -e <env> [--ref r] [--out dir] [--force]
501
+ seq-studio repos clone --url <https://…/repos/<id>/git> -e <env> [--ref r] [--out dir]
502
+ seq-studio repos clone --id <uuid> -e <env> [--ref r] [--out dir]
498
503
  smart-HTTP when ATLAS_GIT_PAT is set;
499
504
  otherwise JSON materialize (<ns>/<name>)
500
- seq-studio repos pull <ns>/<name> [-e env] [--ref r] [--out dir] [--force]
505
+ seq-studio repos pull <ns>/<name> -e <env> [--ref r] [--out dir] [--force]
501
506
  materialize the tree at a ref (JSON API)
502
- seq-studio repos delete <ns>/<name> [-e env] [--yes] delete a repo (confirm prompt)
507
+ seq-studio repos delete <ns>/<name> -e <env> [--yes] delete a repo (confirm prompt)
503
508
 
504
- Flags: -e/--env <env> (see: seq-studio envs list)
509
+ Flags: -e/--env <env> (required; see: seq-studio envs list)
505
510
 
506
511
  clone prefers real git clone (PAT via askpass — never written into the remote
507
512
  URL). Without ATLAS_GIT_PAT, <ns>/<name> falls back to the JSON API and prints
@@ -20,5 +20,5 @@ export declare function secretsSetDefaultCommand(args: ParsedArgs): Promise<numb
20
20
  * UI: pin + redeploy the function's active version / pin only / cancel.
21
21
  */
22
22
  export declare function secretsPinCommand(args: ParsedArgs): Promise<number>;
23
- export declare const SECRETS_USAGE = "usage:\n seq-studio secrets create <NAME> [--description text] register an org-owned secret\n seq-studio secrets set <NAME> set the shared default value (write-only)\n seq-studio secrets list [-e env] secrets you can see (never values)\n seq-studio secrets attach <NAME> --fn <slug> mount default on a function env var\n seq-studio secrets detach <NAME> --fn <slug> remove attachment\n seq-studio secrets apply --from-env-file .env [-e env] push defaults + attach (keys default from manifest)\n seq-studio secrets versions <NAME> value version history (never values)\n seq-studio secrets set-default <NAME> [version] point the default at a prior version (editor)\n seq-studio secrets pin <NAME> --fn <slug> [version] pin one function to a version (sticky; --unpin clears)\n\n Note: for the common deploy loop, secrets declared in managed-function.yml are\n reconciled automatically by `seq-studio functions deploy` using a local .env.\n Use `secrets` commands for CI (no .env), bulk/multi-function ops, or write-only\n value changes without a redeploy.\n\n Flags: -e/--env <env> (see: seq-studio envs list)\n --fn <slug> \u00B7 --env-var <NAME> \u00B7 --yes\n --functions <f1,f2> \u00B7 --keys <K1,K2> \u00B7 --all (override key selection)\n set-default: [version|version-row-id] (defaults to the most recent non-default) \u00B7 --yes\n pin: [version|version-row-id] (defaults to the current default) \u00B7 --unpin \u00B7 --yes (redeploy) \u00B7 --yes --no-redeploy\n";
23
+ export declare const SECRETS_USAGE = "usage:\n seq-studio secrets create <NAME> -e <env> [--description text] register an org-owned secret\n seq-studio secrets set <NAME> -e <env> set the shared default value (write-only)\n seq-studio secrets list -e <env> secrets you can see (never values)\n seq-studio secrets attach <NAME> --fn <slug> -e <env> mount default on a function env var\n seq-studio secrets detach <NAME> --fn <slug> -e <env> remove attachment\n seq-studio secrets apply --from-env-file .env -e <env> push defaults + attach (keys default from manifest)\n seq-studio secrets versions <NAME> -e <env> value version history (never values)\n seq-studio secrets set-default <NAME> [version] -e <env> point the default at a prior version (editor)\n seq-studio secrets pin <NAME> --fn <slug> [version] -e <env> pin one function to a version (sticky; --unpin clears)\n\n Note: for the common deploy loop, secrets declared in managed-function.yml are\n reconciled automatically by `seq-studio functions deploy` using a local .env.\n Use `secrets` commands for CI (no .env), bulk/multi-function ops, or write-only\n value changes without a redeploy.\n\n Flags: -e/--env <env> (required; see: seq-studio envs list)\n --fn <slug> \u00B7 --env-var <NAME> \u00B7 --yes\n --functions <f1,f2> \u00B7 --keys <K1,K2> \u00B7 --all (override key selection)\n set-default: [version|version-row-id] (defaults to the most recent non-default) \u00B7 --yes\n pin: [version|version-row-id] (defaults to the current default) \u00B7 --unpin \u00B7 --yes (redeploy) \u00B7 --yes --no-redeploy\n";
24
24
  export declare function runSecretsCommand(sub: string | undefined, args: ParsedArgs): Promise<number>;
@@ -128,7 +128,7 @@ async function functionExistsBySlugEventually({ ctx, slug, attempts = 3, retryDe
128
128
  export async function secretsCreateCommand(args) {
129
129
  const name = args.positional[0];
130
130
  if (!name) {
131
- console.error('usage: seq-studio secrets create <NAME> [-e env] [--description text]');
131
+ console.error('usage: seq-studio secrets create <NAME> -e <env> [--description text]');
132
132
  return 1;
133
133
  }
134
134
  const ctx = await buildContext(args);
@@ -150,7 +150,7 @@ export async function secretsCreateCommand(args) {
150
150
  export async function secretsSetCommand(args) {
151
151
  const name = args.positional[0];
152
152
  if (!name) {
153
- console.error('usage: seq-studio secrets set <NAME> [-e env]');
153
+ console.error('usage: seq-studio secrets set <NAME> -e <env>');
154
154
  return 1;
155
155
  }
156
156
  const ctx = await buildContext(args);
@@ -194,7 +194,7 @@ export async function secretsAttachCommand(args) {
194
194
  const name = args.positional[0];
195
195
  const fnSlug = typeof args.flags.fn === 'string' ? args.flags.fn : args.positional[1];
196
196
  if (!name || !fnSlug) {
197
- console.error('usage: seq-studio secrets attach <NAME> --fn <slug> [--env-var NAME]');
197
+ console.error('usage: seq-studio secrets attach <NAME> --fn <slug> -e <env> [--env-var NAME]');
198
198
  return 1;
199
199
  }
200
200
  const ctx = await buildContext(args);
@@ -229,7 +229,7 @@ export async function secretsDetachCommand(args) {
229
229
  const name = args.positional[0];
230
230
  const fnSlug = typeof args.flags.fn === 'string' ? args.flags.fn : args.positional[1];
231
231
  if (!name || !fnSlug) {
232
- console.error('usage: seq-studio secrets detach <NAME> --fn <slug>');
232
+ console.error('usage: seq-studio secrets detach <NAME> --fn <slug> -e <env>');
233
233
  return 1;
234
234
  }
235
235
  const ctx = await buildContext(args);
@@ -284,7 +284,7 @@ function resolveApplyKeys({ parsed, manifest, explicitKeys, applyAll, }) {
284
284
  export async function secretsApplyCommand(args) {
285
285
  const fromEnvFile = args.flags['from-env-file'];
286
286
  if (typeof fromEnvFile !== 'string') {
287
- console.error('usage: seq-studio secrets apply --from-env-file .env [-e env] [--yes]');
287
+ console.error('usage: seq-studio secrets apply --from-env-file .env -e <env> [--yes]');
288
288
  return 1;
289
289
  }
290
290
  const dir = workDir(args);
@@ -464,7 +464,7 @@ async function attachedFunctionSlugs(ctx, secretId) {
464
464
  export async function secretsVersionsCommand(args) {
465
465
  const name = args.positional[0];
466
466
  if (!name) {
467
- console.error('usage: seq-studio secrets versions <NAME> [-e env]');
467
+ console.error('usage: seq-studio secrets versions <NAME> -e <env>');
468
468
  return 1;
469
469
  }
470
470
  const ctx = await buildContext(args);
@@ -492,7 +492,7 @@ export async function secretsVersionsCommand(args) {
492
492
  export async function secretsSetDefaultCommand(args) {
493
493
  const name = args.positional[0];
494
494
  if (!name) {
495
- console.error('usage: seq-studio secrets set-default <NAME> [version] [-e env] [--yes]');
495
+ console.error('usage: seq-studio secrets set-default <NAME> [version] -e <env> [--yes]');
496
496
  return 1;
497
497
  }
498
498
  const ctx = await buildContext(args);
@@ -558,7 +558,7 @@ export async function secretsPinCommand(args) {
558
558
  const name = args.positional[0];
559
559
  const fnSlug = typeof args.flags.fn === 'string' ? args.flags.fn : undefined;
560
560
  if (!name || !fnSlug) {
561
- console.error('usage: seq-studio secrets pin <NAME> --fn <slug> [version] [--unpin] [-e env] [--yes] [--no-redeploy]');
561
+ console.error('usage: seq-studio secrets pin <NAME> --fn <slug> [version] [--unpin] -e <env> [--yes] [--no-redeploy]');
562
562
  return 1;
563
563
  }
564
564
  const ctx = await buildContext(args);
@@ -643,22 +643,22 @@ export async function secretsPinCommand(args) {
643
643
  // dispatcher
644
644
  // ---------------------------------------------------------------------------
645
645
  export const SECRETS_USAGE = `usage:
646
- seq-studio secrets create <NAME> [--description text] register an org-owned secret
647
- seq-studio secrets set <NAME> set the shared default value (write-only)
648
- seq-studio secrets list [-e env] secrets you can see (never values)
649
- seq-studio secrets attach <NAME> --fn <slug> mount default on a function env var
650
- seq-studio secrets detach <NAME> --fn <slug> remove attachment
651
- seq-studio secrets apply --from-env-file .env [-e env] push defaults + attach (keys default from manifest)
652
- seq-studio secrets versions <NAME> value version history (never values)
653
- seq-studio secrets set-default <NAME> [version] point the default at a prior version (editor)
654
- seq-studio secrets pin <NAME> --fn <slug> [version] pin one function to a version (sticky; --unpin clears)
646
+ seq-studio secrets create <NAME> -e <env> [--description text] register an org-owned secret
647
+ seq-studio secrets set <NAME> -e <env> set the shared default value (write-only)
648
+ seq-studio secrets list -e <env> secrets you can see (never values)
649
+ seq-studio secrets attach <NAME> --fn <slug> -e <env> mount default on a function env var
650
+ seq-studio secrets detach <NAME> --fn <slug> -e <env> remove attachment
651
+ seq-studio secrets apply --from-env-file .env -e <env> push defaults + attach (keys default from manifest)
652
+ seq-studio secrets versions <NAME> -e <env> value version history (never values)
653
+ seq-studio secrets set-default <NAME> [version] -e <env> point the default at a prior version (editor)
654
+ seq-studio secrets pin <NAME> --fn <slug> [version] -e <env> pin one function to a version (sticky; --unpin clears)
655
655
 
656
656
  Note: for the common deploy loop, secrets declared in managed-function.yml are
657
657
  reconciled automatically by \`seq-studio functions deploy\` using a local .env.
658
658
  Use \`secrets\` commands for CI (no .env), bulk/multi-function ops, or write-only
659
659
  value changes without a redeploy.
660
660
 
661
- Flags: -e/--env <env> (see: seq-studio envs list)
661
+ Flags: -e/--env <env> (required; see: seq-studio envs list)
662
662
  --fn <slug> · --env-var <NAME> · --yes
663
663
  --functions <f1,f2> · --keys <K1,K2> · --all (override key selection)
664
664
  set-default: [version|version-row-id] (defaults to the most recent non-default) · --yes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sequenceholdings/studio-cli",
3
- "version": "0.1.13",
4
- "description": "Unified Sequence Studio CLI — `seq-studio process` (Lattice), `seq-studio artifact` (Artifact Studio), `seq-studio functions` / `secrets`, `seq-studio repos` (platform git-service), and `seq-studio auth pat` (git-service PATs). Includes Auth0 browser login shared with seqapi.",
3
+ "version": "0.1.21",
4
+ "description": "Unified Sequence Studio CLI — `seq-studio agents` (typed agent definitions), `seq-studio process` (Lattice), `seq-studio artifact` (Artifact Studio), `seq-studio functions` / `secrets`, `seq-studio repos` (platform git-service), and `seq-studio auth pat` (git-service PATs). Includes Auth0 browser login shared with seqapi.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
7
7
  "type": "git",
@@ -40,15 +40,20 @@
40
40
  "smol-toml": "^1.4.2",
41
41
  "tsx": "^4.20.3",
42
42
  "zod": "^4.1.13",
43
- "@sequenceholdings/artifact-studio": "0.1.12",
43
+ "@sequenceholdings/agent-spec": "0.1.0",
44
+ "@sequenceholdings/artifact-studio": "0.2.0",
44
45
  "@sequenceholdings/lattice": "0.1.2"
45
46
  },
46
47
  "peerDependencies": {
47
- "@sequenceholdings/orm": "0.1.1"
48
+ "@sequenceholdings/orm": "0.1.2",
49
+ "@sequenceholdings/pipeline-spec": "0.1.0"
48
50
  },
49
51
  "peerDependenciesMeta": {
50
52
  "@sequenceholdings/orm": {
51
53
  "optional": true
54
+ },
55
+ "@sequenceholdings/pipeline-spec": {
56
+ "optional": true
52
57
  }
53
58
  },
54
59
  "devDependencies": {
@@ -56,7 +61,8 @@
56
61
  "@types/node": "^22.0.0",
57
62
  "typescript": "^5.6.0",
58
63
  "vitest": "^4.1.5",
59
- "@sequenceholdings/orm": "0.1.1"
64
+ "@sequenceholdings/orm": "0.1.2",
65
+ "@sequenceholdings/pipeline-spec": "0.1.0"
60
66
  },
61
67
  "engines": {
62
68
  "node": ">=20"
@@ -65,6 +71,7 @@
65
71
  "studio",
66
72
  "sequence",
67
73
  "lattice",
74
+ "agents",
68
75
  "process",
69
76
  "artifact",
70
77
  "cli"