@aiworkbench/vibe-cli 0.0.5 → 0.0.7

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 (2) hide show
  1. package/dist/index.js +304 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5853,6 +5853,9 @@ bridge.navigation.navigate("/some/host/path");
5853
5853
 
5854
5854
  This triggers a host-level route change. It is fire-and-forget — your mini-app will
5855
5855
  be unmounted as the host navigates away.
5856
+
5857
+ See the \`host-design-system\` skill for the complete list of host routes, dynamic
5858
+ segments, query parameters, and navigation code examples.
5856
5859
  `;
5857
5860
  }
5858
5861
  function getViewSwitchingExample(framework) {
@@ -6743,13 +6746,36 @@ The host application has these routes. Use \`bridge.navigation.navigate(path)\`
6743
6746
 
6744
6747
  | Route | Page |
6745
6748
  |-------|------|
6746
- | \`/chat\` | Chat with agents |
6749
+ | \`/[agentId]/chat\` | Chat with a specific agent |
6750
+ | \`/[agentId]/talk\` | Voice conversation |
6747
6751
  | \`/marketplace\` | Marketplace landing |
6748
- | \`/marketplace/agents?state=PUBLISHED\` | Published agents |
6752
+ | \`/marketplace/agents\` | Agent directory |
6753
+ | \`/marketplace/servers\` | MCP server directory |
6754
+ | \`/builder\` | Builder landing |
6755
+ | \`/builder/agent\` | Agent builder |
6749
6756
  | \`/playground\` | Prompt playground |
6750
- | \`/builder\` | Agent builder |
6757
+ | \`/playground/[appId]\` | Mini-app sandbox |
6751
6758
  | \`/documents\` | Document library |
6752
- | \`/administration\` | Admin panel (admins only) |
6759
+
6760
+ ### Dynamic Segments
6761
+
6762
+ | Segment | Description | Example |
6763
+ |---------|-------------|---------|
6764
+ | \`[agentId]\` | Agent UUID — identifies which agent to chat with or call | \`a1b2c3d4-e5f6-7890-abcd-ef1234567890\` |
6765
+ | \`[appId]\` | Mini-app ID from \`manifest.json\` — loads that app in the sandbox | \`my-mini-app\` |
6766
+
6767
+ ### Navigation Examples
6768
+
6769
+ \`\`\`typescript
6770
+ // Navigate to a specific agent's chat
6771
+ bridge.navigation.navigate(\`/\${agentId}/chat\`);
6772
+
6773
+ // Open the marketplace agent directory
6774
+ bridge.navigation.navigate("/marketplace/agents");
6775
+
6776
+ // Open a mini-app in the playground sandbox
6777
+ bridge.navigation.navigate(\`/playground/\${appId}\`);
6778
+ \`\`\`
6753
6779
 
6754
6780
  ## Dark Mode Support
6755
6781
 
@@ -7091,6 +7117,103 @@ private render() {
7091
7117
  }
7092
7118
  }
7093
7119
 
7120
+ // src/skills/platform-design-philosophy.ts
7121
+ function generatePlatformDesignPhilosophy(_config) {
7122
+ return `# Platform Design Philosophy
7123
+
7124
+ ## Core Principle: Be Invisible
7125
+
7126
+ A successful mini-app is one the user cannot distinguish from the host. If someone
7127
+ can tell where the host ends and your mini-app begins, the design has failed. Your
7128
+ goal is not to build something that "looks good" — it is to build something that
7129
+ **disappears** into the platform.
7130
+
7131
+ This means: no branding, no personality, no signature style. The host IS the style.
7132
+ You are extending it, not decorating it.
7133
+
7134
+ ## Design Thinking for Platform Consistency
7135
+
7136
+ ### Match Visual Weight
7137
+
7138
+ Every element in the host has a deliberate visual weight. Buttons are small and quiet.
7139
+ Cards have thin borders and minimal shadow. Headings are understated. If your mini-app
7140
+ introduces elements that are heavier — bolder, larger, more colorful, more shadowed —
7141
+ it will feel foreign even if the colors technically match.
7142
+
7143
+ Before adding any element, look at the host's equivalent. How heavy is it? Match that
7144
+ weight exactly.
7145
+
7146
+ ### Respect Information Hierarchy
7147
+
7148
+ The host uses a strict hierarchy:
7149
+ 1. **Content** comes first — data, text, interactive elements
7150
+ 2. **Chrome** is minimal — thin borders, subtle backgrounds, small labels
7151
+ 3. **Decoration** is absent — no gradients, no illustrations, no ornamental elements
7152
+
7153
+ Your mini-app should follow the same hierarchy. If you're spending time on decoration,
7154
+ you're diverging from the platform aesthetic.
7155
+
7156
+ ### Grayscale-First Philosophy
7157
+
7158
+ The host is intentionally grayscale. Color is used as a **signal**, not a **style**:
7159
+ - **Tertiary accent** (yellow-green) marks featured or promoted items
7160
+ - **Destructive red** marks dangerous actions
7161
+ - **Chart/data colors** convey meaning in visualizations
7162
+
7163
+ Everything else — backgrounds, borders, text, icons, cards, buttons — is grayscale.
7164
+ If your UI uses color for anything other than semantic signaling, it will clash.
7165
+
7166
+ ## What "Native" Means in This Platform
7167
+
7168
+ | Aspect | Native Approach |
7169
+ |--------|----------------|
7170
+ | **Typography** | Geist Sans and Geist Mono. No other fonts, ever. |
7171
+ | **Color palette** | OKLCh grayscale with a single accent. No brand colors, no blues, no greens. |
7172
+ | **Component style** | shadcn/UI "New York" variant — clean, dense, slightly austere. |
7173
+ | **Density** | Dense but not cramped. Cards use \`1rem\` padding, grids use \`0.75rem–1.5rem\` gaps. |
7174
+ | **Interactions** | Subtle and fast. \`150–180ms\` transitions. No bouncing, no sliding, no scaling. |
7175
+ | **Borders** | \`1px solid\` in muted gray. Never thicker. Never colored. |
7176
+ | **Shadows** | Flat by default. Shadow appears only on hover for interactive cards. |
7177
+ | **Icons** | Lucide at \`16–20px\`, stroke-only, \`currentColor\`. No filled icons, no custom icon sets. |
7178
+
7179
+ ## Quick Decision Checklist
7180
+
7181
+ Use this before writing any component:
7182
+
7183
+ - [ ] **Card radius** — \`8px\` standard, \`12px\` for marketplace-style cards, \`6px\` for buttons/inputs
7184
+ - [ ] **Grayscale chrome** — Is every non-content element (borders, backgrounds, labels) grayscale?
7185
+ - [ ] **Type scale** — Body at \`0.875rem\`, headings at \`1.125rem\`, labels at \`0.6875rem\` uppercase
7186
+ - [ ] **Transition timing** — \`180ms ease\` for hover/shadow, \`150ms ease\` for color/opacity
7187
+ - [ ] **Border width** — \`1px\` everywhere, no exceptions
7188
+ - [ ] **Shadow** — None at rest, \`0 2px 6px rgba(0,0,0,0.15)\` on hover for interactive cards only
7189
+ - [ ] **Font** — Geist Sans via \`var(--font-geist-sans)\`, Geist Mono via \`var(--font-geist-mono)\`
7190
+ - [ ] **Spacing** — Multiples of \`0.25rem\` (4px base unit), common values: 8px, 12px, 16px, 24px
7191
+
7192
+ ## Anti-Patterns
7193
+
7194
+ These immediately break the native feel. Avoid them completely:
7195
+
7196
+ | Anti-Pattern | Why It Fails |
7197
+ |-------------|-------------|
7198
+ | **Colored backgrounds** | The host uses white/near-white. Colored sections scream "third-party." |
7199
+ | **Custom fonts** | Even "nice" fonts like Inter or Roboto break consistency. Only Geist. |
7200
+ | **Animated entrances** | Fade-ins, slide-ups, scale animations on mount. The host doesn't do this. |
7201
+ | **Gradient chrome** | Gradient backgrounds, gradient borders, gradient buttons. The host is flat. |
7202
+ | **Shadows at rest** | Drop shadows on cards, panels, or containers that aren't being hovered. |
7203
+ | **Saturated color palettes** | Blues, greens, oranges for UI elements. Only grayscale + the tertiary accent. |
7204
+ | **Oversized headings** | Headings larger than \`1.125rem\`. The host's headings are deliberately small. |
7205
+ | **Thick borders** | Borders thicker than \`1px\`. The host uses hairline borders exclusively. |
7206
+ | **Rounded-full pills** | Pill-shaped elements (\`border-radius: 9999px\`). Cards are \`8–12px\`, badges are \`6px\`. |
7207
+ | **Icon-heavy UI** | Large icons, colored icons, icon grids. The host uses small, monochrome icons sparingly. |
7208
+
7209
+ ## Cross-Reference
7210
+
7211
+ This skill establishes the **design mindset**. For specific implementation values — exact
7212
+ colors, spacing tokens, component CSS, and dark mode support — load the \`host-design-system\`
7213
+ skill. Both skills should be consulted before writing any UI code.
7214
+ `;
7215
+ }
7216
+
7094
7217
  // src/scaffold/write-agent-docs.ts
