@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,97 @@
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
+ export const DEFAULT_FULL_STACK_CROWDY_JSON = `{
17
+ "server": "server",
18
+ "client": "client"
19
+ }
20
+ `;
21
+ const SKIP_DIRS = new Set(['.git', 'node_modules', 'target', 'dist', '.cursor', '.github']);
22
+ const SKIP_FILES = new Set(['crowdy.json', 'readme.md', 'license', '.gitignore']);
23
+ export function trimSlash(path) {
24
+ let start = 0;
25
+ let end = path.length;
26
+ while (start < end && path.charCodeAt(start) === 47)
27
+ start += 1;
28
+ while (end > start && path.charCodeAt(end - 1) === 47)
29
+ end -= 1;
30
+ return start === 0 && end === path.length ? path : path.slice(start, end);
31
+ }
32
+ export function joinRepo(root, rel) {
33
+ const base = trimSlash(root);
34
+ const rest = trimSlash(rel);
35
+ if (!base || base === '.')
36
+ return rest;
37
+ return rest ? `${base}/${rest}` : base;
38
+ }
39
+ export function underRoot(path, root) {
40
+ if (root == null)
41
+ return null;
42
+ const base = trimSlash(root);
43
+ if (!base || base === '.')
44
+ return path;
45
+ if (path === base)
46
+ return '';
47
+ if (path.startsWith(`${base}/`))
48
+ return path.slice(base.length + 1);
49
+ return null;
50
+ }
51
+ export function parseCrowdyJson(content) {
52
+ try {
53
+ const parsed = JSON.parse(content);
54
+ const server = typeof parsed.server === 'string' ? parsed.server.trim() || '.' : null;
55
+ const clientRoot = typeof parsed.client === 'string' ? parsed.client.trim() || '.' : null;
56
+ if (server == null && clientRoot == null)
57
+ return null;
58
+ return { serverRoot: server, clientRoot };
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ export function layoutFromTree(entries) {
65
+ const hasDir = (name) => entries.some((e) => e.type === 'tree' && e.path === name);
66
+ const hasClient = hasDir('client');
67
+ const hasServer = hasDir('server');
68
+ if (hasServer && hasClient)
69
+ return { serverRoot: 'server', clientRoot: 'client' };
70
+ if (hasClient)
71
+ return { serverRoot: '.', clientRoot: 'client' };
72
+ if (hasServer)
73
+ return { serverRoot: 'server', clientRoot: null };
74
+ return { serverRoot: '.', clientRoot: null };
75
+ }
76
+ export function repoPathToStudioFile(layout, repoPath) {
77
+ const segments = repoPath.split('/');
78
+ if (segments.some((s) => SKIP_DIRS.has(s)))
79
+ return null;
80
+ const name = segments[segments.length - 1]?.toLowerCase() ?? '';
81
+ if (SKIP_FILES.has(name) || SKIP_FILES.has(repoPath.toLowerCase()))
82
+ return null;
83
+ const clientRel = underRoot(repoPath, layout.clientRoot);
84
+ if (clientRel != null && clientRel !== '')
85
+ return { target: 'CLIENT', path: clientRel };
86
+ const serverRel = underRoot(repoPath, layout.serverRoot);
87
+ if (serverRel != null && serverRel !== '')
88
+ return { target: 'SERVER', path: serverRel };
89
+ return null;
90
+ }
91
+ export function studioFileToRepoPath(layout, target, path) {
92
+ const root = target === 'CLIENT' ? layout.clientRoot : layout.serverRoot;
93
+ if (root == null)
94
+ return null;
95
+ return joinRepo(root, path);
96
+ }
97
+ //# sourceMappingURL=github-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-layout.js","sourceRoot":"","sources":["../../src/crowdy/github-layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
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
+ export const DEFAULT_ROOT = '/crowdy';
13
+ /** Directory name presented for each target, and the reverse lookup. */
14
+ const TARGET_DIRS = { SERVER: 'server', CLIENT: 'client' };
15
+ const DIR_TARGETS = { server: 'SERVER', client: 'CLIENT' };
16
+ /**
17
+ * Scratch directories beside the two targets. They are not project files:
18
+ * `captures/` holds screenshots the page took, `context/` holds game
19
+ * observations, client logs and the latest build diagnostics. Both live only
20
+ * in memory for the life of the harness.
21
+ */
22
+ export const SCRATCH_DIRS = ['captures', 'context'];
23
+ /**
24
+ * Collapse `.`/`..` segments and duplicate separators without touching the
25
+ * filesystem. Crowdy paths are virtual, so `realpath` semantics do not apply and
26
+ * traversal must be resolved textually.
27
+ *
28
+ * @returns an absolute path with no `.`/`..` segments.
29
+ */
30
+ export function normalizeAbsolute(input) {
31
+ const segments = input.replace(/\\/g, '/').split('/');
32
+ const out = [];
33
+ for (const segment of segments) {
34
+ if (segment === '' || segment === '.')
35
+ continue;
36
+ if (segment === '..') {
37
+ out.pop();
38
+ continue;
39
+ }
40
+ out.push(segment);
41
+ }
42
+ return `/${out.join('/')}`;
43
+ }
44
+ /** Join a possibly-relative path against a cwd, then normalize. */
45
+ export function resolveAgainst(cwd, input) {
46
+ return normalizeAbsolute(input.startsWith('/') ? input : `${cwd}/${input}`);
47
+ }
48
+ /**
49
+ * Interpret an absolute virtual path relative to the configured root.
50
+ *
51
+ * @param absolute - normalized absolute path.
52
+ * @param root - the virtual root the project is mounted at.
53
+ * @returns what the path denotes, or `undefined` when it falls outside the root.
54
+ */
55
+ export function classify(absolute, root = DEFAULT_ROOT) {
56
+ const base = normalizeAbsolute(root);
57
+ if (absolute === base)
58
+ return { kind: 'root' };
59
+ if (!absolute.startsWith(`${base}/`))
60
+ return undefined;
61
+ const rest = absolute.slice(base.length + 1);
62
+ const slash = rest.indexOf('/');
63
+ const dir = slash === -1 ? rest : rest.slice(0, slash);
64
+ const target = DIR_TARGETS[dir];
65
+ if (!target) {
66
+ const scratch = SCRATCH_DIRS.includes(dir) ? dir : undefined;
67
+ if (!scratch)
68
+ return undefined;
69
+ if (slash === -1)
70
+ return { kind: 'scratch-dir', dir: scratch };
71
+ const name = rest.slice(slash + 1);
72
+ if (!name)
73
+ return { kind: 'scratch-dir', dir: scratch };
74
+ return { kind: 'scratch-file', dir: scratch, name };
75
+ }
76
+ if (slash === -1)
77
+ return { kind: 'target', target };
78
+ const path = rest.slice(slash + 1);
79
+ if (!path)
80
+ return { kind: 'target', target };
81
+ return { kind: 'file', location: { target, path } };
82
+ }
83
+ /** Virtual absolute path of a scratch file. */
84
+ export function toScratchPath(dir, name, root = DEFAULT_ROOT) {
85
+ return `${normalizeAbsolute(root)}/${dir}/${name}`;
86
+ }
87
+ /** The scratch directories in name order. */
88
+ export function scratchDirectories(root = DEFAULT_ROOT) {
89
+ const base = normalizeAbsolute(root);
90
+ return [...SCRATCH_DIRS].sort().map((dir) => `${base}/${dir}`);
91
+ }
92
+ /** Build the virtual absolute path for a stored file. */
93
+ export function toVirtualPath(target, path, root = DEFAULT_ROOT) {
94
+ return `${normalizeAbsolute(root)}/${TARGET_DIRS[target]}/${path}`;
95
+ }
96
+ /** The two target directories in name order, used for listing the root. */
97
+ export function targetDirectories(root = DEFAULT_ROOT) {
98
+ const base = normalizeAbsolute(root);
99
+ return Object.values(TARGET_DIRS)
100
+ .sort()
101
+ .map((dir) => `${base}/${dir}`);
102
+ }
103
+ /**
104
+ * Direct children of a directory within one target, derived from the flat file
105
+ * list. Intermediate directories exist only implicitly, so they are synthesized
106
+ * from the path segments of the files beneath them.
107
+ *
108
+ * @param paths - every stored path for the target.
109
+ * @param prefix - project-relative directory prefix, `''` for the target root.
110
+ * @returns the direct children, each flagged as a file or directory.
111
+ */
112
+ export function directChildren(paths, prefix) {
113
+ const scope = prefix === '' ? '' : prefix.endsWith('/') ? prefix : `${prefix}/`;
114
+ const seen = new Map();
115
+ for (const path of paths) {
116
+ if (scope && !path.startsWith(scope))
117
+ continue;
118
+ const rest = path.slice(scope.length);
119
+ if (!rest)
120
+ continue;
121
+ const slash = rest.indexOf('/');
122
+ if (slash === -1) {
123
+ seen.set(rest, false);
124
+ }
125
+ else if (!seen.has(rest.slice(0, slash))) {
126
+ seen.set(rest.slice(0, slash), true);
127
+ }
128
+ }
129
+ return [...seen.entries()]
130
+ .map(([name, isDirectory]) => ({ name, isDirectory }))
131
+ .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
132
+ }
133
+ /**
134
+ * Whether a project-relative path is one Crowdy Studio will accept: `Cargo.toml`
135
+ * at the target root, or a `.rs` file below `src/`. Rejecting early gives the
136
+ * model a precise message instead of a generic server validation failure.
137
+ */
138
+ export function isAcceptableProjectPath(path) {
139
+ if (path.includes('..') || path.startsWith('/'))
140
+ return false;
141
+ if (path === 'Cargo.toml')
142
+ return true;
143
+ return path.startsWith('src/') && path.endsWith('.rs');
144
+ }
145
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/crowdy/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
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 { CrowdyApiError } from './client.js';
12
+ import { layoutFromTree, parseCrowdyJson, repoPathToStudioFile, studioFileToRepoPath, } from './github-layout.js';
13
+ /** Crowdy Studio project files behind `crowdyStudioProject*`. */
14
+ export class StudioProjectStore {
15
+ client;
16
+ projectId;
17
+ kind = 'studio';
18
+ constructor(client, projectId) {
19
+ this.client = client;
20
+ this.projectId = projectId;
21
+ }
22
+ async load() {
23
+ const project = await this.client.loadProject(this.projectId);
24
+ return {
25
+ revision: project.revision,
26
+ files: project.files,
27
+ source: 'studio',
28
+ label: `Crowdy Studio project "${project.name}"`,
29
+ };
30
+ }
31
+ async commit(snapshot, batch) {
32
+ const project = await this.client.saveFiles({
33
+ projectId: this.projectId,
34
+ expectedRevision: snapshot.revision,
35
+ ...batch,
36
+ });
37
+ return {
38
+ revision: project.revision,
39
+ files: project.files,
40
+ source: 'studio',
41
+ label: snapshot.label,
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * The bound GitHub repository, read through `crowdyStudioGitHubTree/File` and
47
+ * written through `crowdyStudioGitHubPutFile` (Contents API, SHA-guarded).
48
+ *
49
+ * After every successful GitHub write the same batch is mirrored onto the
50
+ * Studio project so a draft test or deploy compiles what the agent wrote. The
51
+ * mirror is best-effort: GitHub already holds the truth, and a Studio revision
52
+ * race is reported, not treated as a failed write.
53
+ */
54
+ export class GitHubProjectStore {
55
+ client;
56
+ projectId;
57
+ repoLabel;
58
+ warn;
59
+ kind = 'github';
60
+ shas = new Map();
61
+ layout;
62
+ /** Last mirror failure, surfaced once by the filesystem in its next result. */
63
+ mirrorWarning;
64
+ constructor(client, projectId, repoLabel, warn = () => undefined) {
65
+ this.client = client;
66
+ this.projectId = projectId;
67
+ this.repoLabel = repoLabel;
68
+ this.warn = warn;
69
+ }
70
+ get scope() {
71
+ return { appId: this.client.appId, projectId: this.projectId };
72
+ }
73
+ async load() {
74
+ await this.client.authenticate();
75
+ const entries = await this.client.github.tree(this.scope);
76
+ const crowdyJson = entries.find((entry) => entry.type === 'blob' && entry.path === 'crowdy.json');
77
+ let layout = null;
78
+ if (crowdyJson) {
79
+ const file = await this.client.github.getFile({ ...this.scope, path: 'crowdy.json' });
80
+ layout = parseCrowdyJson(file.content);
81
+ }
82
+ this.layout = layout ?? layoutFromTree(entries);
83
+ const mapped = [];
84
+ for (const entry of entries) {
85
+ if (entry.type !== 'blob')
86
+ continue;
87
+ const studio = repoPathToStudioFile(this.layout, entry.path);
88
+ if (!studio)
89
+ continue;
90
+ if (!isSourcePath(studio.path))
91
+ continue;
92
+ mapped.push({ repoPath: entry.path, ...studio, sha: entry.sha });
93
+ }
94
+ const files = [];
95
+ const shas = new Map();
96
+ // Small projects: fetch sequentially in modest parallel batches so a
97
+ // fleet-wide op limit is not tripped by one listing.
98
+ const batchSize = 4;
99
+ for (let index = 0; index < mapped.length; index += batchSize) {
100
+ const slice = mapped.slice(index, index + batchSize);
101
+ const loaded = await Promise.all(slice.map(async (entry) => {
102
+ const file = await this.client.github.getFile({ ...this.scope, path: entry.repoPath });
103
+ return { entry, file };
104
+ }));
105
+ for (const { entry, file } of loaded) {
106
+ shas.set(key(entry.target, entry.path), { sha: file.sha, repoPath: entry.repoPath });
107
+ files.push({
108
+ target: entry.target,
109
+ path: entry.path,
110
+ content: file.content,
111
+ revision: file.sha,
112
+ updatedAt: '',
113
+ });
114
+ }
115
+ }
116
+ this.shas = shas;
117
+ files.sort((a, b) => (a.target === b.target ? a.path.localeCompare(b.path) : a.target.localeCompare(b.target)));
118
+ return {
119
+ revision: revisionOf(shas),
120
+ files,
121
+ source: 'github',
122
+ label: `GitHub ${this.repoLabel}`,
123
+ };
124
+ }
125
+ async commit(snapshot, batch) {
126
+ if (snapshot.revision !== revisionOf(this.shas)) {
127
+ throw new CrowdyApiError('The repository changed since it was read.', 'GITHUB_STALE_SHA');
128
+ }
129
+ if (batch.deletes?.length) {
130
+ throw new CrowdyApiError('Deleting files in a GitHub-bound project is not supported here; delete it on GitHub or in Crowdy Studio.', 'GITHUB_DELETE_UNSUPPORTED');
131
+ }
132
+ const layout = this.layout ?? layoutFromTree([]);
133
+ for (const upsert of batch.upserts ?? []) {
134
+ const repoPath = studioFileToRepoPath(layout, upsert.target, upsert.path);
135
+ if (!repoPath) {
136
+ throw new CrowdyApiError(`The bound repository has no ${upsert.target.toLowerCase()} root in crowdy.json, so ${upsert.path} has no place to go.`, 'GITHUB_PATH_INVALID');
137
+ }
138
+ const existing = this.shas.get(key(upsert.target, upsert.path));
139
+ const written = await this.client.github.putFile({
140
+ ...this.scope,
141
+ path: repoPath,
142
+ content: upsert.content,
143
+ message: `Crowdy Studio agent: ${existing ? 'update' : 'add'} ${repoPath}`,
144
+ ...(existing ? { sha: existing.sha } : {}),
145
+ });
146
+ this.shas.set(key(upsert.target, upsert.path), { sha: written.sha, repoPath });
147
+ }
148
+ const files = snapshot.files.map((file) => ({ ...file }));
149
+ for (const upsert of batch.upserts ?? []) {
150
+ const index = files.findIndex((file) => file.target === upsert.target && file.path === upsert.path);
151
+ const state = this.shas.get(key(upsert.target, upsert.path));
152
+ const next = {
153
+ target: upsert.target,
154
+ path: upsert.path,
155
+ content: upsert.content,
156
+ revision: state?.sha ?? '',
157
+ updatedAt: new Date().toISOString(),
158
+ };
159
+ if (index === -1)
160
+ files.push(next);
161
+ else
162
+ files[index] = next;
163
+ }
164
+ await this.mirrorToStudio(batch);
165
+ return { revision: revisionOf(this.shas), files, source: 'github', label: snapshot.label };
166
+ }
167
+ /** Copy the batch onto the Studio project so builds see the same bytes. */
168
+ async mirrorToStudio(batch) {
169
+ try {
170
+ const project = await this.client.loadProject(this.projectId);
171
+ await this.client.saveFiles({
172
+ projectId: this.projectId,
173
+ expectedRevision: project.revision,
174
+ ...batch,
175
+ });
176
+ this.mirrorWarning = undefined;
177
+ }
178
+ catch (error) {
179
+ const message = error instanceof Error ? error.message : String(error);
180
+ this.mirrorWarning = `Saved to GitHub, but the Crowdy Studio mirror was not updated: ${message}. Pull from GitHub in Studio before testing.`;
181
+ this.warn(this.mirrorWarning);
182
+ }
183
+ }
184
+ }
185
+ function key(target, path) {
186
+ return `${target}:${path}`;
187
+ }
188
+ function revisionOf(shas) {
189
+ return [...shas.entries()]
190
+ .sort(([a], [b]) => a.localeCompare(b))
191
+ .map(([k, v]) => `${k}=${v.sha}`)
192
+ .join(';');
193
+ }
194
+ /** Crowdy Studio stores only `Cargo.toml` and `.rs` files under `src/`. */
195
+ export function isSourcePath(path) {
196
+ return path === 'Cargo.toml' || (path.startsWith('src/') && path.endsWith('.rs'));
197
+ }
198
+ /**
199
+ * Choose the store for a project: GitHub when the project is bound to a
200
+ * connected repository and the caller prefers it, otherwise Studio files.
201
+ */
202
+ export async function selectProjectStore(client, projectId, options) {
203
+ if (options.githubFirst) {
204
+ try {
205
+ const status = await client.github.status({ appId: client.appId, projectId });
206
+ if (status.configured && status.connected && status.owner && status.repo) {
207
+ const label = `${status.owner}/${status.repo}@${status.branch ?? 'default'}`;
208
+ return {
209
+ store: new GitHubProjectStore(client, projectId, label, options.warn),
210
+ reason: `The project is bound to GitHub (${label}); the repository is the source of truth and Studio mirrors it.`,
211
+ };
212
+ }
213
+ }
214
+ catch (error) {
215
+ options.warn?.(`GitHub status unavailable, falling back to Studio files: ${error instanceof Error ? error.message : String(error)}`);
216
+ }
217
+ }
218
+ return {
219
+ store: new StudioProjectStore(client, projectId),
220
+ reason: 'The project is not bound to a GitHub repository; Crowdy Studio project files are the source of truth.',
221
+ };
222
+ }
223
+ //# sourceMappingURL=project-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-store.js","sourceRoot":"","sources":["../../src/crowdy/project-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAsB,MAAM,aAAa,CAAA;AAEhE,OAAO,EACL,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,oBAAoB,CAAA;AA0B3B,iEAAiE;AACjE,MAAM,OAAO,kBAAkB;IAIV;IACA;IAJV,IAAI,GAAG,QAAiB,CAAA;IAEjC,YACmB,MAA0B,EAC1B,SAAiB;QADjB,WAAM,GAAN,MAAM,CAAoB;QAC1B,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEJ,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC7D,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,0BAA0B,OAAO,CAAC,IAAI,GAAG;SACjD,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAyB,EAAE,KAAmB;QACzD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,gBAAgB,EAAE,QAAQ,CAAC,QAAQ;YACnC,GAAG,KAAK;SACT,CAAC,CAAA;QACF,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAA;IACH,CAAC;CACF;AAOD;;;;;;;;GAQG;AACH,MAAM,OAAO,kBAAkB;IAQV;IACA;IACA;IACA;IAVV,IAAI,GAAG,QAAiB,CAAA;IACzB,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAA;IACzC,MAAM,CAA0B;IACxC,+EAA+E;IAC/E,aAAa,CAAoB;IAEjC,YACmB,MAA0B,EAC1B,SAAiB,EACjB,SAAiB,EACjB,OAAkC,GAAG,EAAE,CAAC,SAAS;QAHjD,WAAM,GAAN,MAAM,CAAoB;QAC1B,cAAS,GAAT,SAAS,CAAQ;QACjB,cAAS,GAAT,SAAS,CAAQ;QACjB,SAAI,GAAJ,IAAI,CAA6C;IACjE,CAAC;IAEJ,IAAY,KAAK;QACf,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAA;IAChE,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAAA;QACjG,IAAI,MAAM,GAAwB,IAAI,CAAA;QACtC,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;YACrF,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,cAAc,CAAC,OAAO,CAAC,CAAA;QAE/C,MAAM,MAAM,GAAwF,EAAE,CAAA;QACtG,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAQ;YACnC,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YAC5D,IAAI,CAAC,MAAM;gBAAE,SAAQ;YACrB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;gBAAE,SAAQ;YACxC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;QAClE,CAAC;QAED,MAAM,KAAK,GAAwB,EAAE,CAAA;QACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAA;QAC/C,qEAAqE;QACrE,qDAAqD;QACrD,MAAM,SAAS,GAAG,CAAC,CAAA;QACnB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,SAAS,EAAE,CAAC;YAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC,CAAA;YACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;gBACtF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;YACxB,CAAC,CAAC,CACH,CAAA;YACD,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;gBACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;gBACpF,KAAK,CAAC,IAAI,CAAC;oBACT,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,QAAQ,EAAE,IAAI,CAAC,GAAG;oBAClB,SAAS,EAAE,EAAE;iBACd,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC/G,OAAO;YACL,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC;YAC1B,KAAK;YACL,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,UAAU,IAAI,CAAC,SAAS,EAAE;SAClC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAyB,EAAE,KAAmB;QACzD,IAAI,QAAQ,CAAC,QAAQ,KAAK,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,cAAc,CAAC,2CAA2C,EAAE,kBAAkB,CAAC,CAAA;QAC3F,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,cAAc,CACtB,0GAA0G,EAC1G,2BAA2B,CAC5B,CAAA;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,EAAE,CAAC,CAAA;QAChD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;YACzE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,cAAc,CACtB,+BAA+B,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,4BAA4B,MAAM,CAAC,IAAI,sBAAsB,EACvH,qBAAqB,CACtB,CAAA;YACH,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;YAC/D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC/C,GAAG,IAAI,CAAC,KAAK;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,wBAAwB,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,EAAE;gBAC1E,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3C,CAAC,CAAA;YACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChF,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAA;QACzD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAA;YACnG,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;YAC5D,MAAM,IAAI,GAAsB;gBAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE;gBAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAA;YACD,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;;gBAC7B,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;QAC1B,CAAC;QAED,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;QAEhC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAA;IAC5F,CAAC;IAED,2EAA2E;IACnE,KAAK,CAAC,cAAc,CAAC,KAAmB;QAC9C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC7D,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC1B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,gBAAgB,EAAE,OAAO,CAAC,QAAQ;gBAClC,GAAG,KAAK;aACT,CAAC,CAAA;YACF,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,IAAI,CAAC,aAAa,GAAG,kEAAkE,OAAO,8CAA8C,CAAA;YAC5I,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;CACF;AAED,SAAS,GAAG,CAAC,MAAoB,EAAE,IAAY;IAC7C,OAAO,GAAG,MAAM,IAAI,IAAI,EAAE,CAAA;AAC5B,CAAC;AAED,SAAS,UAAU,CAAC,IAAkC;IACpD,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;SAChC,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,KAAK,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;AACnF,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAA0B,EAC1B,SAAiB,EACjB,OAAmE;IAEnE,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;YAC7E,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACzE,MAAM,KAAK,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE,CAAA;gBAC5E,OAAO;oBACL,KAAK,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC;oBACrE,MAAM,EAAE,mCAAmC,KAAK,iEAAiE;iBAClH,CAAA;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,EAAE,CACZ,4DAA4D,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACrH,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO;QACL,KAAK,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC;QAChD,MAAM,EAAE,uGAAuG;KAChH,CAAA;AACH,CAAC"}