@ambitresearch/genie 1.3.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 +15 -0
- package/dist/auth/bearer.d.ts +49 -0
- package/dist/auth/bearer.d.ts.map +1 -0
- package/dist/auth/bearer.js +159 -0
- package/dist/auth/bearer.js.map +1 -0
- package/dist/auth/oauth/authorize.d.ts +19 -0
- package/dist/auth/oauth/authorize.d.ts.map +1 -0
- package/dist/auth/oauth/authorize.js +111 -0
- package/dist/auth/oauth/authorize.js.map +1 -0
- package/dist/auth/oauth/config.d.ts +10 -0
- package/dist/auth/oauth/config.d.ts.map +1 -0
- package/dist/auth/oauth/config.js +16 -0
- package/dist/auth/oauth/config.js.map +1 -0
- package/dist/auth/oauth/dcr.d.ts +15 -0
- package/dist/auth/oauth/dcr.d.ts.map +1 -0
- package/dist/auth/oauth/dcr.js +38 -0
- package/dist/auth/oauth/dcr.js.map +1 -0
- package/dist/auth/oauth/jwt.d.ts +13 -0
- package/dist/auth/oauth/jwt.d.ts.map +1 -0
- package/dist/auth/oauth/jwt.js +46 -0
- package/dist/auth/oauth/jwt.js.map +1 -0
- package/dist/auth/oauth/metadata.d.ts +9 -0
- package/dist/auth/oauth/metadata.d.ts.map +1 -0
- package/dist/auth/oauth/metadata.js +19 -0
- package/dist/auth/oauth/metadata.js.map +1 -0
- package/dist/auth/oauth/router.d.ts +32 -0
- package/dist/auth/oauth/router.d.ts.map +1 -0
- package/dist/auth/oauth/router.js +159 -0
- package/dist/auth/oauth/router.js.map +1 -0
- package/dist/auth/oauth/store.d.ts +55 -0
- package/dist/auth/oauth/store.d.ts.map +1 -0
- package/dist/auth/oauth/store.js +63 -0
- package/dist/auth/oauth/store.js.map +1 -0
- package/dist/auth/oauth/token.d.ts +21 -0
- package/dist/auth/oauth/token.d.ts.map +1 -0
- package/dist/auth/oauth/token.js +77 -0
- package/dist/auth/oauth/token.js.map +1 -0
- package/dist/auth/oidc/group-policy.d.ts +43 -0
- package/dist/auth/oidc/group-policy.d.ts.map +1 -0
- package/dist/auth/oidc/group-policy.js +54 -0
- package/dist/auth/oidc/group-policy.js.map +1 -0
- package/dist/auth/oidc/verifier.d.ts +42 -0
- package/dist/auth/oidc/verifier.d.ts.map +1 -0
- package/dist/auth/oidc/verifier.js +145 -0
- package/dist/auth/oidc/verifier.js.map +1 -0
- package/dist/auth/token-cli.d.ts +9 -0
- package/dist/auth/token-cli.d.ts.map +1 -0
- package/dist/auth/token-cli.js +98 -0
- package/dist/auth/token-cli.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +149 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/redact.d.ts +20 -0
- package/dist/config/redact.d.ts.map +1 -0
- package/dist/config/redact.js +77 -0
- package/dist/config/redact.js.map +1 -0
- package/dist/config/secrets.d.ts +100 -0
- package/dist/config/secrets.d.ts.map +1 -0
- package/dist/config/secrets.js +130 -0
- package/dist/config/secrets.js.map +1 -0
- package/dist/framework/html.d.ts +103 -0
- package/dist/framework/html.d.ts.map +1 -0
- package/dist/framework/html.js +271 -0
- package/dist/framework/html.js.map +1 -0
- package/dist/framework/interface.d.ts +130 -0
- package/dist/framework/interface.d.ts.map +1 -0
- package/dist/framework/interface.js +112 -0
- package/dist/framework/interface.js.map +1 -0
- package/dist/framework/react.d.ts +133 -0
- package/dist/framework/react.d.ts.map +1 -0
- package/dist/framework/react.js +243 -0
- package/dist/framework/react.js.map +1 -0
- package/dist/framework/vue.d.ts +99 -0
- package/dist/framework/vue.d.ts.map +1 -0
- package/dist/framework/vue.js +375 -0
- package/dist/framework/vue.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/client.d.ts +81 -0
- package/dist/llm/client.d.ts.map +1 -0
- package/dist/llm/client.js +141 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/component-response.d.ts +111 -0
- package/dist/llm/component-response.d.ts.map +1 -0
- package/dist/llm/component-response.js +167 -0
- package/dist/llm/component-response.js.map +1 -0
- package/dist/llm/generated-files.d.ts +10 -0
- package/dist/llm/generated-files.d.ts.map +1 -0
- package/dist/llm/generated-files.js +26 -0
- package/dist/llm/generated-files.js.map +1 -0
- package/dist/llm/prompts/CHANGELOG.md +70 -0
- package/dist/llm/prompts/generate-component.system.md +99 -0
- package/dist/llm/prompts/refine-component.system.md +112 -0
- package/dist/llm/prompts.d.ts +66 -0
- package/dist/llm/prompts.d.ts.map +1 -0
- package/dist/llm/prompts.js +78 -0
- package/dist/llm/prompts.js.map +1 -0
- package/dist/llm/retry.d.ts +183 -0
- package/dist/llm/retry.d.ts.map +1 -0
- package/dist/llm/retry.js +475 -0
- package/dist/llm/retry.js.map +1 -0
- package/dist/llm/schema.d.ts +129 -0
- package/dist/llm/schema.d.ts.map +1 -0
- package/dist/llm/schema.js +147 -0
- package/dist/llm/schema.js.map +1 -0
- package/dist/llm/validate.d.ts +107 -0
- package/dist/llm/validate.d.ts.map +1 -0
- package/dist/llm/validate.js +174 -0
- package/dist/llm/validate.js.map +1 -0
- package/dist/manifest/compiler.d.ts +112 -0
- package/dist/manifest/compiler.d.ts.map +1 -0
- package/dist/manifest/compiler.js +306 -0
- package/dist/manifest/compiler.js.map +1 -0
- package/dist/manifest/ensure.d.ts +46 -0
- package/dist/manifest/ensure.d.ts.map +1 -0
- package/dist/manifest/ensure.js +49 -0
- package/dist/manifest/ensure.js.map +1 -0
- package/dist/manifest/index.d.ts +13 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +13 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/middleware/plan-guard.d.ts +167 -0
- package/dist/middleware/plan-guard.d.ts.map +1 -0
- package/dist/middleware/plan-guard.js +190 -0
- package/dist/middleware/plan-guard.js.map +1 -0
- package/dist/plans/index.d.ts +71 -0
- package/dist/plans/index.d.ts.map +1 -0
- package/dist/plans/index.js +252 -0
- package/dist/plans/index.js.map +1 -0
- package/dist/schemas/component.schema.json +114 -0
- package/dist/server.d.ts +96 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +258 -0
- package/dist/server.js.map +1 -0
- package/dist/store/empty-manifest.d.ts +58 -0
- package/dist/store/empty-manifest.d.ts.map +1 -0
- package/dist/store/empty-manifest.js +59 -0
- package/dist/store/empty-manifest.js.map +1 -0
- package/dist/store/git-host.d.ts +120 -0
- package/dist/store/git-host.d.ts.map +1 -0
- package/dist/store/git-host.js +796 -0
- package/dist/store/git-host.js.map +1 -0
- package/dist/store/index.d.ts +5 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +4 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/interface.d.ts +322 -0
- package/dist/store/interface.d.ts.map +1 -0
- package/dist/store/interface.js +100 -0
- package/dist/store/interface.js.map +1 -0
- package/dist/store/kit-files.d.ts +88 -0
- package/dist/store/kit-files.d.ts.map +1 -0
- package/dist/store/kit-files.js +199 -0
- package/dist/store/kit-files.js.map +1 -0
- package/dist/store/local.d.ts +70 -0
- package/dist/store/local.d.ts.map +1 -0
- package/dist/store/local.js +651 -0
- package/dist/store/local.js.map +1 -0
- package/dist/store/manifest.d.ts +44 -0
- package/dist/store/manifest.d.ts.map +1 -0
- package/dist/store/manifest.js +116 -0
- package/dist/store/manifest.js.map +1 -0
- package/dist/store/viewer-assets.d.ts +20 -0
- package/dist/store/viewer-assets.d.ts.map +1 -0
- package/dist/store/viewer-assets.js +118 -0
- package/dist/store/viewer-assets.js.map +1 -0
- package/dist/sync/anchor.d.ts +125 -0
- package/dist/sync/anchor.d.ts.map +1 -0
- package/dist/sync/anchor.js +210 -0
- package/dist/sync/anchor.js.map +1 -0
- package/dist/sync/index.d.ts +15 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +15 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/orchestrator.d.ts +160 -0
- package/dist/sync/orchestrator.d.ts.map +1 -0
- package/dist/sync/orchestrator.js +288 -0
- package/dist/sync/orchestrator.js.map +1 -0
- package/dist/tools/bind_kit.d.ts +29 -0
- package/dist/tools/bind_kit.d.ts.map +1 -0
- package/dist/tools/bind_kit.js +70 -0
- package/dist/tools/bind_kit.js.map +1 -0
- package/dist/tools/conjure.d.ts +141 -0
- package/dist/tools/conjure.d.ts.map +1 -0
- package/dist/tools/conjure.js +655 -0
- package/dist/tools/conjure.js.map +1 -0
- package/dist/tools/conjure_screen.d.ts +174 -0
- package/dist/tools/conjure_screen.d.ts.map +1 -0
- package/dist/tools/conjure_screen.js +458 -0
- package/dist/tools/conjure_screen.js.map +1 -0
- package/dist/tools/create_kit.d.ts +32 -0
- package/dist/tools/create_kit.d.ts.map +1 -0
- package/dist/tools/create_kit.js +131 -0
- package/dist/tools/create_kit.js.map +1 -0
- package/dist/tools/create_project.d.ts +267 -0
- package/dist/tools/create_project.d.ts.map +1 -0
- package/dist/tools/create_project.js +546 -0
- package/dist/tools/create_project.js.map +1 -0
- package/dist/tools/delete_files.d.ts +93 -0
- package/dist/tools/delete_files.d.ts.map +1 -0
- package/dist/tools/delete_files.js +276 -0
- package/dist/tools/delete_files.js.map +1 -0
- package/dist/tools/delete_project.d.ts +43 -0
- package/dist/tools/delete_project.d.ts.map +1 -0
- package/dist/tools/delete_project.js +118 -0
- package/dist/tools/delete_project.js.map +1 -0
- package/dist/tools/get_kit.d.ts +28 -0
- package/dist/tools/get_kit.d.ts.map +1 -0
- package/dist/tools/get_kit.js +95 -0
- package/dist/tools/get_kit.js.map +1 -0
- package/dist/tools/get_project.d.ts +37 -0
- package/dist/tools/get_project.d.ts.map +1 -0
- package/dist/tools/get_project.js +71 -0
- package/dist/tools/get_project.js.map +1 -0
- package/dist/tools/list_components.d.ts +42 -0
- package/dist/tools/list_components.d.ts.map +1 -0
- package/dist/tools/list_components.js +125 -0
- package/dist/tools/list_components.js.map +1 -0
- package/dist/tools/list_files.d.ts +32 -0
- package/dist/tools/list_files.d.ts.map +1 -0
- package/dist/tools/list_files.js +109 -0
- package/dist/tools/list_files.js.map +1 -0
- package/dist/tools/list_kits.d.ts +14 -0
- package/dist/tools/list_kits.d.ts.map +1 -0
- package/dist/tools/list_kits.js +41 -0
- package/dist/tools/list_kits.js.map +1 -0
- package/dist/tools/list_projects.d.ts +23 -0
- package/dist/tools/list_projects.d.ts.map +1 -0
- package/dist/tools/list_projects.js +66 -0
- package/dist/tools/list_projects.js.map +1 -0
- package/dist/tools/plan.d.ts +16 -0
- package/dist/tools/plan.d.ts.map +1 -0
- package/dist/tools/plan.js +146 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/preview.d.ts +289 -0
- package/dist/tools/preview.d.ts.map +1 -0
- package/dist/tools/preview.js +672 -0
- package/dist/tools/preview.js.map +1 -0
- package/dist/tools/read_file.d.ts +40 -0
- package/dist/tools/read_file.d.ts.map +1 -0
- package/dist/tools/read_file.js +114 -0
- package/dist/tools/read_file.js.map +1 -0
- package/dist/tools/refine.d.ts +220 -0
- package/dist/tools/refine.d.ts.map +1 -0
- package/dist/tools/refine.js +501 -0
- package/dist/tools/refine.js.map +1 -0
- package/dist/tools/validate.d.ts +74 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +224 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/tools/write_files.d.ts +158 -0
- package/dist/tools/write_files.d.ts.map +1 -0
- package/dist/tools/write_files.js +541 -0
- package/dist/tools/write_files.js.map +1 -0
- package/dist/transport.d.ts +77 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +448 -0
- package/dist/transport.js.map +1 -0
- package/dist/ui/card-asset-broker.d.ts +42 -0
- package/dist/ui/card-asset-broker.d.ts.map +1 -0
- package/dist/ui/card-asset-broker.js +479 -0
- package/dist/ui/card-asset-broker.js.map +1 -0
- package/dist/ui/grid-resource.d.ts +252 -0
- package/dist/ui/grid-resource.d.ts.map +1 -0
- package/dist/ui/grid-resource.js +680 -0
- package/dist/ui/grid-resource.js.map +1 -0
- package/dist/ui/viewer-static/index.html +95 -0
- package/dist/ui/viewer-static/viewer.css +451 -0
- package/dist/ui/viewer-static/viewer.js +1405 -0
- package/dist/validate/full-scan.d.ts +87 -0
- package/dist/validate/full-scan.d.ts.map +1 -0
- package/dist/validate/full-scan.js +299 -0
- package/dist/validate/full-scan.js.map +1 -0
- package/dist/validate/index.d.ts +15 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +18 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/marker.d.ts +89 -0
- package/dist/validate/marker.d.ts.map +1 -0
- package/dist/validate/marker.js +87 -0
- package/dist/validate/marker.js.map +1 -0
- package/dist/validate/phash.d.ts +135 -0
- package/dist/validate/phash.d.ts.map +1 -0
- package/dist/validate/phash.js +307 -0
- package/dist/validate/phash.js.map +1 -0
- package/dist/validate/render.d.ts +38 -0
- package/dist/validate/render.d.ts.map +1 -0
- package/dist/validate/render.js +155 -0
- package/dist/validate/render.js.map +1 -0
- package/dist/watch/index.d.ts +12 -0
- package/dist/watch/index.d.ts.map +1 -0
- package/dist/watch/index.js +12 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/watcher.d.ts +65 -0
- package/dist/watch/watcher.d.ts.map +1 -0
- package/dist/watch/watcher.js +238 -0
- package/dist/watch/watcher.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared kit-file helpers — MIME classification, SRI hashing, and the
|
|
3
|
+
* default/`.genieignore` exclusion matcher.
|
|
4
|
+
*
|
|
5
|
+
* These were previously split across `tools/read_file.ts` (MIME + binary
|
|
6
|
+
* detection) and `tools/list_files.ts` (SHA-256 SRI hashing, ignore matching).
|
|
7
|
+
* DRO-540 re-plumbs those verbs onto the `KitStore` interface, so the pure
|
|
8
|
+
* logic moves here to be shared by BOTH the `LocalFsKitStore` and
|
|
9
|
+
* `GitHostKitStore` implementations of `readFile`/`listFiles` — a `read_file`
|
|
10
|
+
* or `list_files` result is then byte-identical whichever adapter backs it.
|
|
11
|
+
*
|
|
12
|
+
* Nothing here touches the filesystem or the network; it operates on paths and
|
|
13
|
+
* bytes the adapters supply.
|
|
14
|
+
*/
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
import { extname } from "node:path";
|
|
17
|
+
import { lookup } from "mime-types";
|
|
18
|
+
// ─── MIME resolution + text/binary classification ────────────────────────────
|
|
19
|
+
/**
|
|
20
|
+
* Extensions that `mime-types` either misidentifies (e.g. `.ts` → `video/mp2t`)
|
|
21
|
+
* or doesn't know at all (`.tsx`, `.mts`, `.cts`). All are source-code text.
|
|
22
|
+
*/
|
|
23
|
+
const TEXT_EXT_OVERRIDES = {
|
|
24
|
+
".ts": "text/typescript",
|
|
25
|
+
".tsx": "text/tsx",
|
|
26
|
+
".mts": "text/typescript",
|
|
27
|
+
".cts": "text/typescript",
|
|
28
|
+
".svelte": "text/x-svelte",
|
|
29
|
+
".vue": "text/x-vue",
|
|
30
|
+
".mdx": "text/mdx",
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* MIME types (beyond the `text/*` family) that are textual and should be
|
|
34
|
+
* returned as utf-8 rather than base64. `mime-types` labels several source
|
|
35
|
+
* formats with an `application/*` type (e.g. `.cjs` → `application/node`,
|
|
36
|
+
* `.toml` → `application/toml`), so we treat a curated allow-list as text.
|
|
37
|
+
*/
|
|
38
|
+
const TEXT_APPLICATION_MIMES = new Set([
|
|
39
|
+
"application/json",
|
|
40
|
+
"application/xml",
|
|
41
|
+
"application/javascript",
|
|
42
|
+
"application/ecmascript",
|
|
43
|
+
"application/node",
|
|
44
|
+
"application/toml",
|
|
45
|
+
"application/yaml",
|
|
46
|
+
"application/x-yaml",
|
|
47
|
+
"application/graphql",
|
|
48
|
+
"application/x-sh",
|
|
49
|
+
"application/x-httpd-php",
|
|
50
|
+
"application/sql",
|
|
51
|
+
"application/manifest+json",
|
|
52
|
+
]);
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the MIME type for a file path.
|
|
55
|
+
* Prefers our overrides for extensions that `mime-types` misidentifies.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveMime(filePath) {
|
|
58
|
+
const ext = extname(filePath).toLowerCase();
|
|
59
|
+
return TEXT_EXT_OVERRIDES[ext] ?? (lookup(filePath) || "application/octet-stream");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* True when a MIME type is textual (returned as utf-8); everything else is
|
|
63
|
+
* returned as base64. Any MIME parameters (e.g. a `; charset=utf-8` suffix)
|
|
64
|
+
* are stripped before matching.
|
|
65
|
+
*/
|
|
66
|
+
export function isTextMime(mime) {
|
|
67
|
+
const base = mime.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
68
|
+
if (base.startsWith("text/"))
|
|
69
|
+
return true;
|
|
70
|
+
if (base.endsWith("+json"))
|
|
71
|
+
return true;
|
|
72
|
+
if (base.endsWith("+xml"))
|
|
73
|
+
return true;
|
|
74
|
+
if (base.endsWith("+yaml"))
|
|
75
|
+
return true;
|
|
76
|
+
return TEXT_APPLICATION_MIMES.has(base);
|
|
77
|
+
}
|
|
78
|
+
/** Strict base64 validation shared by tool-boundary and generated-file checks. */
|
|
79
|
+
export function isValidBase64Content(data) {
|
|
80
|
+
if (data.length === 0)
|
|
81
|
+
return true;
|
|
82
|
+
return /^[A-Za-z0-9+/]*={0,2}$/.test(data) && data.length % 4 === 0;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Classify raw file bytes into the `{ content, encoding, mimeType }` shape
|
|
86
|
+
* `KitStore.readFile` returns. Text files (by MIME) are decoded to utf-8;
|
|
87
|
+
* everything else is base64-encoded. The MIME type is derived from `path`.
|
|
88
|
+
*/
|
|
89
|
+
export function classifyFileContent(path, bytes) {
|
|
90
|
+
const mimeType = resolveMime(path);
|
|
91
|
+
if (isTextMime(mimeType)) {
|
|
92
|
+
return { content: bytes.toString("utf-8"), encoding: "utf-8", mimeType };
|
|
93
|
+
}
|
|
94
|
+
return { content: bytes.toString("base64"), encoding: "base64", mimeType };
|
|
95
|
+
}
|
|
96
|
+
// ─── SRI hashing ─────────────────────────────────────────────────────────────
|
|
97
|
+
/**
|
|
98
|
+
* Compute a Subresource-Integrity hash (`sha256-<base64>`) over `bytes` — the
|
|
99
|
+
* exact form `list_files` reports and the M4 viewer's CSP references.
|
|
100
|
+
*/
|
|
101
|
+
export function sriSha256(bytes) {
|
|
102
|
+
return `sha256-${createHash("sha256").update(bytes).digest("base64")}`;
|
|
103
|
+
}
|
|
104
|
+
// ─── kitId traversal safety ──────────────────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* The ONE kitId-safety rule shared by the `list_files` and `read_file` tools
|
|
107
|
+
* AND both `KitStore` adapters, so their traversal defenses cannot silently
|
|
108
|
+
* drift apart (DRO-509 / DRO-581 unification). Lives here — not in a tool
|
|
109
|
+
* module — because the store layer (post-#114) also needs it, and `store/*`
|
|
110
|
+
* must not import from `tools/*`.
|
|
111
|
+
*
|
|
112
|
+
* A `kitId` names a single directory (LocalFs) or repo (git host) directly
|
|
113
|
+
* under the store's kits root. `isSafeKitId` returns false for exactly the ids
|
|
114
|
+
* that would let a caller escape that single-kit namespace:
|
|
115
|
+
*
|
|
116
|
+
* - the empty string — `join(kitsRoot, "")` is the kits ROOT itself, so an
|
|
117
|
+
* empty kitId plus a crafted `path` (e.g. `other-kit/secret.txt`) would
|
|
118
|
+
* read across sibling kits; it names no kit and is rejected;
|
|
119
|
+
* - `.` or `..` exactly — the traversal aliases for "this dir" / "the parent",
|
|
120
|
+
* which also resolve to the root or above it;
|
|
121
|
+
* - any id containing a path separator (`/` or `\`), which could introduce a
|
|
122
|
+
* nested or absolute path.
|
|
123
|
+
*
|
|
124
|
+
* Ids that merely EMBED dots (`my..kit`, `..kit`, `kit..`) stay a literal child
|
|
125
|
+
* of the root and are allowed — they simply resolve to a not-found kit if
|
|
126
|
+
* absent. This is deliberately looser than the pre-unification `read_file`
|
|
127
|
+
* guard (`kitId.includes("..")`), which over-rejected `my..kit` yet — crucially
|
|
128
|
+
* — MISSED both `""` and `.` (neither contains `..`), the exact holes that
|
|
129
|
+
* enabled the cross-kit read this rule closes.
|
|
130
|
+
*
|
|
131
|
+
* A predicate (not a throwing helper) on purpose: each caller raises its own
|
|
132
|
+
* error type/code (`ListFilesError` / `McpError` / `NotFoundError`) — only the
|
|
133
|
+
* RULE is centralised here, not the error shape.
|
|
134
|
+
*/
|
|
135
|
+
export function isSafeKitId(kitId) {
|
|
136
|
+
if (kitId.length === 0)
|
|
137
|
+
return false;
|
|
138
|
+
if (kitId === "." || kitId === "..")
|
|
139
|
+
return false;
|
|
140
|
+
if (kitId.includes("/") || kitId.includes("\\"))
|
|
141
|
+
return false;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Directories genie always hides from a kit listing regardless of
|
|
146
|
+
* `.genieignore`. `.genie-tmp` is `write_files`' atomic-rename scratch space —
|
|
147
|
+
* excluded so a listing taken mid-write (or after a crash that orphaned a
|
|
148
|
+
* subdir) never surfaces genie's own bookkeeping as kit content.
|
|
149
|
+
*/
|
|
150
|
+
const DEFAULT_IGNORED_SEGMENTS = ["node_modules", ".git", "dist", ".genie-tmp"];
|
|
151
|
+
/**
|
|
152
|
+
* Build a matcher that returns true for any path that should be excluded from a
|
|
153
|
+
* kit listing: the default-ignored dirs plus every `.genieignore` pattern.
|
|
154
|
+
*/
|
|
155
|
+
export function buildIgnoreMatcher(patterns) {
|
|
156
|
+
const matchers = [
|
|
157
|
+
...DEFAULT_IGNORED_SEGMENTS.map(segmentMatcher),
|
|
158
|
+
...patterns.map(patternMatcher),
|
|
159
|
+
];
|
|
160
|
+
return (path) => matchers.some((matcher) => matcher(path));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Parse a `.genieignore` file body into its active pattern lines (trimmed,
|
|
164
|
+
* blank + `#`-comment lines dropped). Kept here so both adapters read the same
|
|
165
|
+
* ignore semantics from whatever source (a file on disk, a git-host blob).
|
|
166
|
+
*/
|
|
167
|
+
export function parseGenieignore(raw) {
|
|
168
|
+
return raw
|
|
169
|
+
.split(/\r?\n/)
|
|
170
|
+
.map((line) => line.trim())
|
|
171
|
+
.filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
172
|
+
}
|
|
173
|
+
function segmentMatcher(segment) {
|
|
174
|
+
return (path) => path.split("/").includes(segment);
|
|
175
|
+
}
|
|
176
|
+
function patternMatcher(rawPattern) {
|
|
177
|
+
const pattern = rawPattern.replace(/^\/+/, "");
|
|
178
|
+
if (pattern.endsWith("/")) {
|
|
179
|
+
const dir = pattern.replace(/\/+$/, "");
|
|
180
|
+
return (path) => path === dir || path.startsWith(`${dir}/`);
|
|
181
|
+
}
|
|
182
|
+
if (!pattern.includes("*")) {
|
|
183
|
+
return (path) => path === pattern || path.startsWith(`${pattern}/`);
|
|
184
|
+
}
|
|
185
|
+
const regex = globPatternToRegex(pattern);
|
|
186
|
+
return (path) => regex.test(path);
|
|
187
|
+
}
|
|
188
|
+
function globPatternToRegex(pattern) {
|
|
189
|
+
const escaped = pattern
|
|
190
|
+
.split("")
|
|
191
|
+
.map((char) => {
|
|
192
|
+
if (char === "*")
|
|
193
|
+
return "[^/]*";
|
|
194
|
+
return /[\\^$+?.()|[\]{}]/.test(char) ? `\\${char}` : char;
|
|
195
|
+
})
|
|
196
|
+
.join("");
|
|
197
|
+
return new RegExp(`^${escaped}$`);
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=kit-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kit-files.js","sourceRoot":"","sources":["../../src/store/kit-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalFsStore — solo-dev adapter.
|
|
3
|
+
*
|
|
4
|
+
* AC3: Stores kits under `${GENIE_HOME ?? ~/.genie}/kits/<kitId>/`
|
|
5
|
+
* and projects under `${GENIE_HOME ?? ~/.genie}/projects/<projectId>/`.
|
|
6
|
+
* Each plan is a temp staging directory.
|
|
7
|
+
*/
|
|
8
|
+
import type { ComponentEntry, FileOp, KitFileContent, KitFileEntry, KitId, KitMeta, KitStore, PlanId, ProjectId, ProjectMeta, ProjectStore, WriteOp } from "./interface.js";
|
|
9
|
+
export declare class LocalFsKitStore implements KitStore {
|
|
10
|
+
private readonly baseDir;
|
|
11
|
+
private readonly plansDir;
|
|
12
|
+
constructor(baseDir?: string);
|
|
13
|
+
private kitDir;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a kitId to its on-disk directory for the READ verbs
|
|
16
|
+
* (`listFiles`/`readFile`), rejecting unsafe ids BEFORE the join (AC-SEC,
|
|
17
|
+
* DRO-581). This is the store-layer half of the shared `isSafeKitId` rule and
|
|
18
|
+
* the defense-in-depth guard behind each tool's own kitId check: a
|
|
19
|
+
* programmatic caller that bypasses the tool must not be able to pass `""`
|
|
20
|
+
* (whose `join(baseDir, "")` is the kits ROOT — letting a crafted `path` like
|
|
21
|
+
* `other-kit/secret.txt` read a SIBLING kit), `.`/`..`, or a separator.
|
|
22
|
+
*
|
|
23
|
+
* An unsafe id names no valid kit, so it surfaces as the SAME `NotFoundError`
|
|
24
|
+
* a genuinely-missing kit would — this never leaks a sibling's bytes and adds
|
|
25
|
+
* no new error type to the `KitStore` contract (AC4). The write/plan verbs
|
|
26
|
+
* (`createKit`/`deleteFile`/`openPlan`) keep using `kitDir` directly: their
|
|
27
|
+
* ids are server-minted or already plan-gated, and their behavior is
|
|
28
|
+
* unchanged.
|
|
29
|
+
*/
|
|
30
|
+
private safeKitDir;
|
|
31
|
+
private kitMetaPath;
|
|
32
|
+
private planDir;
|
|
33
|
+
listKits(): Promise<KitMeta[]>;
|
|
34
|
+
getKit(kitId: KitId): Promise<KitMeta>;
|
|
35
|
+
listFiles(kitId: KitId): Promise<KitFileEntry[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Read the kit's `.genieignore` (if any) into active pattern lines. Absent
|
|
38
|
+
* file → no extra patterns (the default-dir exclusion still applies).
|
|
39
|
+
*/
|
|
40
|
+
private readIgnorePatterns;
|
|
41
|
+
listComponents(params: {
|
|
42
|
+
kitId: KitId;
|
|
43
|
+
group?: string;
|
|
44
|
+
}): Promise<ComponentEntry[]>;
|
|
45
|
+
readFile(kitId: KitId, path: string): Promise<KitFileContent>;
|
|
46
|
+
deleteFile(kitId: KitId, path: string): Promise<{
|
|
47
|
+
existed: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
writeFiles(kitId: KitId, ops: WriteOp[]): Promise<{
|
|
50
|
+
writtenPaths: string[];
|
|
51
|
+
}>;
|
|
52
|
+
createKit(name: string, kitId?: string): Promise<KitMeta>;
|
|
53
|
+
openPlan(kitId: KitId, ops: FileOp[]): Promise<PlanId>;
|
|
54
|
+
commitPlan(kitId: KitId, planId: PlanId, ops: FileOp[]): Promise<void>;
|
|
55
|
+
closePlan(kitId: KitId, planId: PlanId): Promise<void>;
|
|
56
|
+
private applyOps;
|
|
57
|
+
}
|
|
58
|
+
export declare class LocalFsProjectStore implements ProjectStore {
|
|
59
|
+
private readonly baseDir;
|
|
60
|
+
constructor(baseDir?: string);
|
|
61
|
+
private projectDir;
|
|
62
|
+
private metaPath;
|
|
63
|
+
listProjects(): Promise<ProjectMeta[]>;
|
|
64
|
+
getProject(projectId: ProjectId): Promise<ProjectMeta>;
|
|
65
|
+
createProject(name: string): Promise<ProjectMeta>;
|
|
66
|
+
deleteProject(projectId: ProjectId): Promise<void>;
|
|
67
|
+
bindKit(projectId: ProjectId, kitId: KitId): Promise<void>;
|
|
68
|
+
recordScreen(projectId: ProjectId, screenRef: string): Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/store/local.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,OAAO,KAAK,EACV,cAAc,EACd,MAAM,EACN,cAAc,EACd,YAAY,EACZ,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACX,YAAY,EACZ,OAAO,EACR,MAAM,gBAAgB,CAAC;AAwXxB,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,OAAO,CAAC,EAAE,MAAM;IAK5B,OAAO,CAAC,MAAM;IAId;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,OAAO;IAIT,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAmB9B,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtC,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAYtD;;;OAGG;YACW,kBAAkB;IAU1B,cAAc,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA+BnF,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgC7D,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAerE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAY7E,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA+DzD,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAWtD,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAS9C,QAAQ;CAWvB;AAID,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,CAAC,EAAE,MAAM;IAI5B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ;IAIV,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAmBtC,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAWtD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAcjD,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1D,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3E"}
|