@agentuity/cli 0.0.92 → 0.0.94

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/dist/agents-docs.d.ts +22 -0
  2. package/dist/agents-docs.d.ts.map +1 -0
  3. package/dist/agents-docs.js +36 -0
  4. package/dist/agents-docs.js.map +1 -0
  5. package/dist/banner.d.ts.map +1 -1
  6. package/dist/banner.js +11 -4
  7. package/dist/banner.js.map +1 -1
  8. package/dist/cmd/build/bundler.js +1 -1
  9. package/dist/cmd/build/bundler.js.map +1 -1
  10. package/dist/cmd/cloud/storage/upload.d.ts.map +1 -1
  11. package/dist/cmd/cloud/storage/upload.js +40 -26
  12. package/dist/cmd/cloud/storage/upload.js.map +1 -1
  13. package/dist/cmd/dev/index.d.ts.map +1 -1
  14. package/dist/cmd/dev/index.js +3 -0
  15. package/dist/cmd/dev/index.js.map +1 -1
  16. package/dist/cmd/index.d.ts.map +1 -1
  17. package/dist/cmd/index.js +1 -0
  18. package/dist/cmd/index.js.map +1 -1
  19. package/dist/cmd/project/download.d.ts.map +1 -1
  20. package/dist/cmd/project/download.js +173 -55
  21. package/dist/cmd/project/download.js.map +1 -1
  22. package/dist/cmd/setup/index.d.ts +2 -0
  23. package/dist/cmd/setup/index.d.ts.map +1 -0
  24. package/dist/cmd/setup/index.js +37 -0
  25. package/dist/cmd/setup/index.js.map +1 -0
  26. package/dist/cmd/upgrade/index.d.ts.map +1 -1
  27. package/dist/cmd/upgrade/index.js +6 -1
  28. package/dist/cmd/upgrade/index.js.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/runtime-bootstrap.d.ts +55 -0
  34. package/dist/runtime-bootstrap.d.ts.map +1 -0
  35. package/dist/runtime-bootstrap.js +90 -0
  36. package/dist/runtime-bootstrap.js.map +1 -0
  37. package/dist/tui.d.ts +16 -0
  38. package/dist/tui.d.ts.map +1 -1
  39. package/dist/tui.js +3 -3
  40. package/dist/tui.js.map +1 -1
  41. package/dist/version-check.d.ts.map +1 -1
  42. package/dist/version-check.js +6 -1
  43. package/dist/version-check.js.map +1 -1
  44. package/dist/version.d.ts +17 -0
  45. package/dist/version.d.ts.map +1 -1
  46. package/dist/version.js +24 -0
  47. package/dist/version.js.map +1 -1
  48. package/package.json +3 -3
  49. package/src/agents-docs.ts +52 -0
  50. package/src/banner.ts +18 -4
  51. package/src/cmd/build/bundler.ts +1 -1
  52. package/src/cmd/cloud/storage/upload.ts +43 -29
  53. package/src/cmd/dev/index.ts +5 -1
  54. package/src/cmd/index.ts +1 -0
  55. package/src/cmd/project/download.ts +194 -59
  56. package/src/cmd/setup/index.ts +42 -0
  57. package/src/cmd/upgrade/index.ts +8 -1
  58. package/src/index.ts +5 -0
  59. package/src/runtime-bootstrap.md +161 -0
  60. package/src/runtime-bootstrap.ts +125 -0
  61. package/src/tui.ts +3 -3
  62. package/src/version-check.ts +6 -1
  63. package/src/version.ts +28 -0