7095
7218
  var PERMISSION_DOCS = {
7096
7219
  auth: `### auth
@@ -7287,6 +7410,45 @@ cleanups.forEach((fn) => fn());
7287
7410
  | "Unresolved external" build warning | Dependency not in Vite external config | Add to \`rollupOptions.external\` or bundle it |
7288
7411
  | HMR not reflecting changes | Custom element re-registration conflict | Hard refresh the page (Cmd+Shift+R / Ctrl+Shift+R) |
7289
7412
 
7413
+ ## Always-Loaded Design Skills
7414
+
7415
+ **IMPORTANT**: Always load these two skills BEFORE writing any UI code. They are
7416
+ mandatory for every task that involves creating or modifying visual components.
7417
+
7418
+ | Skill | Purpose |
7419
+ |-------|---------|
7420
+ | \`platform-design-philosophy\` | Design mindset — ensures your UI feels native to the host platform |
7421
+ | \`host-design-system\` | Design tokens — exact colors, spacing, typography, and component CSS |
7422
+
7423
+ Load both skills at the start of any UI task. The philosophy skill establishes the
7424
+ approach; the design system skill provides the implementation details.
7425
+
7426
+ ## Skills Reference
7427
+
7428
+ This project includes detailed skill guides for specific topics. Skills are **not loaded by
7429
+ default** to keep context focused. **Load the relevant skill before writing code** whenever the
7430
+ user's request touches that area. When in doubt, load the skill — it's better to have the
7431
+ reference than to guess.
7432
+
7433
+ | Skill | Load when… |
7434
+ |-------|-----------|
7435
+ | \`bridge-usage\` | Using any bridge capability (auth, api, storage, events, theme, toast, navigation) |
7436
+ | \`component-patterns\` | Creating or modifying components, lifecycle hooks, shadow DOM patterns |
7437
+ | \`manifest-guide\` | Editing manifest.json, adding or changing permissions |
7438
+ | \`security-rules\` | Reviewing code for policy violations, or unsure if a pattern is allowed |
7439
+ | \`vite-config\` | Changing build configuration, adding Vite plugins, optimizing bundles |
7440
+ | \`accessibility\` | Adding interactive elements, forms, ARIA attributes, keyboard navigation |
7441
+ | \`error-handling\` | Implementing try/catch, error boundaries, or graceful degradation |
7442
+ | \`performance\` | Optimizing bundle size, render performance, or memory usage |
7443
+ | \`debugging\` | Troubleshooting issues, tracing bridge calls, fixing HMR problems |
7444
+ | \`navigation-patterns\` | Building multi-view UIs, tabs, wizards, or steppers (no URL routing) |
7445
+ | \`asset-handling\` | Working with images, SVGs, fonts, or other static assets |
7446
+ ${testing ? `| \`testing-guide\` | Writing or modifying tests, mocking the bridge, test setup |
7447
+ ` : ""}
7448
+ **How to use skills:** Read the skill file for the relevant topic before implementing. Multiple
7449
+ skills can apply to a single task — for example, building a new form might involve
7450
+ \`component-patterns\`, \`accessibility\`, and \`bridge-usage\` (if the form submits via the bridge API).
7451
+
7290
7452
  ## Build & Dev
7291
7453
  - \`bun run dev\` — Start Vite dev server with hot reload
7292
7454
  - \`bun run build\` — Production build (ES module, < 50kb gzipped)
@@ -7322,7 +7484,8 @@ function generateEmbeddedSkills(config) {
7322
7484
  { name: "Debugging", content: generateDebugging(config) },
7323
7485
  { name: "Navigation Patterns", content: generateNavigationPatterns(config) },
7324
7486
  { name: "Asset Handling", content: generateAssetHandling(config) },
7325
- { name: "Host Design System", content: generateHostDesignSystem(config) }
7487
+ { name: "Host Design System", content: generateHostDesignSystem(config) },
7488
+ { name: "Platform Design Philosophy", content: generatePlatformDesignPhilosophy(config) }
7326
7489
  ];
7327
7490
  if (config.testing) {
7328
7491
  skills.push({ name: "Testing Guide", content: generateTestingGuide(config) });
@@ -7659,6 +7822,16 @@ var SKILL_DEFS = [
7659
7822
  name: "asset-handling",
7660
7823
  description: "Inline SVGs, imported data URLs, and CDN patterns for production assets",
7661
7824
  generate: generateAssetHandling
7825
+ },
7826
+ {
7827
+ name: "host-design-system",
7828
+ description: "Host app design tokens, typography, spacing, colors, and component patterns",
7829
+ generate: generateHostDesignSystem
7830
+ },
7831
+ {
7832
+ name: "platform-design-philosophy",
7833
+ description: "Design mindset and principles for building UI that feels native to the host platform",
7834
+ generate: generatePlatformDesignPhilosophy
7662
7835
  }
7663
7836
  ];
7664
7837
  async function writeFolderSkill(baseDir, skill, content) {
@@ -8740,7 +8913,47 @@ async function configCommand(args) {
8740
8913
  // src/commands/release.ts
8741
8914
  import { resolve as resolve4 } from "node:path";
8742
8915
  import { readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
8743
- import { execSync as execSync2 } from "node:child_process";
8916
+ import { execFileSync } from "node:child_process";
8917
+ var REQUIRED_ENV_VARS = [
8918
+ "VIBE_STORAGE_ACCOUNT_NAME",
8919
+ "VIBE_STORAGE_ACCOUNT_KEY",
8920
+ "VIBE_STORAGE_CONTAINER_NAME",
8921
+ "VIBE_REGISTRY_REPO",
8922
+ "VIBE_REGISTRY_TOKEN"
8923
+ ];
8924
+ function parseDotenv(content) {
8925
+ const env = {};
8926
+ for (const line of content.split(`
8927
+ `)) {
8928
+ const trimmed = line.trim();
8929
+ if (!trimmed || trimmed.startsWith("#"))
8930
+ continue;
8931
+ const eqIdx = trimmed.indexOf("=");
8932
+ if (eqIdx === -1)
8933
+ continue;
8934
+ const key = trimmed.slice(0, eqIdx).trim();
8935
+ let value = trimmed.slice(eqIdx + 1).trim();
8936
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
8937
+ value = value.slice(1, -1);
8938
+ }
8939
+ env[key] = value;
8940
+ }
8941
+ return env;
8942
+ }
8943
+ async function validateEnvVars(cwd) {
8944
+ let dotenv = {};
8945
+ try {
8946
+ const content = await readFile11(resolve4(cwd, ".env"), "utf-8");
8947
+ dotenv = parseDotenv(content);
8948
+ } catch {}
8949
+ const missing = [];
8950
+ for (const key of REQUIRED_ENV_VARS) {
8951
+ if (!dotenv[key] && !process.env[key]) {
8952
+ missing.push(key);
8953
+ }
8954
+ }
8955
+ return missing.length === 0 ? { ok: true } : { ok: false, missing };
8956
+ }
8744
8957
  function bumpVersion(version, type) {
8745
8958
  if (type === "keep")
8746
8959
  return version;
@@ -8760,8 +8973,8 @@ function bumpVersion(version, type) {
8760
8973
  return `${major + 1}.0.0`;
8761
8974
  }
8762
8975
  }
8763
- function git(cmd, cwd) {
8764
- return execSync2(`git ${cmd}`, { cwd, encoding: "utf-8" }).trim();
8976
+ function git(args, cwd) {
8977
+ return execFileSync("git", args, { cwd, encoding: "utf-8" }).trim();
8765
8978
  }
8766
8979
  function parseGitHubRepo(remoteUrl, host = "github.com") {
8767
8980
  const escaped = host.replace(/\./g, "\\.");
@@ -8808,6 +9021,47 @@ async function releaseCommand(dir) {
8808
9021
  });
8809
9022
  const newVersion = bumpVersion(currentVersion, bumpType);
8810
9023
  const tag = `v${newVersion}`;
9024
+ const publishMode = await dist_default5({
9025
+ message: "Publish method:",
9026
+ choices: [
9027
+ {
9028
+ name: "Local publish (uses .env credentials)",
9029
+ value: "local"
9030
+ },
9031
+ {
9032
+ name: "CI publish (push tag → GitHub Actions)",
9033
+ value: "ci"
9034
+ }
9035
+ ]
9036
+ });
9037
+ let environment = "dev";
9038
+ if (publishMode === "local") {
9039
+ environment = await dist_default5({
9040
+ message: "Target environment:",
9041
+ choices: [
9042
+ { name: "dev", value: "dev" },
9043
+ { name: "staging", value: "staging" },
9044
+ { name: "prod", value: "prod" }
9045
+ ]
9046
+ });
9047
+ const envResult = await validateEnvVars(outputDir);
9048
+ if (!envResult.ok) {
9049
+ blank();
9050
+ error("Missing required environment variables for local publish:");
9051
+ for (const key of envResult.missing) {
9052
+ info(` • ${key}`);
9053
+ }
9054
+ blank();
9055
+ info("Add them to a .env file in your project root, or export them in your shell.");
9056
+ info("Example .env:");
9057
+ blank();
9058
+ for (const key of REQUIRED_ENV_VARS) {
9059
+ info(` ${key}=your-value-here`);
9060
+ }
9061
+ blank();
9062
+ process.exit(1);
9063
+ }
9064
+ }
8811
9065
  blank();
8812
9066
  if (bumpType === "keep") {
8813
9067
  info(`Version: ${currentVersion} (unchanged)`);
@@ -8815,6 +9069,7 @@ async function releaseCommand(dir) {
8815
9069
  info(`Version: ${currentVersion} → ${newVersion}`);
8816
9070
  }
8817
9071
  info(`Tag: ${tag}`);
9072
+ info(`Mode: ${publishMode === "local" ? `Local publish → ${environment}` : "CI publish"}`);
8818
9073
  blank();
8819
9074
  const proceed = await dist_default3({
8820
9075
  message: "Proceed with release?",
@@ -8831,9 +9086,28 @@ async function releaseCommand(dir) {
8831
9086
  `, "utf-8");
