iterate 0.2.7 → 0.4.0

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 (73) hide show
  1. package/README.md +173 -81
  2. package/dist/api.d.ts +643 -0
  3. package/dist/api.mjs +0 -0
  4. package/dist/app-server.d.ts +51 -0
  5. package/dist/app-server.mjs +481 -0
  6. package/dist/app-server.mjs.map +1 -0
  7. package/dist/app-session.d.ts +49 -0
  8. package/dist/app-session.mjs +235 -0
  9. package/dist/app-session.mjs.map +1 -0
  10. package/dist/app.d.ts +29 -0
  11. package/dist/app.mjs +180 -0
  12. package/dist/app.mjs.map +1 -0
  13. package/dist/client/live-state.d.ts +63 -0
  14. package/dist/client/oauth.d.ts +17 -0
  15. package/dist/client/react.d.ts +77 -0
  16. package/dist/client/socket.d.ts +7 -0
  17. package/dist/client.mjs +156 -0
  18. package/dist/client.mjs.map +1 -0
  19. package/dist/expression.d.ts +88 -0
  20. package/dist/expression.mjs +301 -0
  21. package/dist/expression.mjs.map +1 -0
  22. package/dist/lib-BWr-5mFO.mjs +36 -0
  23. package/dist/lib-BWr-5mFO.mjs.map +1 -0
  24. package/dist/lib.d.ts +70 -0
  25. package/dist/lib.mjs +228 -0
  26. package/dist/lib.mjs.map +1 -0
  27. package/dist/node.d.ts +15 -0
  28. package/dist/node.mjs +47 -0
  29. package/dist/node.mjs.map +1 -0
  30. package/dist/oauth-scopes.d.ts +32 -0
  31. package/dist/oauth-scopes.mjs +40 -0
  32. package/dist/oauth-scopes.mjs.map +1 -0
  33. package/dist/oauth.mjs +41 -0
  34. package/dist/oauth.mjs.map +1 -0
  35. package/dist/principal.d.ts +8 -0
  36. package/dist/principal.mjs +8 -0
  37. package/dist/principal.mjs.map +1 -0
  38. package/dist/project-ingress.d.ts +58 -0
  39. package/dist/project-ingress.mjs +104 -0
  40. package/dist/project-ingress.mjs.map +1 -0
  41. package/dist/react.mjs +285 -0
  42. package/dist/react.mjs.map +1 -0
  43. package/dist/sdk/auth.d.ts +25 -0
  44. package/dist/sdk/index.d.ts +155 -0
  45. package/dist/sdk/record-pipelined-steps.d.ts +19 -0
  46. package/dist/sdk.mjs +245 -0
  47. package/dist/sdk.mjs.map +1 -0
  48. package/dist/stream/processor.d.ts +383 -0
  49. package/dist/stream/processor.mjs +605 -0
  50. package/dist/stream/processor.mjs.map +1 -0
  51. package/dist/stream/run.d.ts +61 -0
  52. package/dist/stream/run.mjs +45 -0
  53. package/dist/stream/run.mjs.map +1 -0
  54. package/dist/stream/test-support.d.ts +45 -0
  55. package/dist/stream/test-support.mjs +196 -0
  56. package/dist/stream/test-support.mjs.map +1 -0
  57. package/dist/usingCtx-inzbY1Qz.mjs +57 -0
  58. package/package.json +93 -30
  59. package/bin/iterate.js +0 -86
  60. package/dist/cli-DMS4kJph.mjs +0 -868
  61. package/dist/cli-DMS4kJph.mjs.map +0 -1
  62. package/dist/config-DtnR7Lv7.mjs +0 -170
  63. package/dist/config-DtnR7Lv7.mjs.map +0 -1
  64. package/dist/index.d.mts +0 -5
  65. package/dist/index.d.mts.map +0 -1
  66. package/dist/index.mjs +0 -8
  67. package/dist/index.mjs.map +0 -1
  68. package/dist/stream-tui/agent-chat-terminal.d.mts +0 -1
  69. package/dist/stream-tui/agent-chat-terminal.mjs +0 -933
  70. package/dist/stream-tui/agent-chat-terminal.mjs.map +0 -1
  71. package/dist/worker.d.mts +0 -33
  72. package/dist/worker.mjs +0 -18
  73. package/dist/worker.mjs.map +0 -1
