@crowdedkingdoms/crowdy-dsh 0.2.0-dev.1 → 0.2.0-dev.2

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 (105) hide show
  1. package/THIRD_PARTY_NOTICES.md +226 -0
  2. package/dist/dsh-web/BUILD.json +3 -3
  3. package/dist/dsh-web/preview/vfs-image.tar.gz +0 -0
  4. package/lib/attachments/crowdy-attachment-store.js +200 -0
  5. package/lib/attachments/crowdy-attachment-store.js.map +1 -0
  6. package/lib/bridge/client.js +161 -0
  7. package/lib/bridge/client.js.map +1 -0
  8. package/lib/bridge/index.js +155 -0
  9. package/lib/bridge/index.js.map +1 -0
  10. package/lib/bridge/protocol.js +30 -0
  11. package/lib/bridge/protocol.js.map +1 -0
  12. package/lib/crowdy/client.js +247 -0
  13. package/lib/crowdy/client.js.map +1 -0
  14. package/lib/crowdy/config.js +95 -0
  15. package/lib/crowdy/config.js.map +1 -0
  16. package/lib/crowdy/github-layout.js +97 -0
  17. package/lib/crowdy/github-layout.js.map +1 -0
  18. package/lib/crowdy/paths.js +145 -0
  19. package/lib/crowdy/paths.js.map +1 -0
  20. package/lib/crowdy/project-store.js +223 -0
  21. package/lib/crowdy/project-store.js.map +1 -0
  22. package/lib/fs/crowdy-file-system.js +621 -0
  23. package/lib/fs/crowdy-file-system.js.map +1 -0
  24. package/lib/fs/scratch-store.js +61 -0
  25. package/lib/fs/scratch-store.js.map +1 -0
  26. package/lib/index.js +15 -0
  27. package/lib/index.js.map +1 -0
  28. package/lib/persist/index.js +199 -0
  29. package/lib/persist/index.js.map +1 -0
  30. package/lib/scripts/probe.js +59 -0
  31. package/lib/scripts/probe.js.map +1 -0
  32. package/lib/sdk-index/catalog.js +237 -0
  33. package/lib/sdk-index/catalog.js.map +1 -0
  34. package/lib/sdk-index/index.js +10 -0
  35. package/lib/sdk-index/index.js.map +1 -0
  36. package/lib/sdk-index/parse-sdk.js +131 -0
  37. package/lib/sdk-index/parse-sdk.js.map +1 -0
  38. package/lib/sdk-index/plugin.js +90 -0
  39. package/lib/sdk-index/plugin.js.map +1 -0
  40. package/lib/sdk-index/snapshot.js +215 -0
  41. package/lib/sdk-index/snapshot.js.map +1 -0
  42. package/lib/search/glob-match.js +114 -0
  43. package/lib/search/glob-match.js.map +1 -0
  44. package/lib/search/search-tools.js +414 -0
  45. package/lib/search/search-tools.js.map +1 -0
  46. package/lib/tools/index.js +344 -0
  47. package/lib/tools/index.js.map +1 -0
  48. package/lib/types/attachments/crowdy-attachment-store.d.ts +45 -0
  49. package/lib/types/attachments/crowdy-attachment-store.d.ts.map +1 -0
  50. package/lib/types/attachments/crowdy-attachment-store.test.d.ts.map +1 -0
  51. package/lib/types/bridge/client.d.ts +57 -0
  52. package/lib/types/bridge/client.d.ts.map +1 -0
  53. package/lib/types/bridge/client.test.d.ts.map +1 -0
  54. package/lib/types/bridge/index.d.ts +66 -0
  55. package/lib/types/bridge/index.d.ts.map +1 -0
  56. package/lib/types/bridge/protocol.d.ts +242 -0
  57. package/lib/types/bridge/protocol.d.ts.map +1 -0
  58. package/lib/types/crowdy/client.d.ts +126 -0
  59. package/lib/types/crowdy/client.d.ts.map +1 -0
  60. package/lib/types/crowdy/client.test.d.ts.map +1 -0
  61. package/lib/types/crowdy/config.d.ts +60 -0
  62. package/lib/types/crowdy/config.d.ts.map +1 -0
  63. package/lib/types/crowdy/github-layout.d.ts +36 -0
  64. package/lib/types/crowdy/github-layout.d.ts.map +1 -0
  65. package/lib/types/crowdy/paths.d.ts +89 -0
  66. package/lib/types/crowdy/paths.d.ts.map +1 -0
  67. package/lib/types/crowdy/project-store.d.ts +84 -0
  68. package/lib/types/crowdy/project-store.d.ts.map +1 -0
  69. package/lib/types/crowdy/project-store.test.d.ts.map +1 -0
  70. package/lib/types/fs/crowdy-file-system.d.ts +173 -0
  71. package/lib/types/fs/crowdy-file-system.d.ts.map +1 -0
  72. package/lib/types/fs/crowdy-file-system.test.d.ts.map +1 -0
  73. package/lib/types/fs/scratch-store.d.ts +31 -0
  74. package/lib/types/fs/scratch-store.d.ts.map +1 -0
  75. package/lib/types/index.d.ts +19 -0
  76. package/lib/types/index.d.ts.map +1 -0
  77. package/lib/types/persist/index.d.ts +85 -0
  78. package/lib/types/persist/index.d.ts.map +1 -0
  79. package/lib/types/scripts/probe.d.ts +9 -0
  80. package/lib/types/scripts/probe.d.ts.map +1 -0
  81. package/lib/types/sdk-index/catalog.d.ts +39 -0
  82. package/lib/types/sdk-index/catalog.d.ts.map +1 -0
  83. package/lib/types/sdk-index/catalog.test.d.ts.map +1 -0
  84. package/lib/types/sdk-index/index.d.ts +13 -0
  85. package/lib/types/sdk-index/index.d.ts.map +1 -0
  86. package/lib/types/sdk-index/parse-sdk.d.ts +25 -0
  87. package/lib/types/sdk-index/parse-sdk.d.ts.map +1 -0
  88. package/lib/types/sdk-index/plugin.d.ts +26 -0
  89. package/lib/types/sdk-index/plugin.d.ts.map +1 -0
  90. package/lib/types/sdk-index/snapshot.d.ts +11 -0
  91. package/lib/types/sdk-index/snapshot.d.ts.map +1 -0
  92. package/lib/types/search/glob-match.d.ts +31 -0
  93. package/lib/types/search/glob-match.d.ts.map +1 -0
  94. package/lib/types/search/glob-match.test.d.ts.map +1 -0
  95. package/lib/types/search/search-tools.d.ts +81 -0
  96. package/lib/types/search/search-tools.d.ts.map +1 -0
  97. package/lib/types/search/search-tools.test.d.ts.map +1 -0
  98. package/lib/types/tools/index.d.ts +27 -0
  99. package/lib/types/tools/index.d.ts.map +1 -0
  100. package/lib/types/vendor/crowdyjs-sdk.d.ts +17 -0
  101. package/lib/types/vendor/crowdyjs-sdk.d.ts.map +1 -0
  102. package/lib/vendor/crowdyjs-sdk.js +18338 -0
  103. package/lib/vendor/crowdyjs-sdk.js.map +1 -0
  104. package/lib/vendor/crowdyjs-sdk.version.json +5 -0
  105. package/package.json +151 -38
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Wire protocol between the harness (running in the browser worker) and the
3
+ * Crowdy Studio page that embeds it. Both sides join one `BroadcastChannel`
4
+ * whose name the page chose and wrote into `crowdy.json`.
5
+ *
6
+ * The page executes anything that needs the game or the Studio editor
7
+ * (screenshots, draft tests, deploys, project switching, game observation); the
8
+ * worker executes file edits and model calls. CrowdyJS mirrors these types in
9
+ * `src/crowdy-dsh/protocol.ts`; keep the two in step.
10
+ *
11
+ * @module @crowdedkingdoms/crowdy-dsh/bridge-protocol
12
+ */
13
+ export declare const CROWDY_BRIDGE_PROTOCOL_VERSION: 2;
14
+ export type BridgeSide = 'page' | 'worker';
15
+ /**
16
+ * Envelope: every frame carries the protocol version, the boot nonce `n` and
17
+ * the sender. A `BroadcastChannel` is open to every same-origin script, so
18
+ * both sides drop any frame whose nonce is not the one the page handed the
19
+ * worker in the boot message.
20
+ */
21
+ export type BridgeFrame = {
22
+ v: typeof CROWDY_BRIDGE_PROTOCOL_VERSION;
23
+ n: string;
24
+ from: BridgeSide;
25
+ t: 'req';
26
+ id: string;
27
+ method: string;
28
+ params: unknown;
29
+ } | {
30
+ v: typeof CROWDY_BRIDGE_PROTOCOL_VERSION;
31
+ n: string;
32
+ from: BridgeSide;
33
+ t: 'res';
34
+ id: string;
35
+ result: unknown;
36
+ } | {
37
+ v: typeof CROWDY_BRIDGE_PROTOCOL_VERSION;
38
+ n: string;
39
+ from: BridgeSide;
40
+ t: 'err';
41
+ id: string;
42
+ code: string;
43
+ message: string;
44
+ } | {
45
+ v: typeof CROWDY_BRIDGE_PROTOCOL_VERSION;
46
+ n: string;
47
+ from: BridgeSide;
48
+ t: 'event';
49
+ event: string;
50
+ payload: unknown;
51
+ };
52
+ export interface ScreenshotResult {
53
+ /** Suggested file name, e.g. `capture-0003.png`. */
54
+ name: string;
55
+ mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
56
+ /** Encoded bytes (structured-cloned, not transferred). */
57
+ bytes: ArrayBuffer;
58
+ width: number;
59
+ height: number;
60
+ /** What was on screen, in the page's words (HUD text, phase). */
61
+ caption?: string;
62
+ }
63
+ export interface StudioDiagnostic {
64
+ target: 'SERVER' | 'CLIENT';
65
+ path: string;
66
+ line?: number;
67
+ column?: number;
68
+ severity: 'error' | 'warning' | 'info';
69
+ message: string;
70
+ }
71
+ export interface RuntimeStatus {
72
+ target: 'SERVER' | 'CLIENT';
73
+ phase: string;
74
+ moduleName?: string;
75
+ runningRevision?: string;
76
+ savedRevision?: string;
77
+ message?: string;
78
+ }
79
+ export interface BuildResult {
80
+ ok: boolean;
81
+ /** `draft` or `live`. */
82
+ mode: 'draft' | 'live';
83
+ summary: string;
84
+ diagnostics: StudioDiagnostic[];
85
+ /** Compiler output, truncated by the page. */
86
+ buildLog: string;
87
+ runtime: RuntimeStatus[];
88
+ /** Set when the page captured the game after the client target started. */
89
+ screenshot?: ScreenshotResult;
90
+ }
91
+ export interface ProjectSummary {
92
+ projectId: string;
93
+ name: string;
94
+ kind: string;
95
+ updatedAt: string;
96
+ /** Bound repository label when the project is GitHub-bound. */
97
+ github?: string;
98
+ }
99
+ export interface ProjectListResult {
100
+ projects: ProjectSummary[];
101
+ currentProjectId: string | null;
102
+ }
103
+ export interface ProjectOpenResult {
104
+ project: ProjectSummary;
105
+ }
106
+ export interface ProjectCreateParams {
107
+ name: string;
108
+ /** Template id from the Studio starter catalog; omitted means the blank full-stack template. */
109
+ template?: string;
110
+ }
111
+ export interface LogLinesResult {
112
+ lines: string[];
113
+ truncated: boolean;
114
+ }
115
+ export interface GameObservationResult {
116
+ /** Structured observation as the game's PlayerHost reports it. */
117
+ observation: unknown;
118
+ capturedAt: string;
119
+ }
120
+ /** Method names with their parameter and result shapes. */
121
+ export interface BridgeRequestMap {
122
+ 'studio.screenshot': {
123
+ params: {
124
+ label?: string;
125
+ };
126
+ result: ScreenshotResult;
127
+ };
128
+ 'studio.draftTest': {
129
+ params: Record<string, never>;
130
+ result: BuildResult;
131
+ };
132
+ 'studio.deployLive': {
133
+ params: Record<string, never>;
134
+ result: BuildResult;
135
+ };
136
+ 'studio.runtimeStatus': {
137
+ params: Record<string, never>;
138
+ result: {
139
+ runtime: RuntimeStatus[];
140
+ };
141
+ };
142
+ 'studio.runtimeLogs': {
143
+ params: {
144
+ limit?: number;
145
+ };
146
+ result: LogLinesResult;
147
+ };
148
+ 'studio.clientLogs': {
149
+ params: {
150
+ limit?: number;
151
+ };
152
+ result: LogLinesResult;
153
+ };
154
+ 'studio.projectList': {
155
+ params: Record<string, never>;
156
+ result: ProjectListResult;
157
+ };
158
+ 'studio.projectOpen': {
159
+ params: {
160
+ projectId: string;
161
+ };
162
+ result: ProjectOpenResult;
163
+ };
164
+ 'studio.projectCreate': {
165
+ params: ProjectCreateParams;
166
+ result: ProjectOpenResult;
167
+ };
168
+ 'game.observe': {
169
+ params: Record<string, never>;
170
+ result: GameObservationResult;
171
+ };
172
+ }
173
+ export type BridgeMethod = keyof BridgeRequestMap;
174
+ /** Events the page emits. */
175
+ export interface PageEventMap {
176
+ /** Page joined the channel or reloaded its state. */
177
+ 'page.hello': {
178
+ appId: string;
179
+ projectId: string | null;
180
+ appToken?: string;
181
+ };
182
+ 'page.token': {
183
+ appToken: string;
184
+ };
185
+ 'page.project': {
186
+ projectId: string | null;
187
+ };
188
+ /** The page saved the project itself; cached snapshots are stale. */
189
+ 'page.saved': {
190
+ revision?: string;
191
+ };
192
+ /** Shared context the model may read under `context/`. */
193
+ 'page.context': {
194
+ observation?: unknown;
195
+ clientLogs?: string[];
196
+ diagnostics?: StudioDiagnostic[];
197
+ runtime?: RuntimeStatus[];
198
+ note?: string;
199
+ };
200
+ /** A capture the player took from the pane header. */
201
+ 'page.capture': ScreenshotResult;
202
+ /**
203
+ * Text the page wants the agent to work on (e.g. "Fix with AI" from a
204
+ * diagnostic). Queued into the most recent live session, or a new one.
205
+ */
206
+ 'page.prompt': {
207
+ text: string;
208
+ mode?: 'queue' | 'steer';
209
+ };
210
+ /** The page is going away; tools should fail fast. */
211
+ 'page.bye': Record<string, never>;
212
+ }
213
+ /** Events the worker emits. */
214
+ export interface WorkerEventMap {
215
+ 'worker.ready': {
216
+ root: string;
217
+ store?: string;
218
+ };
219
+ 'worker.fileChanged': {
220
+ target: 'SERVER' | 'CLIENT';
221
+ path: string;
222
+ };
223
+ 'worker.warning': {
224
+ message: string;
225
+ };
226
+ /** Ask the editor to reveal a file, e.g. from a diagnostic the model cited. */
227
+ 'worker.openFile': {
228
+ target: 'SERVER' | 'CLIENT';
229
+ path: string;
230
+ line?: number;
231
+ };
232
+ }
233
+ export type PageEvent = keyof PageEventMap;
234
+ export type WorkerEvent = keyof WorkerEventMap;
235
+ export declare const BRIDGE_ERROR_CODES: {
236
+ readonly unavailable: "BRIDGE_UNAVAILABLE";
237
+ readonly timeout: "BRIDGE_TIMEOUT";
238
+ readonly refused: "BRIDGE_REFUSED";
239
+ readonly pageError: "PAGE_ERROR";
240
+ };
241
+ export declare function isBridgeFrame(value: unknown, nonce?: string): value is BridgeFrame;
242
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/bridge/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Crowdy Studio project-file access for the cockpit, on top of CrowdyJS.
3
+ *
4
+ * The cockpit is a client of the platform exactly like a browser running Studio:
5
+ * it signs in as the modder with the public SDK, mints an app-scoped token for
6
+ * the target app, and reads / writes project files through the same GraphQL
7
+ * operations Studio uses. There is no private wire, no second endpoint, and no
8
+ * server-side component that knows this process exists.
9
+ *
10
+ * Only the operations a filesystem backend needs are exposed: authenticate,
11
+ * load a project with its files, save a batch of upserts / deletes under an
12
+ * expected project revision, and (for the setup script) create a project.
13
+ */
14
+ import { type CrowdyClient } from '../vendor/crowdyjs-sdk.js';
15
+ /** Project targets are two independent file trees with separate quotas. */
16
+ export type CrowdyTarget = 'SERVER' | 'CLIENT';
17
+ export interface CrowdyProjectFile {
18
+ target: CrowdyTarget;
19
+ path: string;
20
+ content: string;
21
+ /** Per-file counter, incremented on every successful upsert of this target/path. */
22
+ revision: string;
23
+ updatedAt: string;
24
+ }
25
+ export interface CrowdyProject {
26
+ projectId: string;
27
+ appId: string;
28
+ ownerUserId: string;
29
+ name: string;
30
+ /** Project-wide counter guarding every mutation; `expectedRevision` must equal it. */
31
+ revision: string;
32
+ archived: boolean;
33
+ files: CrowdyProjectFile[];
34
+ updatedAt: string;
35
+ }
36
+ export interface CrowdyFileUpsert {
37
+ target: CrowdyTarget;
38
+ path: string;
39
+ content: string;
40
+ }
41
+ export interface CrowdyFileDelete {
42
+ target: CrowdyTarget;
43
+ path: string;
44
+ }
45
+ /**
46
+ * A GraphQL error surfaced with the server's error code intact so callers can
47
+ * branch on it. Revision conflicts in particular need distinct handling.
48
+ */
49
+ export declare class CrowdyApiError extends Error {
50
+ readonly code: string | undefined;
51
+ readonly remediation?: string | undefined;
52
+ constructor(message: string, code: string | undefined, remediation?: string | undefined);
53
+ /** True when the write lost an optimistic-concurrency race and must be replayed. */
54
+ get isRevisionConflict(): boolean;
55
+ /** True when the bearer is missing, expired, or not app-scoped. */
56
+ get isAuthFailure(): boolean;
57
+ }
58
+ export interface CrowdyClientOptions {
59
+ /** Absolute GraphQL endpoint, e.g. `http://localhost:3000/graphql`. */
60
+ endpoint: string;
61
+ /** Numeric app id, carried as a string because it is a GraphQL BigInt. */
62
+ appId: string;
63
+ /** Pre-minted app-scoped token; when absent, supply `email`/`password` to mint one. */
64
+ appToken?: string;
65
+ email?: string;
66
+ password?: string;
67
+ }
68
+ /**
69
+ * Project-file client. One instance per configured `(endpoint, appId)`; the
70
+ * bearer is resolved lazily on the first call and held in memory only.
71
+ */
72
+ export declare class CrowdyStudioClient {
73
+ private readonly options;
74
+ private readonly sdk;
75
+ private appToken;
76
+ private authenticating;
77
+ constructor(options: CrowdyClientOptions);
78
+ /** The app id every call is scoped to. */
79
+ get appId(): string;
80
+ /**
81
+ * Replace the bearer, e.g. when the Studio page refreshes the app token over
82
+ * the bridge. An empty token falls back to the credential mint path.
83
+ */
84
+ setToken(token: string | undefined): void;
85
+ /** GitHub loop of the bound repository; every call carries `(appId, projectId)`. */
86
+ get github(): CrowdyClient['crowdyStudioGitHub'];
87
+ /** Projects the caller owns in this app. */
88
+ listProjects(): Promise<Array<{
89
+ projectId: string;
90
+ name: string;
91
+ kind: string;
92
+ updatedAt: string;
93
+ }>>;
94
+ /**
95
+ * Resolve the app-scoped bearer. A pre-minted `appToken` wins; otherwise sign
96
+ * in as the modder (first-party, no browser Origin — the same path
97
+ * CrowdyCPP and the load tests use) and mint a token for `appId`.
98
+ */
99
+ authenticate(): Promise<string>;
100
+ /** Load a project and the full text of every file it contains. */
101
+ loadProject(projectId: string): Promise<CrowdyProject>;
102
+ /**
103
+ * Apply upserts and deletes in one transaction guarded by `expectedRevision`.
104
+ * A stale revision throws {@link CrowdyApiError} with `isRevisionConflict`.
105
+ *
106
+ * Studio's own editor goes through `crowdyStudioProjectSave` with the whole
107
+ * file list; a filesystem needs the files-only twin so a single `write`
108
+ * cannot disturb metadata it never read.
109
+ *
110
+ * @returns the project as it exists after the write, with its new revision.
111
+ */
112
+ saveFiles(args: {
113
+ projectId: string;
114
+ expectedRevision: string;
115
+ upserts?: CrowdyFileUpsert[];
116
+ deletes?: CrowdyFileDelete[];
117
+ idempotencyKey?: string;
118
+ }): Promise<CrowdyProject>;
119
+ /** Create a project, used by the setup script to produce a scratch target. */
120
+ createProject(args: {
121
+ name: string;
122
+ description?: string;
123
+ initialFiles?: CrowdyFileUpsert[];
124
+ }): Promise<CrowdyProject>;
125
+ }
126
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/crowdy/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../src/crowdy/client.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Boot configuration shared by every Crowdy plugin.
3
+ *
4
+ * Two hosts run these plugins:
5
+ *
6
+ * - the **browser worker image** embedded by Crowdy Studio, where the page
7
+ * writes `$DSH_HOME/crowdy.json` into the worker's virtual filesystem as a
8
+ * pre-boot overlay before the harness tree mounts;
9
+ * - the **developer cockpit** (`dsh web --patch profile/crowdy-node.patch.yml`
10
+ * on Node 22), where the same keys arrive as `CROWDY_*` environment
11
+ * variables.
12
+ *
13
+ * Both hosts converge here. Environment wins over the file so a developer can
14
+ * override one field without editing the overlay.
15
+ *
16
+ * @module @crowdedkingdoms/crowdy-dsh/crowdy/config
17
+ */
18
+ /** File the page-side bridge writes into the worker's `$DSH_HOME`. */
19
+ export declare const CROWDY_CONFIG_FILENAME = "crowdy.json";
20
+ export interface CrowdyBootConfig {
21
+ /** GraphQL endpoint of the game API serving Crowdy Studio. */
22
+ graphqlUrl: string;
23
+ /** App tenant id (a GraphQL BigInt carried as a decimal string). */
24
+ appId: string;
25
+ /** Project whose files become the agent's filesystem. */
26
+ projectId: string;
27
+ /**
28
+ * App-scoped bearer. In the browser it arrives ONLY over the bridge
29
+ * (`page.hello` / `page.token`) and is held in memory; the page never writes
30
+ * it into `crowdy.json`. In the cockpit it is `CROWDY_APP_TOKEN`.
31
+ */
32
+ appToken?: string;
33
+ /** Fallback credentials for the cockpit only (never present in the browser). */
34
+ email?: string;
35
+ password?: string;
36
+ /** Virtual mount point for the project trees. */
37
+ root?: string;
38
+ /**
39
+ * Name of the `BroadcastChannel` the Studio page listens on. Absent in the
40
+ * cockpit, where there is no page and page-executed tools are unavailable.
41
+ */
42
+ bridgeChannel?: string;
43
+ /** One-time secret the page put in the boot message; every bridge frame carries it. */
44
+ bridgeNonce?: string;
45
+ /** Prefer the bound GitHub repository as the file source of truth. */
46
+ githubFirst?: boolean;
47
+ /** Studio origin used to render wallet links in tool messages. */
48
+ studioOrigin?: string;
49
+ /** OPFS scope for session persistence (browser only); see `./persist`. */
50
+ persistScope?: string;
51
+ }
52
+ /**
53
+ * Resolve the boot configuration from `$DSH_HOME/crowdy.json` and the
54
+ * environment. Missing required fields are reported together so the first
55
+ * failed tool call names every problem at once.
56
+ */
57
+ export declare function loadCrowdyConfig(overrides?: Partial<CrowdyBootConfig>): CrowdyBootConfig;
58
+ /** Human-readable reason the configuration cannot reach a project yet. */
59
+ export declare function describeMissing(config: CrowdyBootConfig): string | undefined;
60
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/crowdy/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,gBAAgB,CAAA;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AA4BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,gBAAgB,CA2B5F;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAO5E"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Repository layout of a GitHub-bound Crowdy Studio project.
3
+ *
4
+ * Mirrors `CrowdyJS/src/crowdy-studio/github/sync.ts` (the Studio panel's
5
+ * push/pull), which is the source of truth. It is restated here rather than
6
+ * imported because that module lives in the `crowdy-studio` entry beside the
7
+ * Monaco editor, and the worker image must not carry the editor.
8
+ *
9
+ * Layout (from `crowdy.json` at the repo root, else inferred from the tree):
10
+ *
11
+ * SERVER src/lib.rs <-> <serverRoot>/src/lib.rs
12
+ * CLIENT src/lib.rs <-> <clientRoot>/src/lib.rs
13
+ *
14
+ * @module @crowdedkingdoms/crowdy-dsh/crowdy/github-layout
15
+ */
16
+ import type { CrowdyTarget } from './client.js';
17
+ export interface GitHubLayout {
18
+ serverRoot: string | null;
19
+ clientRoot: string | null;
20
+ }
21
+ export interface GitHubTreeEntryLike {
22
+ path: string;
23
+ type: string;
24
+ }
25
+ export declare const DEFAULT_FULL_STACK_CROWDY_JSON = "{\n \"server\": \"server\",\n \"client\": \"client\"\n}\n";
26
+ export declare function trimSlash(path: string): string;
27
+ export declare function joinRepo(root: string, rel: string): string;
28
+ export declare function underRoot(path: string, root: string | null): string | null;
29
+ export declare function parseCrowdyJson(content: string): GitHubLayout | null;
30
+ export declare function layoutFromTree(entries: ReadonlyArray<GitHubTreeEntryLike>): GitHubLayout;
31
+ export declare function repoPathToStudioFile(layout: GitHubLayout, repoPath: string): {
32
+ target: CrowdyTarget;
33
+ path: string;
34
+ } | null;
35
+ export declare function studioFileToRepoPath(layout: GitHubLayout, target: CrowdyTarget, path: string): string | null;
36
+ //# sourceMappingURL=github-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-layout.d.ts","sourceRoot":"","sources":["../../../src/crowdy/github-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,eAAO,MAAM,8BAA8B,gEAI1C,CAAA;AAKD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAO1E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAUpE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAAG,YAAY,CAQxF;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAU/C;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAIf"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Path mapping between the virtual tree the agent sees and the flat
3
+ * `(target, path)` pairs Crowdy Studio stores.
4
+ *
5
+ * A Crowdy project is not a directory tree: it is two independent bags of files
6
+ * keyed by target. We present them as two directories under one root so ordinary
7
+ * path-shaped tools work unchanged:
8
+ *
9
+ * <root>/server/src/main.rs <-> (SERVER, "src/main.rs")
10
+ * <root>/client/Cargo.toml <-> (CLIENT, "Cargo.toml")
11
+ */
12
+ import type { CrowdyTarget } from './client.js';
13
+ export declare const DEFAULT_ROOT = "/crowdy";
14
+ export interface CrowdyLocation {
15
+ target: CrowdyTarget;
16
+ /** Project-relative path, e.g. `src/main.rs`. Never empty. */
17
+ path: string;
18
+ }
19
+ /**
20
+ * Scratch directories beside the two targets. They are not project files:
21
+ * `captures/` holds screenshots the page took, `context/` holds game
22
+ * observations, client logs and the latest build diagnostics. Both live only
23
+ * in memory for the life of the harness.
24
+ */
25
+ export declare const SCRATCH_DIRS: readonly ["captures", "context"];
26
+ export type ScratchDir = (typeof SCRATCH_DIRS)[number];
27
+ /** What a virtual absolute path denotes. */
28
+ export type Resolved = {
29
+ kind: 'root';
30
+ } | {
31
+ kind: 'target';
32
+ target: CrowdyTarget;
33
+ } | {
34
+ kind: 'file';
35
+ location: CrowdyLocation;
36
+ } | {
37
+ kind: 'scratch-dir';
38
+ dir: ScratchDir;
39
+ } | {
40
+ kind: 'scratch-file';
41
+ dir: ScratchDir;
42
+ name: string;
43
+ };
44
+ /**
45
+ * Collapse `.`/`..` segments and duplicate separators without touching the
46
+ * filesystem. Crowdy paths are virtual, so `realpath` semantics do not apply and
47
+ * traversal must be resolved textually.
48
+ *
49
+ * @returns an absolute path with no `.`/`..` segments.
50
+ */
51
+ export declare function normalizeAbsolute(input: string): string;
52
+ /** Join a possibly-relative path against a cwd, then normalize. */
53
+ export declare function resolveAgainst(cwd: string, input: string): string;
54
+ /**
55
+ * Interpret an absolute virtual path relative to the configured root.
56
+ *
57
+ * @param absolute - normalized absolute path.
58
+ * @param root - the virtual root the project is mounted at.
59
+ * @returns what the path denotes, or `undefined` when it falls outside the root.
60
+ */
61
+ export declare function classify(absolute: string, root?: string): Resolved | undefined;
62
+ /** Virtual absolute path of a scratch file. */
63
+ export declare function toScratchPath(dir: ScratchDir, name: string, root?: string): string;
64
+ /** The scratch directories in name order. */
65
+ export declare function scratchDirectories(root?: string): string[];
66
+ /** Build the virtual absolute path for a stored file. */
67
+ export declare function toVirtualPath(target: CrowdyTarget, path: string, root?: string): string;
68
+ /** The two target directories in name order, used for listing the root. */
69
+ export declare function targetDirectories(root?: string): string[];
70
+ /**
71
+ * Direct children of a directory within one target, derived from the flat file
72
+ * list. Intermediate directories exist only implicitly, so they are synthesized
73
+ * from the path segments of the files beneath them.
74
+ *
75
+ * @param paths - every stored path for the target.
76
+ * @param prefix - project-relative directory prefix, `''` for the target root.
77
+ * @returns the direct children, each flagged as a file or directory.
78
+ */
79
+ export declare function directChildren(paths: string[], prefix: string): Array<{
80
+ name: string;
81
+ isDirectory: boolean;
82
+ }>;
83
+ /**
84
+ * Whether a project-relative path is one Crowdy Studio will accept: `Cargo.toml`
85
+ * at the target root, or a `.rs` file below `src/`. Rejecting early gives the
86
+ * model a precise message instead of a generic server validation failure.
87
+ */
88
+ export declare function isAcceptableProjectPath(path: string): boolean;
89
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/crowdy/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,eAAO,MAAM,YAAY,YAAY,CAAA;AAMrC,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,CAAA;IACpB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kCAAmC,CAAA;AAC5D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,GAAG,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAe,GAAG,QAAQ,GAAG,SAAS,CAsBpF;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,SAAe,GAAG,MAAM,CAExF;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,IAAI,SAAe,GAAG,MAAM,EAAE,CAGhE;AAED,yDAAyD;AACzD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,SAAe,GAClB,MAAM,CAER;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,IAAI,SAAe,GAAG,MAAM,EAAE,CAK/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CAmB/C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI7D"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Where a project's files live: the bound GitHub repository when the owner
3
+ * bound one (GitHub is then the source of truth and Studio holds the deployable
4
+ * mirror), otherwise the Crowdy Studio project itself.
5
+ *
6
+ * Both stores present the same versioned bag of `(target, path, content)` so
7
+ * the filesystem backend never learns which one it is talking to.
8
+ *
9
+ * @module @crowdedkingdoms/crowdy-dsh/crowdy/project-store
10
+ */
11
+ import { CrowdyStudioClient } from './client.js';
12
+ import type { CrowdyFileDelete, CrowdyFileUpsert, CrowdyProjectFile } from './client.js';
13
+ export interface ProjectSnapshot {
14
+ /** Opaque store-wide version; every mutation must present the one it read. */
15
+ revision: string;
16
+ files: CrowdyProjectFile[];
17
+ source: 'studio' | 'github';
18
+ /** Human-readable origin for tool messages, e.g. `owner/repo@main`. */
19
+ label: string;
20
+ }
21
+ export interface ProjectBatch {
22
+ upserts?: CrowdyFileUpsert[];
23
+ deletes?: CrowdyFileDelete[];
24
+ }
25
+ export interface ProjectStore {
26
+ readonly kind: 'studio' | 'github';
27
+ load(): Promise<ProjectSnapshot>;
28
+ /**
29
+ * Apply a batch against `snapshot`. A lost race throws {@link CrowdyApiError}
30
+ * with `isRevisionConflict`; the caller re-reads and retries or reports.
31
+ */
32
+ commit(snapshot: ProjectSnapshot, batch: ProjectBatch): Promise<ProjectSnapshot>;
33
+ }
34
+ /** Crowdy Studio project files behind `crowdyStudioProject*`. */
35
+ export declare class StudioProjectStore implements ProjectStore {
36
+ private readonly client;
37
+ private readonly projectId;
38
+ readonly kind: "studio";
39
+ constructor(client: CrowdyStudioClient, projectId: string);
40
+ load(): Promise<ProjectSnapshot>;
41
+ commit(snapshot: ProjectSnapshot, batch: ProjectBatch): Promise<ProjectSnapshot>;
42
+ }
43
+ /**
44
+ * The bound GitHub repository, read through `crowdyStudioGitHubTree/File` and
45
+ * written through `crowdyStudioGitHubPutFile` (Contents API, SHA-guarded).
46
+ *
47
+ * After every successful GitHub write the same batch is mirrored onto the
48
+ * Studio project so a draft test or deploy compiles what the agent wrote. The
49
+ * mirror is best-effort: GitHub already holds the truth, and a Studio revision
50
+ * race is reported, not treated as a failed write.
51
+ */
52
+ export declare class GitHubProjectStore implements ProjectStore {
53
+ private readonly client;
54
+ private readonly projectId;
55
+ private readonly repoLabel;
56
+ private readonly warn;
57
+ readonly kind: "github";
58
+ private shas;
59
+ private layout;
60
+ /** Last mirror failure, surfaced once by the filesystem in its next result. */
61
+ mirrorWarning: string | undefined;
62
+ constructor(client: CrowdyStudioClient, projectId: string, repoLabel: string, warn?: (message: string) => void);
63
+ private get scope();
64
+ load(): Promise<ProjectSnapshot>;
65
+ commit(snapshot: ProjectSnapshot, batch: ProjectBatch): Promise<ProjectSnapshot>;
66
+ /** Copy the batch onto the Studio project so builds see the same bytes. */
67
+ private mirrorToStudio;
68
+ }
69
+ /** Crowdy Studio stores only `Cargo.toml` and `.rs` files under `src/`. */
70
+ export declare function isSourcePath(path: string): boolean;
71
+ export interface StoreSelection {
72
+ store: ProjectStore;
73
+ /** Why this store was chosen, for the system prompt and tool messages. */
74
+ reason: string;
75
+ }
76
+ /**
77
+ * Choose the store for a project: GitHub when the project is bound to a
78
+ * connected repository and the caller prefers it, otherwise Studio files.
79
+ */
80
+ export declare function selectProjectStore(client: CrowdyStudioClient, projectId: string, options: {
81
+ githubFirst: boolean;
82
+ warn?: (message: string) => void;
83
+ }): Promise<StoreSelection>;
84
+ //# sourceMappingURL=project-store.d.ts.map