runwork 0.27.2 → 0.29.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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Runwork is an AI workspace that brings AI agents, custom apps, and human teams i
8
8
 
9
9
  This CLI is the local development interface to the platform. You write TypeScript, and the platform handles deployment, infrastructure, AI, and integrations:
10
10
 
11
- - **Full-stack apps, zero infrastructure** -- Data storage, file hosting, background jobs, durable workflows, AI, and 3,200+ third-party integrations are all built into the platform. You write application code; Runwork runs it.
11
+ - **Full-stack apps, zero infrastructure** -- Data storage, file hosting, background jobs, durable workflows, AI, and thousands of third-party integrations are all built into the platform. You write application code; Runwork runs it.
12
12
  - **Zero to app in seconds** -- Describe what you need and Runwork generates it. Developers customize with code using the [`@runworkai/framework`](https://www.npmjs.com/package/@runworkai/framework).
13
13
  - **Instant deployments** -- Push code and get a live URL. Preview environments while you develop, production at the edge.
14
14
  - **Built-in AI agents** -- Conversational agents that read data, take actions, and coordinate across apps. No API keys or model configuration to manage.
@@ -57,6 +57,7 @@ runwork dev # Start developing with live preview
57
57
  | `runwork clone` | Clone an existing Runwork app to your machine |
58
58
  | `runwork dev` | Start local development with live preview and auto-sync |
59
59
  | `runwork deploy` | Deploy to production |
60
+ | `runwork spaces` | Spaces: containers for one kind of work |
60
61
  | `runwork logout` | Remove stored credentials |
61
62
 
62
63
  ### `runwork dev`
@@ -72,6 +73,64 @@ The main development command. When you run `runwork dev`:
72
73
 
73
74
  Edit files in your editor, and changes appear in the preview automatically.
74
75
 
76
+ Preview data lives inside the sandbox. Every entity starts empty again after the sandbox is
77
+ replaced, which a restart or a recycled container can both do. Your production data is untouched.
78
+
79
+ ### `runwork spaces`
80
+
81
+ A space is a container for one kind of work: its files, AI instructions, skills, apps, automations
82
+ and conversations. `runwork spaces map` keeps a local folder in a space, so what you share is
83
+ uploaded for members of the space to read and conversations you run there are filed under the space
84
+ on this machine.
85
+
86
+ | Subcommand | Description |
87
+ |------------|-------------|
88
+ | `spaces suggest` | Propose spaces and things to keep in them from your local conversations (nothing is uploaded) |
89
+ | `spaces list` | Spaces in the workspace, with the folders on this machine mapped to each |
90
+ | `spaces map <folder>` | Keep a folder in a space: everything in it waits in Changes for you to share, and what you share is uploaded for members of the space to read. Conversations you run there are filed under the space on this machine, not uploaded |
91
+ | `spaces scope <folder>` | What a folder would share with a space, before you map it. Maps nothing and writes nothing |
92
+ | `spaces create <name>` | Create a space |
93
+ | `spaces default-folder [space]` | Where this space's folder would go on this machine if nobody chose. Creates nothing and maps nothing. |
94
+ | `spaces contents [space]` | What is filed under a space: its apps, skills, chats, workflows and endpoints |
95
+ | `spaces ls [space] [path]` | The files a space holds, as a teammate on another machine would see them |
96
+ | `spaces cat [space] <path>` | Print a file the space holds, as it is now or as it was at an earlier commit |
97
+ | `spaces history [space] <path>` | Who changed a file in a space and when, newest first, with the commit each version can be read at |
98
+ | `spaces put [space] <path> [file]` | Write any file into a space, from a local file or from stdin |
99
+ | `spaces rm [space] <path>` | Take a file out of a space. Its history stays, so a teammate can still see what it was. |
100
+ | `spaces instructions [space] [file]` | Read a space's `AGENTS.md`, or replace it from a local file or stdin |
101
+ | `spaces files [path]` | What is in a mapped folder, and which of it the space shares |
102
+ | `spaces include <path>` | Share a file or folder from a mapped folder with its space |
103
+ | `spaces exclude <path...>` | Stop sharing a file or folder, and take it out of the space |
104
+ | `spaces pause <folder>` | Stop this folder sharing on its own: its changes wait for runwork spaces share. Teammates' changes still arrive |
105
+ | `spaces resume <folder>` | Let this folder share its changes on its own, as each file stops changing |
106
+ | `spaces changes [folder]` | What this folder would send to its space next, and what is holding each of it back |
107
+ | `spaces sync [folder]` | Bring mapped folders and their spaces together: commit local changes, push, and pull what teammates added (no system git needed). With no folder named it syncs the mapped folder you are standing in; `--all` syncs every one of them |
108
+ | `spaces share [folder] [path...]` | Share what is waiting in a mapped folder now, without waiting for files to settle. Name any number of paths to share exactly those |
109
+ | `spaces launched <folder>` | Record that a conversation was just opened from this folder's space, so a cloud session with several space folders connected knows which one this is about |
110
+ | `spaces unmap <folder>` | Stop filing a folder under a space (this machine only) |
111
+ | `spaces reset <folder>` | Throw away this machine's copy of a mapped folder's space history, so the next sync rebuilds it from the space |
112
+ | `spaces prune` | Remove space histories on this machine that no folder maps to any more |
113
+ | `spaces mappings` | Folder-to-space mappings on this machine, the one you are standing in first |
114
+
115
+ `spaces rm` is also available as `spaces delete`. A mapped folder shares nothing until you ask for
116
+ it: run `spaces changes` to see what is waiting and `spaces share` to send it. Pass `--auto` to
117
+ `spaces map`, or run `spaces resume`, to have a folder share each file on its own once the file
118
+ stops changing.
119
+
120
+ Anything that files something under a space takes that space from the folder you are in when it is
121
+ mapped to one: `init`, `skills push`, `skills install`, `save-convo` and `share-convo`. `--space`
122
+ always wins, and each of them says which space it chose and why.
123
+
124
+ The verbs above that act on a space take it the same way, so inside a mapped folder `spaces ls`,
125
+ `spaces cat notes/plan.md` and `spaces contents` are about that folder's space. Naming the space
126
+ still works everywhere and still wins. How many arguments you give decides what they mean, so an
127
+ existing command keeps meaning what it always did: one argument to `ls` and `instructions` is the
128
+ space, and two to `put` are the space and the path. `cat`, `history` and `rm` read a single argument
129
+ as the path, and `put` takes the space from the folder when it is given a path alone, with the
130
+ content piped in (`runwork spaces put notes/plan.md < ./plan.md`). Reading falls back to your
131
+ personal space when the folder is mapped to nothing; `put`, `rm` and `instructions` ask you to name
132
+ one instead, because a write must not land somewhere nobody pointed at.
133
+
75
134
  ## How It Works
76
135
 
77
136
  Runwork apps are full-stack TypeScript projects built with the [`@runworkai/framework`](https://www.npmjs.com/package/@runworkai/framework). The CLI handles the development lifecycle:
@@ -93,7 +152,7 @@ Every Runwork app gets built-in access to:
93
152
  - **File storage** -- Upload and manage files and media
94
153
  - **Public endpoints** -- Authenticated APIs for external consumers
95
154
  - **Cross-app workspaces** -- Shared entities, channels, and notifications between apps
96
- - **3,200+ integrations** -- OAuth-managed connections to third-party services
155
+ - **Third-party integrations** -- OAuth-managed connections to third-party services
97
156
 
98
157
  ## Project Structure
99
158
 
@@ -1,2 +1,19 @@
1
+ /**
2
+ * Barrel: `@runworkai/framework/channels` (retired).
3
+ *
4
+ * Kept so apps built against earlier versions keep compiling. The notices below
5
+ * are JSDoc rather than line comments on purpose: tsc drops `//` comments from
6
+ * the emitted `.d.ts`, and these declarations are what every local agent reads
7
+ * out of `.runwork/types/`.
8
+ */
9
+ /**
10
+ * @deprecated Channels are retired. This still posts to the workspace event
11
+ * stream, where the message appears in the activity feed and on the app's
12
+ * timeline, so deployed apps keep working. Use `emitEvent` from
13
+ * `@runworkai/framework/events` for new code.
14
+ */
1
15
  export { postToChannel } from './core-channels';
16
+ /**
17
+ * @deprecated Channels are retired; see `postToChannel`.
18
+ */
2
19
  export type { PostToChannelParams } from './core-channels';
@@ -1,15 +1,17 @@
1
1
  /**
2
- * Core Channels
2
+ * Core Channels (retired)
3
3
  * DO NOT MODIFY THIS FILE - You may break the project functionality
4
4
  *
5
- * This module provides:
6
- * - postToChannel(): Post rich markdown messages to workspace channels
7
- *
8
- * Channels are auto-created if they don't exist, with automatic app event filtering.
5
+ * Workspace channels no longer exist. This module stays only so apps built
6
+ * against earlier framework versions keep working: `postToChannel()` still
7
+ * sends its message to the platform, which files it as an app event in the
8
+ * workspace activity feed and on the app's timeline. New code should call
9
+ * `emitEvent()` from `@runworkai/framework/events` instead.
9
10
  * When running outside a workspace (standalone mode), calls are silently skipped.
10
11
  */
12
+ /** @deprecated Channels are retired; use `emitEvent()` from `@runworkai/framework/events`. */
11
13
  export interface PostToChannelParams {
12
- /** Channel name (e.g., "#inventory-alerts" or "inventory-alerts"). Auto-normalized: # stripped, lowercased, trimmed. */
14
+ /** Former channel name; kept for compatibility and ignored by the platform. */
13
15
  channel: string;
14
16
  /** Markdown message content */
15
17
  content: string;
@@ -31,12 +33,11 @@ interface ChannelEnv {
31
33
  */
32
34
  type WaitUntilContext = Pick<ExecutionContext, 'waitUntil'>;
33
35
  /**
34
- * Post a rich markdown message to a workspace channel.
36
+ * @deprecated Channels are retired. The message is still delivered as an app
37
+ * event that appears in the workspace activity feed and on the app's timeline;
38
+ * use `emitEvent()` from `@runworkai/framework/events` for new code.
35
39
  * Fire-and-forget: uses ctx.waitUntil so it doesn't block the response.
36
40
  * Silently skips if workspace env vars are not configured (standalone mode).
37
- *
38
- * Channels are auto-created on first use. The channel will automatically
39
- * include this app's system events via filter projection.
40
41
  */
41
42
  export declare function postToChannel(ctx: WaitUntilContext, env: ChannelEnv, params: PostToChannelParams): void;
42
43
  export {};
@@ -6,7 +6,7 @@
6
6
  * - emitEvent(): Fire-and-forget event emission to the workspace event stream
7
7
  * - flog(): Structured logging that outputs JSON to sandbox stdout
8
8
  *
9
- * Events appear in the workspace activity feed and channel views.
9
+ * Events appear in the workspace activity feed and on the app's timeline.
10
10
  * When running outside a workspace (standalone mode), calls are silently skipped.
11
11
  */
12
12
  export interface EmitEventParams {
@@ -31,7 +31,8 @@ interface EventEnv {
31
31
  */
32
32
  type WaitUntilContext = Pick<ExecutionContext, 'waitUntil'>;
33
33
  /**
34
- * Convert an app name to a kebab-case channel name.
34
+ * Convert an app name to the kebab-case label the legacy `channel` field carries.
35
+ * @deprecated Channels are retired; the platform ignores the field.
35
36
  * "My Cool App" -> "my-cool-app"
36
37
  */
37
38
  export declare function toChannelName(appName: string): string;
@@ -89,6 +89,15 @@ export interface RegisterEntityRequest extends Record<string, unknown> {
89
89
  schema?: Record<string, unknown>;
90
90
  deploymentMode?: 'preview' | 'production';
91
91
  }
92
+ export interface RegisterAllEntitiesRequest extends Record<string, unknown> {
93
+ appId: string;
94
+ appName: string;
95
+ entities: Array<{
96
+ entityName: string;
97
+ schema?: Record<string, unknown>;
98
+ }>;
99
+ deploymentMode?: 'preview' | 'production';
100
+ }
92
101
  export interface RegisterAppRequest extends Record<string, unknown> {
93
102
  appId: string;
94
103
  appName: string;
@@ -269,6 +278,19 @@ export declare class WorkspaceContext {
269
278
  * Register an entity with the workspace so other apps can query it
270
279
  */
271
280
  registerEntity(entityName: string, schema?: Record<string, unknown>): Promise<void>;
281
+ /**
282
+ * Register every entity this app defines in one call.
283
+ *
284
+ * Ownership rules are the same as registerEntity (first registrant owns,
285
+ * later apps are recorded as references, preview never touches production),
286
+ * but the workspace applies them in a single state write instead of one per
287
+ * entity. A platform that predates the bulk route answers 404; then each
288
+ * entity is registered individually so an older platform keeps working.
289
+ */
290
+ registerAllEntities(entities: Array<{
291
+ entityName: string;
292
+ schema?: Record<string, unknown>;
293
+ }>): Promise<void>;
272
294
  /**
273
295
  * Register this app with the workspace (safe to call multiple times)
274
296
  */
@@ -545,3 +567,9 @@ export declare function deleteWorkspaceEntity(env: Env, entityName: string, id:
545
567
  * Called once when the worker starts
546
568
  */
547
569
  export declare function initializeWorkspace(env: Env): Promise<void>;
570
+ /**
571
+ * Forget that this isolate is initialized so the next request runs a sweep
572
+ * again. The last successful fingerprint is kept: a sweep that finds the
573
+ * definitions unchanged completes without calling the workspace.
574
+ */
575
+ export declare function invalidateWorkspaceInitialization(): void;