@nyte-ai/host 0.0.0-stage → 0.0.19
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 +866 -0
- package/dist/chunks/canvas-preview-0cmbkp2j.js +65 -0
- package/dist/chunks/canvas-preview-0nq75h9k.js +7 -0
- package/dist/chunks/canvas-preview-11nadadc.js +241 -0
- package/dist/chunks/canvas-preview-1sq7z9jq.js +17 -0
- package/dist/chunks/canvas-preview-2jwbe14k.js +130 -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-55s0y68g.js +387 -0
- package/dist/chunks/canvas-preview-5ekjx6sw.js +613 -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-8xc0vn7v.js +458 -0
- package/dist/chunks/canvas-preview-9aqczacs.js +73 -0
- package/dist/chunks/canvas-preview-af86jz8t.js +141 -0
- package/dist/chunks/canvas-preview-aq5j4p25.js +240 -0
- package/dist/chunks/canvas-preview-b2v8wfnz.js +36 -0
- package/dist/chunks/canvas-preview-befkjea2.js +60 -0
- package/dist/chunks/canvas-preview-bxnqt8cd.js +103 -0
- package/dist/chunks/canvas-preview-cawy6vbz.js +352 -0
- package/dist/chunks/canvas-preview-crmzxxt8.js +518 -0
- package/dist/chunks/canvas-preview-drctegz4.js +591 -0
- package/dist/chunks/canvas-preview-e3vnkkc5.js +134 -0
- package/dist/chunks/canvas-preview-ec2mt7es.js +108 -0
- package/dist/chunks/canvas-preview-fxa0rfb0.js +61 -0
- package/dist/chunks/canvas-preview-g5fkjs34.js +598 -0
- package/dist/chunks/canvas-preview-jeddjex8.js +166 -0
- package/dist/chunks/canvas-preview-k1yg4fgp.js +571 -0
- package/dist/chunks/canvas-preview-kdqgrstc.js +194 -0
- package/dist/chunks/canvas-preview-kn7kvbfj.js +12 -0
- package/dist/chunks/canvas-preview-kp75gb63.js +141 -0
- package/dist/chunks/canvas-preview-mgcx2b2p.js +271 -0
- package/dist/chunks/canvas-preview-n2a35zv5.js +81 -0
- package/dist/chunks/canvas-preview-pkzqg96v.js +63 -0
- package/dist/chunks/canvas-preview-rp4x6y1h.js +144 -0
- package/dist/chunks/canvas-preview-s94ebwf5.js +112 -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-tnqe7k0b.js +374 -0
- package/dist/chunks/canvas-preview-vaatfznm.js +189 -0
- package/dist/chunks/canvas-preview-vm9zdp2t.js +398 -0
- package/dist/chunks/canvas-preview-w54ymtb3.js +272 -0
- package/dist/chunks/canvas-preview-wg80rbc2.js +46 -0
- package/dist/chunks/canvas-preview-y5y6ghaw.js +125 -0
- package/dist/chunks/canvas-preview-ycepb05s.js +176 -0
- package/dist/chunks/canvas-preview-yjz0f7n4.js +50 -0
- package/dist/chunks/canvas-preview-zaaj99wd.js +244 -0
- package/dist/src/canvas-preview.d.ts +29 -0
- package/dist/src/canvas-preview.js +271 -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/images/exif.d.ts +1 -0
- package/dist/src/images/exif.js +6 -0
- package/dist/src/images/node.d.ts +37 -0
- package/dist/src/images/node.js +12 -0
- package/dist/src/images/photon.d.ts +3 -0
- package/dist/src/images/photon.js +7 -0
- package/dist/src/images/worker.d.ts +1 -0
- package/dist/src/images/worker.js +23 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.js +121 -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 +20 -0
- package/dist/src/local/command.js +12 -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 +7 -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 +15 -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 +14 -0
- package/dist/src/open.js +46 -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 +8 -0
- package/dist/src/sqlite.js +11 -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 +19 -0
- package/dist/src/usage-history.d.ts +54 -0
- package/dist/src/usage-history.js +14 -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 +23 -0
- package/dist/src/usage-service.js +16 -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 +29 -0
- package/dist/src/usage.d.ts +195 -0
- package/dist/src/usage.js +23 -0
- package/package.json +140 -3
- package/src/canvas-preview.ts +403 -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/images/exif.ts +69 -0
- package/src/images/node.ts +163 -0
- package/src/images/photon.ts +141 -0
- package/src/images/worker.ts +29 -0
- package/src/index.ts +39 -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 +161 -0
- package/src/local/feed.ts +70 -0
- package/src/local/files.ts +817 -0
- package/src/local/git-watch.ts +199 -0
- package/src/local/git.ts +919 -0
- package/src/local/github.ts +691 -0
- package/src/local/identity.ts +21 -0
- package/src/local/jobs.ts +573 -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 +778 -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 +92 -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 +449 -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 +629 -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 +553 -0
- package/src/store-rows.ts +110 -0
- package/src/store-usage.ts +347 -0
- package/src/usage-history.ts +219 -0
- package/src/usage-scan.ts +81 -0
- package/src/usage-service.ts +82 -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 +776 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
oauthKey2,
|
|
3
|
+
oauthStore2,
|
|
4
|
+
createAuthProvider2
|
|
5
|
+
} from "./canvas-preview-5z63am63.js";
|
|
6
|
+
|
|
7
|
+
// src/mcp/connect.ts
|
|
8
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import { StdioTransport, StreamableHttpTransport } from "@earendil-works/pi-mcp";
|
|
11
|
+
var connectServer2 = (entry, context) => {
|
|
12
|
+
const { transport } = entry;
|
|
13
|
+
if (transport.kind === "stdio") {
|
|
14
|
+
const base = context.workspace.root ?? context.home;
|
|
15
|
+
const cwd = transport.cwd === null ? base : home(transport.cwd, context.home);
|
|
16
|
+
return new StdioTransport({
|
|
17
|
+
command: home(transport.command, context.home),
|
|
18
|
+
args: transport.args.map((arg) => home(arg, context.home)),
|
|
19
|
+
env: expand(transport.env, entry.name),
|
|
20
|
+
cwd: isAbsolute(cwd) ? cwd : resolve(base, cwd),
|
|
21
|
+
stderr: "pipe"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const headers = expand(transport.headers, entry.name);
|
|
25
|
+
if (Object.keys(headers).some((name) => name.toLowerCase() === "authorization"))
|
|
26
|
+
return new StreamableHttpTransport({ url: transport.url, headers });
|
|
27
|
+
return new StreamableHttpTransport({
|
|
28
|
+
url: transport.url,
|
|
29
|
+
headers,
|
|
30
|
+
authProvider: createAuthProvider2({
|
|
31
|
+
serverUrl: transport.url,
|
|
32
|
+
store: oauthStore2(context.secrets, oauthKey2(entry.name, transport.url)),
|
|
33
|
+
settings: () => oauthSettings2(transport.oauth, entry.name),
|
|
34
|
+
onChallenge: context.challenged
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
function oauthSettings2(config, server) {
|
|
39
|
+
const { clientSecret, authServerMetadataUrl, ...rest } = config;
|
|
40
|
+
return {
|
|
41
|
+
...rest,
|
|
42
|
+
...clientSecret === undefined ? {} : { clientSecret: expand({ clientSecret }, server).clientSecret },
|
|
43
|
+
...authServerMetadataUrl === undefined ? {} : { authServerMetadataUrl: new URL(authServerMetadataUrl) }
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function home(path, directory) {
|
|
47
|
+
if (path === "~")
|
|
48
|
+
return directory;
|
|
49
|
+
return path.startsWith("~/") ? join(directory, path.slice(2)) : path;
|
|
50
|
+
}
|
|
51
|
+
function expand(values, server) {
|
|
52
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [
|
|
53
|
+
key,
|
|
54
|
+
value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => {
|
|
55
|
+
const found = process.env[name];
|
|
56
|
+
if (found === undefined)
|
|
57
|
+
throw new Error(`${server} needs the environment variable ${name}. Set it where Nyte runs, then restart Nyte.`);
|
|
58
|
+
return found;
|
|
59
|
+
})
|
|
60
|
+
]));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { connectServer2, oauthSettings2 };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// src/serve/stream-server.ts
|
|
2
|
+
import { deflateSync } from "fflate";
|
|
3
|
+
import { SdkError } from "@nyte-ai/schema";
|
|
4
|
+
import { CHANNEL_HEADER, asSdkError, encodeError, streamBuffer } from "@nyte-ai/protocol";
|
|
5
|
+
var encoder = new TextEncoder;
|
|
6
|
+
var CHUNK_BYTES = 48 * 1024;
|
|
7
|
+
var DEFLATE_MIN_BYTES = 16 * 1024;
|
|
8
|
+
function createStreamChannels2() {
|
|
9
|
+
const channels = new Map;
|
|
10
|
+
const owned = (id, connection) => {
|
|
11
|
+
const channel = channels.get(id);
|
|
12
|
+
if (channel === undefined)
|
|
13
|
+
throw new SdkError("unavailable", "The stream channel is closed.");
|
|
14
|
+
if (channel.connection !== connection)
|
|
15
|
+
throw new SdkError("denied", "The stream channel belongs to another connection.");
|
|
16
|
+
return channel;
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
open(connection, signal, deflate) {
|
|
20
|
+
const id = crypto.randomUUID();
|
|
21
|
+
const controller = new AbortController;
|
|
22
|
+
const streams = new Map;
|
|
23
|
+
let timer;
|
|
24
|
+
const finish = () => {
|
|
25
|
+
if (controller.signal.aborted)
|
|
26
|
+
return;
|
|
27
|
+
controller.abort();
|
|
28
|
+
channels.delete(id);
|
|
29
|
+
clearInterval(timer);
|
|
30
|
+
signal.removeEventListener("abort", aborted);
|
|
31
|
+
for (const stream of streams.values())
|
|
32
|
+
stream.abort();
|
|
33
|
+
streams.clear();
|
|
34
|
+
};
|
|
35
|
+
const buffer = streamBuffer(finish);
|
|
36
|
+
const fail = (error) => {
|
|
37
|
+
if (controller.signal.aborted)
|
|
38
|
+
return;
|
|
39
|
+
buffer.end(encoder.encode(`event: error
|
|
40
|
+
data: ${JSON.stringify(encodeError(error))}
|
|
41
|
+
|
|
42
|
+
`));
|
|
43
|
+
finish();
|
|
44
|
+
};
|
|
45
|
+
const aborted = () => {
|
|
46
|
+
fail(signal.reason instanceof SdkError ? signal.reason : new SdkError("unavailable", "The stream channel disconnected."));
|
|
47
|
+
};
|
|
48
|
+
channels.set(id, {
|
|
49
|
+
connection,
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
deflate,
|
|
52
|
+
streams,
|
|
53
|
+
push: (frame, signal) => buffer.write(encoder.encode(`data: ${JSON.stringify(frame)}
|
|
54
|
+
|
|
55
|
+
`), signal)
|
|
56
|
+
});
|
|
57
|
+
buffer.push(encoder.encode(`: connected
|
|
58
|
+
|
|
59
|
+
`));
|
|
60
|
+
timer = setInterval(() => {
|
|
61
|
+
buffer.push(encoder.encode(`: ping
|
|
62
|
+
|
|
63
|
+
`));
|
|
64
|
+
}, 15000);
|
|
65
|
+
if (signal.aborted)
|
|
66
|
+
aborted();
|
|
67
|
+
else
|
|
68
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
69
|
+
return new Response(buffer.body, {
|
|
70
|
+
headers: {
|
|
71
|
+
"Content-Type": "text/event-stream",
|
|
72
|
+
"Cache-Control": "no-cache",
|
|
73
|
+
[CHANNEL_HEADER]: id
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
async start(connection, channelId, streamId, request, serve) {
|
|
78
|
+
const channel = owned(channelId, connection);
|
|
79
|
+
if (channel.streams.has(streamId))
|
|
80
|
+
throw new SdkError("invalid", "The stream identifier is already in use.");
|
|
81
|
+
const controller = new AbortController;
|
|
82
|
+
channel.streams.set(streamId, controller);
|
|
83
|
+
const abortSetup = () => controller.abort(request.reason);
|
|
84
|
+
request.addEventListener("abort", abortSetup, { once: true });
|
|
85
|
+
const signal = AbortSignal.any([controller.signal, channel.signal]);
|
|
86
|
+
(async () => {
|
|
87
|
+
let reader;
|
|
88
|
+
const cancel = () => {
|
|
89
|
+
reader?.cancel().catch(() => {
|
|
90
|
+
return;
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
94
|
+
try {
|
|
95
|
+
if (request.aborted)
|
|
96
|
+
abortSetup();
|
|
97
|
+
signal.throwIfAborted();
|
|
98
|
+
const response = await serve(signal);
|
|
99
|
+
reader = response.body?.getReader();
|
|
100
|
+
request.removeEventListener("abort", abortSetup);
|
|
101
|
+
if (signal.aborted)
|
|
102
|
+
return;
|
|
103
|
+
if (reader !== undefined)
|
|
104
|
+
for (;; ) {
|
|
105
|
+
const next = await reader.read();
|
|
106
|
+
if (signal.aborted || next.done)
|
|
107
|
+
break;
|
|
108
|
+
for (let start = 0;start < next.value.byteLength; start += CHUNK_BYTES) {
|
|
109
|
+
if (signal.aborted)
|
|
110
|
+
break;
|
|
111
|
+
const chunk = next.value.subarray(start, start + CHUNK_BYTES);
|
|
112
|
+
await channel.push(channel.deflate && chunk.byteLength >= DEFLATE_MIN_BYTES ? {
|
|
113
|
+
kind: "deflated",
|
|
114
|
+
stream: streamId,
|
|
115
|
+
data: deflateSync(chunk, { level: 1 }).toBase64()
|
|
116
|
+
} : { kind: "chunk", stream: streamId, data: chunk.toBase64() }, signal);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!signal.aborted)
|
|
120
|
+
await channel.push({ kind: "end", stream: streamId }, signal);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (!signal.aborted)
|
|
123
|
+
await channel.push({
|
|
124
|
+
kind: "error",
|
|
125
|
+
stream: streamId,
|
|
126
|
+
error: JSON.stringify(encodeError(asSdkError(error)))
|
|
127
|
+
}, signal);
|
|
128
|
+
} finally {
|
|
129
|
+
request.removeEventListener("abort", abortSetup);
|
|
130
|
+
signal.removeEventListener("abort", cancel);
|
|
131
|
+
channel.streams.delete(streamId);
|
|
132
|
+
controller.abort();
|
|
133
|
+
cancel();
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
return new Response(null, { status: 202 });
|
|
137
|
+
},
|
|
138
|
+
cancel(connection, channelId, streamId) {
|
|
139
|
+
owned(channelId, connection).streams.get(streamId)?.abort();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { createStreamChannels2 };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readErrorCode2
|
|
3
|
+
} from "./canvas-preview-mgcx2b2p.js";
|
|
4
|
+
|
|
5
|
+
// src/plugins/loader.ts
|
|
6
|
+
import { readdir, realpath, stat } from "node:fs/promises";
|
|
7
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
8
|
+
import { pathToFileURL } from "node:url";
|
|
9
|
+
import { SdkError } from "@nyte-ai/schema";
|
|
10
|
+
import { dev } from "@nyte-ai/core";
|
|
11
|
+
var EXTENSIONS = [".ts", ".mts", ".js", ".mjs"];
|
|
12
|
+
async function loadPluginFiles2(dir) {
|
|
13
|
+
return loadAll(await pluginFilesIn(dir));
|
|
14
|
+
}
|
|
15
|
+
async function loadPluginDirectory2(dir) {
|
|
16
|
+
return importEach(await pluginFilesIn(dir));
|
|
17
|
+
}
|
|
18
|
+
function pluginLoader2(dirs) {
|
|
19
|
+
return async (paths) => {
|
|
20
|
+
const roots = (await Promise.all(dirs.map((dir) => realpath(dir).catch(() => null)))).filter((root) => root !== null);
|
|
21
|
+
const files = await Promise.all(paths.map(async (path) => {
|
|
22
|
+
const real = await realpath(path).catch(() => null);
|
|
23
|
+
if (real === null)
|
|
24
|
+
throw new SdkError("invalid", `No plugin file is at ${path}.`);
|
|
25
|
+
if (!roots.some((root) => inside(root, real)))
|
|
26
|
+
throw new SdkError("denied", `${path} is not in a plugin directory this host loads.`);
|
|
27
|
+
return real;
|
|
28
|
+
}));
|
|
29
|
+
return (await loadAll(files)).map((loaded) => loaded.plugin);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function loadAll(files) {
|
|
33
|
+
const { loaded, failed } = await importEach(files);
|
|
34
|
+
const issues = failed.map((entry) => entry.issue);
|
|
35
|
+
if (issues.length > 0)
|
|
36
|
+
throw new SdkError("invalid", `${issues.length === 1 ? "A plugin file" : `${issues.length} plugin files`} did not load: ${failed.map((entry) => `${entry.path}: ${entry.issue.message}`).join("; ")}`, { issues });
|
|
37
|
+
return loaded;
|
|
38
|
+
}
|
|
39
|
+
async function importEach(files) {
|
|
40
|
+
const loaded = [];
|
|
41
|
+
const failed = [];
|
|
42
|
+
for (const path of files) {
|
|
43
|
+
const outcome = await importPlugin(path);
|
|
44
|
+
dev("plugins", "file", { path, outcome: "plugin" in outcome ? "loaded" : "failed" });
|
|
45
|
+
if ("plugin" in outcome)
|
|
46
|
+
loaded.push({ plugin: outcome.plugin, path });
|
|
47
|
+
else
|
|
48
|
+
failed.push({
|
|
49
|
+
path,
|
|
50
|
+
issue: {
|
|
51
|
+
severity: "error",
|
|
52
|
+
path: [path],
|
|
53
|
+
message: outcome.reason,
|
|
54
|
+
source: { plugin: path, file: path }
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return { loaded, failed };
|
|
59
|
+
}
|
|
60
|
+
async function pluginFilesIn(dir) {
|
|
61
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch((error) => {
|
|
62
|
+
if (readErrorCode2(error) === "ENOENT" || readErrorCode2(error) === "ENOTDIR")
|
|
63
|
+
return [];
|
|
64
|
+
throw error;
|
|
65
|
+
});
|
|
66
|
+
return (await Promise.all(entries.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0).map(async (entry) => {
|
|
67
|
+
const path = join(dir, entry.name);
|
|
68
|
+
if (entry.isFile())
|
|
69
|
+
return EXTENSIONS.some((extension) => entry.name.endsWith(extension)) ? [path] : [];
|
|
70
|
+
if (!entry.isDirectory())
|
|
71
|
+
return [];
|
|
72
|
+
for (const extension of EXTENSIONS) {
|
|
73
|
+
const index = join(path, `index${extension}`);
|
|
74
|
+
if ((await stat(index).catch(() => null))?.isFile() === true)
|
|
75
|
+
return [index];
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}))).flat();
|
|
79
|
+
}
|
|
80
|
+
async function importPlugin(path) {
|
|
81
|
+
try {
|
|
82
|
+
const stats = await stat(path);
|
|
83
|
+
const url = pathToFileURL(path);
|
|
84
|
+
url.searchParams.set("nyte", `${stats.mtimeMs}-${stats.size}`);
|
|
85
|
+
const imported = await import(url.href);
|
|
86
|
+
const exported = typeof imported === "object" && imported !== null && "default" in imported ? imported.default : undefined;
|
|
87
|
+
return fitsCorePlugin(exported) ? { plugin: exported } : { reason: "Its default export is not a core plugin (an object with a string id)." };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return { reason: error instanceof Error ? error.message : String(error) };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function fitsCorePlugin(value) {
|
|
93
|
+
if (typeof value !== "object" || value === null || !("id" in value) || typeof value.id !== "string")
|
|
94
|
+
return false;
|
|
95
|
+
const object = (field) => field === undefined || typeof field === "object" && field !== null;
|
|
96
|
+
if ("contribute" in value && !object(value.contribute))
|
|
97
|
+
return false;
|
|
98
|
+
if ("hooks" in value && !object(value.hooks))
|
|
99
|
+
return false;
|
|
100
|
+
if ("activate" in value && value.activate !== undefined && typeof value.activate !== "function")
|
|
101
|
+
return false;
|
|
102
|
+
if (!("environment" in value) || value.environment === undefined)
|
|
103
|
+
return true;
|
|
104
|
+
const environment = value.environment;
|
|
105
|
+
return typeof environment === "object" && environment !== null && "kind" in environment && typeof environment.kind === "string" && "inspect" in environment && typeof environment.inspect === "function" && "attach" in environment && typeof environment.attach === "function";
|
|
106
|
+
}
|
|
107
|
+
function inside(root, path) {
|
|
108
|
+
const within = relative(root, path);
|
|
109
|
+
return within !== "" && !within.startsWith("..") && !isAbsolute(within);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { loadPluginFiles2, loadPluginDirectory2, pluginLoader2 };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readKeyFile2
|
|
3
|
+
} from "./canvas-preview-wg80rbc2.js";
|
|
4
|
+
|
|
5
|
+
// src/secrets.ts
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
function defaultSecrets2(home) {
|
|
8
|
+
const path = join(home, ".nyte", "secret.key");
|
|
9
|
+
let key = null;
|
|
10
|
+
return {
|
|
11
|
+
key: () => {
|
|
12
|
+
const known = key ?? readKeyFile2(path, "secrets key");
|
|
13
|
+
key = known;
|
|
14
|
+
known.catch(() => {
|
|
15
|
+
if (key === known)
|
|
16
|
+
key = null;
|
|
17
|
+
});
|
|
18
|
+
return known;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { defaultSecrets2 };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/usage-summary.ts
|
|
2
|
+
import { addUsage } from "@nyte-ai/core/server";
|
|
3
|
+
function emptyModelUsage2() {
|
|
4
|
+
return {
|
|
5
|
+
input: 0,
|
|
6
|
+
output: 0,
|
|
7
|
+
cacheRead: 0,
|
|
8
|
+
cacheWrite: 0,
|
|
9
|
+
totalTokens: 0,
|
|
10
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function recordedUsage2(usage) {
|
|
14
|
+
return {
|
|
15
|
+
input: usage.input,
|
|
16
|
+
output: usage.output,
|
|
17
|
+
cacheRead: usage.cacheRead,
|
|
18
|
+
cacheWrite: usage.cacheWrite,
|
|
19
|
+
reasoning: usage.reasoning ?? null,
|
|
20
|
+
total: usage.totalTokens,
|
|
21
|
+
cost: { ...usage.cost }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function emptyUsageSummary2() {
|
|
25
|
+
return {
|
|
26
|
+
models: [],
|
|
27
|
+
compaction: recordedUsage2(emptyModelUsage2()),
|
|
28
|
+
tools: recordedUsage2(emptyModelUsage2()),
|
|
29
|
+
total: recordedUsage2(emptyModelUsage2()),
|
|
30
|
+
cacheSavings: 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function summarizeModels2(rows) {
|
|
34
|
+
const models = new Map;
|
|
35
|
+
let total = recordedUsage2(emptyModelUsage2());
|
|
36
|
+
let savings = 0;
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
savings += cacheSavings2(row.usage);
|
|
39
|
+
const key = JSON.stringify([row.provider, row.model]);
|
|
40
|
+
const previous = models.get(key);
|
|
41
|
+
models.set(key, previous === undefined ? row : { ...row, turns: previous.turns + row.turns, usage: addUsage(previous.usage, row.usage) });
|
|
42
|
+
total = addUsage(total, row.usage);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
...emptyUsageSummary2(),
|
|
46
|
+
models: [...models.values()].toSorted((left, right) => right.usage.cost.total - left.usage.cost.total || right.usage.total - left.usage.total || left.model.localeCompare(right.model) || left.provider.localeCompare(right.provider)),
|
|
47
|
+
total,
|
|
48
|
+
cacheSavings: savings
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function cacheSavings2(usage) {
|
|
52
|
+
if (usage.input === 0)
|
|
53
|
+
return 0;
|
|
54
|
+
return usage.cacheRead * (usage.cost.input / usage.input) - usage.cost.cacheRead;
|
|
55
|
+
}
|
|
56
|
+
function usageTokens2(usage) {
|
|
57
|
+
return usage.total || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { emptyModelUsage2, recordedUsage2, emptyUsageSummary2, summarizeModels2, cacheSavings2, usageTokens2 };
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sha2562
|
|
3
|
+
} from "./canvas-preview-0nq75h9k.js";
|
|
4
|
+
|
|
5
|
+
// src/local/patch.ts
|
|
6
|
+
import { lineDiff } from "@nyte-ai/core";
|
|
7
|
+
import { writePatch } from "@nyte-ai/schema";
|
|
8
|
+
var PATCH_LIMIT2 = 1024 * 1024;
|
|
9
|
+
var ESCAPES = new Map([
|
|
10
|
+
["a", 7],
|
|
11
|
+
["b", 8],
|
|
12
|
+
["f", 12],
|
|
13
|
+
["n", 10],
|
|
14
|
+
["r", 13],
|
|
15
|
+
["t", 9],
|
|
16
|
+
["v", 11],
|
|
17
|
+
['"', 34],
|
|
18
|
+
["\\", 92]
|
|
19
|
+
]);
|
|
20
|
+
function splitDiff(output) {
|
|
21
|
+
const lines = output.split(`
|
|
22
|
+
`);
|
|
23
|
+
if (lines.at(-1) === "")
|
|
24
|
+
lines.pop();
|
|
25
|
+
const sections = [];
|
|
26
|
+
let index = 0;
|
|
27
|
+
while (index < lines.length) {
|
|
28
|
+
const header = lines[index] ?? "";
|
|
29
|
+
if (!header.startsWith("diff --git ")) {
|
|
30
|
+
index += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const start = index;
|
|
34
|
+
const named = headerPaths(header.slice("diff --git ".length));
|
|
35
|
+
let oldPath = named?.old ?? null;
|
|
36
|
+
let newPath = named?.new ?? null;
|
|
37
|
+
let binary = false;
|
|
38
|
+
let hunked = false;
|
|
39
|
+
let added = 0;
|
|
40
|
+
let removed = 0;
|
|
41
|
+
index += 1;
|
|
42
|
+
while (index < lines.length && !(lines[index] ?? "").startsWith("diff --git ")) {
|
|
43
|
+
const line = lines[index] ?? "";
|
|
44
|
+
index += 1;
|
|
45
|
+
if (line.startsWith("@@ "))
|
|
46
|
+
hunked = true;
|
|
47
|
+
else if (hunked && line.startsWith("+"))
|
|
48
|
+
added += 1;
|
|
49
|
+
else if (hunked && line.startsWith("-"))
|
|
50
|
+
removed += 1;
|
|
51
|
+
else if (hunked)
|
|
52
|
+
continue;
|
|
53
|
+
else if (line.startsWith("--- "))
|
|
54
|
+
oldPath = sidePath(line.slice(4), "a/");
|
|
55
|
+
else if (line.startsWith("+++ "))
|
|
56
|
+
newPath = sidePath(line.slice(4), "b/");
|
|
57
|
+
else if (/^(?:rename|copy) from /u.test(line))
|
|
58
|
+
oldPath = unquote(line.replace(/^(?:rename|copy) from /u, ""));
|
|
59
|
+
else if (/^(?:rename|copy) to /u.test(line))
|
|
60
|
+
newPath = unquote(line.replace(/^(?:rename|copy) to /u, ""));
|
|
61
|
+
else if (line.startsWith("new file mode "))
|
|
62
|
+
oldPath = null;
|
|
63
|
+
else if (line.startsWith("deleted file mode "))
|
|
64
|
+
newPath = null;
|
|
65
|
+
else if (line.startsWith("Binary files ") || line === "GIT binary patch")
|
|
66
|
+
binary = true;
|
|
67
|
+
}
|
|
68
|
+
sections.push({
|
|
69
|
+
oldPath,
|
|
70
|
+
newPath,
|
|
71
|
+
binary,
|
|
72
|
+
hunked,
|
|
73
|
+
added,
|
|
74
|
+
removed,
|
|
75
|
+
text: `${lines.slice(start, index).join(`
|
|
76
|
+
`)}
|
|
77
|
+
`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return sections;
|
|
81
|
+
}
|
|
82
|
+
function sectionEntry(path, status, section) {
|
|
83
|
+
const digest = sha2562(section.text);
|
|
84
|
+
if (section.binary)
|
|
85
|
+
return { path, status, digest, kind: "binary" };
|
|
86
|
+
if (section.text.length > PATCH_LIMIT2)
|
|
87
|
+
return { path, status, digest, kind: "too-large", limit: PATCH_LIMIT2 };
|
|
88
|
+
if (!section.hunked)
|
|
89
|
+
return { path, status, digest, kind: "empty" };
|
|
90
|
+
return {
|
|
91
|
+
path,
|
|
92
|
+
status,
|
|
93
|
+
digest,
|
|
94
|
+
kind: "text",
|
|
95
|
+
added: section.added,
|
|
96
|
+
removed: section.removed,
|
|
97
|
+
patch: section.text
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function textEntry2(path, status, before, after, options) {
|
|
101
|
+
const { hunks, added, removed } = lineDiff(before ?? "", after ?? "", options);
|
|
102
|
+
if (hunks.length === 0) {
|
|
103
|
+
const mode = options?.ignoreWhitespace === true ? "ignore-whitespace" : "";
|
|
104
|
+
return {
|
|
105
|
+
path,
|
|
106
|
+
status,
|
|
107
|
+
digest: sha2562(`${mode}\x00${before ?? ""}\x00${after ?? ""}`),
|
|
108
|
+
kind: "empty"
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const patch = writePatch(path, status, hunks);
|
|
112
|
+
return { path, status, digest: sha2562(patch), kind: "text", added, removed, patch };
|
|
113
|
+
}
|
|
114
|
+
async function readPatches2(files, read, emptyDigest) {
|
|
115
|
+
const settle = (batch, ran) => {
|
|
116
|
+
const sections = splitDiff(ran.stdout.toString("utf8"));
|
|
117
|
+
return batch.map((file) => {
|
|
118
|
+
const section = sections.find((candidate) => (candidate.newPath ?? candidate.oldPath) === file.path);
|
|
119
|
+
return section === undefined ? { path: file.path, status: file.status, digest: emptyDigest(file), kind: "empty" } : sectionEntry(file.path, file.status, section);
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const together = await read(files, PATCH_LIMIT2 * files.length + 4096).catch(() => null);
|
|
123
|
+
if (together !== null && !together.truncated && (together.code === 0 || together.code === 1))
|
|
124
|
+
return settle(files, together);
|
|
125
|
+
const entries = [];
|
|
126
|
+
for (const file of files) {
|
|
127
|
+
const failed = (reason) => ({
|
|
128
|
+
path: file.path,
|
|
129
|
+
status: file.status,
|
|
130
|
+
digest: "",
|
|
131
|
+
kind: "failed",
|
|
132
|
+
reason
|
|
133
|
+
});
|
|
134
|
+
const alone = await read([file], PATCH_LIMIT2 + 1).catch((error) => error instanceof Error ? error.message : String(error));
|
|
135
|
+
if (typeof alone === "string")
|
|
136
|
+
entries.push(failed(alone));
|
|
137
|
+
else if (alone.truncated)
|
|
138
|
+
entries.push({
|
|
139
|
+
path: file.path,
|
|
140
|
+
status: file.status,
|
|
141
|
+
digest: sha2562(alone.stdout),
|
|
142
|
+
kind: "too-large",
|
|
143
|
+
limit: PATCH_LIMIT2
|
|
144
|
+
});
|
|
145
|
+
else if (alone.code !== 0 && alone.code !== 1)
|
|
146
|
+
entries.push(failed(alone.stderr.trim() || "git diff failed"));
|
|
147
|
+
else
|
|
148
|
+
entries.push(...settle([file], alone));
|
|
149
|
+
}
|
|
150
|
+
return entries;
|
|
151
|
+
}
|
|
152
|
+
function lineStat2(before, after) {
|
|
153
|
+
const { added, removed } = lineDiff(before, after);
|
|
154
|
+
return { kind: "text", added, removed };
|
|
155
|
+
}
|
|
156
|
+
function headerPaths(rest) {
|
|
157
|
+
if (rest.startsWith('"')) {
|
|
158
|
+
const end = quotedEnd(rest);
|
|
159
|
+
const old = unquote(rest.slice(0, end + 1));
|
|
160
|
+
const next = unquote(rest.slice(end + 2));
|
|
161
|
+
return { old: old.replace(/^a\//, ""), new: next.replace(/^b\//, "") };
|
|
162
|
+
}
|
|
163
|
+
const half = (rest.length - 5) / 2;
|
|
164
|
+
if (Number.isInteger(half) && rest.startsWith("a/") && rest.slice(half + 2, half + 5) === " b/") {
|
|
165
|
+
const path = rest.slice(2, half + 2);
|
|
166
|
+
if (rest.slice(half + 5) === path)
|
|
167
|
+
return { old: path, new: path };
|
|
168
|
+
}
|
|
169
|
+
const split = /^.{2}(.*?) b\/(.*)$/su.exec(rest);
|
|
170
|
+
return split === null ? null : { old: split[1] ?? "", new: unquote(split[2] ?? "") };
|
|
171
|
+
}
|
|
172
|
+
function quotedEnd(text) {
|
|
173
|
+
for (let index = 1;index < text.length; index += 1) {
|
|
174
|
+
if (text[index] === "\\")
|
|
175
|
+
index += 1;
|
|
176
|
+
else if (text[index] === '"')
|
|
177
|
+
return index;
|
|
178
|
+
}
|
|
179
|
+
return text.length - 1;
|
|
180
|
+
}
|
|
181
|
+
function sidePath(text, prefix) {
|
|
182
|
+
const name = unquote(text.replace(/\t$/, ""));
|
|
183
|
+
if (name === "/dev/null")
|
|
184
|
+
return null;
|
|
185
|
+
return name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
186
|
+
}
|
|
187
|
+
function unquote(text) {
|
|
188
|
+
if (!text.startsWith('"') || !text.endsWith('"') || text.length < 2)
|
|
189
|
+
return text;
|
|
190
|
+
const bytes = [];
|
|
191
|
+
const encoder = new TextEncoder;
|
|
192
|
+
for (let index = 1;index < text.length - 1; index += 1) {
|
|
193
|
+
const char = text[index] ?? "";
|
|
194
|
+
if (char !== "\\") {
|
|
195
|
+
bytes.push(...encoder.encode(char));
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const next = text[index + 1] ?? "";
|
|
199
|
+
const octal = /^[0-7]{3}$/.exec(text.slice(index + 1, index + 4));
|
|
200
|
+
if (octal !== null) {
|
|
201
|
+
bytes.push(Number.parseInt(octal[0], 8));
|
|
202
|
+
index += 3;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
bytes.push(ESCAPES.get(next) ?? next.charCodeAt(0));
|
|
206
|
+
index += 1;
|
|
207
|
+
}
|
|
208
|
+
return new TextDecoder().decode(new Uint8Array(bytes));
|
|
209
|
+
}
|
|
210
|
+
function parseNumstat2(output) {
|
|
211
|
+
const tokens = output.split("\x00");
|
|
212
|
+
const stats = new Map;
|
|
213
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
214
|
+
const token = tokens[index] ?? "";
|
|
215
|
+
if (token === "")
|
|
216
|
+
continue;
|
|
217
|
+
const [added = "", removed = "", path = ""] = token.split("\t");
|
|
218
|
+
let name = path;
|
|
219
|
+
if (path === "") {
|
|
220
|
+
name = tokens[index + 2] ?? "";
|
|
221
|
+
index += 2;
|
|
222
|
+
}
|
|
223
|
+
stats.set(name, added === "-" || removed === "-" ? { kind: "binary" } : { kind: "text", added: Number(added) || 0, removed: Number(removed) || 0 });
|
|
224
|
+
}
|
|
225
|
+
return stats;
|
|
226
|
+
}
|
|
227
|
+
function parseNameStatus2(output) {
|
|
228
|
+
const tokens = output.split("\x00");
|
|
229
|
+
const changed = [];
|
|
230
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
231
|
+
const code = tokens[index] ?? "";
|
|
232
|
+
if (code === "")
|
|
233
|
+
continue;
|
|
234
|
+
const letter = code[0];
|
|
235
|
+
if (letter === "R" || letter === "C") {
|
|
236
|
+
const from = tokens[index + 1] ?? "";
|
|
237
|
+
const path = tokens[index + 2] ?? "";
|
|
238
|
+
index += 2;
|
|
239
|
+
changed.push(letter === "R" ? { path, status: "renamed", from } : { path, status: "added" });
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const path = tokens[index + 1] ?? "";
|
|
243
|
+
index += 1;
|
|
244
|
+
changed.push({
|
|
245
|
+
path,
|
|
246
|
+
status: letter === "A" ? "added" : letter === "D" ? "deleted" : letter === "U" ? "conflicted" : "modified"
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return changed;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export { PATCH_LIMIT2, textEntry2, readPatches2, lineStat2, parseNumstat2, parseNameStatus2 };
|