8832
9087
  success(`Updated manifest.json to ${newVersion}`);
8833
9088
  }
9089
+ if (publishMode === "local") {
9090
+ info("Building mini-app...");
9091
+ try {
9092
+ execFileSync("bun", ["run", "build"], { cwd: outputDir, stdio: "inherit" });
9093
+ success("Build complete.");
9094
+ } catch {
9095
+ error("Build failed. Fix the errors above and retry.");
9096
+ process.exit(1);
9097
+ }
9098
+ info(`Publishing to ${environment}...`);
9099
+ try {
9100
+ execFileSync("npx", ["@aiworkbench/vibe-publish", "-e", environment, "--direct-push", "--app-dir", "."], { cwd: outputDir, stdio: "inherit" });
9101
+ success(`Published to ${environment} registry.`);
9102
+ } catch {
9103
+ error("Publish failed. Fix the error above and retry.");
9104
+ info("Your manifest.json has been updated but no git operations were performed.");
9105
+ process.exit(1);
9106
+ }
9107
+ }
8834
9108
  try {
8835
- git(`add manifest.json`, outputDir);
8836
- git(`commit -m "release: ${tag}"`, outputDir);
9109
+ git(["add", "manifest.json"], outputDir);
9110
+ git(["commit", "-m", `release: ${tag}`], outputDir);
8837
9111
  success(`Committed: release: ${tag}`);
8838
9112
  } catch (err) {
8839
9113
  const msg = err instanceof Error ? err.message : String(err);
@@ -8849,7 +9123,7 @@ async function releaseCommand(dir) {
8849
9123
  }
8850
9124
  }
