@crowdedkingdoms/crowdy-dsh 0.4.14 → 0.5.1-dev.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.
- package/README.md +61 -10
- package/dist/dsh-web/BUILD.json +5 -5
- package/dist/dsh-web/preview/vfs-image.tar.gz +0 -0
- package/lib/bridge/client-service.js +33 -0
- package/lib/bridge/client-service.js.map +1 -0
- package/lib/bridge/client.js +20 -1
- package/lib/bridge/client.js.map +1 -1
- package/lib/bridge/index.js +33 -24
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/protocol.js +30 -1
- package/lib/bridge/protocol.js.map +1 -1
- package/lib/crowdy/config.js +6 -0
- package/lib/crowdy/config.js.map +1 -1
- package/lib/crowdy/playbook.js +24 -0
- package/lib/crowdy/playbook.js.map +1 -0
- package/lib/crowdy/repo-paths.js +27 -0
- package/lib/crowdy/repo-paths.js.map +1 -0
- package/lib/crowdy/token.js +16 -0
- package/lib/crowdy/token.js.map +1 -0
- package/lib/fs/crowdy-file-system.js +4 -10
- package/lib/fs/crowdy-file-system.js.map +1 -1
- package/lib/fs/entry.js +22 -0
- package/lib/fs/entry.js.map +1 -0
- package/lib/fs/game-file-system.js +532 -0
- package/lib/fs/game-file-system.js.map +1 -0
- package/lib/fs/studio-fs.js +14 -0
- package/lib/fs/studio-fs.js.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/search/search-tools.js +4 -5
- package/lib/search/search-tools.js.map +1 -1
- package/lib/skills/playbook.js +80 -0
- package/lib/skills/playbook.js.map +1 -0
- package/lib/tools/game.js +155 -0
- package/lib/tools/game.js.map +1 -0
- package/lib/tools/index.js +21 -12
- package/lib/tools/index.js.map +1 -1
- package/lib/types/bridge/client-service.d.ts +32 -0
- package/lib/types/bridge/client-service.d.ts.map +1 -0
- package/lib/types/bridge/client.d.ts +6 -0
- package/lib/types/bridge/client.d.ts.map +1 -1
- package/lib/types/bridge/index.d.ts +9 -13
- package/lib/types/bridge/index.d.ts.map +1 -1
- package/lib/types/bridge/protocol.d.ts +189 -2
- package/lib/types/bridge/protocol.d.ts.map +1 -1
- package/lib/types/crowdy/config.d.ts +7 -0
- package/lib/types/crowdy/config.d.ts.map +1 -1
- package/lib/types/crowdy/playbook.d.ts +13 -0
- package/lib/types/crowdy/playbook.d.ts.map +1 -0
- package/lib/types/crowdy/repo-paths.d.ts +15 -0
- package/lib/types/crowdy/repo-paths.d.ts.map +1 -0
- package/lib/types/crowdy/repo-paths.test.d.ts.map +1 -0
- package/lib/types/crowdy/token.d.ts +10 -0
- package/lib/types/crowdy/token.d.ts.map +1 -0
- package/lib/types/crowdy/token.test.d.ts.map +1 -0
- package/lib/types/fs/crowdy-file-system.d.ts +7 -2
- package/lib/types/fs/crowdy-file-system.d.ts.map +1 -1
- package/lib/types/fs/entry.d.ts +21 -0
- package/lib/types/fs/entry.d.ts.map +1 -0
- package/lib/types/fs/game-file-system.d.ts +107 -0
- package/lib/types/fs/game-file-system.d.ts.map +1 -0
- package/lib/types/fs/game-file-system.test.d.ts.map +1 -0
- package/lib/types/fs/studio-fs.d.ts +42 -0
- package/lib/types/fs/studio-fs.d.ts.map +1 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/search/search-tools.d.ts.map +1 -1
- package/lib/types/skills/playbook.d.ts +25 -0
- package/lib/types/skills/playbook.d.ts.map +1 -0
- package/lib/types/skills/playbook.test.d.ts.map +1 -0
- package/lib/types/tools/game.d.ts +25 -0
- package/lib/types/tools/game.d.ts.map +1 -0
- package/lib/types/tools/game.test.d.ts.map +1 -0
- package/lib/types/tools/index.d.ts +5 -0
- package/lib/types/tools/index.d.ts.map +1 -1
- package/lib/vendor/crowdyjs-sdk.js +50 -10
- package/lib/vendor/crowdyjs-sdk.version.json +1 -1
- package/package.json +25 -9
- package/presets/crowdy/agent.cordis.yml +1 -0
- package/presets/crowdy-game/agent.cordis.yml +143 -0
- package/presets/crowdy-game/preset.yml +3 -0
- package/profile/crowdy-node.patch.yml +3 -0
- package/profile/crowdy-web.patch.yml +10 -3
package/README.md
CHANGED
|
@@ -6,7 +6,9 @@ packs them — with the stock harness web UI — into a static artifact that run
|
|
|
6
6
|
**entirely in the player's browser**. Crowdy Studio embeds that artifact as the
|
|
7
7
|
agent pane; the harness edits the project through the game API exactly as the
|
|
8
8
|
Studio editor does, and calls the model through the tier's metered model
|
|
9
|
-
endpoint with the player's own app token.
|
|
9
|
+
endpoint with the player's own app token. In **game mode** the same harness
|
|
10
|
+
edits a game's own repository instead, as a draft the page owns and the world
|
|
11
|
+
previews, and commits only when the player asks ([Game mode](#game-mode)).
|
|
10
12
|
|
|
11
13
|
Replaces the Crowdy Agent orchestrator in the CK API and the CrowdyJS agent
|
|
12
14
|
dock (CrowdyJS 16). The page side of the bridge lives in CrowdyJS
|
|
@@ -31,11 +33,12 @@ game page (the-construct) iframe /dsh/index.html Web
|
|
|
31
33
|
|
|
32
34
|
| Seam | Stock | Here |
|
|
33
35
|
|---|---|---|
|
|
34
|
-
| `ctx.fs` | `dsh-fs-sandbox` over the local disk | [`./fs`](src/fs/crowdy-file-system.ts): the project. Reads are always the project's files (`crowdyStudioProject`); for a project bound to GitHub those are the server's mirror of the repository at `githubSha`. Writes go by `source`: a STUDIO project through the files-only save under `expectedRevision`, a GITHUB project as one commit per changed file (`crowdyStudioGitHubPutFile` / `DeleteFile` carrying `expectedCommitSha`). Nothing is mirrored from here; the server advances the mirror with each commit, so Monaco and the agent look at one tree. Layout comes from `crowdyStudioGitHubLayout`; this package does not parse `crowdy.json`. GitHub is never required. `captures/` and `context/` are in-memory scratch dirs the page fills. |
|
|
36
|
+
| `ctx.fs` | `dsh-fs-sandbox` over the local disk | [`./fs`](src/fs/crowdy-file-system.ts): the project. Reads are always the project's files (`crowdyStudioProject`); for a project bound to GitHub those are the server's mirror of the repository at `githubSha`. Writes go by `source`: a STUDIO project through the files-only save under `expectedRevision`, a GITHUB project as one commit per changed file (`crowdyStudioGitHubPutFile` / `DeleteFile` carrying `expectedCommitSha`). Nothing is mirrored from here; the server advances the mirror with each commit, so Monaco and the agent look at one tree. Layout comes from `crowdyStudioGitHubLayout`; this package does not parse `crowdy.json`. GitHub is never required. `captures/` and `context/` are in-memory scratch dirs the page fills. In game mode the same row mounts [`GameFileSystem`](src/fs/game-file-system.ts) instead: the page's draft of the bound repository (see below). |
|
|
35
37
|
| `ctx.attachments` | `dsh-attachment-local` (sharp) | [`./attachments`](src/attachments/crowdy-attachment-store.ts): in-memory, header-sniffed dimensions; the browser worker has no native image codec. |
|
|
36
|
-
| agent preset | `standard` | [`presets/crowdy`](presets/crowdy/agent.cordis.yml): file tools, in-memory `glob`/`grep`, `sdk_lookup`, and the Studio tools below. No shell, no web, no subagents. |
|
|
37
|
-
| page link | — | [`./bridge`](src/bridge/
|
|
38
|
-
| tools | — | [`./tools`](src/tools/index.ts): `draft_test` and `deploy_live` (both confirmed by the player on the page, since a draft deploys the mod to the grid too; `deploy_live` is also approval-gated in the harness), `screenshot`, `runtime_status`, `client_logs`, `game_observe`, `project_list/open/create`, and (bridge v4) `grid_context`, `grid_program_run`, `grid_program_status` for JS grid programs in the project's grid. The page executes them with the player's authority. |
|
|
38
|
+
| agent preset | `standard` | [`presets/crowdy`](presets/crowdy/agent.cordis.yml): file tools, in-memory `glob`/`grep`, `sdk_lookup`, and the Studio tools below. No shell, no web, no subagents. [`presets/crowdy-game`](presets/crowdy-game/agent.cordis.yml) is the game editor's: file tools and search over the draft, the page's `screenshot` / `game_observe` / `client_logs`, the game tools, the game's skills and its `STUDIO.md`. |
|
|
39
|
+
| page link | — | [`./bridge-client`](src/bridge/client-service.ts): `ctx.crowdyBridgeClient`, a `BroadcastChannel` to the Studio page ([protocol](src/bridge/protocol.ts)). [`./bridge`](src/bridge/index.ts): `ctx.crowdyBridge`, the session side (boot handshake, token, scratch, change events). |
|
|
40
|
+
| tools | — | [`./tools`](src/tools/index.ts): `draft_test` and `deploy_live` (both confirmed by the player on the page, since a draft deploys the mod to the grid too; `deploy_live` is also approval-gated in the harness), `screenshot`, `runtime_status`, `client_logs`, `game_observe`, `project_list/open/create`, and (bridge v4) `grid_context`, `grid_program_run`, `grid_program_status` for JS grid programs in the project's grid. The page executes them with the player's authority. `only` limits the list (the game preset takes the page tools alone). [`./game-tools`](src/tools/game.ts): `commit_game_files` (approval-gated here and confirmed on the page), `preview_status`, `read_playbook`. |
|
|
41
|
+
| skills | `skill-filesystem` | [`./playbook-skills`](src/skills/playbook.ts): an upstream skill provider over `studio.listSkills` / `studio.readPlaybook`, so the skills are whatever the game's playbook lists. Game preset only. |
|
|
39
42
|
| model route | pi-ai | `llm-deepseek` (direct fetch; pi-ai is a stub in the worker) pointed at the tier model endpoint via `settings.yaml`. |
|
|
40
43
|
| persistence | disk | [`./persist`](src/persist/index.ts): mirrors `home/sessions`, `home/storages`, `settings.yaml` to OPFS; the page restores them as a boot overlay. |
|
|
41
44
|
|
|
@@ -47,8 +50,9 @@ The iframe posts `{type:'crowdy-dsh:ready'}`; the page answers with:
|
|
|
47
50
|
iframe.contentWindow.postMessage({
|
|
48
51
|
type: 'crowdy-dsh:boot',
|
|
49
52
|
files: {
|
|
50
|
-
'crowdy.json': JSON.stringify({ graphqlUrl, appId, projectId, bridgeChannel, bridgeNonce, root: '/dsh/workspace', persistScope }),
|
|
51
|
-
'settings.yaml': `llm-deepseek:\n apiKeyEnv: CROWDY_APP_TOKEN\n baseURL: ${modelBaseUrl}\n thinking: disabled\n models: [...]\nagent-default-model:\n provider: deepseek-official\n model: ${defaultModel}\n
|
|
53
|
+
'crowdy.json': JSON.stringify({ graphqlUrl, appId, projectId, bridgeChannel, bridgeNonce, root: '/dsh/workspace', persistScope, studioMode }),
|
|
54
|
+
'settings.yaml': `llm-deepseek:\n apiKeyEnv: CROWDY_APP_TOKEN\n baseURL: ${modelBaseUrl}\n thinking: disabled\n models: [...]\nagent-default-model:\n provider: deepseek-official\n model: ${defaultModel}\n`
|
|
55
|
+
+ (studioMode === 'game' ? 'agent-presets:\n default: crowdy-game\n' : ''),
|
|
52
56
|
},
|
|
53
57
|
nonce: bridgeNonce, // one-time secret; every bridge frame carries it
|
|
54
58
|
persistScope, // OPFS directory, e.g. `${appId}/${userId}`
|
|
@@ -69,14 +73,58 @@ cached files. Both sides drop frames without the boot nonce: a
|
|
|
69
73
|
implements the page side in `src/crowdy-dsh/`; it also confirms a live deploy
|
|
70
74
|
with the player on the page before running it.
|
|
71
75
|
|
|
76
|
+
The game's own host serves the page and `/dsh/`. Crowded Kingdoms does not
|
|
77
|
+
host games: the developer deploys both to the game's origin, on any static
|
|
78
|
+
host that can set response headers.
|
|
79
|
+
[Host your game](https://docs.crowdedkingdoms.com/build-a-game/host-your-game)
|
|
80
|
+
and the Construct's
|
|
81
|
+
[hosting guide](https://github.com/CrowdedKingdoms/the-construct/blob/prod/docs/HOSTING.md)
|
|
82
|
+
have the full header set and recipes for common hosts.
|
|
83
|
+
|
|
72
84
|
Headers the host must send (verified with `crossOriginIsolated === true`):
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
the cross-origin isolation headers (COOP `same-origin` and a COEP) on every
|
|
86
|
+
response, `/dsh/*` included; game page CSP unchanged except `frame-src 'self'`;
|
|
87
|
+
every `/dsh/*` response carries
|
|
88
|
+
`script-src 'self' 'unsafe-eval' 'unsafe-inline' blob:`,
|
|
75
89
|
`connect-src 'self' blob:`, `worker-src 'self' blob:`, `frame-ancestors 'self'`
|
|
76
90
|
(the worker compiles pre-lowered module bodies with `new Function`; the harness
|
|
77
91
|
document runs its own client module system). The API and model endpoints must
|
|
78
92
|
be same-origin or in `connect-src`.
|
|
79
93
|
|
|
94
|
+
## Game mode
|
|
95
|
+
|
|
96
|
+
A Construct-template game (the API reports its layout `kind` as
|
|
97
|
+
`CONSTRUCT_GAME`) is edited as its own repository, not as Studio crates. The
|
|
98
|
+
page decides: it boots the worker with `studioMode: 'game'` in `crowdy.json`,
|
|
99
|
+
a `persistScope` of its own (sessions of the two editors never mix) and
|
|
100
|
+
`agent-presets.default: crowdy-game` in `settings.yaml`. The worker reports
|
|
101
|
+
`modes: ['mod', 'game']` in `worker.ready`; a page that boots game mode on an
|
|
102
|
+
older worker says so instead of running the mod editor on a game.
|
|
103
|
+
|
|
104
|
+
- **The draft is the page's.** CrowdyJS keeps it (a `DraftStore`: an overlay
|
|
105
|
+
over the repository at a base commit, in the browser when the game runs from
|
|
106
|
+
its own deployed origin, on the dev server's checkout locally). The worker's
|
|
107
|
+
filesystem is a view of it: `draft.tree` once, then every change through
|
|
108
|
+
`page.draftChanged`; text by `draft.read` in batches, cached by blob id.
|
|
109
|
+
Versions are git blob SHA-1s, so listing, `stat` and `read_file` agree with
|
|
110
|
+
what the page shows.
|
|
111
|
+
- **Writes are guarded the harness's way.** A write carries the tool's intent
|
|
112
|
+
(`createIfAbsent`, or `replaceIfVersion` as `ifHash`); a file the player
|
|
113
|
+
changed since the model read it is a stale write (`FS_STALE_VERSION`), never
|
|
114
|
+
an overwrite. `.git`, `node_modules`, `.env*` and `.github/workflows` are not
|
|
115
|
+
repository files here; `captures/` and `context/` are page scratch.
|
|
116
|
+
- **Nothing commits on its own.** `commit_game_files {message, paths?}` asks
|
|
117
|
+
the harness approval, then the page shows the files and the message and the
|
|
118
|
+
player confirms; the page commits them as one commit against the draft's
|
|
119
|
+
base. A conflict (the branch moved under an edited file) comes back for the
|
|
120
|
+
player to settle in the Files pane.
|
|
121
|
+
- **The game brings its guidance.** The preset reads the game's `STUDIO.md` as
|
|
122
|
+
its instructions (not `AGENTS.md`, which a repository writes for an agent
|
|
123
|
+
with a shell) and lists the skills the game's playbook names in
|
|
124
|
+
`skills/index.json`. Nothing in this package names a game.
|
|
125
|
+
- **`preview_status`** asks the page whether the running world took the latest
|
|
126
|
+
draft revision, with the errors it hit by file and line.
|
|
127
|
+
|
|
80
128
|
## Building the artifact
|
|
81
129
|
|
|
82
130
|
Requires Node **22.19+** and pnpm (corepack). The upstream DeepSeek Harness is a
|
|
@@ -104,7 +152,10 @@ Once the pin publishes, the hint is inert; drop it with the next SDK bump.
|
|
|
104
152
|
`vfs-image.tar.gz`, ~7 MB), `BUILD.json` (package version, this repo's commit,
|
|
105
153
|
upstream tag and commit, the CrowdyJS the worker bundles, sha256 of every file),
|
|
106
154
|
`LICENSE.deepseek-harness` and `THIRD_PARTY_NOTICES.md`. Serve it under
|
|
107
|
-
`/dsh/` of the game origin.
|
|
155
|
+
`/dsh/` of the game's own origin, with the headers above.
|
|
156
|
+
`preview/vfs-image.tar.gz` must reach the browser with no `Content-Encoding`
|
|
157
|
+
header, because the worker decompresses it itself; a host that adds
|
|
158
|
+
`Content-Encoding: gzip` to `.gz` files needs an exception for that file.
|
|
108
159
|
|
|
109
160
|
The build refuses an artifact that names the builder's home directory or the
|
|
110
161
|
upstream checkout path (`//#region` markers and `patched by` comments are
|
package/dist/dsh-web/BUILD.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@crowdedkingdoms/crowdy-dsh",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"builtAt": "2026-10-
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"builtAt": "2026-10-30T01:05:53.106Z",
|
|
5
5
|
"source": {
|
|
6
6
|
"repository": "CrowdedKingdoms/crowdy-dsh",
|
|
7
|
-
"commit": "
|
|
7
|
+
"commit": "49abf09223d4718ced71f85e22ff2d9cccd13a5c",
|
|
8
8
|
"dirty": false
|
|
9
9
|
},
|
|
10
10
|
"upstream": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"crowdyjs": {
|
|
17
17
|
"name": "@crowdedkingdoms/crowdyjs",
|
|
18
|
-
"version": "18.
|
|
18
|
+
"version": "18.23.1-dev.1",
|
|
19
19
|
"source": "node_modules"
|
|
20
20
|
},
|
|
21
21
|
"files": {
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"manifest.webmanifest": "sha256:9b54d57eea00f2fdd1affe6e7999a4209a515755f12ac1a3299da2d55e178d4c",
|
|
113
113
|
"preview/bootstrap-CYECZNXt.js": "sha256:9f303a0485c0badfdd19fad0c357ef050c5b9a343744ab5bf0c70015e7d95092",
|
|
114
114
|
"preview/crowdy-boot-Cklh1qNl.js": "sha256:b21e8eb126e1cd8a52159d2d577e610df6c8af36a436f9ed5028cfabd11a85ff",
|
|
115
|
-
"preview/vfs-image.tar.gz": "sha256:
|
|
115
|
+
"preview/vfs-image.tar.gz": "sha256:1f7ea58f56f33bbb97db31be2fd556851f6948ace2e6320d49cca076d1d15f37",
|
|
116
116
|
"preview/worker-C8-_ANaz.js": "sha256:81099e5732dfe0c32bacd5897316b7956c5a0a22da01b4a0c6e21d0a3b9d9aa1"
|
|
117
117
|
}
|
|
118
118
|
}
|
|
Binary file
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cordis service `ctx.crowdyBridgeClient`: the worker's end of the page
|
|
3
|
+
* channel, on its own. The game filesystem talks to the page through it and
|
|
4
|
+
* so does `ctx.crowdyBridge`; neither depends on the other, which is what
|
|
5
|
+
* keeps the filesystem and the bridge from needing each other at startup.
|
|
6
|
+
*
|
|
7
|
+
* @module @crowdedkingdoms/crowdy-dsh/bridge-client
|
|
8
|
+
*/
|
|
9
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
10
|
+
import z from '@deepseek-ai/schemastery';
|
|
11
|
+
import { loadCrowdyConfig } from '../crowdy/config.js';
|
|
12
|
+
import { BridgeClient } from './client.js';
|
|
13
|
+
export const name = 'crowdy-bridge-client';
|
|
14
|
+
export class CrowdyBridgeClientService extends Service {
|
|
15
|
+
static Config = z.object({
|
|
16
|
+
channel: z.string(),
|
|
17
|
+
nonce: z.string(),
|
|
18
|
+
timeoutMs: z.number().default(15_000),
|
|
19
|
+
});
|
|
20
|
+
client;
|
|
21
|
+
constructor(ctx, config = {}) {
|
|
22
|
+
super(ctx, 'crowdyBridgeClient');
|
|
23
|
+
const boot = loadCrowdyConfig();
|
|
24
|
+
this.client = new BridgeClient({
|
|
25
|
+
channel: config.channel ?? boot.bridgeChannel,
|
|
26
|
+
nonce: config.nonce ?? boot.bridgeNonce,
|
|
27
|
+
timeoutMs: config.timeoutMs,
|
|
28
|
+
});
|
|
29
|
+
ctx.effect(() => () => this.client.close(), 'crowdy bridge client');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export default CrowdyBridgeClientService;
|
|
33
|
+
//# sourceMappingURL=client-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-service.js","sourceRoot":"","sources":["../../src/bridge/client-service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAW,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAiB1C,MAAM,CAAC,MAAM,IAAI,GAAG,sBAAsB,CAAA;AAE1C,MAAM,OAAO,yBAA0B,SAAQ,OAAO;IACpD,MAAM,CAAC,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;QAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;KACtC,CAAyB,CAAA;IAEjB,MAAM,CAAc;IAE7B,YAAY,GAAY,EAAE,SAAiB,EAAE;QAC3C,KAAK,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAA;QAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC;YAC7B,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa;YAC7C,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW;YACvC,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAA;QACF,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAA;IACrE,CAAC;;AAGH,eAAe,yBAAyB,CAAA"}
|
package/lib/bridge/client.js
CHANGED
|
@@ -29,6 +29,7 @@ export class BridgeClient {
|
|
|
29
29
|
channel;
|
|
30
30
|
pending = new Map();
|
|
31
31
|
listeners = new Map();
|
|
32
|
+
presenceWaiters = [];
|
|
32
33
|
timeoutMs;
|
|
33
34
|
nonce;
|
|
34
35
|
sequence = 0;
|
|
@@ -52,6 +53,21 @@ export class BridgeClient {
|
|
|
52
53
|
get available() {
|
|
53
54
|
return this.channel !== undefined;
|
|
54
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolves once the page has said hello, or after `timeoutMs` either way
|
|
58
|
+
* (a request made then fails with the usual not-connected error).
|
|
59
|
+
*/
|
|
60
|
+
whenPagePresent(timeoutMs = 10_000) {
|
|
61
|
+
if (this.pagePresent || !this.channel)
|
|
62
|
+
return Promise.resolve();
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
65
|
+
this.presenceWaiters.push(() => {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
55
71
|
on(event, listener) {
|
|
56
72
|
let set = this.listeners.get(event);
|
|
57
73
|
if (!set) {
|
|
@@ -136,8 +152,11 @@ export class BridgeClient {
|
|
|
136
152
|
return;
|
|
137
153
|
}
|
|
138
154
|
case 'event': {
|
|
139
|
-
if (data.event === 'page.hello')
|
|
155
|
+
if (data.event === 'page.hello') {
|
|
140
156
|
this.pagePresent = true;
|
|
157
|
+
for (const wake of this.presenceWaiters.splice(0))
|
|
158
|
+
wake();
|
|
159
|
+
}
|
|
141
160
|
if (data.event === 'page.bye')
|
|
142
161
|
this.pagePresent = false;
|
|
143
162
|
const set = this.listeners.get(data.event);
|
package/lib/bridge/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/bridge/client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/bridge/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,kBAAkB,EAClB,8BAA8B,EAC9B,aAAa,GAQd,MAAM,eAAe,CAAA;AAEtB,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGzB;IAFX,YACE,OAAe,EACN,IAAY;QAErB,KAAK,CAAC,OAAO,CAAC,CAAA;QAFL,SAAI,GAAJ,IAAI,CAAQ;QAGrB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAA;IAC3B,CAAC;CACF;AAUD,SAAS,qBAAqB;IAC5B,MAAM,KAAK,GAAG,UAAsE,CAAA;IACpF,IAAI,OAAO,KAAK,CAAC,gBAAgB,KAAK,UAAU;QAAE,OAAO,SAAS,CAAA;IAClE,MAAM,IAAI,GAAG,KAAK,CAAC,gBAAgB,CAAA;IACnC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAA;AACjC,CAAC;AAaD,MAAM,OAAO,YAAY;IACN,OAAO,CAAyB;IAChC,OAAO,GAAG,IAAI,GAAG,EAG/B,CAAA;IACc,SAAS,GAAG,IAAI,GAAG,EAA2C,CAAA;IAC9D,eAAe,GAAsB,EAAE,CAAA;IACvC,SAAS,CAAQ;IACjB,KAAK,CAAQ;IACtB,QAAQ,GAAG,CAAC,CAAA;IACpB,8DAA8D;IAC9D,WAAW,GAAG,KAAK,CAAA;IAEnB,YAAY,UAA+B,EAAE;QAC3C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAA;QAC5C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAA;QAChC,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,IAAI,qBAAqB,EAAE,CAAA;QACjE,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,mHAAmH,CAAC,CAAA;QACnI,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;YAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YACvC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAA;IACnC,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,SAAS,GAAG,MAAM;QAChC,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC/D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;YAC5C,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE;gBAC7B,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,EAAE,CAAsB,KAAQ,EAAE,QAA4C;QAC5E,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAA;YACf,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAChC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,QAAsC,CAAC,CAAA;QAC/C,OAAO,GAAG,EAAE;YACV,GAAG,EAAE,MAAM,CAAC,QAAsC,CAAC,CAAA;QACrD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,CAAwB,KAAQ,EAAE,OAA0B;QAC9D,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,KAAK,GAAgB,EAAE,CAAC,EAAE,8BAA8B,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QAC3H,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAED,KAAK,CAAC,OAAO,CACX,MAAS,EACT,MAAqC,EACrC,UAAwD,EAAE;QAE1D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,WAAW,CACnB,sGAAsG,EACtG,kBAAkB,CAAC,WAAW,CAC/B,CAAA;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,WAAW,CACnB,qGAAqG,EACrG,kBAAkB,CAAC,WAAW,CAC/B,CAAA;QACH,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAA;QAChC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA;QAClB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;QACzD,MAAM,KAAK,GAAgB,EAAE,CAAC,EAAE,8BAA8B,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;QAC7H,OAAO,IAAI,OAAO,CAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACpE,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAA;YACnD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACvB,MAAM,CAAC,IAAI,WAAW,CAAC,gCAAgC,MAAM,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAA;YACtI,CAAC,EAAE,OAAO,CAAC,CAAA;YACX,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACvB,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAA;YACjF,CAAC,CAAA;YACD,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YAClE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE;gBACnB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBACjB,YAAY,CAAC,KAAK,CAAC,CAAA;oBACnB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBACrD,OAAO,CAAC,KAAsC,CAAC,CAAA;gBACjD,CAAC;gBACD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;oBAChB,YAAY,CAAC,KAAK,CAAC,CAAA;oBACnB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBACrD,MAAM,CAAC,KAAK,CAAC,CAAA;gBACf,CAAC;gBACD,KAAK;aACN,CAAC,CAAA;YACF,IAAI,CAAC,OAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAClC,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK;QACH,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,KAAK,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAA;QACrF,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QACpB,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAA;IACvB,CAAC;IAEO,MAAM,CAAC,IAAa;QAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAM;QACpE,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC;YACf,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACvC,IAAI,CAAC,KAAK;oBAAE,OAAM;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAC5B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAC1B,OAAM;YACR,CAAC;YACD,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACvC,IAAI,CAAC,KAAK;oBAAE,OAAM;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAC5B,KAAK,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAA;gBACtF,OAAM;YACR,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;oBAChC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;oBACvB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;wBAAE,IAAI,EAAE,CAAA;gBAC3D,CAAC;gBACD,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;oBAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;gBACvD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC1C,IAAI,CAAC,GAAG;oBAAE,OAAM;gBAChB,KAAK,MAAM,QAAQ,IAAI,GAAG,EAAE,CAAC;oBAC3B,IAAI,CAAC;wBACH,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;oBACxB,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,IAAI,CAAC,+BAA+B,IAAI,CAAC,KAAK,QAAQ,EAAE,KAAK,CAAC,CAAA;oBACxE,CAAC;gBACH,CAAC;gBACD,OAAM;YACR,CAAC;YACD;gBACE,OAAM;QACV,CAAC;IACH,CAAC;CACF"}
|
package/lib/bridge/index.js
CHANGED
|
@@ -9,45 +9,42 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { Service } from '@deepseek-ai/cordis';
|
|
11
11
|
import z from '@deepseek-ai/schemastery';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { publishAppToken } from '../crowdy/token.js';
|
|
13
|
+
import { isStudioFileSystem } from '../fs/studio-fs.js';
|
|
14
14
|
export { BridgeClient, BridgeError } from './client.js';
|
|
15
15
|
export * from './protocol.js';
|
|
16
|
+
/** What this worker can mount; the page refuses game mode against a worker without it. */
|
|
17
|
+
const MODES = ['mod', 'game'];
|
|
16
18
|
/** Cordis plugin name used by loader diagnostics. */
|
|
17
19
|
export const name = 'crowdy-bridge';
|
|
18
20
|
export class CrowdyBridge extends Service {
|
|
19
|
-
static inject = ['fs'];
|
|
20
|
-
static Config = z.object({
|
|
21
|
-
channel: z.string(),
|
|
22
|
-
nonce: z.string(),
|
|
23
|
-
timeoutMs: z.number().default(15_000),
|
|
24
|
-
});
|
|
21
|
+
static inject = ['fs', 'crowdyBridgeClient'];
|
|
22
|
+
static Config = z.object({});
|
|
25
23
|
client;
|
|
26
24
|
fs;
|
|
27
25
|
captureCounter = 0;
|
|
28
26
|
disposers = [];
|
|
29
|
-
constructor(ctx,
|
|
27
|
+
constructor(ctx, _config = {}) {
|
|
30
28
|
super(ctx, 'crowdyBridge');
|
|
31
29
|
const fs = ctx.fs;
|
|
32
|
-
if (!(fs
|
|
33
|
-
throw new Error('crowdy-bridge: ctx.fs must be
|
|
30
|
+
if (!isStudioFileSystem(fs)) {
|
|
31
|
+
throw new Error('crowdy-bridge: ctx.fs must be a Crowdy Studio filesystem (@crowdedkingdoms/crowdy-dsh/fs).');
|
|
34
32
|
}
|
|
35
33
|
this.fs = fs;
|
|
36
|
-
this.client =
|
|
37
|
-
channel: config.channel ?? fs.boot.bridgeChannel,
|
|
38
|
-
nonce: config.nonce ?? fs.boot.bridgeNonce,
|
|
39
|
-
timeoutMs: config.timeoutMs,
|
|
40
|
-
});
|
|
34
|
+
this.client = ctx.crowdyBridgeClient.client;
|
|
41
35
|
this.wire();
|
|
42
|
-
// Registrations unwind with the plugin: the
|
|
43
|
-
//
|
|
36
|
+
// Registrations unwind with the plugin: the fs listeners detach when the row unloads.
|
|
37
|
+
// The channel belongs to the bridge-client service and closes with it.
|
|
44
38
|
ctx.effect(() => () => {
|
|
45
39
|
for (const dispose of this.disposers)
|
|
46
40
|
dispose();
|
|
47
41
|
this.disposers.length = 0;
|
|
48
|
-
this.client.close();
|
|
49
42
|
}, 'crowdy bridge');
|
|
50
43
|
}
|
|
44
|
+
/** The editor this worker mounted. */
|
|
45
|
+
get studioMode() {
|
|
46
|
+
return this.fs.studioMode;
|
|
47
|
+
}
|
|
51
48
|
/** Whether a Studio page is attached (page-executed tools can work). */
|
|
52
49
|
get pageConnected() {
|
|
53
50
|
return this.client.available && this.client.pagePresent;
|
|
@@ -100,7 +97,10 @@ export class CrowdyBridge extends Service {
|
|
|
100
97
|
const live = agents?.list() ?? [];
|
|
101
98
|
let sessionId = live.length > 0 ? live[live.length - 1].session.id : undefined;
|
|
102
99
|
if (sessionId === undefined) {
|
|
103
|
-
const created = await sessions.create({
|
|
100
|
+
const created = await sessions.create({
|
|
101
|
+
cwd: this.fs.mountRoot,
|
|
102
|
+
agentPreset: this.fs.studioMode === 'game' ? 'crowdy-game' : 'crowdy',
|
|
103
|
+
});
|
|
104
104
|
sessionId = created.sessionId;
|
|
105
105
|
}
|
|
106
106
|
await sessions.prompt({
|
|
@@ -115,15 +115,20 @@ export class CrowdyBridge extends Service {
|
|
|
115
115
|
if (!client.available)
|
|
116
116
|
return;
|
|
117
117
|
this.disposers.push(client.on('page.hello', (payload) => {
|
|
118
|
-
if (payload.appToken)
|
|
118
|
+
if (payload.appToken) {
|
|
119
|
+
publishAppToken(payload.appToken);
|
|
119
120
|
fs.setToken(payload.appToken);
|
|
121
|
+
}
|
|
120
122
|
if (payload.projectId)
|
|
121
123
|
fs.setProject(payload.projectId);
|
|
122
124
|
fs.invalidate();
|
|
123
|
-
client.emit('worker.ready',
|
|
125
|
+
client.emit('worker.ready', this.readyPayload());
|
|
124
126
|
}), client.on('page.token', (payload) => {
|
|
125
|
-
//
|
|
127
|
+
// CROWDY_APP_TOKEN is what the model route reads per request.
|
|
128
|
+
publishAppToken(payload.appToken);
|
|
126
129
|
fs.setToken(payload.appToken);
|
|
130
|
+
}), client.on('page.draftChanged', (payload) => {
|
|
131
|
+
fs.applyDraftChange(payload);
|
|
127
132
|
}), client.on('page.project', (payload) => {
|
|
128
133
|
if (payload.projectId)
|
|
129
134
|
fs.setProject(payload.projectId);
|
|
@@ -153,7 +158,11 @@ export class CrowdyBridge extends Service {
|
|
|
153
158
|
for (const message of fs.drainWarnings())
|
|
154
159
|
client.emit('worker.warning', { message });
|
|
155
160
|
// Announce so a page that connected before the worker booted learns we exist.
|
|
156
|
-
client.emit('worker.ready',
|
|
161
|
+
client.emit('worker.ready', this.readyPayload());
|
|
162
|
+
}
|
|
163
|
+
readyPayload() {
|
|
164
|
+
const store = this.fs.storeReason;
|
|
165
|
+
return { root: this.fs.mountRoot, ...(store ? { store } : {}), modes: MODES, mode: this.fs.studioMode };
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
168
|
export default CrowdyBridge;
|
package/lib/bridge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAW,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAKxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"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"}
|
package/lib/bridge/protocol.js
CHANGED
|
@@ -24,7 +24,36 @@
|
|
|
24
24
|
* `grid.programStatus` run a JS grid program from a project file inside it.
|
|
25
25
|
* The page answers them only when its game offers a grid capability.
|
|
26
26
|
*/
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* v5 (crowdy-dsh 0.5 / CrowdyJS 18.23): game mode. A boot with
|
|
29
|
+
* `studioMode: 'game'` edits the bound Construct game, not the mod crates. The
|
|
30
|
+
* page owns a draft of the repository; the worker reads it as a snapshot
|
|
31
|
+
* (`draft.tree`, batched `draft.read`), writes under the harness's own write
|
|
32
|
+
* preconditions (`draft.write` / `draft.delete`), and learns of every other
|
|
33
|
+
* change from `page.draftChanged`. `draft.commit` publishes the draft as ONE
|
|
34
|
+
* commit with the agent's message after the player confirms on the page;
|
|
35
|
+
* `preview.status` reports whether the world took the draft. Versions are git
|
|
36
|
+
* blob SHA-1 hashes, so an unchanged draft file hashes to its GitHub blob.
|
|
37
|
+
* `worker.ready` names the modes the worker can mount; a page that booted
|
|
38
|
+
* game mode against a worker without it keeps the mod editor. The v4 game
|
|
39
|
+
* requests (`studio.putGameFile`, `listRepo`, ...) were never published.
|
|
40
|
+
*/
|
|
41
|
+
export const CROWDY_BRIDGE_PROTOCOL_VERSION = 5;
|
|
42
|
+
/** Stable `err` codes the page answers draft requests with. */
|
|
43
|
+
export const DRAFT_ERROR_CODES = {
|
|
44
|
+
/** An `ifHash` or `createIfAbsent` precondition failed. */
|
|
45
|
+
stale: 'DRAFT_STALE',
|
|
46
|
+
notFound: 'DRAFT_NOT_FOUND',
|
|
47
|
+
/** The path is outside what the dock may touch. */
|
|
48
|
+
refused: 'DRAFT_PATH_REFUSED',
|
|
49
|
+
tooLarge: 'DRAFT_TOO_LARGE',
|
|
50
|
+
/** The branch moved and these paths changed on both sides. */
|
|
51
|
+
conflict: 'DRAFT_CONFLICT',
|
|
52
|
+
/** The player declined the commit. */
|
|
53
|
+
declined: 'DRAFT_DECLINED',
|
|
54
|
+
/** This page or project has no draft (mod mode, unbound project). */
|
|
55
|
+
unavailable: 'DRAFT_UNAVAILABLE',
|
|
56
|
+
};
|
|
28
57
|
export const BRIDGE_ERROR_CODES = {
|
|
29
58
|
unavailable: 'BRIDGE_UNAVAILABLE',
|
|
30
59
|
timeout: 'BRIDGE_TIMEOUT',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/bridge/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;GAOG;AACH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/bridge/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;GAOG;AACH;;;;;GAKG;AACH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAU,CAAA;AAqMxD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,2DAA2D;IAC3D,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE,iBAAiB;IAC3B,mDAAmD;IACnD,OAAO,EAAE,oBAAoB;IAC7B,QAAQ,EAAE,iBAAiB;IAC3B,8DAA8D;IAC9D,QAAQ,EAAE,gBAAgB;IAC1B,sCAAsC;IACtC,QAAQ,EAAE,gBAAgB;IAC1B,qEAAqE;IACrE,WAAW,EAAE,mBAAmB;CACxB,CAAA;AA+FV,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW,EAAE,oBAAoB;IACjC,OAAO,EAAE,gBAAgB;IACzB,OAAO,EAAE,gBAAgB;IACzB,SAAS,EAAE,YAAY;CACf,CAAA;AAEV,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,KAAc;IAC1D,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,KAAK,GAAG,KAA6B,CAAA;IAC3C,IAAI,KAAK,CAAC,CAAC,KAAK,8BAA8B,IAAI,OAAO,KAAK,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC1H,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAClE,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,KAAK,KAAK,CAAA;AACjD,CAAC"}
|
package/lib/crowdy/config.js
CHANGED
|
@@ -31,6 +31,7 @@ const ENV_KEYS = {
|
|
|
31
31
|
bridgeNonce: 'CROWDY_BRIDGE_NONCE',
|
|
32
32
|
studioOrigin: 'CROWDY_STUDIO_ORIGIN',
|
|
33
33
|
persistScope: 'CROWDY_PERSIST_SCOPE',
|
|
34
|
+
studioMode: 'CROWDY_STUDIO_MODE',
|
|
34
35
|
};
|
|
35
36
|
function readFile(home) {
|
|
36
37
|
if (!home)
|
|
@@ -74,9 +75,14 @@ export function loadCrowdyConfig(overrides = {}) {
|
|
|
74
75
|
bridgeNonce: pick('bridgeNonce'),
|
|
75
76
|
studioOrigin: pick('studioOrigin'),
|
|
76
77
|
persistScope: pick('persistScope'),
|
|
78
|
+
studioMode: pick('studioMode') === 'game' ? 'game' : pick('studioMode') === 'mod' ? 'mod' : undefined,
|
|
77
79
|
};
|
|
78
80
|
return config;
|
|
79
81
|
}
|
|
82
|
+
/** The pair this boot mounts. Anything other than `game` is the mod editor. */
|
|
83
|
+
export function activeStudioMode(overrides = {}) {
|
|
84
|
+
return loadCrowdyConfig(overrides).studioMode === 'game' ? 'game' : 'mod';
|
|
85
|
+
}
|
|
80
86
|
/** Human-readable reason the configuration cannot reach a project yet. */
|
|
81
87
|
export function describeMissing(config) {
|
|
82
88
|
const missing = [];
|
package/lib/crowdy/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/crowdy/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/crowdy/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playbook pages: markdown the game ships under its playbook base, read
|
|
3
|
+
* through the page (`studio.readPlaybook`). The page applies the same check
|
|
4
|
+
* (CrowdyJS `crowdy-dsh/game-paths.ts`); this copy refuses a bad name before
|
|
5
|
+
* it crosses the bridge.
|
|
6
|
+
*/
|
|
7
|
+
export function assertPlaybookPage(page) {
|
|
8
|
+
const trimmed = String(page ?? '').trim().replace(/^\/+/, '');
|
|
9
|
+
if (!trimmed || trimmed.includes('..') || trimmed.includes('\\') || /[?#\0]/.test(trimmed) || trimmed.startsWith('.')) {
|
|
10
|
+
throw new Error('Playbook pages are markdown files shipped with the game.');
|
|
11
|
+
}
|
|
12
|
+
if (!/^[\w./-]+\.md$/.test(trimmed)) {
|
|
13
|
+
throw new Error('Name a playbook page such as playbook/authoring-loop.md.');
|
|
14
|
+
}
|
|
15
|
+
return trimmed;
|
|
16
|
+
}
|
|
17
|
+
/** Split `---` frontmatter off a skill page; returns the body (trimmed) and the raw frontmatter. */
|
|
18
|
+
export function splitFrontmatter(text) {
|
|
19
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(text.replace(/^\uFEFF/, '').trimStart());
|
|
20
|
+
if (!match)
|
|
21
|
+
return { frontmatter: null, body: text.trim() };
|
|
22
|
+
return { frontmatter: match[1] ?? null, body: (match[2] ?? '').trim() };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=playbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playbook.js","sourceRoot":"","sources":["../../src/crowdy/playbook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC7D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtH,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,6CAA6C,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;IACzG,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAA;IAC3D,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAA;AACzE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository paths the game filesystem lists and writes. The page's draft
|
|
3
|
+
* store (CrowdyJS `crowdy-studio/draft/paths.ts`) applies the same rule and
|
|
4
|
+
* is the one that decides; this copy keeps the worker from asking for paths
|
|
5
|
+
* the page will refuse. Keep the two in step.
|
|
6
|
+
*
|
|
7
|
+
* Out: `.git`, `node_modules`, dotenv files, any path starting with a dot
|
|
8
|
+
* (`.github/` included) and workflow files, which the Studio GitHub App has
|
|
9
|
+
* no permission to write.
|
|
10
|
+
*/
|
|
11
|
+
const SAFE_PATH = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;
|
|
12
|
+
function deniedSegment(segment) {
|
|
13
|
+
return segment === '.git' || segment === 'node_modules' || segment === '.env' || segment.startsWith('.env.');
|
|
14
|
+
}
|
|
15
|
+
/** A relative repository path the game editor may list and write. */
|
|
16
|
+
export function isRepoPath(path) {
|
|
17
|
+
if (typeof path !== 'string' || !SAFE_PATH.test(path) || path.includes('..') || path.endsWith('/'))
|
|
18
|
+
return false;
|
|
19
|
+
if (path.split('/').some((segment) => segment === '' || deniedSegment(segment)))
|
|
20
|
+
return false;
|
|
21
|
+
return !/^\.github\/workflows(\/|$)/i.test(path);
|
|
22
|
+
}
|
|
23
|
+
/** A directory inside the repository, including the root (`''`). */
|
|
24
|
+
export function isRepoDir(path) {
|
|
25
|
+
return path === '' || isRepoPath(path);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=repo-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-paths.js","sourceRoot":"","sources":["../../src/crowdy/repo-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,SAAS,GAAG,+BAA+B,CAAA;AAEjD,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,cAAc,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;AAC9G,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAChH,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAC7F,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAClD,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The player's app token in this worker. It arrives over the bridge
|
|
3
|
+
* (`page.hello`, `page.token`), lives in memory only, and is published to
|
|
4
|
+
* `process.env.CROWDY_APP_TOKEN` because the model route reads it from there
|
|
5
|
+
* per request. It is never written to a seed file, the virtual filesystem or
|
|
6
|
+
* OPFS.
|
|
7
|
+
*/
|
|
8
|
+
export const APP_TOKEN_ENV = 'CROWDY_APP_TOKEN';
|
|
9
|
+
export function publishAppToken(token) {
|
|
10
|
+
if (!token)
|
|
11
|
+
return;
|
|
12
|
+
if (typeof process === 'undefined' || !process.env)
|
|
13
|
+
return;
|
|
14
|
+
process.env[APP_TOKEN_ENV] = token;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/crowdy/token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAA;AAE/C,MAAM,UAAU,eAAe,CAAC,KAAyB;IACvD,IAAI,CAAC,KAAK;QAAE,OAAM;IAClB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG;QAAE,OAAM;IAC1D,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,KAAK,CAAA;AACpC,CAAC"}
|
|
@@ -60,16 +60,9 @@ export function versionOf(content) {
|
|
|
60
60
|
* absent there), so the token is published to `process.env` directly. In the
|
|
61
61
|
* cockpit the variable is already set by the operator and this is a no-op.
|
|
62
62
|
*/
|
|
63
|
-
export
|
|
63
|
+
export { APP_TOKEN_ENV } from '../crowdy/token.js';
|
|
64
64
|
/** How long the first project load waits for the page to hand over the token. */
|
|
65
65
|
const CREDENTIAL_WAIT_MS = 5_000;
|
|
66
|
-
function publishTokenToEnvironment(token) {
|
|
67
|
-
if (!token)
|
|
68
|
-
return;
|
|
69
|
-
if (typeof process === 'undefined' || !process.env)
|
|
70
|
-
return;
|
|
71
|
-
process.env[APP_TOKEN_ENV] = token;
|
|
72
|
-
}
|
|
73
66
|
function byteLength(text) {
|
|
74
67
|
return new TextEncoder().encode(text).byteLength;
|
|
75
68
|
}
|
|
@@ -85,6 +78,9 @@ function countOccurrences(haystack, needle) {
|
|
|
85
78
|
return count;
|
|
86
79
|
}
|
|
87
80
|
export class CrowdyFileSystem extends FileSystem {
|
|
81
|
+
studioMode = 'mod';
|
|
82
|
+
/** The mod crates do not follow a game draft. */
|
|
83
|
+
applyDraftChange(_change) { }
|
|
88
84
|
static Config = z.object({
|
|
89
85
|
graphqlUrl: z.string(),
|
|
90
86
|
appId: z.string(),
|
|
@@ -124,7 +120,6 @@ export class CrowdyFileSystem extends FileSystem {
|
|
|
124
120
|
this.snapshotTtl = snapshotTtlMs ?? 750;
|
|
125
121
|
this.boot = loadCrowdyConfig(overrides);
|
|
126
122
|
this.root = normalizeAbsolute(this.boot.root ?? DEFAULT_ROOT);
|
|
127
|
-
publishTokenToEnvironment(this.boot.appToken);
|
|
128
123
|
this.client = new CrowdyStudioClient({
|
|
129
124
|
endpoint: this.boot.graphqlUrl,
|
|
130
125
|
appId: this.boot.appId,
|
|
@@ -154,7 +149,6 @@ export class CrowdyFileSystem extends FileSystem {
|
|
|
154
149
|
setToken(token) {
|
|
155
150
|
this.boot = { ...this.boot, appToken: token };
|
|
156
151
|
this.client.setToken(token);
|
|
157
|
-
publishTokenToEnvironment(token);
|
|
158
152
|
if (token) {
|
|
159
153
|
const waiters = this.tokenWaiters;
|
|
160
154
|
this.tokenWaiters = [];
|