babavoss 0.12.6 → 0.13.1

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 (62) hide show
  1. package/gui/babavoss-web.js +4 -1
  2. package/gui/{chunk-9gmmm54v.js → chunk-qgzmajan.js} +619 -574
  3. package/gui/gui.js +1538 -277
  4. package/gui/theme.css +2007 -1128
  5. package/index.ts +1 -1
  6. package/package.json +5 -5
  7. package/src/{promptware → agents}/compile.ts +23 -31
  8. package/src/{promptware → agents}/define.ts +2 -2
  9. package/src/{promptware → agents}/disk.ts +7 -4
  10. package/src/{promptware → agents}/sync.ts +2 -2
  11. package/src/{promptware → agents}/system.ts +17 -17
  12. package/src/baba/check.ts +3 -3
  13. package/src/baba/config.ts +5 -2
  14. package/src/baba/init.ts +13 -18
  15. package/src/baba/node.ts +2 -2
  16. package/src/baba/project.ts +2 -2
  17. package/src/baba/requirements.ts +39 -0
  18. package/src/baba/setup.ts +30 -0
  19. package/src/baba/worker.ts +13 -5
  20. package/src/build/mdx.ts +4 -4
  21. package/src/build/project.ts +6 -1
  22. package/src/build/views.ts +3 -3
  23. package/src/desktop/desktop.css +35 -39
  24. package/src/desktop/index.ts +9 -7
  25. package/src/desktop/keys.ts +153 -0
  26. package/src/desktop/view.tsx +174 -130
  27. package/src/door/core.ts +2 -2
  28. package/src/ecs/baba.ts +27 -17
  29. package/src/generated/build.ts +1 -1
  30. package/src/gui/gui.tsx +21 -31
  31. package/src/gui/index.ts +6 -2
  32. package/src/gui/{promptware.tsx → instructions.tsx} +12 -12
  33. package/src/gui/levels.tsx +241 -59
  34. package/src/gui/lockup.ts +11 -0
  35. package/src/gui/settings.tsx +241 -0
  36. package/src/gui/setup.tsx +77 -0
  37. package/src/gui/theme.css +205 -58
  38. package/src/gui/theme.ts +9 -5
  39. package/src/gui/voss-settings.ts +48 -0
  40. package/src/gui/wizard.tsx +17 -40
  41. package/src/guide/add-a-desktop.mdx +7 -7
  42. package/src/guide/index.ts +4 -4
  43. package/src/guide/write-a-system.mdx +3 -3
  44. package/src/guide/{write-promptware.mdx → write-agentic-instructions.mdx} +17 -24
  45. package/src/http/server.ts +140 -17
  46. package/src/{prompt → instructions}/evals.ts +1 -1
  47. package/src/{prompt → instructions}/index.ts +9 -8
  48. package/src/{prompt → instructions}/jsx-runtime.ts +3 -3
  49. package/src/mcp/main.ts +3 -3
  50. package/src/mcp/tools.ts +4 -4
  51. package/src/runtime/harness.ts +2 -2
  52. package/src/server/edge.ts +31 -3
  53. package/src/server/main.ts +2 -1
  54. package/src/server/messages.ts +47 -7
  55. package/src/shell/run.ts +18 -18
  56. package/src/spec/index.ts +1 -1
  57. package/src/web/core.tsx +2 -2
  58. package/src/web/index.tsx +1 -1
  59. package/src/desktop/bob.ts +0 -76
  60. /package/src/{promptware → agents}/markdown.d.ts +0 -0
  61. /package/src/{prompt → instructions}/jsx-dev-runtime.ts +0 -0
  62. /package/src/{prompt → instructions}/mdx.d.ts +0 -0
@@ -6,7 +6,7 @@ import { manifestOf, type Baba } from "../ecs/baba.ts";
6
6
  import { Runtime, ContractError } from "../ecs/runtime.ts";
7
7
  import { StateError, type Snapshot } from "../ecs/state.ts";
8
8
  import { makeBridge, portOver } from "./bridge.ts";
9
- import { withPromptware } from "../promptware/system.ts";
9
+ import { withInstructions } from "../agents/system.ts";
10
10
 
11
11
  /** How long a `state` read waits for the round past `since` before answering the state as it is. */
12
12
  export const STATE_WAIT_MS = 25_000;