8851
9125
  try {
8852
- git(`tag ${tag}`, outputDir);
9126
+ git(["tag", tag], outputDir);
8853
9127
  success(`Tagged: ${tag}`);
8854
9128
  } catch (err) {
8855
9129
  const msg = err instanceof Error ? err.message : String(err);
@@ -8862,8 +9136,8 @@ async function releaseCommand(dir) {
8862
9136
  process.exit(1);
8863
9137
  }
8864
9138
  try {
8865
- git(`push`, outputDir);
8866
- git(`push --tags`, outputDir);
9139
+ git(["push"], outputDir);
9140
+ git(["push", "--tags"], outputDir);
8867
9141
  success(`Pushed commit and tag.`);
8868
9142
  } catch (err) {
8869
9143
  const msg = err instanceof Error ? err.message : String(err);
@@ -8874,20 +9148,24 @@ async function releaseCommand(dir) {
8874
9148
  process.exit(1);
8875
9149
  }
8876
9150
  blank();
8877
- success(`Released ${tag} CI will now build and publish your mini-app.`);
8878
- try {
8879
- const remoteUrl = git("remote get-url origin", outputDir);
8880
- const globalConfig = await loadGlobalConfig();
8881
- const host = globalConfig.githubHost ?? "github.com";
8882
- const repo = parseGitHubRepo(remoteUrl, host);
8883
- if (repo) {
8884
- blank();
8885
- info(`Check CI progress: https://${host}/${repo}/actions`);
8886
- if (globalConfig.registryRepo) {
8887
- info(`After CI completes, your app will appear in: https://${host}/${globalConfig.registryRepo}`);
9151
+ if (publishMode === "local") {
9152
+ success(`Released ${tag} — published locally to ${environment} registry.`);
9153
+ } else {
9154
+ success(`Released ${tag} CI will now build and publish your mini-app.`);
9155
+ try {
9156
+ const remoteUrl = git(["remote", "get-url", "origin"], outputDir);
9157
+ const globalConfig = await loadGlobalConfig();
9158
+ const host = globalConfig.githubHost ?? "github.com";
9159
+ const repo = parseGitHubRepo(remoteUrl, host);
9160
+ if (repo) {
9161
+ blank();
9162
+ info(`Check CI progress: https://${host}/${repo}/actions`);
9163
+ if (globalConfig.registryRepo) {
9164
+ info(`After CI completes, your app will appear in: https://${host}/${globalConfig.registryRepo}`);
9165
+ }
8888
9166
  }
8889
- }
8890
- } catch {}
9167
+ } catch {}
9168
+ }
8891
9169
  blank();
8892
9170
  }
8893
9171
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiworkbench/vibe-cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },