@graview/ship 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +96 -0
- package/README.md +95 -0
- package/dist/browser-adapter.d.ts +84 -0
- package/dist/browser-adapter.d.ts.map +1 -0
- package/dist/browser-adapter.js +111 -0
- package/dist/browser-adapter.js.map +1 -0
- package/dist/browser.d.ts +26 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +16 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +48 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +170 -0
- package/dist/cli.js.map +1 -0
- package/dist/dev.d.ts +148 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +286 -0
- package/dist/dev.js.map +1 -0
- package/dist/door.d.ts +22 -0
- package/dist/door.d.ts.map +1 -0
- package/dist/door.js +43 -0
- package/dist/door.js.map +1 -0
- package/dist/export.d.ts +25 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +30 -0
- package/dist/export.js.map +1 -0
- package/dist/file-adapter.d.ts +28 -0
- package/dist/file-adapter.d.ts.map +1 -0
- package/dist/file-adapter.js +50 -0
- package/dist/file-adapter.js.map +1 -0
- package/dist/health.d.ts +19 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +16 -0
- package/dist/health.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations.d.ts +31 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +59 -0
- package/dist/migrations.js.map +1 -0
- package/dist/open-store.d.ts +57 -0
- package/dist/open-store.d.ts.map +1 -0
- package/dist/open-store.js +103 -0
- package/dist/open-store.js.map +1 -0
- package/dist/photos.d.ts +89 -0
- package/dist/photos.d.ts.map +1 -0
- package/dist/photos.js +102 -0
- package/dist/photos.js.map +1 -0
- package/dist/presence.d.ts +33 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +99 -0
- package/dist/presence.js.map +1 -0
- package/dist/remote.d.ts +73 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +271 -0
- package/dist/remote.js.map +1 -0
- package/dist/serve.d.ts +121 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +249 -0
- package/dist/serve.js.map +1 -0
- package/dist/snapshot.d.ts +20 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +41 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/source-edit.d.ts +52 -0
- package/dist/source-edit.d.ts.map +1 -0
- package/dist/source-edit.js +455 -0
- package/dist/source-edit.js.map +1 -0
- package/dist/steps.d.ts +98 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +189 -0
- package/dist/steps.js.map +1 -0
- package/dist/studio-door.d.ts +36 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +102 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync-seed.d.ts +61 -0
- package/dist/sync-seed.d.ts.map +1 -0
- package/dist/sync-seed.js +95 -0
- package/dist/sync-seed.js.map +1 -0
- package/dist/typecheck.d.ts +15 -0
- package/dist/typecheck.d.ts.map +1 -0
- package/dist/typecheck.js +59 -0
- package/dist/typecheck.js.map +1 -0
- package/package.json +75 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { loadApp } from "@graview/core/cli";
|
|
4
|
+
import { createFileAdapter } from "./file-adapter.js";
|
|
5
|
+
import { openStore } from "./open-store.js";
|
|
6
|
+
import { serveStore } from "./serve.js";
|
|
7
|
+
import { sayStep } from "./steps.js";
|
|
8
|
+
import { applySteps, seedSteps } from "./sync-seed.js";
|
|
9
|
+
/**
|
|
10
|
+
* `graview serve` — the store behind HTTP, and the data in a folder you can
|
|
11
|
+
* open.
|
|
12
|
+
*
|
|
13
|
+
* The file adapter is the default because the point of this command is the
|
|
14
|
+
* answer to "where is my data": a directory holding `snapshot.json`, a
|
|
15
|
+
* `log.jsonl` with one operation per line that a person can `grep`, and a
|
|
16
|
+
* `meta.json` carrying the stored version. `--sqlite` swaps the adapter and
|
|
17
|
+
* changes nothing else, which is the actual claim about adapters.
|
|
18
|
+
*/
|
|
19
|
+
export const SERVE_USAGE = ` graview serve <entry> [--data <dir>] [--port <n>] [--seed <file>] [--sqlite <file>]
|
|
20
|
+
Serves the app's store over HTTP. The op log is the wire: a client
|
|
21
|
+
sends calls, the store judges them under the caller's own seat, and
|
|
22
|
+
the ops come back. Data lives in <dir> (default ./data) as readable
|
|
23
|
+
JSON, or in a SQLite file with --sqlite.
|
|
24
|
+
|
|
25
|
+
graview sync-seed <entry> --seed <file> [--data <dir> | --sqlite <file>]
|
|
26
|
+
[--apply] [--prune] [--json]
|
|
27
|
+
Diffs the bootstrap seed against the live store and says, as content
|
|
28
|
+
steps, what would bring the store in step with it: records put,
|
|
29
|
+
fields patched, ties made. Prints and exits by default; --apply lands
|
|
30
|
+
the steps as one logged, undoable operation; --prune also drops what
|
|
31
|
+
the seed no longer has. The seed itself is only ever read at first
|
|
32
|
+
install — this is how default content moves afterwards, in place of
|
|
33
|
+
deleting the store.
|
|
34
|
+
`;
|
|
35
|
+
/** The same store, whichever command asked: parsed from the flags every store command shares. */
|
|
36
|
+
export const STORE_FLAGS = `--data <dir> (default ./data) | --sqlite <file>, and --seed <file> for a first install`;
|
|
37
|
+
export function flag(argv, name) {
|
|
38
|
+
const at = argv.indexOf(name);
|
|
39
|
+
if (at === -1)
|
|
40
|
+
return undefined;
|
|
41
|
+
return argv[at + 1];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* THE BACKEND FLAGS, PARSED ONCE. `serve`, `sync-seed`, `mcp` and `apply`
|
|
45
|
+
* all take the same store: a folder of readable JSON, or a SQLite file, and
|
|
46
|
+
* a seed for a first install. One parser, so the four commands cannot come
|
|
47
|
+
* to mean different things by the same words.
|
|
48
|
+
*/
|
|
49
|
+
export async function backendFrom(argv, cwd = process.cwd()) {
|
|
50
|
+
const sqlite = flag(argv, "--sqlite");
|
|
51
|
+
const data = resolve(cwd, flag(argv, "--data") ?? "data");
|
|
52
|
+
const seedFile = flag(argv, "--seed");
|
|
53
|
+
const seed = seedFile ? readSeed(resolve(cwd, seedFile)) : undefined;
|
|
54
|
+
if (sqlite) {
|
|
55
|
+
const file = resolve(cwd, sqlite);
|
|
56
|
+
return { adapter: await sqliteAdapter(file), where: file, ...(seed ? { seed } : {}) };
|
|
57
|
+
}
|
|
58
|
+
return { adapter: createFileAdapter(data), where: data, ...(seed ? { seed } : {}) };
|
|
59
|
+
}
|
|
60
|
+
function readSeed(file) {
|
|
61
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
62
|
+
if (!Array.isArray(parsed.nodes) || !Array.isArray(parsed.edges)) {
|
|
63
|
+
throw new Error(`${file} is not a graph snapshot: it needs "nodes" and "edges" arrays.`);
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
/** The entry module, or the reason it is not one — said before anything is opened. */
|
|
68
|
+
async function entryOf(argv, command, usage) {
|
|
69
|
+
const entry = argv[0];
|
|
70
|
+
if (!entry || entry.startsWith("--")) {
|
|
71
|
+
process.stderr.write(`graview ${command}: an entry module is required\n\n${usage}`);
|
|
72
|
+
return 2;
|
|
73
|
+
}
|
|
74
|
+
return loadApp(entry);
|
|
75
|
+
}
|
|
76
|
+
export async function serve(argv) {
|
|
77
|
+
const app = await entryOf(argv, "serve", SERVE_USAGE);
|
|
78
|
+
if (typeof app === "number")
|
|
79
|
+
return app;
|
|
80
|
+
const port = Number(flag(argv, "--port") ?? 5196);
|
|
81
|
+
const backend = await backendFrom(argv);
|
|
82
|
+
const served = await serveStore({
|
|
83
|
+
app: app,
|
|
84
|
+
adapter: backend.adapter,
|
|
85
|
+
...(backend.seed ? { seed: backend.seed } : {}),
|
|
86
|
+
port,
|
|
87
|
+
where: backend.where,
|
|
88
|
+
});
|
|
89
|
+
process.stdout.write(`graview serve: ${app.name} on ${served.url}\n` +
|
|
90
|
+
` data: ${backend.where} (${backend.adapter.name})\n` +
|
|
91
|
+
` ${served.store.graph.allNodes().length} nodes, ${served.opened.store.log.all().length} operations` +
|
|
92
|
+
`${served.opened.migrated.length > 0 ? `, migrated: ${served.opened.migrated.map((op) => op.intent).join("; ")}` : ""}\n`);
|
|
93
|
+
const stop = () => {
|
|
94
|
+
void served.close().then(() => process.exit(0));
|
|
95
|
+
};
|
|
96
|
+
process.on("SIGINT", stop);
|
|
97
|
+
process.on("SIGTERM", stop);
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* `graview sync-seed` — default content moves without a wipe.
|
|
102
|
+
*
|
|
103
|
+
* Read-only unless `--apply` is said, because the steps are the product: a
|
|
104
|
+
* person or an agent reads what WOULD change and decides. Applying lands
|
|
105
|
+
* them through `applySteps`, which is `receive` on the open store — the
|
|
106
|
+
* adapter hears it like any change, the log carries it with its inverse,
|
|
107
|
+
* and undo is the ordinary undo.
|
|
108
|
+
*/
|
|
109
|
+
export async function syncSeed(argv) {
|
|
110
|
+
const app = await entryOf(argv, "sync-seed", SERVE_USAGE);
|
|
111
|
+
if (typeof app === "number")
|
|
112
|
+
return app;
|
|
113
|
+
if (flag(argv, "--remote-url")) {
|
|
114
|
+
process.stderr.write(`graview sync-seed: runs where the data is — against --data or --sqlite on the host, not a remote URL.\n`);
|
|
115
|
+
return 2;
|
|
116
|
+
}
|
|
117
|
+
const backend = await backendFrom(argv);
|
|
118
|
+
if (!backend.seed) {
|
|
119
|
+
process.stderr.write(`graview sync-seed: --seed <file> is required\n\n${SERVE_USAGE}`);
|
|
120
|
+
return 2;
|
|
121
|
+
}
|
|
122
|
+
const opened = await openStore({ app: app, adapter: backend.adapter, scope: app.name, seed: backend.seed });
|
|
123
|
+
try {
|
|
124
|
+
const live = opened.store.graph.snapshot();
|
|
125
|
+
const steps = seedSteps(backend.seed, live, { prune: argv.includes("--prune") });
|
|
126
|
+
const json = argv.includes("--json");
|
|
127
|
+
if (steps.length === 0) {
|
|
128
|
+
process.stdout.write(json ? `{"steps":[],"applied":null}\n` : `graview sync-seed: ${backend.where} already has everything the seed has.\n`);
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
if (!argv.includes("--apply")) {
|
|
132
|
+
process.stdout.write(json
|
|
133
|
+
? `${JSON.stringify({ steps, applied: null }, null, 2)}\n`
|
|
134
|
+
: `graview sync-seed: ${steps.length} step${steps.length === 1 ? "" : "s"} would bring ${backend.where} in step with the seed:\n` +
|
|
135
|
+
steps.map((step) => ` ${sayStep(step)}\n`).join("") +
|
|
136
|
+
`Nothing was written. Add --apply to land them as one undoable operation.\n`);
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
const landed = applySteps(opened.store, steps);
|
|
140
|
+
await opened.flush();
|
|
141
|
+
if (!landed) {
|
|
142
|
+
process.stdout.write(json ? `{"steps":[],"applied":null}\n` : `graview sync-seed: the steps came to nothing against ${backend.where}.\n`);
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
process.stdout.write(json
|
|
146
|
+
? `${JSON.stringify({ steps, applied: { id: landed.id, batch: landed.batch, primitives: landed.primitives.length } }, null, 2)}\n`
|
|
147
|
+
: `graview sync-seed: landed ${landed.primitives.length} change${landed.primitives.length === 1 ? "" : "s"} on ${backend.where} as batch ${landed.batch}.\n` +
|
|
148
|
+
steps.map((step) => ` ${sayStep(step)}\n`).join("") +
|
|
149
|
+
`Undo with: graview apply <entry> --undo ${JSON.stringify(landed.batch)} [--data|--sqlite as above]\n`);
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
opened.close();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The sqlite adapter, imported only when asked for.
|
|
158
|
+
*
|
|
159
|
+
* `better-sqlite3` is a native module. A static import would make every
|
|
160
|
+
* `graview serve` — and every bundler that ever saw this file — need it
|
|
161
|
+
* built, for a flag most people never pass.
|
|
162
|
+
*/
|
|
163
|
+
async function sqliteAdapter(file) {
|
|
164
|
+
const { createSqliteAdapter } = await import("@graview/core");
|
|
165
|
+
const { default: Database } = (await import("better-sqlite3"));
|
|
166
|
+
// `createTables` because this is the "point it at a file" case: an app
|
|
167
|
+
// with its own Drizzle schema passes its own database and leaves it alone.
|
|
168
|
+
return createSqliteAdapter({ database: new Database(file), createTables: true });
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/dev.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import { type LocalBridgeAsk, type LocalBridgeStatus } from "@graview/core";
|
|
3
|
+
import { type DevServerPlugin } from "./door.js";
|
|
4
|
+
export { sameOrigin } from "./door.js";
|
|
5
|
+
export type { DevServerPlugin } from "./door.js";
|
|
6
|
+
/**
|
|
7
|
+
* THE FOURTH DOOR: a process on this machine, and the dev server as the
|
|
8
|
+
* only thing that can open it.
|
|
9
|
+
*
|
|
10
|
+
* `openStore` is the lifecycle every deployment repeats — an adapter, a
|
|
11
|
+
* version, migrations. There was nothing equivalent for the other thing a
|
|
12
|
+
* locally-run product has and a deployed one does not: A MACHINE WITH TOOLS
|
|
13
|
+
* ON IT. Somebody running an app from `pnpm dev` very often has a coding
|
|
14
|
+
* agent installed, logged in and paid for; the browser cannot spawn it and
|
|
15
|
+
* the dev server can. Every product with a `local` reach was going to write
|
|
16
|
+
* this file, and the first one that did paid for it in hung processes.
|
|
17
|
+
*
|
|
18
|
+
* What it learned, each item the price of one:
|
|
19
|
+
*
|
|
20
|
+
* - `claude -p` READS STDIN when stdin is not a terminal. Spawned with an
|
|
21
|
+
* open pipe it waits forever. Stdin is closed here, always.
|
|
22
|
+
* - A session spawned from inside another session inherits the parent's
|
|
23
|
+
* `CLAUDE*` environment and misbehaves. Every such variable is stripped,
|
|
24
|
+
* because "the dev server was started from a Claude Code terminal" is the
|
|
25
|
+
* normal case for the person this is for.
|
|
26
|
+
* - Given Bash, a model will spend ten turns trying to decode an image it
|
|
27
|
+
* cannot see. Read and only Read, a turn cap of one per photograph plus a
|
|
28
|
+
* few to answer in, and a dollar budget, keep a bad answer cheap and short.
|
|
29
|
+
*
|
|
30
|
+
* It is a DEV-SERVER plugin and nothing else. A built deployment has no
|
|
31
|
+
* server here: the probe gets a 404 and the door reads as closed, which is
|
|
32
|
+
* exactly right. And it answers same-origin callers only — a dev server
|
|
33
|
+
* allows every origin by default, and a page on another site must not be
|
|
34
|
+
* able to spend this machine's session.
|
|
35
|
+
*/
|
|
36
|
+
export interface Spawned {
|
|
37
|
+
readonly code: number | null;
|
|
38
|
+
readonly stdout: string;
|
|
39
|
+
readonly stderr: string;
|
|
40
|
+
}
|
|
41
|
+
/** Runs a command to completion. Injected, so a test never starts a real session. */
|
|
42
|
+
export type Runner = (command: string, args: readonly string[], options: {
|
|
43
|
+
readonly cwd: string;
|
|
44
|
+
readonly env: NodeJS.ProcessEnv;
|
|
45
|
+
readonly timeoutMs: number;
|
|
46
|
+
}) => Promise<Spawned>;
|
|
47
|
+
export interface LocalIntelligenceOptions {
|
|
48
|
+
/** The executable. `claude` on PATH unless said otherwise. */
|
|
49
|
+
readonly command?: string;
|
|
50
|
+
/** The path the door answers on. Must match the provider's `bridge`. */
|
|
51
|
+
readonly path?: string;
|
|
52
|
+
/** A model alias for `--model`; the CLI's own default when absent. */
|
|
53
|
+
readonly model?: string;
|
|
54
|
+
/** How long one answer may take. Ten minutes: a dozen photographs is a slow read. */
|
|
55
|
+
readonly timeoutMs?: number;
|
|
56
|
+
/** The most one answer may cost, in dollars. */
|
|
57
|
+
readonly budgetUsd?: number;
|
|
58
|
+
/** The most one request may carry, in bytes. Photographs are large. */
|
|
59
|
+
readonly limitBytes?: number;
|
|
60
|
+
/** How the command is run. Injected by tests; `runProcess` otherwise. */
|
|
61
|
+
readonly run?: Runner;
|
|
62
|
+
/** The argv for a prompt and the photograph filenames beside it. */
|
|
63
|
+
readonly argv?: (prompt: string, files: readonly string[], options: LocalIntelligenceOptions) => readonly string[];
|
|
64
|
+
/** What the command printed, read back as text. Throws with a sentence. */
|
|
65
|
+
readonly parse?: (stdout: string) => string;
|
|
66
|
+
}
|
|
67
|
+
/** Runs a command with stdin closed, returning what it wrote. */
|
|
68
|
+
export declare const runProcess: Runner;
|
|
69
|
+
/** The environment a spawned session gets: this one, minus the parent session's own. */
|
|
70
|
+
export declare function environmentFor(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
71
|
+
/** A data URL to bytes and an extension a Read tool will treat as an image. */
|
|
72
|
+
export declare function decodePhoto(dataUrl: string): {
|
|
73
|
+
readonly bytes: Buffer;
|
|
74
|
+
readonly extension: string;
|
|
75
|
+
};
|
|
76
|
+
/** The argv a Claude Code session is run with. Replaceable for another CLI. */
|
|
77
|
+
export declare function argumentsFor(prompt: string, files: readonly string[], options: LocalIntelligenceOptions): readonly string[];
|
|
78
|
+
/** Reads the CLI's JSON envelope, or says plainly what was wrong with it. */
|
|
79
|
+
export declare function parseEnvelope(stdout: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Photographs and a prompt in, text out.
|
|
82
|
+
*
|
|
83
|
+
* The temporary directory is the session's working directory, so a Read tool
|
|
84
|
+
* needs no extra permission to see the files, and it is removed whatever
|
|
85
|
+
* happens.
|
|
86
|
+
*/
|
|
87
|
+
export declare function askLocally(ask: LocalBridgeAsk, options?: LocalIntelligenceOptions): Promise<string>;
|
|
88
|
+
/** Is the command on this machine? Cached: a version check per keystroke would be silly. */
|
|
89
|
+
export declare function probeLocal(options?: LocalIntelligenceOptions): () => Promise<LocalBridgeStatus>;
|
|
90
|
+
/**
|
|
91
|
+
* The request handler, without Vite around it — so a test can drive the door
|
|
92
|
+
* with two fake messages rather than a server, and a host that is not Vite
|
|
93
|
+
* can mount it wherever it mounts things.
|
|
94
|
+
*/
|
|
95
|
+
export declare function localIntelligenceHandler(options?: LocalIntelligenceOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* The Vite plugin. One path: GET says whether the door is open, POST walks
|
|
98
|
+
* through it.
|
|
99
|
+
*
|
|
100
|
+
* `apply: "serve"` is the whole deployment story — a build never carries it,
|
|
101
|
+
* so the probe 404s on a static host and the door reads as closed.
|
|
102
|
+
*/
|
|
103
|
+
export declare function localIntelligence(options?: LocalIntelligenceOptions): DevServerPlugin;
|
|
104
|
+
/**
|
|
105
|
+
* THE DOOR TO A DECISION PROVIDER, with the key on this side of it.
|
|
106
|
+
*
|
|
107
|
+
* A browser page must not hold a service key, and the environment the dev
|
|
108
|
+
* server runs in already does: `TYPESAFE_API_KEY`, set once by the person
|
|
109
|
+
* who runs `pnpm dev`. So the page posts a state and a map of questions to
|
|
110
|
+
* this path and the server forwards them with the key in the header — one
|
|
111
|
+
* call, the provider's own shape, and the answer back untouched. GET says
|
|
112
|
+
* whether the door is open, which is whether a key is set.
|
|
113
|
+
*
|
|
114
|
+
* Same-origin only, for the same reason as the local door: a page on some
|
|
115
|
+
* other site must not spend this key. And the key is NEVER in a response,
|
|
116
|
+
* a thrown error or a log line — a refused key is reported as refused.
|
|
117
|
+
*/
|
|
118
|
+
export interface DecisionBridgeOptions {
|
|
119
|
+
/** The path the door answers on. Must match the provider's `bridge`. */
|
|
120
|
+
readonly path?: string;
|
|
121
|
+
/** Where the provider is. Its real endpoint unless a test says otherwise. */
|
|
122
|
+
readonly endpoint?: string;
|
|
123
|
+
readonly model?: string;
|
|
124
|
+
/** Where the key is read from. The process environment unless a test says otherwise. */
|
|
125
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
126
|
+
/** Injectable for tests. */
|
|
127
|
+
readonly fetch?: (input: string, init: {
|
|
128
|
+
method: string;
|
|
129
|
+
headers: Record<string, string>;
|
|
130
|
+
body: string;
|
|
131
|
+
}) => Promise<{
|
|
132
|
+
status: number;
|
|
133
|
+
text(): Promise<string>;
|
|
134
|
+
}>;
|
|
135
|
+
/** The most one request may carry, in bytes. A fan-out over a big graph is large. */
|
|
136
|
+
readonly limitBytes?: number;
|
|
137
|
+
}
|
|
138
|
+
/** The key the door holds, from the documented name or the older one. */
|
|
139
|
+
export declare function decisionKey(env: Readonly<Record<string, string | undefined>> | undefined): string | undefined;
|
|
140
|
+
export declare function decisionBridgeHandler(options?: DecisionBridgeOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
141
|
+
/** The Vite plugin. One path; GET is the probe, POST is the ask. */
|
|
142
|
+
export declare function decisionBridge(options?: DecisionBridgeOptions): DevServerPlugin;
|
|
143
|
+
export { studioDoor, studioDoorHandler } from "./studio-door.js";
|
|
144
|
+
export type { StudioDoorOptions } from "./studio-door.js";
|
|
145
|
+
export { declaredCode, editDeclaration } from "./source-edit.js";
|
|
146
|
+
export { typecheckWith } from "./typecheck.js";
|
|
147
|
+
export type { SourceEdit, SourceText } from "./source-edit.js";
|
|
148
|
+
//# sourceMappingURL=dev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
|
package/dist/dev.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { DECISION_BRIDGE_PATH, LOCAL_BRIDGE_PATH, } from "@graview/core";
|
|
6
|
+
import { fromThisApp, readBody, sendJson } from "./door.js";
|
|
7
|
+
export { sameOrigin } from "./door.js";
|
|
8
|
+
const DEFAULTS = {
|
|
9
|
+
command: "claude",
|
|
10
|
+
timeoutMs: 10 * 60 * 1000,
|
|
11
|
+
budgetUsd: 5,
|
|
12
|
+
limitBytes: 40_000_000,
|
|
13
|
+
};
|
|
14
|
+
/** Runs a command with stdin closed, returning what it wrote. */
|
|
15
|
+
export const runProcess = (command, args, { cwd, env, timeoutMs }) => new Promise((resolve, reject) => {
|
|
16
|
+
const child = spawn(command, args, { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
17
|
+
let stdout = "";
|
|
18
|
+
let stderr = "";
|
|
19
|
+
child.stdout.on("data", (chunk) => (stdout += chunk.toString()));
|
|
20
|
+
child.stderr.on("data", (chunk) => (stderr += chunk.toString()));
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
child.kill("SIGTERM");
|
|
23
|
+
reject(new Error(`The local session did not answer within ${Math.round(timeoutMs / 60000)} minutes and was stopped.`));
|
|
24
|
+
}, timeoutMs);
|
|
25
|
+
child.on("error", (error) => {
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
reject(error);
|
|
28
|
+
});
|
|
29
|
+
child.on("close", (code) => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
resolve({ code, stdout, stderr });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
/** The environment a spawned session gets: this one, minus the parent session's own. */
|
|
35
|
+
export function environmentFor(env) {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const [key, value] of Object.entries(env)) {
|
|
38
|
+
if (key.startsWith("CLAUDE"))
|
|
39
|
+
continue;
|
|
40
|
+
out[key] = value;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
/** A data URL to bytes and an extension a Read tool will treat as an image. */
|
|
45
|
+
export function decodePhoto(dataUrl) {
|
|
46
|
+
const match = /^data:image\/(jpeg|jpg|png|webp|gif);base64,(.+)$/s.exec(dataUrl);
|
|
47
|
+
if (match === null) {
|
|
48
|
+
throw new Error("A photograph must be a base64 data URL of a JPEG, PNG, WebP or GIF.");
|
|
49
|
+
}
|
|
50
|
+
const extension = match[1] === "jpeg" ? "jpg" : match[1];
|
|
51
|
+
return { bytes: Buffer.from(match[2], "base64"), extension };
|
|
52
|
+
}
|
|
53
|
+
/** The argv a Claude Code session is run with. Replaceable for another CLI. */
|
|
54
|
+
export function argumentsFor(prompt, files, options) {
|
|
55
|
+
const lead = files.length === 0
|
|
56
|
+
? ""
|
|
57
|
+
: `The photographs are in this directory, at these paths: ${files.join(", ")}. ` +
|
|
58
|
+
`Read every one of them with the Read tool before you answer.\n\n`;
|
|
59
|
+
return [
|
|
60
|
+
"-p",
|
|
61
|
+
`${lead}${prompt}`,
|
|
62
|
+
"--output-format",
|
|
63
|
+
"json",
|
|
64
|
+
"--no-session-persistence",
|
|
65
|
+
// Read, and only Read. Bash would let a stuck model spend an hour
|
|
66
|
+
// decoding pixels by hand; Write would let it change the machine.
|
|
67
|
+
"--tools",
|
|
68
|
+
"Read",
|
|
69
|
+
"--allowedTools",
|
|
70
|
+
"Read",
|
|
71
|
+
// One turn per photograph, and a few to answer in.
|
|
72
|
+
"--max-turns",
|
|
73
|
+
String(files.length + 3),
|
|
74
|
+
"--max-budget-usd",
|
|
75
|
+
String(options.budgetUsd ?? DEFAULTS.budgetUsd),
|
|
76
|
+
...(options.model === undefined ? [] : ["--model", options.model]),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
/** Reads the CLI's JSON envelope, or says plainly what was wrong with it. */
|
|
80
|
+
export function parseEnvelope(stdout) {
|
|
81
|
+
let parsed;
|
|
82
|
+
try {
|
|
83
|
+
parsed = JSON.parse(stdout);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new Error(`The local session answered with something other than its JSON envelope: ${stdout.slice(0, 200)}`);
|
|
87
|
+
}
|
|
88
|
+
if (parsed.is_error === true) {
|
|
89
|
+
throw new Error(`The local session reported an error: ${parsed.result ?? parsed.subtype ?? "unnamed"}`);
|
|
90
|
+
}
|
|
91
|
+
if (typeof parsed.result !== "string" || parsed.result.trim().length === 0) {
|
|
92
|
+
throw new Error(parsed.subtype === "error_max_turns"
|
|
93
|
+
? "The local session ran out of turns before answering — fewer photographs, or larger ones, usually fixes it."
|
|
94
|
+
: "The local session answered with nothing at all.");
|
|
95
|
+
}
|
|
96
|
+
return parsed.result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Photographs and a prompt in, text out.
|
|
100
|
+
*
|
|
101
|
+
* The temporary directory is the session's working directory, so a Read tool
|
|
102
|
+
* needs no extra permission to see the files, and it is removed whatever
|
|
103
|
+
* happens.
|
|
104
|
+
*/
|
|
105
|
+
export async function askLocally(ask, options = {}) {
|
|
106
|
+
const run = options.run ?? runProcess;
|
|
107
|
+
const dir = await mkdtemp(join(tmpdir(), "graview-local-"));
|
|
108
|
+
try {
|
|
109
|
+
const files = [];
|
|
110
|
+
for (const [index, photo] of (ask.photos ?? []).entries()) {
|
|
111
|
+
const { bytes, extension } = decodePhoto(photo);
|
|
112
|
+
const name = `photo-${index + 1}.${extension}`;
|
|
113
|
+
await writeFile(join(dir, name), bytes);
|
|
114
|
+
files.push(name);
|
|
115
|
+
}
|
|
116
|
+
const argv = (options.argv ?? argumentsFor)(ask.prompt, files, options);
|
|
117
|
+
const result = await run(options.command ?? DEFAULTS.command, argv, {
|
|
118
|
+
cwd: dir,
|
|
119
|
+
env: environmentFor(process.env),
|
|
120
|
+
timeoutMs: options.timeoutMs ?? DEFAULTS.timeoutMs,
|
|
121
|
+
});
|
|
122
|
+
if (result.code !== 0 && result.stdout.trim().length === 0) {
|
|
123
|
+
throw new Error(`The local session stopped (exit ${String(result.code)}): ${result.stderr.trim() || "and said nothing"}`);
|
|
124
|
+
}
|
|
125
|
+
return (options.parse ?? parseEnvelope)(result.stdout);
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
await rm(dir, { recursive: true, force: true });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Is the command on this machine? Cached: a version check per keystroke would be silly. */
|
|
132
|
+
export function probeLocal(options = {}) {
|
|
133
|
+
let cached = null;
|
|
134
|
+
return async () => {
|
|
135
|
+
if (cached !== null && Date.now() - cached.at < 60_000)
|
|
136
|
+
return cached.status;
|
|
137
|
+
const status = await new Promise((resolve) => {
|
|
138
|
+
execFile(options.command ?? DEFAULTS.command, ["--version"], { env: environmentFor(process.env), timeout: 10_000 }, (error, stdout) => {
|
|
139
|
+
if (error) {
|
|
140
|
+
resolve({
|
|
141
|
+
available: false,
|
|
142
|
+
reason: `Nothing to run on this machine (${error.message.split("\n")[0]})`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else
|
|
146
|
+
resolve({ available: true, version: stdout.trim() });
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
cached = { at: Date.now(), status };
|
|
150
|
+
return status;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** What the local and decision doors answer with, and nothing else. */
|
|
154
|
+
const send = (res, status, body) => sendJson(res, status, body);
|
|
155
|
+
/**
|
|
156
|
+
* The request handler, without Vite around it — so a test can drive the door
|
|
157
|
+
* with two fake messages rather than a server, and a host that is not Vite
|
|
158
|
+
* can mount it wherever it mounts things.
|
|
159
|
+
*/
|
|
160
|
+
export function localIntelligenceHandler(options = {}) {
|
|
161
|
+
const probe = probeLocal(options);
|
|
162
|
+
return async (req, res) => {
|
|
163
|
+
if (!fromThisApp(req)) {
|
|
164
|
+
send(res, 403, { error: "The local door answers this app only." });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (req.method === "GET") {
|
|
168
|
+
send(res, 200, await probe());
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (req.method !== "POST") {
|
|
172
|
+
send(res, 405, { error: "GET to ask whether the door is open; POST to ask it something." });
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const ask = JSON.parse(await readBody(req, options.limitBytes ?? DEFAULTS.limitBytes, "photographs"));
|
|
177
|
+
if (typeof ask.prompt !== "string") {
|
|
178
|
+
send(res, 400, { error: "A request is { prompt, photos }." });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const photos = Array.isArray(ask.photos) ? ask.photos : [];
|
|
182
|
+
send(res, 200, { text: await askLocally({ prompt: ask.prompt, photos }, options) });
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
send(res, 500, { error: error instanceof Error ? error.message : String(error) });
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The Vite plugin. One path: GET says whether the door is open, POST walks
|
|
191
|
+
* through it.
|
|
192
|
+
*
|
|
193
|
+
* `apply: "serve"` is the whole deployment story — a build never carries it,
|
|
194
|
+
* so the probe 404s on a static host and the door reads as closed.
|
|
195
|
+
*/
|
|
196
|
+
export function localIntelligence(options = {}) {
|
|
197
|
+
const handler = localIntelligenceHandler(options);
|
|
198
|
+
return {
|
|
199
|
+
name: "graview:local-intelligence",
|
|
200
|
+
apply: "serve",
|
|
201
|
+
configureServer(server) {
|
|
202
|
+
server.middlewares.use(options.path ?? LOCAL_BRIDGE_PATH, (req, res) => {
|
|
203
|
+
void handler(req, res);
|
|
204
|
+
});
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const DECISION_DEFAULTS = {
|
|
209
|
+
endpoint: "https://api.typesafe.ai/v1/systemone",
|
|
210
|
+
model: "jev-latest",
|
|
211
|
+
limitBytes: 4_000_000,
|
|
212
|
+
};
|
|
213
|
+
/** The key the door holds, from the documented name or the older one. */
|
|
214
|
+
export function decisionKey(env) {
|
|
215
|
+
const key = env?.["TYPESAFE_API_KEY"] || env?.["JEV_API_KEY"];
|
|
216
|
+
return key && key.length > 0 ? key : undefined;
|
|
217
|
+
}
|
|
218
|
+
export function decisionBridgeHandler(options = {}) {
|
|
219
|
+
const env = options.env ?? process.env;
|
|
220
|
+
const endpoint = options.endpoint ?? DECISION_DEFAULTS.endpoint;
|
|
221
|
+
const model = options.model ?? DECISION_DEFAULTS.model;
|
|
222
|
+
const call = options.fetch ?? globalThis.fetch;
|
|
223
|
+
return async (req, res) => {
|
|
224
|
+
if (!fromThisApp(req)) {
|
|
225
|
+
send(res, 403, { error: "The decision door answers this app only." });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const key = decisionKey(env);
|
|
229
|
+
if (req.method === "GET") {
|
|
230
|
+
send(res, 200, key
|
|
231
|
+
? { available: true, model }
|
|
232
|
+
: { available: false, reason: "No TYPESAFE_API_KEY in the environment this server was started from." });
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (req.method !== "POST") {
|
|
236
|
+
send(res, 405, { error: "GET to ask whether the door is open; POST a state and questions." });
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!key) {
|
|
240
|
+
send(res, 503, { error: "No TYPESAFE_API_KEY in the environment this server was started from.", status: 503 });
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const ask = JSON.parse(await readBody(req, options.limitBytes ?? DECISION_DEFAULTS.limitBytes));
|
|
245
|
+
if (typeof ask.questions !== "object" || ask.questions === null) {
|
|
246
|
+
send(res, 400, { error: "A request is { state, questions }.", status: 400 });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const upstream = await call(endpoint, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${key}` },
|
|
252
|
+
body: JSON.stringify({ model, state: ask.state ?? null, questions: ask.questions }),
|
|
253
|
+
});
|
|
254
|
+
const text = await upstream.text();
|
|
255
|
+
/*
|
|
256
|
+
* The provider's status is the page's status, so the page-side
|
|
257
|
+
* provider tells failures apart the same way it would have with the
|
|
258
|
+
* key in hand — 401 a seat problem, 422 ours, 429/529 busy. The body
|
|
259
|
+
* is passed through as it came: it never held the key.
|
|
260
|
+
*/
|
|
261
|
+
res.statusCode = upstream.status;
|
|
262
|
+
res.setHeader("content-type", "application/json");
|
|
263
|
+
res.end(text);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
send(res, 500, { error: error instanceof Error ? error.message : String(error), status: 500 });
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/** The Vite plugin. One path; GET is the probe, POST is the ask. */
|
|
271
|
+
export function decisionBridge(options = {}) {
|
|
272
|
+
const handler = decisionBridgeHandler(options);
|
|
273
|
+
return {
|
|
274
|
+
name: "graview:decision-bridge",
|
|
275
|
+
apply: "serve",
|
|
276
|
+
configureServer(server) {
|
|
277
|
+
server.middlewares.use(options.path ?? DECISION_BRIDGE_PATH, (req, res) => {
|
|
278
|
+
void handler(req, res);
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
export { studioDoor, studioDoorHandler } from "./studio-door.js";
|
|
284
|
+
export { declaredCode, editDeclaration } from "./source-edit.js";
|
|
285
|
+
export { typecheckWith } from "./typecheck.js";
|
|
286
|
+
//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
|