@@ -23,7 +23,7 @@ export class Harness {
23
23
  /** Loads the baba over the snapshot given; answers `loaded`, or throws for `failed`. */
24
24
  load(own: Baba, project: { name: string; dir: string; baba: string }, env: Record<string, string>, snapshot: Snapshot | null, prepare = false): void {
25
25
  // Voss's own systems join every baba after its own.
26
- const v = withPromptware(own);
26
+ const v = withInstructions(own);
27
27
  const manifest = manifestOf(v);
28
28
  const make = (snapshot: Snapshot | null, auto: boolean) => new Runtime(v, {
29
29
  auto,
@@ -5,13 +5,13 @@
5
5
  // same socket, in order. No file, no project, no Node here: only memory and IPC.
6
6
  import { isIP } from "node:net";
7
7
  import type { Server, ServerWebSocket, WebSocketHandler } from "bun";
8
- import type { Serve, Described, Failure, Describe, DescribeAnswer, View, ViewAnswer, Call, CallAnswer, Refresh, RefreshAnswer, Restart, RestartAnswer, Browse, BrowseAnswer, Add, AddAnswer } from "./messages.ts";
8
+ import type { Serve, Described, Failure, Describe, DescribeAnswer, View, ViewAnswer, Call, CallAnswer, Refresh, RefreshAnswer, Restart, RestartAnswer, Browse, BrowseAnswer, Add, AddAnswer, Remove, Setup, SetSettings, SettingsAnswer, Rename } from "./messages.ts";
9
9
  import type { Raw } from "../ecs/runtime.ts";
10
10
  import type { Json } from "../kernel/schema.ts";
11
11
  import { frameHeader, resolveInterest, sliceFrame, type Resolved } from "../ecs/codec.ts";
12
12
  import { CLOSE, SOCKET_PROTOCOL, type Down, type Interest, type Up } from "./protocol.ts";
13
13
 
14
- interface Pairs { describe: [Describe, DescribeAnswer]; view: [View, ViewAnswer]; call: [Call, CallAnswer]; refresh: [Refresh, RefreshAnswer]; restart: [Restart, RestartAnswer]; browse: [Browse, BrowseAnswer]; add: [Add, AddAnswer] }
14
+ interface Pairs { describe: [Describe, DescribeAnswer]; view: [View, ViewAnswer]; call: [Call, CallAnswer]; refresh: [Refresh, RefreshAnswer]; restart: [Restart, RestartAnswer]; browse: [Browse, BrowseAnswer]; add: [Add, AddAnswer]; remove: [Remove, AddAnswer]; setup: [Setup, AddAnswer]; "set-settings": [SetSettings, SettingsAnswer]; rename: [Rename, AddAnswer] }
15
15
  type Unnumbered<T> = T extends unknown ? Omit<T, "id"> : never;
16
16
  /** Sends a request to the kernel, numbered by the sender, and resolves with its answer. */
17
17
  export type Ask = <K extends keyof Pairs>(m: Unnumbered<Pairs[K][0]>) => Promise<Pairs[K][1]>;
@@ -294,7 +294,35 @@ export function edge(state: Serve, ask: Ask): Edge {
294
294
  const a = await ask<"add">({ type: "add", dir: body.dir, init: body.init === true, ...(typeof body.name === "string" && body.name ? { name: body.name } : {}), ...(typeof body.title === "string" && body.title ? { title: body.title } : {}) });
295
295
  return a.ok ? json(a.value) : failed(a);
296
296
  }
297
- if (parts[1] === "projects") return json({ projects: state.projects, voss: state.voss, home: state.home });
297
+ // /api/projects/remove: forget a folder, its files kept. /api/projects/setup: set what voss requires of the folder's baba, making its .baba first when there is none.
298
+ if (parts[1] === "projects" && (parts[2] === "remove" || parts[2] === "setup") && parts.length === 3) {
299
+ if (req.method !== "POST") return json({ error: { code: "notfound", message: "no such route" } }, 404);
300
+ let body: { dir?: unknown; values?: unknown } = {};
301
+ try { body = await req.json() as typeof body; } catch { return json({ error: { code: "args", message: "the body is not JSON" } }, 400); }
302
+ if (typeof body.dir !== "string" || !body.dir) return json({ error: { code: "args", message: "dir: the folder, absolute" } }, 400);
303
+ if (parts[2] === "remove") { const a = await ask<"remove">({ type: "remove", dir: body.dir }); return a.ok ? json(a.value) : failed(a); }
304
+ const v = (typeof body.values === "object" && body.values ? body.values : {}) as Record<string, unknown>;
305
+ const a = await ask<"setup">({ type: "setup", dir: body.dir, values: typeof v.name === "string" ? { name: v.name } : {} });
306
+ return a.ok ? json(a.value) : failed(a);
307
+ }
308
+ // /api/projects/rename: a baba under another name, its address moving with it.
309
+ if (parts[1] === "projects" && parts[2] === "rename" && parts.length === 3) {
310
+ if (req.method !== "POST") return json({ error: { code: "notfound", message: "no such route" } }, 404);
311
+ let body: { name?: unknown; to?: unknown } = {};
312
+ try { body = await req.json() as typeof body; } catch { return json({ error: { code: "args", message: "the body is not JSON" } }, 400); }
313
+ if (typeof body.name !== "string" || typeof body.to !== "string") return json({ error: { code: "args", message: "name: the baba's name now; to: the name it takes" } }, 400);
314
+ const a = await ask<"rename">({ type: "rename", name: body.name, to: body.to });
315
+ return a.ok ? json(a.value) : failed(a);
316
+ }
317
+ if (parts[1] === "projects") return json({ projects: state.projects, pending: state.pending, voss: state.voss, home: state.home });
318
+ // /api/settings: voss's own settings, the person's; a POST changes them, `keys` naming commands with a binding or null for the default.
319
+ if (parts[1] === "settings" && parts.length === 2) {
320
+ if (req.method !== "POST") return json(state.settings);
321
+ let body: { theme?: unknown; keys?: unknown } = {};
322
+ try { body = await req.json() as typeof body; } catch { return json({ error: { code: "args", message: "the body is not JSON" } }, 400); }
323
+ const a = await ask<"set-settings">({ type: "set-settings", ...(typeof body.theme === "string" ? { theme: body.theme as SetSettings["theme"] & string } : {}), ...(body.keys && typeof body.keys === "object" ? { keys: body.keys as SetSettings["keys"] } : {}) });
324
+ return a.ok ? json(a.value) : failed(a);
325
+ }
298
326
  // /api/dirs?path=: the directories under one, for picking where a baba is or goes.
299
327
  if (parts[1] === "dirs" && parts.length === 2) {
300
328
  const a = await ask<"browse">({ type: "browse", path: url.searchParams.get("path") ?? "" });
@@ -34,8 +34,9 @@ kernel.onMessage((m) => {
34
34
  return;
35
35
  }
36
36
  // The edge reads the projects and pages from the served state on every request.
37
- if (m.type === "projects") { if (served) { served.projects = m.projects; served.pages = m.pages; } return; }
37
+ if (m.type === "projects") { if (served) { served.projects = m.projects; served.pending = m.pending; served.pages = m.pages; } return; }
38
38
  if (m.type === "voss") { if (served) served.voss = m.voss; return; }
39
+ if (m.type === "settings") { if (served) served.settings = m.settings; return; }
39
40
  if (m.type === "round") { live?.push(m.name, m.round, m.frame); return; }
40
41
  if (m.type === "generation") { live?.generation(m.name, m.gen); return; }
41
42
  const resolve = pending.get(m.id);
@@ -4,6 +4,9 @@
4
4
  import type { Described } from "../baba/node.ts";
5
5
  import type { Raw } from "../ecs/runtime.ts";
6
6
  import type { Interest } from "./protocol.ts";
7
+ import type { Requirement, RequirementValues } from "../baba/requirements.ts";
8
+ import type { Theme } from "../desktop/index.ts";
9
+ import type { KeyChanges, KeyOverrides } from "../desktop/keys.ts";
7
10
 
8
11
  // ---- kernel → server ---------------------------------------------------
9
12
 
@@ -14,6 +17,20 @@ export interface Voss {
14
17
  kept: boolean;
15
18
  stale: boolean;
16
19
  installed: { version: string; sha: string; at: string } | null;
20
+ /** Where this voss is and what it runs on, for the settings' About page. */
21
+ about?: About;
22
+ }
23
+ /** Where a running voss is and what it runs on: its runtime, the package it runs from, the state it keeps, the service that keeps it running. */
24
+ export interface About {
25
+ /** When this voss started, ISO. */
26
+ started: string;
27
+ runtime: { bun: string; platform: string; arch: string; executable: string };
28
+ /** The framework's package directory, and the CLI it was started with. */
29
+ framework: string; cli: string;
30
+ /** voss's own state: its root, the registry of babas, the page token. */
31
+ root: string; registry: string; token: string;
32
+ /** The user service's file and log, when one is installed; null otherwise. */
33
+ service: { file: string; log: string } | null;
17
34
  }
18
35
 
19
36
  /** Everything the server holds, sent once: it listens when this arrives. */
@@ -24,6 +41,10 @@ export interface Serve {
24
41
  token: string;
25
42
  voss: Voss;
26
43
  projects: ProjectEntry[];
44
+ /** The folders voss remembers that it does not run: each to be set up, or failed. */
45
+ pending: PendingEntry[];
46
+ /** The person's settings, voss-wide: what every baba's pages look like and the keys they run. */
47
+ settings: VossSettings;
27
48
  /** The user's home directory: the picker writes paths under it as ~/… and starts browsing there. */
28
49
  home: string;
29
50
  /** The page per scope: "" is the picker's, a project's name its own. The token meta is already in. */
@@ -34,6 +55,13 @@ export interface Serve {
34
55
 
35
56
  /** A registered project; `parent` is the nearest registered project whose directory holds it, for nesting. */
36
57
  export interface ProjectEntry { name: string; title: string; dir: string; parent: string | null }
58
+ /**
59
+ * A folder voss remembers but does not run. To be set up when it lacks a required property, a .baba among them:
60
+ * `missing` names them, and the picker opens its wizard. Failed when it has them all and still does not open: `error` says why.
61
+ */
62
+ export interface PendingEntry { dir: string; baba: boolean; missing: Requirement[]; error: string | null; parent: string | null }
63
+ /** voss's own settings, the person's, kept in its root's settings.json: the theme of every page, the keys remapped on every desktop. */
64
+ export interface VossSettings { theme: Theme; keys?: KeyOverrides }
37
65
  export interface Asset { mime: string; bytes: Uint8Array<ArrayBuffer> }
38
66
 
39
67
  export type { Described };
@@ -48,9 +76,9 @@ export type ViewAnswer = { type: "view-answer"; id: number } & ({ ok: true; gen:
48
76
  export type CallAnswer = { type: "call-answer"; id: number } & ({ ok: true; value: unknown; /** The round a fire or a raw write ran in. */ round?: number } | Failure);
49
77
 
50
78
  /** The registry changed: the projects and their pages, replacing what `serve` sent. */
51
- export interface Projects { type: "projects"; projects: ProjectEntry[]; pages: Record<string, string> }
52
- /** What a refresh did: the projects now open, and the directories that did not load, with why. */
53
- export interface Refreshed { projects: ProjectEntry[]; errors: { dir: string; error: string }[] }
79
+ export interface Projects { type: "projects"; projects: ProjectEntry[]; pending: PendingEntry[]; pages: Record<string, string> }
80
+ /** What a refresh did: the projects now open, the folders remembered but not run, and the directories that did not load, with why. */
81
+ export interface Refreshed { projects: ProjectEntry[]; pending: PendingEntry[]; errors: { dir: string; error: string }[] }
54
82
  export type RefreshAnswer = { type: "refresh-answer"; id: number } & ({ ok: true; value: Refreshed } | Failure);
55
83
 
56
84
  /** A round of a project's live generation, as the frame every window of it gets. */
@@ -58,16 +86,19 @@ export interface RoundPush { type: "round"; name: string; round: number; frame:
58
86
  /** A project's generation advanced: its windows re-read the contract and resync. */
59
87
  export interface Generation { type: "generation"; name: string; gen: number }
60
88
 
89
+ /** voss's settings changed: the edge answers with these from now on. */
90
+ export interface SettingsPush { type: "settings"; settings: VossSettings }
91
+ export type SettingsAnswer = { type: "settings-answer"; id: number } & ({ ok: true; value: VossSettings } | Failure);
61
92
  /** Voss's own standing changed: a newer one is installed. */
62
93
  export interface VossPush { type: "voss"; voss: Voss }
63
94
  export type RestartAnswer = { type: "restart-answer"; id: number } & ({ ok: true; value: { restarting: true; kept: boolean } } | Failure);
64
95
  /** A directory and what is under it: each child, whether it holds a baba, and whether it is already remembered. */
65
96
  export interface Browsed { path: string; home: string; parent: string | null; baba: boolean; known: boolean; dirs: { name: string; path: string; baba: boolean; known: boolean }[] }
66
97
  export type BrowseAnswer = { type: "browse-answer"; id: number } & ({ ok: true; value: Browsed } | Failure);
67
- /** What an add did: the project made or remembered, and the registry re-read. */
68
- export type AddAnswer = { type: "add-answer"; id: number } & ({ ok: true; value: Refreshed & { name: string; dir: string } } | Failure);
98
+ /** What an add, a setup or a removal did: the folder, the baba's name when it runs, and the registry re-read. */
99
+ export type AddAnswer = { type: "add-answer"; id: number } & ({ ok: true; value: Refreshed & { name: string | null; dir: string } } | Failure);
69
100
 
70
- export type ToServer = Serve | Projects | VossPush | DescribeAnswer | ViewAnswer | CallAnswer | RefreshAnswer | RestartAnswer | BrowseAnswer | AddAnswer | RoundPush | Generation;
101
+ export type ToServer = Serve | Projects | VossPush | SettingsPush | DescribeAnswer | ViewAnswer | CallAnswer | RefreshAnswer | RestartAnswer | BrowseAnswer | AddAnswer | SettingsAnswer | RoundPush | Generation;
71
102
 
72
103
  // ---- server → kernel ---------------------------------------------------
73
104
 
@@ -93,5 +124,14 @@ export interface Restart { type: "restart"; id: number }
93
124
  export interface Browse { type: "browse"; id: number; path: string }
94
125
  /** Remember a project at `dir`; with `init`, make its .baba first, named and titled as given or after the directory. */
95
126
  export interface Add { type: "add"; id: number; dir: string; init: boolean; name?: string; title?: string }
127
+ /** Forget the folder at `dir`: voss stops running its baba; its files stay. */
128
+ export interface Remove { type: "remove"; id: number; dir: string }
129
+ /** Set the required properties of the folder at `dir`, making its .baba first when it has none; then it runs. */
130
+ export interface Setup { type: "setup"; id: number; dir: string; values: RequirementValues }
131
+
132
+ /** Change voss's settings: the theme, keys remapped or given back their defaults. */
133
+ export interface SetSettings { type: "set-settings"; id: number; theme?: Theme; keys?: KeyChanges }
134
+ /** Rename the baba called `name`: its address moves to `/TO/`, and it runs again under it. */
135
+ export interface Rename { type: "rename"; id: number; name: string; to: string }
96
136
 
97
- export type FromServer = Ready | Listening | Failed | Describe | View | Call | Refresh | Restart | Browse | Add;
137
+ export type FromServer = Ready | Listening | Failed | Describe | View | Call | Refresh | Restart | Browse | Add | Remove | Setup | SetSettings | Rename;
package/src/shell/run.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  // voss baba follow ENTITY | COMPONENT KEY [--until C | C.field=value] [--for 30s] [--changes]
10
10
  // voss baba follow QUERY [args…] --changed [--for 30s]
11
11
  // voss baba run [FILE | LINE …] | raw spawn JSON | add E COMPONENT [JSON] | remove E COMPONENT … | despawn E | set RESOURCE JSON
12
- // voss baba check | install | add-system NAME | promptware … | serve [HOST:PORT]
12
+ // voss baba check | install | add-system NAME | agents … | serve [HOST:PORT]
13
13
  // voss init [DIR] | babas … | gui [HOST:PORT] | service …
14
14
  //
15
15
  // Stdout is one line of JSON per answer (`--pretty` indents it); stderr is
@@ -30,8 +30,8 @@ import { serve } from "../http/server.ts";
30
30
  import { words, callArgs, usage, describeArgs, UsageError } from "./args.ts";
31
31
  import { init, install, addSystem } from "../baba/init.ts";
32
32
  import { check } from "../baba/check.ts";
33
- import { planProject, syncProject, outputOf, sources } from "../promptware/disk.ts";
34
- import { report } from "../promptware/sync.ts";
33
+ import { planProject, syncProject, outputOf, sources } from "../agents/disk.ts";
34
+ import { report } from "../agents/sync.ts";
35
35
  import * as service from "./service.ts";
36
36
  import { connect, daemon, type Client, type Daemon } from "./client.ts";
37
37
  import { runMcp } from "../mcp/main.ts";
@@ -131,7 +131,7 @@ const builtinHelp: Record<string, string> = {
131
131
  "add-system": "a system under .baba/systems/NAME: add-system NAME",
132
132
  serve: "the GUI for this baba alone: serve [HOST:PORT]",
133
133
  mcp: "an MCP server over stdio for agents, a client of the running voss",
134
- promptware: "the harness files: promptware compile | sync | output PATH",
134
+ agents: "the agentic instructions compiled: agents compile | sync | output PATH",
135
135
  };
136
136
 
137
137
  /**
@@ -177,7 +177,7 @@ function globals(argv: string[]): { ws: string[]; pretty: boolean; max: number }
177
177
 
178
178
  export async function run(argv: string[], sh: Shell): Promise<number> {
179
179
  const reg = new Registry(sh.rootDir);
180
- // Every answer is JSON; the promptware block below still reads this.
180
+ // Every answer is JSON; the agentic instructions block below still reads this.
181
181
  const json = true;
182
182
  let callUsage: string | undefined;
183
183
  let outDir: string | undefined;
@@ -304,7 +304,7 @@ export async function run(argv: string[], sh: Shell): Promise<number> {
304
304
  }
305
305
  if (name === "manifest") {
306
306
  // The baba loaded once, in this process, and let go: what every load writes, .baba/.voss/manifest.json, is there
307
- // for the index, --schema and the promptware before the baba ever runs under the daemon, as in a fresh worktree.
307
+ // for the index, --schema and the agentic instructions before the baba ever runs under the daemon, as in a fresh worktree.
308
308
  const lines: string[] = [];
309
309
  const n = new Node(project, (l) => lines.push(l));
310
310
  try { await n.start(); } finally { await n.stop(); }
@@ -345,36 +345,36 @@ export async function run(argv: string[], sh: Shell): Promise<number> {
345
345
  const c = await connect(project, sh.rootDir, prog).catch(downOnly);
346
346
  const down = c instanceof NodeError ? c : null;
347
347
  const d = c instanceof NodeError ? null : await c.describe();
348
- // Down, the promptware compiles from a manifest of the code as it is now: the baba is loaded once in this process and let
349
- // go, as \`manifest\` does, so a fresh worktree has one and an edit to the promptware is in it. Busy or broken, the last one stands.
348
+ // Down, the agentic instructions compiles from a manifest of the code as it is now: the baba is loaded once in this process and let
349
+ // go, as \`manifest\` does, so a fresh worktree has one and an edit to the agentic instructions is in it. Busy or broken, the last one stands.
350
350
  let loadError: string | null = null;
351
- if (down && name === "promptware") {
351
+ if (down && name === "agents") {
352
352
  const n = new Node(project, () => {});
353
353
  try { await n.start(); } catch (err) { loadError = err instanceof Error ? err.message : String(err); } finally { await n.stop().catch(() => {}); }
354
354
  }
355
355
  const m = d ? d.manifest : await readManifest(project);
356
356
  if (!m && loadError) throw new ShellError("failed", `${project.name} did not load: ${loadError}`);
357
357
  if (!m) { if (down) throw down; throw new ShellError("down", `${project.name} is not running${d?.error ? `: ${d.error}` : ""}`); }
358
- if (name === "promptware") {
359
- // Running, the baba's promptware system syncs, and the answer waits for it; down, the same compiler runs here over the files.
358
+ if (name === "agents") {
359
+ // Running, the baba's agents system syncs, and the answer waits for it; down, the same compiler runs here over the files.
360
360
  const [cmd, path] = args;
361
- if (cmd === "sync" && d && !d.error && "promptware-sync" in m.actions) {
361
+ if (cmd === "sync" && d && !d.error && "agents-sync" in m.actions) {
362
362
  const live = c as Client;
363
- const syncs = async () => await live.read("promptware-plan", {}) as { syncs: number; error: string | null };
363
+ const syncs = async () => await live.read("agents-plan", {}) as { syncs: number; error: string | null };
364
364
  const before = (await syncs()).syncs;
365
- await live.fire("promptware-sync", {});
365
+ await live.fire("agents-sync", {});
366
366
  for (let i = 0; i < 200; i++) {
367
367
  const p = await syncs();
368
- if (p.syncs > before) { if (p.error) return fail(`promptware sync: ${p.error}`); out(p); return 0; }
368
+ if (p.syncs > before) { if (p.error) return fail(`agents sync: ${p.error}`); out(p); return 0; }
369
369
  await new Promise((r) => setTimeout(r, 50));
370
370
  }
371
- return fail("promptware sync: asked, not finished within 10s; promptware-plan says how it went");
371
+ return fail("agents sync: asked, not finished within 10s; agents-plan says how it went");
372
372
  }
373
373
  const input = sources(project.dir, m, project.title);
374
374
  if (cmd === "compile") { out(report(await planProject(project.dir, input))); return 0; }
375
375
  if (cmd === "sync") { out(await syncProject(project.dir, input)); return 0; }
376
376
  if (cmd === "output" && path) { const o = await outputOf(project.dir, input, path); out(json ? o : { path: o.path, status: o.status }); if (!json) sh.stdout(o.text); return 0; }
377
- sh.stdout(`Usage: ${prog} promptware compile | sync | output PATH\n`);
377
+ sh.stdout(`Usage: ${prog} agents compile | sync | output PATH\n`);
378
378
  return help ? 0 : 2;
379
379
  }
380
380
  if (!name) {
@@ -462,7 +462,7 @@ function contract(prog: string, title: string, m: Manifest, error: string | null
462
462
  section("Resources", Object.entries(m.resources).map(([n, r]) => [n, r.owner]));
463
463
  section("Effects", Object.entries(m.effects).map(([n, e]) => [n, `${e.owner}${e.every ? ` · every ${e.every} ms` : ""}${e.retry ? ` · retry ${e.retry} ms` : ""}${e.summary ? ` · ${e.summary}` : ""}`]));
464
464
  section("The state", Object.entries(builtinHelp).filter(([k]) => ["state", "follow", "run", "raw"].includes(k)).map(([k, h]) => [k, h]));
465
- section("Voss", Object.entries(builtinHelp).filter(([k]) => ["start", "stop", "status", "mcp", "check", "manifest", "install", "add-system", "serve", "promptware"].includes(k)).map(([k, h]) => [k, h]));
465
+ section("Voss", Object.entries(builtinHelp).filter(([k]) => ["start", "stop", "status", "mcp", "check", "manifest", "install", "add-system", "serve", "agents"].includes(k)).map(([k, h]) => [k, h]));
466
466
  lines.push(`State: ${where}${error ? ` · the last load failed: ${error}` : ""}`);
467
467
  return lines.join("\n") + "\n";
468
468
  }
package/src/spec/index.ts CHANGED
@@ -91,7 +91,7 @@ export function spec(target: System | Baba, def: SpecDef<any, any> = {}): Spec<a
91
91
  if (!NAME.test(name)) throw new Error(`spec ${JSON.stringify(name)}: lowercase words joined by single dashes`);
92
92
  const base = whole ? (target as Baba) : baba({ systems: closureOf([target as System]) });
93
93
  const tick = def.tick === undefined ? base.tick : def.tick;
94
- const v = tick === base.tick ? base : baba({ systems: base.systems, ...(tick !== null ? { tick } : {}), promptware: base.promptware, apps: base.apps });
94
+ const v = tick === base.tick ? base : baba({ systems: base.systems, ...(tick !== null ? { tick } : {}), instructions: base.instructions, apps: base.apps });
95
95
  const names = new Set<string>();
96
96
  for (const sc of def.scenarios ?? []) { if (names.has(sc.name)) throw new Error(`spec ${name}: two scenarios are named ${JSON.stringify(sc.name)}`); names.add(sc.name); }
97
97
  const also = def.also ?? [];
package/src/web/core.tsx CHANGED
@@ -47,7 +47,7 @@ function routed(key: string, table: RouteTable): ComponentType<AppProps> {
47
47
  * the baba declares in `baba({ apps })`, and none other; the keys are checked against them. An app that
48
48
  * declares routes may be given a component per route instead, `{ "/": Prs, "/pr/:n": Pr }`, checked
49
49
  * against its routes: every route, none other. One of voss's own apps, `maker`, `state`, `contract`,
50
- * `promptware`, `settings`, may be given a component of the baba's to replace voss's.
50
+ * `agentic instructions`, `settings`, may be given a component of the baba's to replace voss's.
51
51
  * The old form, `compose({ shell })`, still loads.
52
52
  */
53
53
  export function compose<V extends { $app: string }>(def: { apps: { [K in V["$app"]]: EntryFor<RoutesFor<V, K>> } & { [K in VossApp]?: ComponentType<AppProps> } }): AppsDef;
@@ -111,7 +111,7 @@ export async function api(kind: "fire" | "read" | "state" | "raw", scope: string
111
111
  * The baba's manifest, as the server describes it: null until it arrives.
112
112
  * Asked once, then asked again "since the generation I have", so the answer
113
113
  * comes when the baba reloads: a page that draws the manifest, the Maker's
114
- * objects or the promptware, follows a change to the code as the state
114
+ * objects or the agentic instructions, follows a change to the code as the state
115
115
  * follows a round. A baba that is down is asked again in a moment.
116
116
  */
117
117
  export function useManifest(): Manifest | null {
package/src/web/index.tsx CHANGED
@@ -14,4 +14,4 @@ export { formatFailure, placeOf, type ViewFailure, type Stage as FailureStage }
14
14
  export { Button, Input, Textarea, Select, Kbd, Panel, Rows, Row, Table, Dialog, CommandList, type ButtonVariant } from "./ui.tsx";
15
15
  export { plan, collect, tableOf, describeType, FieldError, type Plan, type Field, type Values } from "./form.ts";
16
16
  export { filterItems, type Item } from "./list.ts";
17
- export { Desktop, DesktopFrame, SpecDesktop, LocalDesktop, Eyes, AppIcon, desktopAddress, parseDesktopAddress, parseDesktopHash, routeOf, type DesktopProps, type AppProps, type SurfaceProps } from "../desktop/view.tsx";
17
+ export { Desktop, DesktopFrame, DesktopSkeleton, SpecDesktop, LocalDesktop, Eyes, AppIcon, desktopAddress, parseDesktopAddress, parseDesktopHash, routeOf, type DesktopProps, type LauncherMode, type AppProps, type SurfaceProps } from "../desktop/view.tsx";
@@ -1,76 +0,0 @@
1
- // The launcher's dot as a body on a string: a point with a velocity, moved by
2
- // a small simulation rather than by CSS transitions, so a fall can gather
3
- // speed, the string can catch it, and a new aim mid-flight keeps the momentum.
4
- // The page says where the dot should be (`aim`); the bob decides how it gets
5
- // there and draws itself and its string on every frame until it rests.
6
-
7
- export interface Point { x: number; y: number }
8
- /** A spring toward the aim: stiffness pulls, damping calms. Below critical damping (2√stiffness) it overshoots. */
9
- export interface Spring { stiffness: number; damping: number }
10
- /** Falling: gravity until the string is taut. Caught: the string springs it to rest. Gliding: a spring between rows. */
11
- export type Phase = "falling" | "caught" | "gliding";
12
- export interface BobState { at: Point; v: Point; phase: Phase }
13
-
14
- /** Pixels per second squared: a fall of a few rows lasts about a tenth of a second. */
15
- export const gravity = 9000;
16
- /** The string catching the fall: stiff and loose, so it bounces. */
17
- export const catchSpring: Spring = { stiffness: 1400, damping: 28 };
18
- /** Moving between rows: quick, with a small overshoot. */
19
- export const glideSpring: Spring = { stiffness: 1100, damping: 40 };
20
- /** Sideways onto the string's vertical, while falling. */
21
- export const swingSpring: Spring = { stiffness: 1600, damping: 56 };
22
-
23
- const axis = (at: number, v: number, to: number, s: Spring, dt: number) => {
24
- const a = s.stiffness * (to - at) - s.damping * v;
25
- const nv = v + a * dt;
26
- return [at + nv * dt, nv] as const;
27
- };
28
-
29
- /** One step of the simulation. A falling bob is pulled down by gravity until it reaches the aim, where the string goes taut and catches it. */
30
- export function step(s: BobState, aim: Point, dt: number): BobState {
31
- const [x, vx] = axis(s.at.x, s.v.x, aim.x, s.phase === "gliding" ? glideSpring : swingSpring, dt);
32
- if (s.phase === "falling") {
33
- const vy = s.v.y + gravity * dt, y = s.at.y + vy * dt;
34
- return y < aim.y ? { at: { x, y }, v: { x: vx, y: vy }, phase: "falling" } : { at: { x, y: aim.y }, v: { x: vx, y: vy }, phase: "caught" };
35
- }
36
- const [y, vy] = axis(s.at.y, s.v.y, aim.y, s.phase === "caught" ? catchSpring : glideSpring, dt);
37
- return { at: { x, y }, v: { x: vx, y: vy }, phase: s.phase };
38
- }
39
-
40
- /** Whether a bob has come to rest at its aim. */
41
- export const resting = (s: BobState, aim: Point) => s.phase !== "falling" && Math.abs(s.at.x - aim.x) < .05 && Math.abs(s.at.y - aim.y) < .05 && Math.hypot(s.v.x, s.v.y) < 2;
42
-
43
- /** Runs a bob on animation frames and draws it with `draw`; it sleeps while at rest. */
44
- export class Bob {
45
- private state: BobState | null = null;
46
- private aim: Point = { x: 0, y: 0 };
47
- private frame = 0;
48
- private last = 0;
49
- constructor(private draw: (at: Point) => void, private still = () => false) {}
50
- /** Starts a fall from a point, from rest. */
51
- drop(from: Point) { this.state = { at: { ...from }, v: { x: 0, y: 0 }, phase: "falling" }; this.draw(from); this.wake(); }
52
- /** Where the dot should be. With `now`, it is there at once (a scroll moves it with the list). */
53
- to(aim: Point, now = false) {
54
- const moved = Math.abs(aim.y - this.aim.y) > .5;
55
- this.aim = aim;
56
- if (!this.state || now || this.still()) { this.state = { at: { ...aim }, v: { x: 0, y: 0 }, phase: "gliding" }; this.draw(aim); return; }
57
- // A new aim after the catch is a move between rows; a fall keeps falling toward it.
58
- if (this.state.phase === "caught" && moved) this.state = { ...this.state, phase: "gliding" };
59
- this.wake();
60
- }
61
- stop() { cancelAnimationFrame(this.frame); this.frame = 0; this.state = null; }
62
- private wake() {
63
- if (this.frame) return;
64
- this.last = performance.now();
65
- const tick = (now: number) => {
66
- // Fixed small steps keep a stiff spring stable on a slow frame.
67
- let left = Math.min(.05, (now - this.last) / 1000); this.last = now;
68
- while (left > 0 && this.state) { const dt = Math.min(left, 1 / 240); this.state = step(this.state, this.aim, dt); left -= dt; }
69
- if (!this.state) { this.frame = 0; return; }
70
- if (resting(this.state, this.aim)) { this.state = { at: { ...this.aim }, v: { x: 0, y: 0 }, phase: "gliding" }; this.draw(this.aim); this.frame = 0; return; }
71
- this.draw(this.state.at);
72
- this.frame = requestAnimationFrame(tick);
73
- };
74
- this.frame = requestAnimationFrame(tick);
75
- }
76
- }
File without changes
File without changes
File without changes