@@ -0,0 +1,161 @@
1
+ # Runtime Bootstrap Utility
2
+
3
+ ## Problem
4
+
5
+ When running SDK test applications locally (integration-suite, cloud-deployment), they weren't respecting:
6
+
7
+ - Profile-specific `.env` files (`.env.local`, `.env.production`)
8
+ - Profile-specific config files (`agentuity.local.json`, `agentuity.production.json`)
9
+
10
+ This caused tests to fail because:
11
+
12
+ 1. `AGENTUITY_SDK_KEY` wasn't loaded from `.env.local`
13
+ 2. `AGENTUITY_REGION` wasn't set to `local` for local profile
14
+ 3. Services tried to connect to production URLs instead of `*.agentuity.io`
15
+
16
+ ## Solution
17
+
18
+ The `bootstrapRuntimeEnv()` function loads profile-aware configuration and environment variables **before** `createApp()` is called.
19
+
20
+ ### What it does:
21
+
22
+ 1. **Resolves active profile** via `loadConfig()`
23
+ - Checks `AGENTUITY_PROFILE` env var
24
+ - Reads `~/.config/agentuity/profile` file
25
+ - Falls back to `production` profile
26
+
27
+ 2. **Loads `.env` files** based on profile:
28
+ - For `local` profile: `.env.local`, `.env.development`, `.env`
29
+ - For `production` profile: `.env.production`, `.env`
30
+
31
+ 3. **Sets environment variables**:
32
+ - Only sets if not already defined (existing env wins)
33
+ - For `local` profile: defaults `AGENTUITY_REGION=local`
34
+ - Sets `AGENTUITY_PROFILE` to match active profile
35
+
36
+ 4. **Loads project config**:
37
+ - For `local` profile: `agentuity.local.json`
38
+ - For `production` profile: `agentuity.json` or `agentuity.production.json`
39
+
40
+ ### Usage
41
+
42
+ Call `bootstrapRuntimeEnv()` at the top of your `app.ts` **before** `createApp()`:
43
+
44
+ ```ts
45
+ import { createApp } from '@agentuity/runtime';
46
+ import { bootstrapRuntimeEnv } from '@agentuity/cli';
47
+
48
+ // Bootstrap runtime environment based on active profile
49
+ await bootstrapRuntimeEnv();
50
+
51
+ // Now createApp() will use the correct env vars
52
+ const app = await createApp();
53
+ ```
54
+
55
+ ### Options
56
+
57
+ ```ts
58
+ await bootstrapRuntimeEnv({
59
+ projectDir: '/path/to/project', // default: process.cwd()
60
+ profile: 'local', // override active profile
61
+ });
62
+ ```
63
+
64
+ ### Local Development Setup
65
+
66
+ To run tests locally with local services:
67
+
68
+ 1. **Create local profile** (if not exists):
69
+
70
+ ```bash
71
+ cd ~/.config/agentuity
72
+ touch local.yaml
73
+ echo "name: local" > local.yaml
74
+ ```
75
+
76
+ 2. **Select local profile**:
77
+
78
+ ```bash
79
+ agentuity profile switch local
80
+ # Or set env var:
81
+ export AGENTUITY_PROFILE=local
82
+ ```
83
+
84
+ 3. **Create `.env.local`** in project root:
85
+
86
+ ```bash
87
+ AGENTUITY_SDK_KEY=your-sdk-key-here
88
+ AGENTUITY_REGION=local # Optional, auto-set for local profile
89
+ ```
90
+
91
+ 4. **(Optional) Create `agentuity.local.json`** for project-specific overrides:
92
+ ```json
93
+ {
94
+ "projectId": "proj_local_test",
95
+ "orgId": "org_local",
96
+ "region": "local"
97
+ }
98
+ ```
99
+
100
+ ### How it works
101
+
102
+ The bootstrap process follows this precedence (highest to lowest):
103
+
104
+ 1. **Explicit env vars** (from shell/CI) - always wins
105
+ 2. **Profile-specific .env** (`.env.local` for local profile)
106
+ 3. **Development/production .env** (`.env.development` or `.env.production`)
107
+ 4. **Default .env** (`.env`)
108
+
109
+ For config files:
110
+
111
+ 1. **Profile-specific config** (`agentuity.local.json` for local profile)
112
+ 2. **Default config** (`agentuity.json`)
113
+
114
+ ### Integration Points
115
+
116
+ This utility is used by:
117
+
118
+ - `sdk/apps/testing/integration-suite/app.ts`
119
+ - `sdk/apps/testing/cloud-deployment/app.ts`
120
+
121
+ It reuses existing infrastructure from the CLI:
122
+
123
+ - `loadConfig()` - Resolves active profile
124
+ - `loadProjectConfig()` - Loads profile-specific project config
125
+ - `getEnvFilePaths()` - Determines which .env files to load
126
+ - `readEnvFile()` - Parses .env files
127
+
128
+ ### Design Decisions
129
+
130
+ **Why not embed in `createApp()`?**
131
+
132
+ - `createApp()` is a runtime primitive that should work in any environment
133
+ - CLI config and profile logic is Bun-specific
134
+ - Test harnesses can opt-in to this behavior without forcing it on all SDK users
135
+
136
+ **Why not auto-detect local vs production?**
137
+
138
+ - Profile system is the single source of truth
139
+ - `NODE_ENV` alone is insufficient (can be `development` in production)
140
+ - Region alone is insufficient (multiple regions, not just local vs cloud)
141
+ - Profile explicitly declares intent: "I want local services"
142
+
143
+ ### Testing
144
+
145
+ To verify it works:
146
+
147
+ ```bash
148
+ # Set local profile
149
+ export AGENTUITY_PROFILE=local
150
+
151
+ # Build and run
152
+ cd sdk/apps/testing/integration-suite
153
+ bun run build
154
+ cd .agentuity && bun run app.js
155
+
156
+ # Check logs for:
157
+ # [TEST-SUITE] Profile: local
158
+ # [TEST-SUITE] Region: local
159
+ ```
160
+
161
+ Services should connect to `*.agentuity.io` instead of `*.agentuity.cloud`.
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Runtime environment bootstrapping utility
3
+ *
4
+ * Loads configuration and environment variables based on the active profile
5
+ * before createApp() is called. This ensures .env.{profile} files and
6
+ * agentuity.{profile}.json configs are respected.
7
+ */
8
+
9
+ import { loadConfig, loadProjectConfig } from './config';
10
+ import { getEnvFilePaths, readEnvFile, type EnvVars } from './env-util';
11
+ import type { Config, ProjectConfig } from './types';
12
+
13
+ export interface RuntimeBootstrapOptions {
14
+ /**
15
+ * Project directory containing agentuity.json and .env files
16
+ * @default process.cwd()
17
+ */
18
+ projectDir?: string;
19
+
20
+ /**
21
+ * Override the active profile (otherwise uses loadConfig())
22
+ */
23
+ profile?: string;
24
+ }
25
+
26
+ export interface RuntimeBootstrapResult {
27
+ /**
28
+ * Resolved CLI config (from ~/.config/agentuity/)
29
+ */
30
+ config: Config | null;
31
+
32
+ /**
33
+ * Resolved project config (agentuity.json or agentuity.{profile}.json)
34
+ */
35
+ projectConfig: ProjectConfig | null;
36
+ }
37
+
38
+ /**
39
+ * Bootstrap runtime environment by loading profile-aware config and env files.
40
+ *
41
+ * This function:
42
+ * 1. Resolves the active profile (from AGENTUITY_PROFILE env or profile config)
43
+ * 2. Loads .env.{profile}, .env.development, or .env based on profile
44
+ * 3. Sets AGENTUITY_REGION=local for local profile
45
+ * 4. Loads agentuity.{profile}.json if it exists
46
+ * 5. Does NOT override environment variables already set
47
+ *
48
+ * Call this BEFORE createApp() in your app.ts:
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * import { bootstrapRuntimeEnv } from '@agentuity/cli/runtime-bootstrap';
53
+ * import { createApp } from '@agentuity/runtime';
54
+ *
55
+ * // Load config and env based on active profile
56
+ * await bootstrapRuntimeEnv();
57
+ *
58
+ * // Now createApp() will use the correct env vars
59
+ * const app = await createApp();
60
+ * ```
61
+ */
62
+ export async function bootstrapRuntimeEnv(
63
+ options: RuntimeBootstrapOptions = {}
64
+ ): Promise<RuntimeBootstrapResult> {
65
+ const projectDir = options.projectDir || process.cwd();
66
+
67
+ // Load CLI config to determine active profile
68
+ let cfg: Config | null = null;
69
+ try {
70
+ cfg = await loadConfig();
71
+ // Override profile if specified
72
+ if (options.profile) {
73
+ cfg = { ...cfg, name: options.profile };
74
+ }
75
+ } catch {
76
+ // No config found - OK for tests without CLI setup
77
+ }
78
+
79
+ // Determine which .env files to load based on profile
80
+ const isProduction = process.env.NODE_ENV === 'production';
81
+ const envPaths = getEnvFilePaths(projectDir, {
82
+ configName: cfg?.name,
83
+ isProduction,
84
+ });
85
+
86
+ // Load and merge env files (later files override earlier ones)
87
+ let fileEnv: EnvVars = {};
88
+ for (const path of envPaths) {
89
+ const vars = await readEnvFile(path);
90
+ // Later files override earlier ones
91
+ fileEnv = { ...fileEnv, ...vars };
92
+ }
93
+
94
+ // Apply to process.env ONLY if not already set
95
+ // This ensures existing env vars (from shell/CI) always win
96
+ for (const [key, value] of Object.entries(fileEnv)) {
97
+ if (process.env[key] === undefined) {
98
+ process.env[key] = value;
99
+ }
100
+ }
101
+
102
+ // For local profile, default AGENTUITY_REGION to 'local'
103
+ // This makes getServiceUrls() use *.agentuity.io instead of *.agentuity.cloud
104
+ if (cfg?.name === 'local' && !process.env.AGENTUITY_REGION) {
105
+ process.env.AGENTUITY_REGION = 'local';
106
+ }
107
+
108
+ // Propagate profile name into env for consistency
109
+ if (cfg?.name && !process.env.AGENTUITY_PROFILE) {
110
+ process.env.AGENTUITY_PROFILE = cfg.name;
111
+ }
112
+
113
+ // Load project config (agentuity.json or agentuity.{profile}.json)
114
+ let projectConfig: ProjectConfig | null = null;
115
+ try {
116
+ projectConfig = await loadProjectConfig(projectDir, cfg ?? undefined);
117
+ } catch {
118
+ // OK for tests that don't need project config
119
+ }
120
+
121
+ return {
122
+ config: cfg,
123
+ projectConfig,
124
+ };
125
+ }
package/src/tui.ts CHANGED
@@ -307,7 +307,7 @@ export function link(url: string, title?: string, color = getColor('link')): str
307
307
  /**
308
308
  * Check if terminal supports OSC 8 hyperlinks
309
309
  */