package/README.md CHANGED
@@ -1,97 +1,189 @@
1
1
  # iterate
2
2
 
3
- CLI for Iterate.
4
-
5
- `npx iterate` opens the Iterate chat terminal UI. It is equivalent to
6
- `npx iterate chat`.
7
-
8
- The package also runs as a thin bootstrapper: inside this repo it delegates to
9
- the local `packages/iterate` source, and from npm it runs the published build.
10
-
11
- ## Requirements
12
-
13
- - Node `>=22`
14
- - Bun, for the current OpenTUI-based chat terminal runtime
15
-
16
- ## Quick start
17
-
18
- Run without installing globally:
3
+ The SDK for Iterate (`apps/os`): context APIs, stream processors, reactive clients, React
4
+ bindings, and OAuth app sessions, under `iterate/*`. The package exports source in this
5
+ workspace and compiled JavaScript with declarations when packed. The `iterate` command is
6
+ [`@iterate-com/cli`](../cli/README.md).
7
+
8
+ ## The SDK/platform line
9
+
10
+ The SDK holds what user code runs or speaks, and the platform is its first user: apps/os builds
11
+ its own entities on `iterate/sdk`, and the first-party apps' code uses only `iterate/*`. Each
12
+ subpath in `package.json`'s `exports` is one public module; nothing else is importable.
13
+
14
+ - A module belongs here when user code runs it or speaks it: a loaded worker, a facet, a
15
+ processor, a browser or Node client, or the wire contract between them and the platform. It
16
+ belongs in apps/os when only the platform's Worker runs it, and in packages/shared when more
17
+ than one app needs it and user code never does.
18
+ - Outside apps/os, no package and no app imports apps/os. `import-js/no-restricted-paths` in
19
+ `.oxlintrc.json` resolves each import under `packages/**` and `apps/**` to a file, so type
20
+ imports, re-exports, dynamic `import()` and an app added later are covered, and
21
+ `lint/oxlintrc-platform-line.test.ts` pins it. Tests may import apps/os's two harnesses,
22
+ `apps/os/e2e/support/` and `apps/os/__workers-tests__/support.ts`, which drive a real platform.
23
+ - The one known exception: the git codec (`@iterate-com/shared/git-wire`) and the GitHub template
24
+ reader live in packages/shared, though only the platform's Worker runs them. packages/shared is
25
+ private, so they do not cross the line.
26
+ - No private core package behind a thin `iterate`: apps/os would then import modules user code
27
+ cannot, and the SDK's types would have to be bundled or published anyway.
28
+
29
+ Follow-ups: move the git codec and the template reader into `apps/os/src/repo/`, and type the test
30
+ harnesses against `iterate/api`. The decision's reasons, and how workerd, the Agents SDK, Convex,
31
+ Supabase, tRPC, Hono and Wrangler draw the same line:
32
+ [the decision record](https://github.com/iterate/iterate/blob/d52a4e8e0f791c96b683fe178b56570532123c05/docs/2026-09-24-sdk-platform-line.md)
33
+ (#3018).
34
+
35
+ ## Reaching the context from loaded code
36
+
37
+ Code the platform loads for a project (a config worker, a facet, a worker behind a rewrite rule)
38
+ imports the SDK as `./processor.js` and reaches its context through `withItx`: one round trip,
39
+ after which the scope, every call made through it and every handle it awaited are released.
40
+
41
+ ```js
42
+ import { ConfigWorker, withItx } from "./processor.js";
43
+
44
+ export default class extends ConfigWorker {
45
+ async fetch() {
46
+ // An SDK host (ConfigWorker, StreamProcessorDurableObject) has it as a method.
47
+ const { projectSlug } = await this.withItx((itx) => itx.whoami());
48
+ return new Response(`Homepage of ${projectSlug}`);
49
+ }
50
+ }
19
51
 
20
- ```bash
21
- npx iterate
52
+ // Anywhere else: withItx(this.env.ITX, (itx) => itx.kv.get("key"))
22
53
  ```
23
54
 
24
- If you are not logged in yet, `iterate chat` starts the browser OAuth flow. The
25
- auth flow asks for project access and can create your first organization and
26
- project before returning to the CLI.
55
+ Never keep what `env.ITX.get()` hands out, and answer data, not handles, from `withItx`: a kept
56
+ scope, step or handle keeps the context, and any facet holding it, resident after the project goes
57
+ idle. An object that needs
58
+ reach takes a `WithItx` accessor (`(call) => withItx(this.env.ITX, call)`), never a scope; work
59
+ that outlives the call runs under a processor's `runInBackground` claim. Lint refuses a raw
60
+ `ITX.get()` in this repository (`iterate/no-raw-itx-get`).
27
61
 
28
- ```bash
29
- npx iterate chat
30
- ```
62
+ ## Testing a processor
31
63
 
32
- For help and other commands:
64
+ `iterate/stream/test-support` (Node) is the harness the SDK's own engine tests use:
33
65
 
34
- ```bash
35
- npx iterate --help
36
- npx iterate login
37
- npx iterate orgs list
38
- npx iterate config list
39
- ```
66
+ ```ts
67
+ import { reduceProcessor } from "iterate/stream/test-support";
40
68
 
41
- ## Commands
42
-
43
- - `iterate` - open chat
44
- - `iterate chat` - open the Iterate agent chat terminal UI
45
- - `iterate login` - authenticate with browser-based OAuth
46
- - `iterate logout` - remove the stored session for the current config
47
- - `iterate orgs list`
48
- - `iterate config ...`
49
- - `iterate os ...`
50
-
51
- ## Config file
52
-
53
- Config path:
54
-
55
- `${XDG_CONFIG_HOME:-~/.config}/iterate/config.json`
56
-
57
- Config shape:
58
-
59
- ```json
60
- {
61
- "configs": {
62
- "default": {
63
- "osBaseUrl": "https://os.iterate.com",
64
- "authBaseUrl": "https://auth.iterate.com",
65
- "defaultProject": "my-project"
66
- },
67
- "dev": {
68
- "osBaseUrl": "http://localhost:54896",
69
- "authBaseUrl": "http://localhost:7101"
70
- }
71
- },
72
- "default": "default",
73
- "workspaces": {
74
- "/absolute/workspace/path": "dev"
75
- }
76
- }
69
+ // apps/os/src/client/presence/processor.test.ts: durable ticks are reduced, ephemeral pokes are not
70
+ const state = reduceProcessor(new PresenceProcessor(), [{ type: "tick" }, { type: "poke" }]);
71
+ // state.ticks === 1
77
72
  ```
78
73
 
79
- Config resolution priority: `--config` flag > workspace match (walk up from cwd) > `default` key > single-config auto-select.
80
-
81
- ## Local iterate dev
74
+ `memoryStream`, `memoryStorage` and `settle` drive a whole `ProcessorEngine` against an
75
+ in-memory log (`src/stream/processor.test.ts` shows how).
82
76
 
83
- If you run inside an `iterate/iterate` clone, the CLI auto-detects it and
84
- delegates to the local source instead of the published build.
77
+ ## Node connections
85
78
 
86
- ## Publishing (maintainers)
79
+ `iterate/node` exposes a connection owner for Iterate scripts and live
80
+ providers. It uses the same protocol and cleanup as the CLI:
87
81
 
88
- From repo root:
82
+ ```js
83
+ import { connectIterate } from "iterate/node";
89
84
 
90
- ```bash
91
- pnpm --filter ./packages/iterate build
92
- pnpm --filter ./packages/iterate typecheck
93
- pnpm --filter ./packages/iterate test
94
- pnpm exec oxlint packages/iterate/src/cli.ts packages/iterate/src/cli.test.ts
95
- pnpm exec oxfmt --check packages/iterate
96
- pnpm --filter ./packages/iterate publish --access public
85
+ using connection = await connectIterate({
86
+ baseUrl: "https://os.iterate.com",
87
+ auth: { type: "bearer", token: process.env.ITERATE_BEARER_TOKEN },
88
+ });
89
+ using project = await connection.session.projects.get("my-project");
90
+ console.log(await project.run("async (itx) => await itx.whoami()"));
97
91
  ```
92
+
93
+ ## Event types
94
+
95
+ A platform event type is `events.iterate.com/<namespace>/<event>`: one namespace segment and one
96
+ event segment, both lowercase kebab-case, and never a third segment.
97
+
98
+ Every type under `events.iterate.com/` follows these rules, test types included. A type without
99
+ that prefix belongs to whoever appends it and is opaque to the platform: tests use types like
100
+ `demo/ping` on purpose, and a project may use its own domain (`events.garple.com/sales/…`).
101
+
102
+ ### Namespaces
103
+
104
+ - **`itx`** holds the context engine's own events: everything the core contract
105
+ (`apps/os/src/stream/core-processor.ts`) reduces, validates or refuses, plus the records the
106
+ Stream, the context Durable Object and the SDK processor host write themselves. Where the schema
107
+ and the reduce live decides it, not which contexts hold the event: fetch routes and the apex
108
+ ingress target are core state, so they are `itx` even though only a project root's copy is read.
109
+ A domain processor may consume an `itx` event (the agent consumes `itx/run-*`, the Project
110
+ processor `itx/ingress-configured`); it names the core's catalog in its `processorDeps` rather than
111
+ defining the event itself. The core's checkpoint slug is `core`: it is a storage key, not a type
112
+ prefix.
113
+ - **A domain namespace** is the singular name of the kind of context whose log the event belongs
114
+ to, which is the defining contract's slug when there is one: `account`, `organization`,
115
+ `project`, `repo`, `workspace`, `secret`, `agent`, `voice-agent`. A fact cross-posted to another
116
+ log keeps its own namespace: `repo/created` on `/` is still a repo fact.
117
+ - **An integration** uses its own name as its namespace, for example `chrome`.
118
+ - **`test`** holds types that only tests append. Production code never matches a `test/*` type. A
119
+ test contract may keep a slug of its own (`counter`), but its events go under `test/`. A test must
120
+ not borrow a production namespace for a type that does not exist.
121
+
122
+ ### Event names
123
+
124
+ - **A fact is past tense**: `<object>-<verb-ed>`, or a bare `<verb-ed>` when the object is the
125
+ namespace's own subject (`itx/created` is the context, `agent/paused` is the agent). The object
126
+ comes first and is singular.
127
+ - **Spell words out.** Clipped words are not allowed (`spk`); a real word is (`mic`), and so is an
128
+ acronym the API already spells (`llm`, `rpc`, `itx`).
129
+ - **Asking and answering.** `<x>-requested` asks, and its offset identifies the ask. The answer
130
+ takes one of three shapes:
131
+ - `<x>-settled` is the one terminal fact when the asker reads a result. It names
132
+ `requestOffset` and carries the outcome: succeeded, failed or cancelled, a status, or an error.
133
+ Examples: `itx/run-*`, `agent/llm-request-*`, `project/hostname-add-*`.
134
+ - `<verb-ed>` or `<verb>-failed` is used when success is a fact that other logs wait on, like a
135
+ certificate: `create-requested` → `created` or `create-failed`, `delete-requested` → `deleted`,
136
+ `hostname-remove-requested` → `hostname-removed`. A failure that is retried rather than
137
+ reported gets no `-failed` fact.
138
+ - An answer that is also a fact of its own names the ask by id:
139
+ `voice-agent/delegation-requested` is answered by one `commentary-added` carrying its
140
+ `delegationId`.
141
+ - **One verb pair per kind of change:**
142
+ - `added` / `removed` for membership in a set: `organization/member-added`,
143
+ `organization/project-added`, hostnames.
144
+ - `created` / `deleted` for an entity with a lifecycle: projects, repos, workspaces, agents.
145
+ - `set` / `deleted` for a keyed value: `secret/*`.
146
+ - `set` / `cancelled` for a schedule: `itx/schedule-*`. Each occurrence is `fired` or `failed`.
147
+ - `-configured` for one fact that sets a row or clears it with `null`
148
+ (`itx/subscription-configured`, `itx/rewrite-rule-configured`, `itx/fetch-route-configured`),
149
+ sets a singleton (`itx/ingress-configured`), or merges a partial configuration
150
+ (`agent/configured`: omitted keys keep their values).
151
+ - **Things the platform does on its own** are plain facts about the object: `itx/schedule-fired`,
152
+ `itx/schedule-failed`, `itx/subscription-delivery-halted`.
153
+ - **Ephemeral events.** An ephemeral event that records something happening is named like any other
154
+ fact: `itx/rpc-stub-attached`, `itx/live-state-changed`, `chrome/navigated`. Three kinds may be
155
+ singular nouns: a sequenced slice of a live stream is a `<stream>-frame`
156
+ (`voice-agent/mic-frame`, `agent/llm-response-frame`), a heartbeat (`voice-agent/keepalive`), and
157
+ a diagnostic record (`itx/alarm-trace`). A durable event is never a noun.
158
+ - **Families and prefixes.** Code matches some families by prefix: `…/itx/run-`,
159
+ `…/itx/subscription-`, `…/itx/schedule-`, `…/project/hostname-`. Before naming a new type, check
160
+ it doesn't join one of these families by accident. Never match `…/itx/` as a whole: it is not a
161
+ permission boundary, and it catches live-state deltas, stub presence and child
162
+ announcements.
163
+ - **Code follows the type.** A constant, schema, test fixture or idempotency key built from a type
164
+ follows its name (`itx/child-created:<path>`). Broader concepts, modules and Workers log
165
+ event names keep theirs: the Stream, scheduled appends, `core`, `scheduled-append.completed`.
166
+ - **Renaming.** A rename has to serve one of these rules, not taste. If a type is stored outside the
167
+ platform's Durable Objects (device firmware, a published SDK, a project's config repo),
168
+ rename it only in a change that migrates that store too.
169
+
170
+ | Namespace | Defined in |
171
+ | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
172
+ | `itx` | `apps/os/src/stream/core-processor.ts` (and its leaf event catalog), `stream.ts`, `scheduled-appends.ts`, `subscription-delivery.ts`, `apps/os/src/context/built-ins.ts`, `apps/os/src/fetch-routes.ts`, `apps/os/src/iterate-context-durable-object.ts`, `packages/iterate/src/stream/{run,processor}.ts` |
173
+ | `account`, `organization`, `project`, `repo`, `workspace`, `secret` | `apps/os/src/<name>/contract.ts` (repo and workspace also use `project/entity-lifecycle.ts`) |
174
+ | `agent` | `apps/agents/runtime/contract.ts` |
175
+ | `voice-agent` | `apps/agents/voice/voice-agent.ts`, `apps/agents/voice/events.ts` |
176
+ | `chrome` | `apps/browser-extension/panel.js` |
177
+ | `test` | tests only |
178
+
179
+ Two types break these rules until the Kit firmware migrates:
180
+
181
+ - `voice-agent/spk-frame` will become `voice-agent/speaker-frame`.
182
+ - `voice-agent/conversation-ended` will become `voice-agent/call-ended`. It pairs with `call-started`
183
+ and names the activation; the provider session is the `conversation`.
184
+
185
+ `note/added` is only an example in the Agents composer; no contract defines `note`.
186
+ `email/received` is only an integration's transcript in an agent UI test; no contract defines
187
+ `email`.
188
+ `capability-host/script-run-*` is never written to a log: the agent UI's adapter builds it in
189
+ memory.