@nyte-ai/host 0.0.0-stage → 0.0.18
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 +21 -0
- package/README.md +6 -2
- package/THIRD-PARTY-NOTICES.md +800 -0
- package/dist/chunks/canvas-preview-0cmbkp2j.js +65 -0
- package/dist/chunks/canvas-preview-0nq75h9k.js +7 -0
- package/dist/chunks/canvas-preview-0nrnbt76.js +497 -0
- package/dist/chunks/canvas-preview-1sq7z9jq.js +17 -0
- package/dist/chunks/canvas-preview-1ta3avah.js +56 -0
- package/dist/chunks/canvas-preview-2zdyh9ny.js +26 -0
- package/dist/chunks/canvas-preview-31w7xm8z.js +34 -0
- package/dist/chunks/canvas-preview-4b6sayhg.js +295 -0
- package/dist/chunks/canvas-preview-4e0pxa32.js +63 -0
- package/dist/chunks/canvas-preview-518dh8by.js +169 -0
- package/dist/chunks/canvas-preview-5hxat7hh.js +239 -0
- package/dist/chunks/canvas-preview-5mex725c.js +14 -0
- package/dist/chunks/canvas-preview-5z63am63.js +295 -0
- package/dist/chunks/canvas-preview-65xqjw7f.js +20 -0
- package/dist/chunks/canvas-preview-69fkk9yn.js +95 -0
- package/dist/chunks/canvas-preview-75db60xy.js +457 -0
- package/dist/chunks/canvas-preview-76fwvd6e.js +272 -0
- package/dist/chunks/canvas-preview-8xgt67ka.js +598 -0
- package/dist/chunks/canvas-preview-98aj5p34.js +176 -0
- package/dist/chunks/canvas-preview-9aqczacs.js +73 -0
- package/dist/chunks/canvas-preview-a3yw0j70.js +72 -0
- package/dist/chunks/canvas-preview-azg56359.js +68 -0
- package/dist/chunks/canvas-preview-d9wwhbtz.js +240 -0
- package/dist/chunks/canvas-preview-ehf3vp31.js +411 -0
- package/dist/chunks/canvas-preview-evh92ywd.js +369 -0
- package/dist/chunks/canvas-preview-ewgspmsd.js +81 -0
- package/dist/chunks/canvas-preview-g3qj3y3k.js +156 -0
- package/dist/chunks/canvas-preview-h8hshnff.js +63 -0
- package/dist/chunks/canvas-preview-j1tnf51w.js +36 -0
- package/dist/chunks/canvas-preview-kdqgrstc.js +194 -0
- package/dist/chunks/canvas-preview-kn7kvbfj.js +12 -0
- package/dist/chunks/canvas-preview-m02v4yy6.js +386 -0
- package/dist/chunks/canvas-preview-mgcx2b2p.js +271 -0
- package/dist/chunks/canvas-preview-rp4x6y1h.js +144 -0
- package/dist/chunks/canvas-preview-rp6fz0w5.js +130 -0
- package/dist/chunks/canvas-preview-s94ebwf5.js +112 -0
- package/dist/chunks/canvas-preview-senpjwep.js +518 -0
- package/dist/chunks/canvas-preview-skzwvw4d.js +23 -0
- package/dist/chunks/canvas-preview-srgfpdmf.js +60 -0
- package/dist/chunks/canvas-preview-tjhabynd.js +252 -0
- package/dist/chunks/canvas-preview-vaatfznm.js +189 -0
- package/dist/chunks/canvas-preview-vax9ne4e.js +341 -0
- package/dist/chunks/canvas-preview-wg80rbc2.js +46 -0
- package/dist/chunks/canvas-preview-xn10d4f8.js +608 -0
- package/dist/chunks/canvas-preview-yjz0f7n4.js +50 -0
- package/dist/chunks/canvas-preview-ymgz0937.js +587 -0
- package/dist/chunks/canvas-preview-yrfz2ak6.js +134 -0
- package/dist/chunks/canvas-preview-zaaj99wd.js +244 -0
- package/dist/chunks/canvas-preview-zn2d0k9d.js +133 -0
- package/dist/src/canvas-preview.d.ts +29 -0
- package/dist/src/canvas-preview.js +267 -0
- package/dist/src/credentials.d.ts +44 -0
- package/dist/src/credentials.js +10 -0
- package/dist/src/deploy/cloudflare/worker.d.ts +50 -0
- package/dist/src/deploy/cloudflare/worker.js +196 -0
- package/dist/src/deploy/vercel/nitro.config.d.ts +2 -0
- package/dist/src/deploy/vercel/nitro.config.js +30 -0
- package/dist/src/deploy/vercel/server/routes/[...].d.ts +2 -0
- package/dist/src/deploy/vercel/server/routes/[...].js +18 -0
- package/dist/src/deploy/vercel/server/utils/host.d.ts +13 -0
- package/dist/src/deploy/vercel/server/utils/host.js +7 -0
- package/dist/src/deploy/vercel/server/utils/repair.d.ts +1 -0
- package/dist/src/deploy/vercel/server/utils/repair.js +6 -0
- package/dist/src/deploy/vercel/server/utils/step.d.ts +10 -0
- package/dist/src/deploy/vercel/server/utils/step.js +6 -0
- package/dist/src/deploy/vercel/server/workflows/drive.d.ts +14 -0
- package/dist/src/deploy/vercel/server/workflows/drive.js +13 -0
- package/dist/src/durable-object.d.ts +14 -0
- package/dist/src/durable-object.js +231 -0
- package/dist/src/hash.d.ts +1 -0
- package/dist/src/hash.js +6 -0
- package/dist/src/identity-key.d.ts +11 -0
- package/dist/src/identity-key.js +9 -0
- package/dist/src/identity.d.ts +12 -0
- package/dist/src/identity.js +6 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +120 -0
- package/dist/src/key-file.d.ts +1 -0
- package/dist/src/key-file.js +7 -0
- package/dist/src/listen-fetch.d.ts +8 -0
- package/dist/src/listen-fetch.js +9 -0
- package/dist/src/listen.d.ts +4 -0
- package/dist/src/listen.js +10 -0
- package/dist/src/local/command.d.ts +15 -0
- package/dist/src/local/command.js +8 -0
- package/dist/src/local/feed.d.ts +7 -0
- package/dist/src/local/feed.js +6 -0
- package/dist/src/local/files.d.ts +18 -0
- package/dist/src/local/files.js +13 -0
- package/dist/src/local/git-watch.d.ts +15 -0
- package/dist/src/local/git-watch.js +7 -0
- package/dist/src/local/git.d.ts +5 -0
- package/dist/src/local/git.js +13 -0
- package/dist/src/local/github.d.ts +30 -0
- package/dist/src/local/github.js +9 -0
- package/dist/src/local/identity.d.ts +3 -0
- package/dist/src/local/identity.js +7 -0
- package/dist/src/local/jobs.d.ts +7 -0
- package/dist/src/local/jobs.js +6 -0
- package/dist/src/local/legacy-trust.d.ts +10 -0
- package/dist/src/local/legacy-trust.js +6 -0
- package/dist/src/local/patch.d.ts +16 -0
- package/dist/src/local/patch.js +17 -0
- package/dist/src/local/provider.d.ts +11 -0
- package/dist/src/local/provider.js +20 -0
- package/dist/src/local/snapshots.d.ts +7 -0
- package/dist/src/local/snapshots.js +11 -0
- package/dist/src/local/text.d.ts +1 -0
- package/dist/src/local/text.js +6 -0
- package/dist/src/local/tree.d.ts +50 -0
- package/dist/src/local/tree.js +16 -0
- package/dist/src/local/workspace-migration.d.ts +2 -0
- package/dist/src/local/workspace-migration.js +7 -0
- package/dist/src/local/worktrees.d.ts +46 -0
- package/dist/src/local/worktrees.js +14 -0
- package/dist/src/mcp/config.d.ts +75 -0
- package/dist/src/mcp/config.js +12 -0
- package/dist/src/mcp/connect.d.ts +28 -0
- package/dist/src/mcp/connect.js +9 -0
- package/dist/src/mcp/hub.d.ts +19 -0
- package/dist/src/mcp/hub.js +11 -0
- package/dist/src/mcp/oauth.d.ts +46 -0
- package/dist/src/mcp/oauth.js +12 -0
- package/dist/src/mcp/tools.d.ts +29 -0
- package/dist/src/mcp/tools.js +12 -0
- package/dist/src/open.d.ts +42 -0
- package/dist/src/open.js +44 -0
- package/dist/src/plugins/loader.d.ts +21 -0
- package/dist/src/plugins/loader.js +11 -0
- package/dist/src/postgres.d.ts +19 -0
- package/dist/src/postgres.js +8 -0
- package/dist/src/providers.d.ts +16 -0
- package/dist/src/providers.js +112 -0
- package/dist/src/secrets.d.ts +12 -0
- package/dist/src/secrets.js +8 -0
- package/dist/src/serve/binding.d.ts +39 -0
- package/dist/src/serve/binding.js +6 -0
- package/dist/src/serve/handler.d.ts +15 -0
- package/dist/src/serve/handler.js +8 -0
- package/dist/src/serve/stream-server.d.ts +6 -0
- package/dist/src/serve/stream-server.js +6 -0
- package/dist/src/session-index.d.ts +11 -0
- package/dist/src/session-index.js +11 -0
- package/dist/src/shell-env.d.ts +14 -0
- package/dist/src/shell-env.js +108 -0
- package/dist/src/sqlite-workers.d.ts +6 -0
- package/dist/src/sqlite-workers.js +6 -0
- package/dist/src/sqlite.d.ts +7 -0
- package/dist/src/sqlite.js +10 -0
- package/dist/src/store-owner.d.ts +15 -0
- package/dist/src/store-owner.js +9 -0
- package/dist/src/store-rows.d.ts +13 -0
- package/dist/src/store-rows.js +26 -0
- package/dist/src/store-usage.d.ts +25 -0
- package/dist/src/store-usage.js +16 -0
- package/dist/src/usage-scan.d.ts +24 -0
- package/dist/src/usage-scan.js +65 -0
- package/dist/src/usage-service.d.ts +22 -0
- package/dist/src/usage-service.js +12 -0
- package/dist/src/usage-summary.d.ts +9 -0
- package/dist/src/usage-summary.js +16 -0
- package/dist/src/usage-types.d.ts +86 -0
- package/dist/src/usage-types.js +0 -0
- package/dist/src/usage-worker.d.ts +1 -0
- package/dist/src/usage-worker.js +25 -0
- package/dist/src/usage.d.ts +72 -0
- package/dist/src/usage.js +13 -0
- package/package.json +132 -3
- package/src/canvas-preview.ts +402 -0
- package/src/credentials.ts +294 -0
- package/src/deploy/cloudflare/README.md +3 -0
- package/src/deploy/cloudflare/worker.ts +306 -0
- package/src/deploy/cloudflare/wrangler.jsonc +12 -0
- package/src/deploy/vercel/README.md +3 -0
- package/src/deploy/vercel/nitro.config.ts +29 -0
- package/src/deploy/vercel/server/routes/[...].ts +10 -0
- package/src/deploy/vercel/server/utils/host.ts +104 -0
- package/src/deploy/vercel/server/utils/repair.ts +35 -0
- package/src/deploy/vercel/server/utils/step.ts +25 -0
- package/src/deploy/vercel/server/workflows/drive.ts +46 -0
- package/src/deploy/vercel/tsconfig.json +9 -0
- package/src/deploy/vercel/types/bun.d.ts +2 -0
- package/src/durable-object.ts +386 -0
- package/src/hash.ts +5 -0
- package/src/identity-key.ts +20 -0
- package/src/identity.ts +66 -0
- package/src/index.ts +21 -0
- package/src/key-file.ts +53 -0
- package/src/listen-fetch.ts +409 -0
- package/src/listen.ts +228 -0
- package/src/local/command.ts +109 -0
- package/src/local/feed.ts +70 -0
- package/src/local/files.ts +812 -0
- package/src/local/git-watch.ts +189 -0
- package/src/local/git.ts +914 -0
- package/src/local/github.ts +692 -0
- package/src/local/identity.ts +21 -0
- package/src/local/jobs.ts +587 -0
- package/src/local/legacy-trust.ts +105 -0
- package/src/local/patch.ts +334 -0
- package/src/local/provider.ts +184 -0
- package/src/local/snapshots.ts +776 -0
- package/src/local/text.ts +9 -0
- package/src/local/tree.ts +398 -0
- package/src/local/workspace-migration.ts +95 -0
- package/src/local/worktrees.ts +239 -0
- package/src/mcp/config.ts +330 -0
- package/src/mcp/connect.ts +105 -0
- package/src/mcp/hub.ts +836 -0
- package/src/mcp/oauth.ts +436 -0
- package/src/mcp/tools.ts +333 -0
- package/src/open.ts +469 -0
- package/src/plugins/loader.ts +186 -0
- package/src/postgres.ts +492 -0
- package/src/providers.ts +135 -0
- package/src/secrets.ts +31 -0
- package/src/serve/binding.ts +628 -0
- package/src/serve/handler.ts +362 -0
- package/src/serve/stream-server.ts +176 -0
- package/src/session-index.ts +99 -0
- package/src/shell-env.ts +153 -0
- package/src/sqlite-workers.ts +283 -0
- package/src/sqlite.ts +528 -0
- package/src/store-owner.ts +98 -0
- package/src/store-rows.ts +110 -0
- package/src/store-usage.ts +344 -0
- package/src/usage-scan.ts +81 -0
- package/src/usage-service.ts +73 -0
- package/src/usage-summary.ts +79 -0
- package/src/usage-types.ts +87 -0
- package/src/usage-worker.ts +24 -0
- package/src/usage.ts +701 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AdvanceReport, HeadName, SessionId } from "@nyte-ai/schema";
|
|
2
|
+
/** Hands a head's wake to the workflow that drives it. */
|
|
3
|
+
export declare function dispatchHead(target: {
|
|
4
|
+
readonly session: SessionId;
|
|
5
|
+
readonly head: HeadName;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
export declare function driveHead(input: {
|
|
8
|
+
readonly session: SessionId;
|
|
9
|
+
readonly head: HeadName;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function advanceHead(input: {
|
|
12
|
+
readonly session: SessionId;
|
|
13
|
+
readonly head: HeadName;
|
|
14
|
+
}): Promise<AdvanceReport>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dispatchHead2,
|
|
3
|
+
driveHead2,
|
|
4
|
+
advanceHead2
|
|
5
|
+
} from "../../../../../chunks/canvas-preview-j1tnf51w.js";
|
|
6
|
+
import"../../../../../chunks/canvas-preview-65xqjw7f.js";
|
|
7
|
+
import"../../../../../chunks/canvas-preview-ewgspmsd.js";
|
|
8
|
+
import"../../../../../chunks/canvas-preview-2zdyh9ny.js";
|
|
9
|
+
export {
|
|
10
|
+
advanceHead2 as advanceHead,
|
|
11
|
+
dispatchHead2 as dispatchHead,
|
|
12
|
+
driveHead2 as driveHead
|
|
13
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Store } from "@nyte-ai/core";
|
|
2
|
+
/** Returns one value Durable Object SQL binds and answers: text, a number, a blob as an `ArrayBuffer`, or null. */
|
|
3
|
+
export type SqlValue = ArrayBuffer | string | number | null;
|
|
4
|
+
/** Returns the part of a Durable Object's storage `durableObjectStore` uses, structurally, so a Worker passes `state.storage` as it is and a test passes a shim: `sql.exec` runs one statement with `?` bindings and answers its rows keyed by column name, and `transactionSync` runs a synchronous closure whose writes land all together or, when it throws, not at all (Durable Object SQL refuses `BEGIN`, so this is the only transaction). */
|
|
5
|
+
export type DurableObjectSql = {
|
|
6
|
+
readonly sql: {
|
|
7
|
+
exec(query: string, ...bindings: SqlValue[]): {
|
|
8
|
+
toArray(): Record<string, SqlValue>[];
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
transactionSync<T>(closure: () => T): T;
|
|
12
|
+
};
|
|
13
|
+
/** Returns a `Store` over a Durable Object's SQLite storage, node-free, with the sqlite store's tables, row helpers (`store-rows.ts`) and semantics (§41f): `objects(id TEXT PRIMARY KEY, body TEXT NULL, bytes BLOB NULL)`, `refs(name TEXT PRIMARY KEY, target TEXT NULL, revision TEXT NOT NULL)` and `log(session TEXT, seq INTEGER, at INTEGER, event TEXT, PRIMARY KEY (session, seq))`, brought to core's `STORE_VERSION` by `migrateStore` on first `open()`, each commit one `transactionSync` and no backup; the open rejects with `SdkError("unavailable")` for a store a newer Nyte migrated. `put` ids the value with core's `objectId` and stores its JSON once; `putBlob` buffers the stream, ids it with `blobId` and stores the bytes once as an `ArrayBuffer`; an object and a blob that share an id share the row, each column filled once; `blob` reads the bytes back with their size and a null mime; a body, blob or logged event past the Durable Object's 2 MB row limit throws `SdkError("invalid")` before anything is written (§42k). `refs.set` runs inside one `transactionSync` with no await between its reads and writes, first rejecting with `SdkError("unavailable")` when a newer Nyte has migrated the store, with `RefStore.set`'s semantics, each revision a random UUID, any throw inside rolling the whole batch back. `list(prefix)` reads the name range from `prefix` in name order; `log` returns the events after `after` in seq order up to `limit`, each validated as a `SessionEvent`; `tail` is the session's last seq, or 0. Every `open()` returns a connection over the one storage; `close()` releases nothing, the storage being the object's. In workerd, which allows code generation only while modules load, the Worker turns TypeBox acceleration off at startup (`Settings.Set({ useAcceleration: false })` from `typebox/system`, as `deploy/cloudflare/worker.ts` does), or `log`'s validation throws inside a request. */
|
|
14
|
+
export declare function durableObjectStore(storage: DurableObjectSql): Store;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import {
|
|
2
|
+
prefixEnd2,
|
|
3
|
+
mintRevision2,
|
|
4
|
+
decodeEvent2,
|
|
5
|
+
parseNumber2,
|
|
6
|
+
parseText2,
|
|
7
|
+
parseRef2,
|
|
8
|
+
parseStoredRecord2,
|
|
9
|
+
parseStoredObject2,
|
|
10
|
+
loggedRow2,
|
|
11
|
+
collect2,
|
|
12
|
+
memoryReader2
|
|
13
|
+
} from "../chunks/canvas-preview-69fkk9yn.js";
|
|
14
|
+
import {
|
|
15
|
+
sessionIndexChanges2,
|
|
16
|
+
sqlSessionIndex2
|
|
17
|
+
} from "../chunks/canvas-preview-0cmbkp2j.js";
|
|
18
|
+
|
|
19
|
+
// src/durable-object.ts
|
|
20
|
+
import { asSeq, SdkError } from "@nyte-ai/schema";
|
|
21
|
+
import {
|
|
22
|
+
admits,
|
|
23
|
+
fenceNames,
|
|
24
|
+
assertStoreVersion,
|
|
25
|
+
blobId,
|
|
26
|
+
decodeObject,
|
|
27
|
+
collectSessionEvents,
|
|
28
|
+
migrateStore,
|
|
29
|
+
objectId,
|
|
30
|
+
sessionIndexRef,
|
|
31
|
+
parseSessionRef
|
|
32
|
+
} from "@nyte-ai/core/store";
|
|
33
|
+
var ROW_LIMIT = 2000000;
|
|
34
|
+
var encoder = new TextEncoder;
|
|
35
|
+
function durableObjectStore(storage) {
|
|
36
|
+
let connection = null;
|
|
37
|
+
return {
|
|
38
|
+
async open() {
|
|
39
|
+
if (connection !== null)
|
|
40
|
+
return connection;
|
|
41
|
+
await migrateStore(durableObjectTarget(storage));
|
|
42
|
+
connection = connect(storage);
|
|
43
|
+
return connection;
|
|
44
|
+
},
|
|
45
|
+
async close() {
|
|
46
|
+
connection = null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function storedVersion(storage) {
|
|
51
|
+
const stamped = storage.sql.exec("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'store_meta'").toArray();
|
|
52
|
+
if (stamped.length === 0)
|
|
53
|
+
return 0;
|
|
54
|
+
const version = storage.sql.exec("SELECT version FROM store_meta WHERE id = 1").toArray()[0]?.version;
|
|
55
|
+
return version === undefined ? 0 : parseNumber2(version);
|
|
56
|
+
}
|
|
57
|
+
function durableObjectTarget(storage) {
|
|
58
|
+
const rows = (query, ...bindings) => storage.sql.exec(query, ...bindings).toArray();
|
|
59
|
+
return {
|
|
60
|
+
dialect: "sqlite",
|
|
61
|
+
async stamp() {
|
|
62
|
+
const present = rows("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'refs'").length > 0;
|
|
63
|
+
return {
|
|
64
|
+
version: storedVersion(storage),
|
|
65
|
+
empty: !present || rows("SELECT 1 FROM refs LIMIT 1").length === 0
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
async records() {
|
|
69
|
+
return rows("SELECT refs.name, refs.target, refs.revision, objects.body FROM refs JOIN objects ON objects.id = refs.target WHERE objects.body IS NOT NULL").map(parseStoredRecord2);
|
|
70
|
+
},
|
|
71
|
+
async* objects(kind) {
|
|
72
|
+
yield* rows("SELECT id, body FROM objects WHERE body IS NOT NULL AND instr(body, ?) > 0", `"kind":${JSON.stringify(kind)}`).map(parseStoredObject2);
|
|
73
|
+
},
|
|
74
|
+
async* logs() {
|
|
75
|
+
if (rows("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'log'").length === 0)
|
|
76
|
+
return;
|
|
77
|
+
for (const row of rows("SELECT DISTINCT session FROM log")) {
|
|
78
|
+
const session = parseText2(row.session);
|
|
79
|
+
if (session !== null)
|
|
80
|
+
yield {
|
|
81
|
+
session,
|
|
82
|
+
events: rows("SELECT seq, event FROM log WHERE session = ? ORDER BY seq", session).map(loggedRow2)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
async commit(change) {
|
|
87
|
+
return storage.transactionSync(() => {
|
|
88
|
+
if (storedVersion(storage) !== change.from)
|
|
89
|
+
return "moved";
|
|
90
|
+
const conflicted = change.repoints.some((moved) => rows("SELECT 1 FROM refs WHERE name = ? AND revision = ?", moved.name, moved.expect).length === 0);
|
|
91
|
+
const relogged = change.relogs.every((relog) => rows("SELECT 1 FROM log WHERE session = ? AND seq = ? AND event = ?", relog.session, relog.seq, relog.expect).length > 0);
|
|
92
|
+
if (conflicted || !relogged)
|
|
93
|
+
return "conflict";
|
|
94
|
+
for (const statement of change.sql)
|
|
95
|
+
rows(statement);
|
|
96
|
+
for (const moved of change.repoints) {
|
|
97
|
+
rows("INSERT INTO objects (id, body) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", moved.id, moved.body);
|
|
98
|
+
rows("UPDATE refs SET target = ?, revision = ? WHERE name = ?", moved.id, mintRevision2(), moved.name);
|
|
99
|
+
updateSessionIndex(storage, moved.name, moved.id, mintRevision2());
|
|
100
|
+
}
|
|
101
|
+
for (const created of change.creates) {
|
|
102
|
+
rows("INSERT INTO objects (id, body) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", created.target, created.body);
|
|
103
|
+
const revision = mintRevision2();
|
|
104
|
+
if (rows("INSERT INTO refs (name, target, revision) VALUES (?, ?, ?) ON CONFLICT (name) DO NOTHING RETURNING name", created.name, created.target, revision).length > 0)
|
|
105
|
+
updateSessionIndex(storage, created.name, created.target, revision);
|
|
106
|
+
}
|
|
107
|
+
for (const relog of change.relogs)
|
|
108
|
+
rows("UPDATE log SET event = ? WHERE session = ? AND seq = ?", relog.event, relog.session, relog.seq);
|
|
109
|
+
if (change.reindexSessions)
|
|
110
|
+
for (const row of rows("SELECT name, target, revision FROM refs")) {
|
|
111
|
+
const ref = parseRef2(row);
|
|
112
|
+
updateSessionIndex(storage, ref.name, ref.target, ref.revision);
|
|
113
|
+
}
|
|
114
|
+
rows("INSERT INTO store_meta (id, version) VALUES (1, ?) ON CONFLICT (id) DO UPDATE SET version = excluded.version", change.to);
|
|
115
|
+
return "committed";
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function connect(storage) {
|
|
121
|
+
const rows = (query, ...bindings) => storage.sql.exec(query, ...bindings).toArray();
|
|
122
|
+
const tail = (session) => {
|
|
123
|
+
const value = rows("SELECT MAX(seq) AS tail FROM log WHERE session = ?", session)[0]?.tail;
|
|
124
|
+
return asSeq(value === null || value === undefined ? 0 : parseNumber2(value));
|
|
125
|
+
};
|
|
126
|
+
const ref = (name) => {
|
|
127
|
+
const row = rows("SELECT name, target, revision FROM refs WHERE name = ?", name)[0];
|
|
128
|
+
return row === undefined ? null : parseRef2(row);
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
sessions: sqlSessionIndex2(async (text, values) => rows(text, ...values)),
|
|
132
|
+
objects: {
|
|
133
|
+
async put(object) {
|
|
134
|
+
const id = await objectId(object);
|
|
135
|
+
const body = JSON.stringify(object);
|
|
136
|
+
fits(encoder.encode(body).byteLength, `Object ${id}`);
|
|
137
|
+
rows("INSERT INTO objects (id, body) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", id, body);
|
|
138
|
+
return id;
|
|
139
|
+
},
|
|
140
|
+
async get(id) {
|
|
141
|
+
const body = parseText2(rows("SELECT body FROM objects WHERE id = ?", id)[0]?.body);
|
|
142
|
+
return body === null ? null : decodeObject(body);
|
|
143
|
+
},
|
|
144
|
+
async putBlob(bytes) {
|
|
145
|
+
const joined = await collect2(bytes);
|
|
146
|
+
const id = await blobId(joined);
|
|
147
|
+
fits(joined.byteLength, `Blob ${id}`);
|
|
148
|
+
rows("INSERT INTO objects (id, bytes) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET bytes = excluded.bytes WHERE objects.bytes IS NULL", id, joined.slice().buffer);
|
|
149
|
+
return id;
|
|
150
|
+
},
|
|
151
|
+
async blob(id) {
|
|
152
|
+
const bytes = rows("SELECT bytes FROM objects WHERE id = ?", id)[0]?.bytes;
|
|
153
|
+
return bytes instanceof ArrayBuffer ? memoryReader2(new Uint8Array(bytes)) : null;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
refs: {
|
|
157
|
+
get: async (name) => ref(name),
|
|
158
|
+
async list(prefix) {
|
|
159
|
+
const end = prefixEnd2(prefix);
|
|
160
|
+
const found = end === null ? rows("SELECT name, target, revision FROM refs WHERE name >= ? ORDER BY name", prefix) : rows("SELECT name, target, revision FROM refs WHERE name >= ? AND name < ? ORDER BY name", prefix, end);
|
|
161
|
+
return found.map(parseRef2);
|
|
162
|
+
},
|
|
163
|
+
async set(updates) {
|
|
164
|
+
const logged = collectSessionEvents(updates).map(({ session, event }) => {
|
|
165
|
+
const text = JSON.stringify(event);
|
|
166
|
+
fits(encoder.encode(text).byteLength, `An event on ${session}`);
|
|
167
|
+
return { session, text };
|
|
168
|
+
});
|
|
169
|
+
return storage.transactionSync(() => {
|
|
170
|
+
assertStoreVersion(storedVersion(storage));
|
|
171
|
+
const before = new Map;
|
|
172
|
+
for (const update of updates)
|
|
173
|
+
if (!before.has(update.name))
|
|
174
|
+
before.set(update.name, ref(update.name) ?? undefined);
|
|
175
|
+
const fenced = fenceNames(updates).find((name) => ref(name) === null);
|
|
176
|
+
if (fenced !== undefined)
|
|
177
|
+
return { kind: "fenced", name: fenced };
|
|
178
|
+
const stale = updates.find((update) => !admits(update, before.get(update.name)));
|
|
179
|
+
if (stale !== undefined)
|
|
180
|
+
return {
|
|
181
|
+
kind: "stale",
|
|
182
|
+
name: stale.name,
|
|
183
|
+
revision: before.get(stale.name)?.revision ?? null
|
|
184
|
+
};
|
|
185
|
+
const touched = new Map;
|
|
186
|
+
const revisions = updates.map((update) => {
|
|
187
|
+
const revision = mintRevision2();
|
|
188
|
+
if (update.target === null)
|
|
189
|
+
rows("DELETE FROM refs WHERE name = ?", update.name);
|
|
190
|
+
else
|
|
191
|
+
rows("INSERT INTO refs (name, target, revision) VALUES (?, ?, ?) ON CONFLICT (name) DO UPDATE SET target = excluded.target, revision = excluded.revision", update.name, update.target, revision);
|
|
192
|
+
updateSessionIndex(storage, update.name, update.target, revision);
|
|
193
|
+
const session = parseSessionRef(update.name);
|
|
194
|
+
if (session !== null)
|
|
195
|
+
touched.set(session, revision);
|
|
196
|
+
return revision;
|
|
197
|
+
});
|
|
198
|
+
for (const [session, version] of touched)
|
|
199
|
+
rows("UPDATE session_index SET version = ? WHERE session = ?", version, session);
|
|
200
|
+
const at = Date.now();
|
|
201
|
+
const tails = new Map;
|
|
202
|
+
const appended = logged.map(({ session, text }) => {
|
|
203
|
+
const seq = (tails.get(session) ?? tail(session)) + 1;
|
|
204
|
+
tails.set(session, seq);
|
|
205
|
+
rows("INSERT INTO log (session, seq, at, event) VALUES (?, ?, ?, ?)", session, seq, at, text);
|
|
206
|
+
return asSeq(seq);
|
|
207
|
+
});
|
|
208
|
+
return { kind: "set", logged: appended, at, revisions };
|
|
209
|
+
});
|
|
210
|
+
},
|
|
211
|
+
async log(session, after, limit) {
|
|
212
|
+
return rows("SELECT seq, at, event FROM log WHERE session = ? AND seq > ? ORDER BY seq LIMIT ?", session, after, limit).map((row) => decodeEvent2(parseNumber2(row.seq), parseNumber2(row.at), parseText2(row.event) ?? ""));
|
|
213
|
+
},
|
|
214
|
+
tail: async (session) => tail(session)
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function updateSessionIndex(storage, name, target, revision) {
|
|
219
|
+
if (sessionIndexRef(name) === null)
|
|
220
|
+
return;
|
|
221
|
+
const body = target === null ? null : parseText2(storage.sql.exec("SELECT body FROM objects WHERE id = ?", target).toArray()[0]?.body);
|
|
222
|
+
for (const change of sessionIndexChanges2(name, body === null ? null : decodeObject(body), revision))
|
|
223
|
+
storage.sql.exec(change.text, ...change.values);
|
|
224
|
+
}
|
|
225
|
+
function fits(bytes, what) {
|
|
226
|
+
if (bytes > ROW_LIMIT)
|
|
227
|
+
throw new SdkError("invalid", `${what} is ${bytes} bytes, past the Durable Object store's 2 MB row limit.`);
|
|
228
|
+
}
|
|
229
|
+
export {
|
|
230
|
+
durableObjectStore
|
|
231
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sha256(data: string | Uint8Array): string;
|
package/dist/src/hash.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HostId } from "@nyte-ai/schema";
|
|
2
|
+
import type { ListenOptions } from "@nyte-ai/core";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the Node host's identity signer (§50a): `seedSigner` over the
|
|
5
|
+
* Ed25519 seed in `<home>/.nyte/identity.key`, 32 raw bytes minted `0600` by
|
|
6
|
+
* `link` on first use as the secrets key is. The file is not encrypted; it is
|
|
7
|
+
* a signing key, protected as ssh protects one, and it never touches the
|
|
8
|
+
* secrets key. Named apart from core's `hostIdentity(store)`, which reads or
|
|
9
|
+
* mints the host's id.
|
|
10
|
+
*/
|
|
11
|
+
export declare function identitySigner(id: HostId, home: string): Promise<NonNullable<ListenOptions["identity"]>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
identitySigner2
|
|
3
|
+
} from "../chunks/canvas-preview-5mex725c.js";
|
|
4
|
+
import"../chunks/canvas-preview-31w7xm8z.js";
|
|
5
|
+
import"../chunks/canvas-preview-wg80rbc2.js";
|
|
6
|
+
import"../chunks/canvas-preview-mgcx2b2p.js";
|
|
7
|
+
export {
|
|
8
|
+
identitySigner2 as identitySigner
|
|
9
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HostId } from "@nyte-ai/schema";
|
|
2
|
+
import type { ListenOptions } from "@nyte-ai/core";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the signer a listener answers `GET /.nyte/identity?nonce=` with
|
|
5
|
+
* (`ListenOptions.identity`, §43a), over a 32-byte Ed25519 seed: `id` the
|
|
6
|
+
* host's id and `sign(nonce)` a signature over the UTF-8 bytes of
|
|
7
|
+
* `nyte/identity\n<id>\n<nonce>`, answered with the raw public key, both
|
|
8
|
+
* base64url without padding (§43k). The Node host reads the seed from
|
|
9
|
+
* `<home>/.nyte/identity.key` (`identitySigner`); a deploy passes one from its
|
|
10
|
+
* environment (§50a). Web Crypto only, no `node:*` (the `./identity` subpath).
|
|
11
|
+
*/
|
|
12
|
+
export declare function seedSigner(id: HostId, seed: Uint8Array): Promise<NonNullable<ListenOptions["identity"]>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from "./credentials.ts";
|
|
2
|
+
export * from "./identity.ts";
|
|
3
|
+
export { identitySigner } from "./identity-key.ts";
|
|
4
|
+
export * from "./listen.ts";
|
|
5
|
+
export * from "./listen-fetch.ts";
|
|
6
|
+
export * from "./local/files.ts";
|
|
7
|
+
export * from "./local/git.ts";
|
|
8
|
+
export * from "./local/github.ts";
|
|
9
|
+
export * from "./local/identity.ts";
|
|
10
|
+
export * from "./local/jobs.ts";
|
|
11
|
+
export * from "./local/provider.ts";
|
|
12
|
+
export { createMcpHub } from "./mcp/hub.ts";
|
|
13
|
+
export type { McpConnector } from "./mcp/connect.ts";
|
|
14
|
+
export * from "./local/snapshots.ts";
|
|
15
|
+
export * from "./local/worktrees.ts";
|
|
16
|
+
export * from "./open.ts";
|
|
17
|
+
export * from "./plugins/loader.ts";
|
|
18
|
+
export * from "./postgres.ts";
|
|
19
|
+
export * from "./secrets.ts";
|
|
20
|
+
export * from "./sqlite.ts";
|
|
21
|
+
export { StoreOwned } from "./store-owner.ts";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
credentialStore2,
|
|
3
|
+
sealSecret2,
|
|
4
|
+
openSecret2
|
|
5
|
+
} from "../chunks/canvas-preview-518dh8by.js";
|
|
6
|
+
import {
|
|
7
|
+
seedSigner2
|
|
8
|
+
} from "../chunks/canvas-preview-31w7xm8z.js";
|
|
9
|
+
import"../chunks/canvas-preview-mgcx2b2p.js";
|
|
10
|
+
import"../chunks/canvas-preview-wg80rbc2.js";
|
|
11
|
+
import {
|
|
12
|
+
identitySigner2
|
|
13
|
+
} from "../chunks/canvas-preview-5mex725c.js";
|
|
14
|
+
import"../chunks/canvas-preview-m02v4yy6.js";
|
|
15
|
+
import"../chunks/canvas-preview-rp4x6y1h.js";
|
|
16
|
+
import"../chunks/canvas-preview-d9wwhbtz.js";
|
|
17
|
+
import {
|
|
18
|
+
listenFetch2
|
|
19
|
+
} from "../chunks/canvas-preview-76fwvd6e.js";
|
|
20
|
+
import {
|
|
21
|
+
listen2
|
|
22
|
+
} from "../chunks/canvas-preview-98aj5p34.js";
|
|
23
|
+
import"../chunks/canvas-preview-0nq75h9k.js";
|
|
24
|
+
import"../chunks/canvas-preview-azg56359.js";
|
|
25
|
+
import"../chunks/canvas-preview-yjz0f7n4.js";
|
|
26
|
+
import"../chunks/canvas-preview-kn7kvbfj.js";
|
|
27
|
+
import {
|
|
28
|
+
TEXT_LIMIT2,
|
|
29
|
+
localFiles2
|
|
30
|
+
} from "../chunks/canvas-preview-ymgz0937.js";
|
|
31
|
+
import"../chunks/canvas-preview-tjhabynd.js";
|
|
32
|
+
import"../chunks/canvas-preview-zn2d0k9d.js";
|
|
33
|
+
import {
|
|
34
|
+
localGit2
|
|
35
|
+
} from "../chunks/canvas-preview-xn10d4f8.js";
|
|
36
|
+
import {
|
|
37
|
+
localGitHubAccount2,
|
|
38
|
+
localGitHub2
|
|
39
|
+
} from "../chunks/canvas-preview-75db60xy.js";
|
|
40
|
+
import {
|
|
41
|
+
folderIdentity2
|
|
42
|
+
} from "../chunks/canvas-preview-1sq7z9jq.js";
|
|
43
|
+
import {
|
|
44
|
+
localExec2
|
|
45
|
+
} from "../chunks/canvas-preview-ehf3vp31.js";
|
|
46
|
+
import {
|
|
47
|
+
localSnapshots2
|
|
48
|
+
} from "../chunks/canvas-preview-senpjwep.js";
|
|
49
|
+
import {
|
|
50
|
+
listWorktrees2,
|
|
51
|
+
addWorktree2,
|
|
52
|
+
hasBranch2,
|
|
53
|
+
localWorktrees2
|
|
54
|
+
} from "../chunks/canvas-preview-rp6fz0w5.js";
|
|
55
|
+
import {
|
|
56
|
+
localProvider2
|
|
57
|
+
} from "../chunks/canvas-preview-yrfz2ak6.js";
|
|
58
|
+
import"../chunks/canvas-preview-kdqgrstc.js";
|
|
59
|
+
import"../chunks/canvas-preview-5z63am63.js";
|
|
60
|
+
import"../chunks/canvas-preview-h8hshnff.js";
|
|
61
|
+
import"../chunks/canvas-preview-vaatfznm.js";
|
|
62
|
+
import {
|
|
63
|
+
createMcpHub2
|
|
64
|
+
} from "../chunks/canvas-preview-8xgt67ka.js";
|
|
65
|
+
import"../chunks/canvas-preview-9aqczacs.js";
|
|
66
|
+
import"../chunks/canvas-preview-4e0pxa32.js";
|
|
67
|
+
import {
|
|
68
|
+
loadPluginFiles2,
|
|
69
|
+
loadPluginDirectory2,
|
|
70
|
+
pluginLoader2
|
|
71
|
+
} from "../chunks/canvas-preview-s94ebwf5.js";
|
|
72
|
+
import {
|
|
73
|
+
defaultSecrets2
|
|
74
|
+
} from "../chunks/canvas-preview-skzwvw4d.js";
|
|
75
|
+
import"../chunks/canvas-preview-69fkk9yn.js";
|
|
76
|
+
import"../chunks/canvas-preview-zaaj99wd.js";
|
|
77
|
+
import"../chunks/canvas-preview-0cmbkp2j.js";
|
|
78
|
+
import {
|
|
79
|
+
StoreOwned2
|
|
80
|
+
} from "../chunks/canvas-preview-a3yw0j70.js";
|
|
81
|
+
import {
|
|
82
|
+
sqliteStore2
|
|
83
|
+
} from "../chunks/canvas-preview-evh92ywd.js";
|
|
84
|
+
import {
|
|
85
|
+
openHost2
|
|
86
|
+
} from "../chunks/canvas-preview-vax9ne4e.js";
|
|
87
|
+
import {
|
|
88
|
+
postgresStore2
|
|
89
|
+
} from "../chunks/canvas-preview-4b6sayhg.js";
|
|
90
|
+
export {
|
|
91
|
+
StoreOwned2 as StoreOwned,
|
|
92
|
+
TEXT_LIMIT2 as TEXT_LIMIT,
|
|
93
|
+
addWorktree2 as addWorktree,
|
|
94
|
+
createMcpHub2 as createMcpHub,
|
|
95
|
+
credentialStore2 as credentialStore,
|
|
96
|
+
defaultSecrets2 as defaultSecrets,
|
|
97
|
+
folderIdentity2 as folderIdentity,
|
|
98
|
+
hasBranch2 as hasBranch,
|
|
99
|
+
identitySigner2 as identitySigner,
|
|
100
|
+
listWorktrees2 as listWorktrees,
|
|
101
|
+
listen2 as listen,
|
|
102
|
+
listenFetch2 as listenFetch,
|
|
103
|
+
loadPluginDirectory2 as loadPluginDirectory,
|
|
104
|
+
loadPluginFiles2 as loadPluginFiles,
|
|
105
|
+
localExec2 as localExec,
|
|
106
|
+
localFiles2 as localFiles,
|
|
107
|
+
localGit2 as localGit,
|
|
108
|
+
localGitHub2 as localGitHub,
|
|
109
|
+
localGitHubAccount2 as localGitHubAccount,
|
|
110
|
+
localProvider2 as localProvider,
|
|
111
|
+
localSnapshots2 as localSnapshots,
|
|
112
|
+
localWorktrees2 as localWorktrees,
|
|
113
|
+
openHost2 as openHost,
|
|
114
|
+
openSecret2 as openSecret,
|
|
115
|
+
pluginLoader2 as pluginLoader,
|
|
116
|
+
postgresStore2 as postgresStore,
|
|
117
|
+
sealSecret2 as sealSecret,
|
|
118
|
+
seedSigner2 as seedSigner,
|
|
119
|
+
sqliteStore2 as sqliteStore
|
|
120
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readKeyFile(path: string, name: string): Promise<Uint8Array>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ListenOptions, Listener } from "@nyte-ai/core";
|
|
2
|
+
import type { ServedHost } from "@nyte-ai/core/server";
|
|
3
|
+
/** Serves a composed host as a bare fetch handler with no socket and no `node:*` import, so a Worker can serve it (§41j): `before`, the unauthenticated identity and describe routes, then `createHandler` over one cached connection per principal and authority, every response carrying `X-Nyte-Host` (§43a, §43j). A request authenticates by a pairing code, then the listener token (compared in constant time over SHA-256 digests) or a device token remembered until a commit from another process moves the host's principals, then `authorize` under `custom`; a revoke aborts that principal's open requests and streams. A `token` shorter than 16 characters throws `SdkError("invalid")`; `execution` (default: run covering all) drives covered sessions in process on an `admit-only` host, covers their leases otherwise and takes nothing on a `dispatch` host (§42v); `close()` disconnects the clients and releases the execution once, after which every request answers `unavailable`. */
|
|
4
|
+
export declare function listenFetch(host: ServedHost, options: ListenOptions & {
|
|
5
|
+
readonly transport: {
|
|
6
|
+
readonly kind: "fetch";
|
|
7
|
+
};
|
|
8
|
+
}): Promise<Listener>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ListenOptions, Listener } from "@nyte-ai/core";
|
|
2
|
+
import type { ServedHost } from "@nyte-ai/core/server";
|
|
3
|
+
/** Serves a composed host, the `Host.listen` `openHost` attaches: everything but the socket is `listenFetch`'s, and the `fetch` transport answers with it directly. The `http` transport binds `node:http` on `hostname` (default 127.0.0.1) and `port` (default 0), streaming each request body in and each response body out chunk by chunk, with a client gone aborting its request; a failed bind throws `SdkError("unavailable")` after releasing the execution. `disconnectClients()` also destroys every open Node response, and `close()` closes the socket once. */
|
|
4
|
+
export declare function listen(host: ServedHost, options: ListenOptions): Promise<Listener>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listen2
|
|
3
|
+
} from "../chunks/canvas-preview-98aj5p34.js";
|
|
4
|
+
import"../chunks/canvas-preview-76fwvd6e.js";
|
|
5
|
+
import"../chunks/canvas-preview-d9wwhbtz.js";
|
|
6
|
+
import"../chunks/canvas-preview-m02v4yy6.js";
|
|
7
|
+
import"../chunks/canvas-preview-rp4x6y1h.js";
|
|
8
|
+
export {
|
|
9
|
+
listen2 as listen
|
|
10
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Ran = {
|
|
2
|
+
readonly code: number | null;
|
|
3
|
+
readonly stdout: Buffer;
|
|
4
|
+
readonly stderr: string;
|
|
5
|
+
readonly truncated: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function run(file: string, args: readonly string[], options: {
|
|
8
|
+
readonly cwd: string;
|
|
9
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
10
|
+
readonly input?: string | Uint8Array;
|
|
11
|
+
readonly limit?: number;
|
|
12
|
+
/** Kills the command after this long; it then ends with a null code. */
|
|
13
|
+
readonly timeoutMs?: number;
|
|
14
|
+
}): Promise<Ran>;
|
|
15
|
+
export declare function findExecutable(name: string, directories?: readonly string[]): Promise<string | null>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Disposer } from "@nyte-ai/schema";
|
|
2
|
+
export type FeedSink<T> = {
|
|
3
|
+
push(value: T): void;
|
|
4
|
+
fail(error: unknown): void;
|
|
5
|
+
end(): void;
|
|
6
|
+
};
|
|
7
|
+
export declare function feed<T>(start: (sink: FeedSink<T>) => Disposer, merge?: (waiting: T, next: T) => T): AsyncIterable<T>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ByteReader, FileVersion } from "@nyte-ai/schema";
|
|
2
|
+
import type { FilesApi } from "@nyte-ai/core";
|
|
3
|
+
/** Returns a byte reader that carries the version of the file it read, which the server answers as `X-Nyte-Version` (§40h, §40p). */
|
|
4
|
+
export type VersionedReader = ByteReader & {
|
|
5
|
+
readonly version: FileVersion;
|
|
6
|
+
};
|
|
7
|
+
/** Returns the local `FilesApi`, its `bytes` typed with the version it read. */
|
|
8
|
+
export type LocalFiles = Omit<FilesApi, "bytes"> & {
|
|
9
|
+
bytes(path: string): Promise<VersionedReader>;
|
|
10
|
+
};
|
|
11
|
+
/** The size past which `read` answers `large`: 1 MiB. */
|
|
12
|
+
export declare const TEXT_LIMIT: number;
|
|
13
|
+
/** Returns a folder's files over `node:fs`: a relative path resolves against `root`, an absolute one is taken as given (the ancestor context files are read through it, §37g). A version is the SHA-256 of what is there, never an mtime: a file's contents (through a symlink, its target's), a directory's sorted entry names, and, for `stat` of a symlink itself, its target path. `read` answers `text` for UTF-8 without NUL up to 1 MiB, `large` above, `binary` otherwise, `missing` when absent (`SdkError("invalid")` for a directory); `bytes` streams the file with its size, a null mime and its version (`SdkError("unknown")` when absent); `stat` uses `lstat` (a symlink with its `target`), null when absent. `write` compares `expect` with the current version first (`stale { current }`, `absent` needing no file), answers `missing-parent` unless `parents`, and writes through a temporary file renamed into place (through a symlink, at its target), keeping an existing file's mode; `remove` compares `expect` the same way (`stale { current: null }` when nothing is there) and answers `saved` with the version it removed. `batch()` returns a plan whose `apply` and `upload()` reject with `SdkError("unavailable")`: core lays its own over them (`wrapFiles`). `format` runs `formatter`, else the first of `oxfmt`, `prettier` and `biome` under `<root>/node_modules/.bin`, then on the `PATH`, with the contents on stdin and the path for its config, answering `unchanged` when equal and `unavailable { reason }` when there is none or it fails. `scan` walks `directory` (default the root; an absolute one is walked as its own root and answered with absolute paths) breadth-first in pages of 500 entries, skipping `.git` and, unless `ignored: "include"` or the directory is itself ignored, what `.gitignore` files and `.git/info/exclude` ignore (`ignore`), then `complete`, or `incomplete` with `limit` after 50,000 entries or `permission` after an unreadable directory; entries carry no version. `find` matches the query against the scanned file paths, case-insensitively: exact name, name prefix, name substring, path substring, then a fuzzy subsequence, shorter first, at most `limit` (default 20, capped at 50), the scan reused for 5 s. `search` runs `ripgrep` (else `rg` on the PATH; with neither, a scan of the text files up to 1 MiB with a JavaScript regex) for the query, literal unless `regex`, with smart case unless `caseSensitive` is given, whole words alone when `wholeWord`, over the files the `include` globs pick (all when none) less the `exclude` globs; a file with a draft is searched in its draft's contents instead of on disk. It yields a `match` per matching line (1-based line and column and the first match's length, the line cut at 500 characters), drafts first, then `complete`, or `truncated` at `limit` (default 200); a regex or glob `rg` cannot read throws `SdkError("invalid")`. `watch` uses a recursive `fs.watch` on the root (a 1 s poll where there is none) or, given `paths`, a watch on each of them alone that waits for a missing one to appear and never polls, without ignored paths or directories, coalescing changes over 100 ms into `created`, `modified` and `removed` events with the version after (null when removed), a path's last change winning while the reader is behind. `signal` ends every open `watch`. */
|
|
14
|
+
export declare function localFiles(root: string, options?: {
|
|
15
|
+
readonly ripgrep?: string;
|
|
16
|
+
readonly formatter?: string;
|
|
17
|
+
readonly signal?: AbortSignal;
|
|
18
|
+
}): LocalFiles;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TEXT_LIMIT2,
|
|
3
|
+
localFiles2
|
|
4
|
+
} from "../../chunks/canvas-preview-ymgz0937.js";
|
|
5
|
+
import"../../chunks/canvas-preview-kn7kvbfj.js";
|
|
6
|
+
import"../../chunks/canvas-preview-azg56359.js";
|
|
7
|
+
import"../../chunks/canvas-preview-yjz0f7n4.js";
|
|
8
|
+
import"../../chunks/canvas-preview-0nq75h9k.js";
|
|
9
|
+
import"../../chunks/canvas-preview-mgcx2b2p.js";
|
|
10
|
+
export {
|
|
11
|
+
TEXT_LIMIT2 as TEXT_LIMIT,
|
|
12
|
+
localFiles2 as localFiles
|
|
13
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Disposer, GitStatus } from "@nyte-ai/schema";
|
|
2
|
+
import type { FeedSink } from "./feed.ts";
|
|
3
|
+
/** Where `localGit` found the repository holding its workspace: the worktree root, its git directory, the common directory linked worktrees share (the git directory otherwise), and the workspace's path below the root (`""` or ending in `/`). */
|
|
4
|
+
export type Repository = {
|
|
5
|
+
readonly root: string;
|
|
6
|
+
readonly gitDir: string;
|
|
7
|
+
readonly commonDir: string;
|
|
8
|
+
readonly prefix: string;
|
|
9
|
+
};
|
|
10
|
+
/** One status watch shared by `localGit`'s feeds. */
|
|
11
|
+
export type GitWatcher = {
|
|
12
|
+
subscribe(listener: (status: GitStatus) => void, fail: FeedSink<GitStatus>["fail"]): Disposer;
|
|
13
|
+
};
|
|
14
|
+
/** Returns the status watch `localGit` shares among its watchers: the first subscriber starts it and the last one stops it, and each gets the status at once, then again whenever a change could move it. A recursive `fs.watch` on the workspace hears worktree paths that `.gitignore` and `.git/info/exclude` do not ignore, and, in the git directory and the common directory, only HEAD, the index, branch and remote refs, `packed-refs`, `config` and the merge, cherry-pick, revert and rebase state, so object writes, logs and Nyte's snapshot refs read nothing; the `.git` entry itself appearing or going drops the remembered repository and starts over. Only where `fs.watch` is unavailable does it poll, every 2 s. */
|
|
15
|
+
export declare function createWatcher(cwd: string, read: () => Promise<GitStatus>, repository: () => Promise<Repository | null>, forget: () => void): GitWatcher;
|