310
- function supportsHyperlinks(): boolean {
310
+ export function supportsHyperlinks(): boolean {
311
311
  const term = process.env.TERM || '';
312
312
  const termProgram = process.env.TERM_PROGRAM || '';
313
313
  const wtSession = process.env.WT_SESSION || '';
@@ -361,7 +361,7 @@ export function output(message: string): void {
361
361
  * which causes incorrect alignment. We strip OSC 8 codes first, then use Bun.stringWidth()
362
362
  * to handle regular ANSI codes and unicode characters correctly.
363
363
  */
364
- function getDisplayWidth(str: string): number {
364
+ export function getDisplayWidth(str: string): number {
365
365
  // Remove OSC-8 hyperlink sequences using Unicode escapes (\u001b = ESC, \u0007 = BEL) to satisfy linter
366
366
  // eslint-disable-next-line no-control-regex
367
367
  const withoutOSC8 = str.replace(/\u001b\]8;;[^\u0007]*\u0007/g, '');
@@ -371,7 +371,7 @@ function getDisplayWidth(str: string): number {
371
371
  /**
372
372
  * Strip all ANSI escape sequences from a string
373
373
  */
374
- function stripAnsi(str: string): string {
374
+ export function stripAnsi(str: string): string {
375
375
  // eslint-disable-next-line no-control-regex
376
376
  return str.replace(/\u001b\[[0-9;]*m/g, '').replace(/\u001b\]8;;[^\u0007]*\u0007/g, '');
377
377
  }
@@ -1,6 +1,6 @@
1
1
  import type { Config, Logger, CommandDefinition } from './types';
2
2
  import { isRunningFromExecutable, fetchLatestVersion } from './cmd/upgrade';
3
- import { getVersion } from './version';
3
+ import { getVersion, getCompareUrl, getReleaseUrl, toTag } from './version';
4
4
  import * as tui from './tui';
5
5
  import { saveConfig } from './config';
6
6
  import { $ } from 'bun';
@@ -97,6 +97,11 @@ async function promptUpgrade(currentVersion: string, latestVersion: string): Pro
97
97
  tui.info(`Current version: ${tui.muted(currentVersion)}`);
98
98
  tui.info(`Latest version: ${tui.bold(latestVersion)}`);
99
99
  tui.newline();
100
+ if (toTag(currentVersion) !== toTag(latestVersion)) {
101
+ tui.warning(`What's changed: ${tui.link(getCompareUrl(currentVersion, latestVersion))}`);
102
+ }
103
+ tui.success(`Release notes: ${tui.link(getReleaseUrl(latestVersion))}`);
104
+ tui.newline();
100
105
 
101
106
  return await tui.confirm('Would you like to upgrade now?', true);
102
107
  }
package/src/version.ts CHANGED
@@ -27,3 +27,31 @@ export function getRevision(): string {
27
27
  // Bun provides git SHA via Bun.revision
28
28
  return typeof Bun !== 'undefined' && Bun.revision ? Bun.revision.substring(0, 8) : 'unknown';
29
29
  }
30
+
31
+ const GITHUB_REPO_URL = 'https://github.com/agentuity/sdk';
32
+
33
+ /**
34
+ * Normalize a version string to a Git tag format (with 'v' prefix)
35
+ */
36
+ export function toTag(version: string): string {
37
+ return version.startsWith('v') ? version : `v${version}`;
38
+ }
39
+
40
+ /**
41
+ * Get the GitHub URL for comparing two versions
42
+ * @param fromVersion - The current/old version
43
+ * @param toVersion - The new/target version
44
+ * @returns GitHub compare URL
45
+ */
46
+ export function getCompareUrl(fromVersion: string, toVersion: string): string {
47
+ return `${GITHUB_REPO_URL}/compare/${toTag(fromVersion)}...${toTag(toVersion)}`;
48
+ }
49
+
50
+ /**
51
+ * Get the GitHub URL for a specific release
52
+ * @param version - The version to get the release URL for
53
+ * @returns GitHub release URL
54
+ */
55
+ export function getReleaseUrl(version: string): string {
56
+ return `${GITHUB_REPO_URL}/releases/tag/${toTag(version)}`;
57
+ }