oasis_test_v2 2.2.45 → 2.2.47
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/dist/index.js +288 -128
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -109,22 +109,27 @@ var init_manifest = __esm({
|
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
// ../contract/src/file-limits.ts
|
|
112
|
+
function fileUploadRequestMaxBytes(limits) {
|
|
113
|
+
return Math.min(Number.MAX_SAFE_INTEGER, Math.max(
|
|
114
|
+
4 * Math.ceil(Math.max(limits.attachmentBytes, limits.knowledgeBytes, limits.cliBytes) / 3),
|
|
115
|
+
6 * Math.max(limits.skillFileBytes, limits.textEditBytes)
|
|
116
|
+
) + MIB);
|
|
117
|
+
}
|
|
112
118
|
function validateFileLimits(input) {
|
|
113
119
|
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error("\u6587\u4EF6\u9650\u5236\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
114
120
|
const raw = input;
|
|
115
|
-
if (Object.keys(raw).some((key2) => !Object.hasOwn(DEFAULT_FILE_LIMITS, key2))) throw new Error("\u5B58\u5728\u672A\u77E5\u7684\u6587\u4EF6\u9650\u5236\u5B57\u6BB5");
|
|
121
|
+
if (Object.keys(raw).some((key2) => !Object.hasOwn(DEFAULT_FILE_LIMITS, key2) && key2 !== "skillBundleBytes" && key2 !== "skillFileCount")) throw new Error("\u5B58\u5728\u672A\u77E5\u7684\u6587\u4EF6\u9650\u5236\u5B57\u6BB5");
|
|
116
122
|
const result = { ...DEFAULT_FILE_LIMITS };
|
|
117
123
|
for (const key2 of Object.keys(result)) {
|
|
118
124
|
const value2 = raw[key2];
|
|
119
|
-
if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 <= 0
|
|
120
|
-
throw new Error(`${key2} \u5FC5\u987B\u662F
|
|
125
|
+
if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 <= 0) {
|
|
126
|
+
throw new Error(`${key2} \u5FC5\u987B\u662F\u6B63\u6574\u6570\uFF08\u5B57\u8282\uFF09`);
|
|
121
127
|
}
|
|
122
128
|
result[key2] = value2;
|
|
123
129
|
}
|
|
124
|
-
if (result.skillFileBytes > result.skillBundleBytes) throw new Error("\u6280\u80FD\u5355\u6587\u4EF6\u4E0A\u9650\u4E0D\u80FD\u8D85\u8FC7\u6574\u5305\u4E0A\u9650");
|
|
125
130
|
return result;
|
|
126
131
|
}
|
|
127
|
-
var MIB, DEFAULT_FILE_LIMITS,
|
|
132
|
+
var MIB, DEFAULT_FILE_LIMITS, FILE_TRANSFER_MAX_BYTES;
|
|
128
133
|
var init_file_limits = __esm({
|
|
129
134
|
"../contract/src/file-limits.ts"() {
|
|
130
135
|
"use strict";
|
|
@@ -133,16 +138,11 @@ var init_file_limits = __esm({
|
|
|
133
138
|
attachmentBytes: 200 * MIB,
|
|
134
139
|
knowledgeBytes: 200 * MIB,
|
|
135
140
|
cliBytes: 200 * MIB,
|
|
136
|
-
skillFileBytes:
|
|
137
|
-
skillBundleBytes: 200 * MIB,
|
|
138
|
-
skillFileCount: 128,
|
|
141
|
+
skillFileBytes: 200 * MIB,
|
|
139
142
|
textEditBytes: 20 * MIB,
|
|
140
143
|
officePreviewBytes: 200 * MIB
|
|
141
144
|
});
|
|
142
|
-
|
|
143
|
-
FILE_UPLOAD_REQUEST_MAX_BYTES = 4 * Math.ceil(200 * MIB / 3) + MIB;
|
|
144
|
-
FILE_TRANSFER_INPUT_MAX_BYTES = DEFAULT_FILE_LIMITS.attachmentBytes;
|
|
145
|
-
FILE_TRANSFER_MAX_BYTES = 4 * Math.ceil((FILE_TRANSFER_INPUT_MAX_BYTES + 32 * MIB) / 3) + MIB;
|
|
145
|
+
FILE_TRANSFER_MAX_BYTES = 4 * Math.ceil((200 * MIB + 32 * MIB) / 3) + MIB;
|
|
146
146
|
}
|
|
147
147
|
});
|
|
148
148
|
|
|
@@ -1749,6 +1749,130 @@ var init_file_preview = __esm({
|
|
|
1749
1749
|
}
|
|
1750
1750
|
});
|
|
1751
1751
|
|
|
1752
|
+
// ../contract/src/chunked-message.ts
|
|
1753
|
+
function* tokens(value2, key2 = null, strings2 = /* @__PURE__ */ new Map()) {
|
|
1754
|
+
if (value2 && typeof value2 === "object" && "toJSON" in value2 && typeof value2.toJSON === "function") value2 = value2.toJSON();
|
|
1755
|
+
if (typeof value2 === "string") {
|
|
1756
|
+
if (strings2.has(value2)) {
|
|
1757
|
+
yield ["ref", key2, strings2.get(value2)];
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
strings2.set(value2, strings2.size);
|
|
1761
|
+
yield ["string", key2];
|
|
1762
|
+
for (let i = 0; i < value2.length; i += STRING_CHARS) yield ["part", value2.slice(i, i + STRING_CHARS)];
|
|
1763
|
+
yield ["end"];
|
|
1764
|
+
} else if (value2 && typeof value2 === "object") {
|
|
1765
|
+
yield [Array.isArray(value2) ? "array" : "object", key2];
|
|
1766
|
+
if (Array.isArray(value2)) {
|
|
1767
|
+
for (const child of value2) yield* tokens(child, null, strings2);
|
|
1768
|
+
} else {
|
|
1769
|
+
for (const [name, child] of Object.entries(value2)) {
|
|
1770
|
+
if (child !== void 0 && typeof child !== "function" && typeof child !== "symbol") yield* tokens(child, name, strings2);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
yield ["end"];
|
|
1774
|
+
} else {
|
|
1775
|
+
if (typeof value2 === "bigint") throw new Error("BigInt is not JSON serializable");
|
|
1776
|
+
yield ["value", key2, value2 ?? null];
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
function* encodeChunkedMessage(value2) {
|
|
1780
|
+
let parts = [], length = 0, start = true;
|
|
1781
|
+
const frame = (done) => `{"type":"chunked_message","start":${start},"done":${done},"tokens":[${parts.join(",")}]}`;
|
|
1782
|
+
for (const token of tokens(value2)) {
|
|
1783
|
+
const part = JSON.stringify(token);
|
|
1784
|
+
if (length + part.length > FRAME_CHARS && parts.length) {
|
|
1785
|
+
yield frame(false);
|
|
1786
|
+
start = false;
|
|
1787
|
+
parts = [];
|
|
1788
|
+
length = 0;
|
|
1789
|
+
}
|
|
1790
|
+
parts.push(part);
|
|
1791
|
+
length += part.length + 1;
|
|
1792
|
+
}
|
|
1793
|
+
yield frame(true);
|
|
1794
|
+
}
|
|
1795
|
+
var FRAME_CHARS, STRING_CHARS, ChunkedMessageDecoder;
|
|
1796
|
+
var init_chunked_message = __esm({
|
|
1797
|
+
"../contract/src/chunked-message.ts"() {
|
|
1798
|
+
"use strict";
|
|
1799
|
+
FRAME_CHARS = 512 * 1024;
|
|
1800
|
+
STRING_CHARS = 64 * 1024;
|
|
1801
|
+
ChunkedMessageDecoder = class {
|
|
1802
|
+
stack = [];
|
|
1803
|
+
strings = [];
|
|
1804
|
+
active = false;
|
|
1805
|
+
hasRoot = false;
|
|
1806
|
+
root;
|
|
1807
|
+
attach(key2, value2) {
|
|
1808
|
+
const parent = this.stack.at(-1);
|
|
1809
|
+
if (!parent) {
|
|
1810
|
+
if (this.hasRoot || key2 !== null) throw new Error("Invalid chunked message root");
|
|
1811
|
+
this.root = value2;
|
|
1812
|
+
this.hasRoot = true;
|
|
1813
|
+
} else if (parent.kind === "array") {
|
|
1814
|
+
if (key2 !== null) throw new Error("Invalid array key");
|
|
1815
|
+
parent.value.push(value2);
|
|
1816
|
+
} else if (parent.kind === "object") {
|
|
1817
|
+
if (typeof key2 !== "string" || Object.hasOwn(parent.value, key2)) throw new Error("Invalid object key");
|
|
1818
|
+
Object.defineProperty(parent.value, key2, { value: value2, enumerable: true, writable: true, configurable: true });
|
|
1819
|
+
} else throw new Error("Unclosed string");
|
|
1820
|
+
}
|
|
1821
|
+
/** undefined means that more frames are needed; plain legacy JSON passes through. */
|
|
1822
|
+
accept(input) {
|
|
1823
|
+
if (!input || typeof input !== "object" || !("type" in input) || input.type !== "chunked_message") return input;
|
|
1824
|
+
const frame = input;
|
|
1825
|
+
if (typeof frame.start !== "boolean" || typeof frame.done !== "boolean" || !Array.isArray(frame.tokens)) throw new Error("Invalid chunked frame");
|
|
1826
|
+
if (frame.start) {
|
|
1827
|
+
if (this.active) throw new Error("Overlapping chunked messages");
|
|
1828
|
+
this.active = true;
|
|
1829
|
+
this.hasRoot = false;
|
|
1830
|
+
this.root = void 0;
|
|
1831
|
+
this.stack = [];
|
|
1832
|
+
this.strings = [];
|
|
1833
|
+
}
|
|
1834
|
+
if (!this.active) throw new Error("Missing chunked message start");
|
|
1835
|
+
for (const token of frame.tokens) {
|
|
1836
|
+
if (!Array.isArray(token)) throw new Error("Invalid chunked token");
|
|
1837
|
+
const [kind, key2, value2] = token;
|
|
1838
|
+
if (kind === "object" || kind === "array") {
|
|
1839
|
+
const child = kind === "array" ? [] : {};
|
|
1840
|
+
this.attach(key2, child);
|
|
1841
|
+
this.stack.push({ kind, value: child });
|
|
1842
|
+
} else if (kind === "string") {
|
|
1843
|
+
if (key2 !== null && typeof key2 !== "string") throw new Error("Invalid string key");
|
|
1844
|
+
this.stack.push({ kind, key: key2, parts: [] });
|
|
1845
|
+
} else if (kind === "part") {
|
|
1846
|
+
const parent = this.stack.at(-1);
|
|
1847
|
+
if (parent?.kind !== "string" || typeof key2 !== "string") throw new Error("Invalid string part");
|
|
1848
|
+
parent.parts.push(key2);
|
|
1849
|
+
} else if (kind === "ref") {
|
|
1850
|
+
if (!Number.isInteger(value2) || value2 < 0 || value2 >= this.strings.length) throw new Error("Invalid string reference");
|
|
1851
|
+
this.attach(key2, this.strings[value2]);
|
|
1852
|
+
} else if (kind === "value") this.attach(key2, value2);
|
|
1853
|
+
else if (kind === "end") {
|
|
1854
|
+
const parent = this.stack.pop();
|
|
1855
|
+
if (!parent) throw new Error("Unexpected end");
|
|
1856
|
+
if (parent.kind === "string") {
|
|
1857
|
+
const text6 = parent.parts.join("");
|
|
1858
|
+
this.strings.push(text6);
|
|
1859
|
+
this.attach(parent.key, text6);
|
|
1860
|
+
}
|
|
1861
|
+
} else throw new Error("Unknown chunked token");
|
|
1862
|
+
}
|
|
1863
|
+
if (!frame.done) return void 0;
|
|
1864
|
+
if (!this.hasRoot || this.stack.length) throw new Error("Incomplete chunked message");
|
|
1865
|
+
const result = this.root;
|
|
1866
|
+
this.root = void 0;
|
|
1867
|
+
this.active = false;
|
|
1868
|
+
this.hasRoot = false;
|
|
1869
|
+
this.strings = [];
|
|
1870
|
+
return result;
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
|
|
1752
1876
|
// ../contract/src/index.ts
|
|
1753
1877
|
var init_src = __esm({
|
|
1754
1878
|
"../contract/src/index.ts"() {
|
|
@@ -1814,6 +1938,7 @@ var init_src = __esm({
|
|
|
1814
1938
|
init_http_api();
|
|
1815
1939
|
init_file_preview();
|
|
1816
1940
|
init_file_limits();
|
|
1941
|
+
init_chunked_message();
|
|
1817
1942
|
}
|
|
1818
1943
|
});
|
|
1819
1944
|
|
|
@@ -1884,17 +2009,16 @@ function withFileLimits(limits, fn) {
|
|
|
1884
2009
|
}
|
|
1885
2010
|
function assertSkillFileLimits(files) {
|
|
1886
2011
|
const limits = currentFileLimits();
|
|
1887
|
-
if (files.length > limits.skillFileCount) throw new ApiError(413, "SKILL_TOO_LARGE", `\u6280\u80FD\u6587\u4EF6\u6570\u8D85\u8FC7 ${limits.skillFileCount} \u4E2A`);
|
|
1888
|
-
let total = 0;
|
|
1889
2012
|
for (const file of files) {
|
|
1890
2013
|
if (file.size > limits.skillFileBytes) throw new ApiError(413, "SKILL_TOO_LARGE", `\u6280\u80FD\u6587\u4EF6\u8D85\u8FC7 ${limits.skillFileBytes / 1024 / 1024} MiB\uFF1A${file.path}`);
|
|
1891
|
-
total += file.size;
|
|
1892
2014
|
}
|
|
1893
|
-
if (total > limits.skillBundleBytes) throw new ApiError(413, "SKILL_TOO_LARGE", `\u6280\u80FD\u6574\u5305\u8D85\u8FC7 ${limits.skillBundleBytes / 1024 / 1024} MiB`);
|
|
1894
2015
|
}
|
|
1895
2016
|
function assertFileBytes(bytes2, maxBytes = currentFileLimits().attachmentBytes) {
|
|
1896
2017
|
if (bytes2.byteLength > maxBytes) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${maxBytes / 1024 / 1024} MiB \u4E0A\u9650`);
|
|
1897
2018
|
}
|
|
2019
|
+
function currentFileReadMaxBytes() {
|
|
2020
|
+
return Math.max(DEFAULT_FILE_LIMITS.attachmentBytes, ...Object.values(currentFileLimits()));
|
|
2021
|
+
}
|
|
1898
2022
|
function assertEditableBytes(bytes2) {
|
|
1899
2023
|
assertFileBytes(bytes2, currentFileLimits().textEditBytes);
|
|
1900
2024
|
if (bytes2.includes(0)) throw new ApiError(400, "INVALID_TEXT", "\u4EC5\u652F\u6301 UTF-8 \u6587\u672C");
|
|
@@ -2061,12 +2185,12 @@ async function readArtifactFile(kernel, blobs, artifactId, path40, expectedRef,
|
|
|
2061
2185
|
if (!entry) throw new ApiError(404, "NOT_FOUND", "\u5305\u5185\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
2062
2186
|
hash3 = entry.hash;
|
|
2063
2187
|
name = entry.path;
|
|
2064
|
-
if (entry.size !== void 0 && entry.size >
|
|
2188
|
+
if (entry.size !== void 0 && entry.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2065
2189
|
} else if (output.contentKind !== "inline-blob") {
|
|
2066
2190
|
throw new ApiError(404, "NOT_FOUND", "\u6B64\u4EA7\u7269\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684\u539F\u6587\u4EF6");
|
|
2067
2191
|
}
|
|
2068
2192
|
const meta = await blobs.meta?.(hash3);
|
|
2069
|
-
if (meta && meta.size >
|
|
2193
|
+
if (meta && meta.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2070
2194
|
try {
|
|
2071
2195
|
return { bytes: await blobs.get(hash3), name, contentType: meta?.contentType };
|
|
2072
2196
|
} catch {
|
|
@@ -2094,7 +2218,7 @@ async function serveFileRequest(req, res, url, engine) {
|
|
|
2094
2218
|
url.searchParams.get("ref"),
|
|
2095
2219
|
url.searchParams.get("revisionId")
|
|
2096
2220
|
);
|
|
2097
|
-
if (bytes2.length >
|
|
2221
|
+
if (bytes2.length > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2098
2222
|
res.writeHead(200, {
|
|
2099
2223
|
"content-type": contentType ?? sniffContentType(bytes2) ?? "application/octet-stream",
|
|
2100
2224
|
"content-length": String(bytes2.length),
|
|
@@ -2123,6 +2247,7 @@ var init_file_http = __esm({
|
|
|
2123
2247
|
init_src();
|
|
2124
2248
|
init_artifact_content2();
|
|
2125
2249
|
init_router();
|
|
2250
|
+
init_file_limits2();
|
|
2126
2251
|
}
|
|
2127
2252
|
});
|
|
2128
2253
|
|
|
@@ -3256,12 +3381,12 @@ function recordSubagentCall(calls, id, call) {
|
|
|
3256
3381
|
}
|
|
3257
3382
|
function byModelOf(calls) {
|
|
3258
3383
|
const out = {};
|
|
3259
|
-
for (const { model, tokens } of calls.values()) {
|
|
3384
|
+
for (const { model, tokens: tokens2 } of calls.values()) {
|
|
3260
3385
|
const acc = out[model] ?? (out[model] = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 });
|
|
3261
|
-
acc.inputTokens +=
|
|
3262
|
-
acc.outputTokens +=
|
|
3263
|
-
acc.cacheReadTokens +=
|
|
3264
|
-
acc.cacheCreationTokens +=
|
|
3386
|
+
acc.inputTokens += tokens2.inputTokens;
|
|
3387
|
+
acc.outputTokens += tokens2.outputTokens;
|
|
3388
|
+
acc.cacheReadTokens += tokens2.cacheReadTokens;
|
|
3389
|
+
acc.cacheCreationTokens += tokens2.cacheCreationTokens;
|
|
3265
3390
|
}
|
|
3266
3391
|
return out;
|
|
3267
3392
|
}
|
|
@@ -5115,18 +5240,19 @@ async function probeCodexAppServer(bin, timeoutMs = 15e3) {
|
|
|
5115
5240
|
if (config2 === void 0 || listState === "pending") return;
|
|
5116
5241
|
finish({ config: config2, models: listState === "done" ? listed : null });
|
|
5117
5242
|
};
|
|
5118
|
-
const
|
|
5243
|
+
const abort = () => finish(config2 === void 0 ? null : { config: config2, models: listState === "done" ? listed : null });
|
|
5244
|
+
const timer = setTimeout(abort, timeoutMs);
|
|
5119
5245
|
const send = (id, method, params) => {
|
|
5120
5246
|
try {
|
|
5121
5247
|
child.stdin?.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
5122
5248
|
`);
|
|
5123
5249
|
} catch {
|
|
5124
|
-
|
|
5250
|
+
abort();
|
|
5125
5251
|
}
|
|
5126
5252
|
};
|
|
5127
|
-
child.on("error",
|
|
5128
|
-
child.stdin?.on("error",
|
|
5129
|
-
child.on("close",
|
|
5253
|
+
child.on("error", abort);
|
|
5254
|
+
child.stdin?.on("error", abort);
|
|
5255
|
+
child.on("close", abort);
|
|
5130
5256
|
let buf = "";
|
|
5131
5257
|
child.stdout?.on("data", (chunk) => {
|
|
5132
5258
|
if (settled) return;
|
|
@@ -10140,14 +10266,14 @@ function accountUsage(model, usage) {
|
|
|
10140
10266
|
const input = nonNegative(usage.inputTokens);
|
|
10141
10267
|
const output = nonNegative(usage.outputTokens);
|
|
10142
10268
|
const cache = nonNegative(usage.cacheReadTokens) + nonNegative(usage.cacheCreationTokens);
|
|
10143
|
-
const
|
|
10269
|
+
const tokens2 = { input, cache, output, total: input + cache + output };
|
|
10144
10270
|
const estimated = estimateUsageCostBreakdown(resolved, usage);
|
|
10145
10271
|
const weights = estimated ? { input: estimated.inputMicros, cache: estimated.cacheMicros, output: estimated.outputMicros } : null;
|
|
10146
10272
|
const reported = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
10147
10273
|
if (reported > 0) {
|
|
10148
10274
|
const parts = weights && estimated?.currency === "USD" ? splitByWeight(reported, weights) : { input: 0, cache: 0, output: reported };
|
|
10149
10275
|
return {
|
|
10150
|
-
tokens,
|
|
10276
|
+
tokens: tokens2,
|
|
10151
10277
|
currency: "USD",
|
|
10152
10278
|
amountMicros: reported,
|
|
10153
10279
|
parts,
|
|
@@ -10160,7 +10286,7 @@ function accountUsage(model, usage) {
|
|
|
10160
10286
|
const amount = weights.input + weights.cache + weights.output;
|
|
10161
10287
|
const displayUsdMicros = toDisplayUsd(estimated.currency, amount);
|
|
10162
10288
|
return {
|
|
10163
|
-
tokens,
|
|
10289
|
+
tokens: tokens2,
|
|
10164
10290
|
currency: estimated.currency,
|
|
10165
10291
|
amountMicros: amount,
|
|
10166
10292
|
parts: weights,
|
|
@@ -10170,7 +10296,7 @@ function accountUsage(model, usage) {
|
|
|
10170
10296
|
};
|
|
10171
10297
|
}
|
|
10172
10298
|
return {
|
|
10173
|
-
tokens,
|
|
10299
|
+
tokens: tokens2,
|
|
10174
10300
|
currency: "USD",
|
|
10175
10301
|
amountMicros: 0,
|
|
10176
10302
|
parts: { input: 0, cache: 0, output: 0 },
|
|
@@ -10195,8 +10321,8 @@ function estimateSubagentCostUsdMicros(usage) {
|
|
|
10195
10321
|
const models = Object.entries(usage.byModel);
|
|
10196
10322
|
if (models.length === 0) return void 0;
|
|
10197
10323
|
let total = 0;
|
|
10198
|
-
for (const [model,
|
|
10199
|
-
const account = accountUsage(model, { ...
|
|
10324
|
+
for (const [model, tokens2] of models) {
|
|
10325
|
+
const account = accountUsage(model, { ...tokens2, costUsdMicros: null });
|
|
10200
10326
|
if (!account || account.source !== "estimated") return void 0;
|
|
10201
10327
|
total += account.displayUsdMicros;
|
|
10202
10328
|
}
|
|
@@ -24975,13 +25101,13 @@ var require_axios = __commonJS({
|
|
|
24975
25101
|
return utils$1.isArray(value2) ? value2.map(normalizeValue) : String(value2);
|
|
24976
25102
|
}
|
|
24977
25103
|
function parseTokens(str5) {
|
|
24978
|
-
const
|
|
25104
|
+
const tokens2 = /* @__PURE__ */ Object.create(null);
|
|
24979
25105
|
const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;
|
|
24980
25106
|
let match;
|
|
24981
25107
|
while (match = tokensRE.exec(str5)) {
|
|
24982
|
-
|
|
25108
|
+
tokens2[match[1]] = match[2];
|
|
24983
25109
|
}
|
|
24984
|
-
return
|
|
25110
|
+
return tokens2;
|
|
24985
25111
|
}
|
|
24986
25112
|
var isValidHeaderName = (str5) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str5.trim());
|
|
24987
25113
|
function matchHeaderValue(context2, value2, header, filter, isHeaderNameFilter) {
|
|
@@ -166604,8 +166730,6 @@ async function prepareSessionFileRestore(input) {
|
|
|
166604
166730
|
}
|
|
166605
166731
|
if (input.fresh) issues.push(...saveIssues.map((i) => ({ ...i, phase: "restore", message: `\u539F\u6587\u4EF6\u5C1A\u672A\u4FDD\u5B58\uFF1A${i.message}` })));
|
|
166606
166732
|
const lines = ["# \u4F1A\u8BDD\u6587\u4EF6", "", "\u4EE5\u4E0B\u6587\u4EF6\u6765\u81EA\u672C\u4F1A\u8BDD\u7684\u6301\u4E45\u8BB0\u5F55\u3002\u5386\u53F2\u8F93\u5165\u6309\u7248\u672C\u4FDD\u7559\uFF1Boutputs \u662F\u6700\u8FD1\u4FDD\u5B58\u7684\u4EA7\u51FA\u3002", ""];
|
|
166607
|
-
let total = 0;
|
|
166608
|
-
const inlineMax = input.inlineMaxBytes ?? RESTORE_INLINE_MAX_BYTES;
|
|
166609
166733
|
const seen = /* @__PURE__ */ new Set();
|
|
166610
166734
|
const add = async (name, ref2, path40, replace2) => {
|
|
166611
166735
|
if (seen.has(path40)) return;
|
|
@@ -166615,12 +166739,9 @@ async function prepareSessionFileRestore(input) {
|
|
|
166615
166739
|
return;
|
|
166616
166740
|
}
|
|
166617
166741
|
try {
|
|
166618
|
-
if (Object.keys(restoreFiles).length >= RESTORE_MAX_FILES) throw new Error("\u8FD9\u4E00\u8F6E\u8981\u968F\u4EFB\u52A1\u5E26\u8FC7\u53BB\u7684\u6587\u4EF6\u592A\u591A\uFF0C\u5B83\u6CA1\u6392\u4E0A\uFF1B\u539F\u4EF6\u5728\u670D\u52A1\u7AEF\u5B8C\u597D\uFF0C\u53EF\u5728\u9879\u76EE\u300C\u76F8\u5173\u6587\u4EF6\u300D\u91CC\u6253\u5F00");
|
|
166619
166742
|
const bytes2 = await input.readBlob(ref2);
|
|
166620
|
-
if (total + bytes2.byteLength > inlineMax) throw new Error(`\u8FD9\u4E00\u8F6E\u968F\u4EFB\u52A1\u9001\u5230\u8FD0\u884C\u673A\u5668\u7684\u6587\u4EF6\u603B\u91CF\u5DF2\u6EE1 ${Math.round(inlineMax / 1024 / 1024)} MiB\uFF0C\u5B83\u8FD9\u6B21\u6CA1\u9001\u8FC7\u53BB\uFF1B\u539F\u4EF6\u5728\u670D\u52A1\u7AEF\u5B8C\u597D\uFF0C\u53EF\u5728\u9879\u76EE\u300C\u76F8\u5173\u6587\u4EF6\u300D\u91CC\u6253\u5F00`);
|
|
166621
166743
|
const hash3 = (0, import_node_crypto24.createHash)("sha256").update(bytes2).digest("hex");
|
|
166622
166744
|
if (hash3 !== ref2.replace(/^blob:/, "")) throw new Error("\u539F\u4EF6\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
166623
|
-
total += bytes2.byteLength;
|
|
166624
166745
|
restoreFiles[path40] = { contentBase64: Buffer.from(bytes2).toString("base64"), sha256: hash3, overwrite: replace2 };
|
|
166625
166746
|
lines.push(`- ${JSON.stringify(name)} \u2192 ${JSON.stringify(path40)}`);
|
|
166626
166747
|
} catch (error2) {
|
|
@@ -166652,17 +166773,14 @@ async function prepareSessionFileRestore(input) {
|
|
|
166652
166773
|
if (blocking.length) throw new ApiError(409, "CHAT_FILE_RESTORE_FAILED", `\u6587\u4EF6\u6062\u590D\u672A\u5B8C\u6210\uFF1A${blocking.map((i) => i.message).join("\uFF1B")}`);
|
|
166653
166774
|
return { restoreFiles, index: lines.join("\n") };
|
|
166654
166775
|
}
|
|
166655
|
-
var import_node_crypto24
|
|
166776
|
+
var import_node_crypto24;
|
|
166656
166777
|
var init_file_restore = __esm({
|
|
166657
166778
|
"../server/src/domains/chat-sessions/file-restore.ts"() {
|
|
166658
166779
|
"use strict";
|
|
166659
166780
|
import_node_crypto24 = require("node:crypto");
|
|
166660
|
-
init_src();
|
|
166661
166781
|
init_chat_attachment_files();
|
|
166662
166782
|
init_router();
|
|
166663
166783
|
init_persistent_files();
|
|
166664
|
-
RESTORE_INLINE_MAX_BYTES = FILE_TRANSFER_INPUT_MAX_BYTES;
|
|
166665
|
-
RESTORE_MAX_FILES = 500;
|
|
166666
166784
|
}
|
|
166667
166785
|
});
|
|
166668
166786
|
|
|
@@ -179356,20 +179474,20 @@ function knowledgeSearchTokenStream(value2) {
|
|
|
179356
179474
|
raw.push(token);
|
|
179357
179475
|
}
|
|
179358
179476
|
}
|
|
179359
|
-
const
|
|
179477
|
+
const tokens2 = [];
|
|
179360
179478
|
for (let index2 = 0; index2 < raw.length; index2++) {
|
|
179361
179479
|
const token = raw[index2];
|
|
179362
179480
|
const next = raw[index2 + 1];
|
|
179363
179481
|
const merged = new RegExp("^\\p{Script=Han}$", "u").test(token) && next && new RegExp("^\\p{Script=Han}$", "u").test(next) ? `${token}${next}` : token;
|
|
179364
179482
|
if (merged !== token) index2++;
|
|
179365
179483
|
if (LEXICAL_STOPWORDS.has(merged)) continue;
|
|
179366
|
-
|
|
179484
|
+
tokens2.push(merged);
|
|
179367
179485
|
const chars = [...merged];
|
|
179368
179486
|
if (new RegExp("^\\p{Script=Han}+$", "u").test(merged) && chars.length > 2) {
|
|
179369
|
-
for (let index3 = 0; index3 < chars.length - 1; index3++)
|
|
179487
|
+
for (let index3 = 0; index3 < chars.length - 1; index3++) tokens2.push(`${chars[index3]}${chars[index3 + 1]}`);
|
|
179370
179488
|
}
|
|
179371
179489
|
}
|
|
179372
|
-
return
|
|
179490
|
+
return tokens2;
|
|
179373
179491
|
}
|
|
179374
179492
|
function knowledgeSearchTerms(value2) {
|
|
179375
179493
|
return [...new Set(knowledgeSearchTokenStream(value2))];
|
|
@@ -179381,20 +179499,20 @@ function documentSearchTokens(chunk) {
|
|
|
179381
179499
|
[chunk.logicalPath, 2]
|
|
179382
179500
|
];
|
|
179383
179501
|
return fields.flatMap(([value2, repeats]) => {
|
|
179384
|
-
const
|
|
179385
|
-
return Array.from({ length: repeats }, () =>
|
|
179502
|
+
const tokens2 = knowledgeSearchTokenStream(value2);
|
|
179503
|
+
return Array.from({ length: repeats }, () => tokens2).flat();
|
|
179386
179504
|
});
|
|
179387
179505
|
}
|
|
179388
179506
|
function layeredSearchTokens(chunk, lexicalLayer) {
|
|
179389
179507
|
return lexicalLayer === "document" ? documentSearchTokens(chunk) : knowledgeSearchTokenStream(chunk.text);
|
|
179390
179508
|
}
|
|
179391
179509
|
function knowledgeSearchIndexFields(chunk, lexicalLayer) {
|
|
179392
|
-
const
|
|
179510
|
+
const tokens2 = layeredSearchTokens(chunk, lexicalLayer);
|
|
179393
179511
|
return {
|
|
179394
|
-
terms: [...new Set(
|
|
179512
|
+
terms: [...new Set(tokens2)],
|
|
179395
179513
|
lexicalIndexVersion: KNOWLEDGE_LEXICAL_INDEX_VERSION,
|
|
179396
179514
|
lexicalLayer,
|
|
179397
|
-
tokenCount:
|
|
179515
|
+
tokenCount: tokens2.length
|
|
179398
179516
|
};
|
|
179399
179517
|
}
|
|
179400
179518
|
function knowledgeSearchIndexEntries(input) {
|
|
@@ -179478,10 +179596,10 @@ function splitKnowledgeChunks(content3, maxChars = 1600) {
|
|
|
179478
179596
|
function scoreKnowledgeChunk(query, chunk, corpus) {
|
|
179479
179597
|
const queryTerms = knowledgeSearchTerms(query);
|
|
179480
179598
|
if (queryTerms.length === 0) return 0;
|
|
179481
|
-
const
|
|
179599
|
+
const tokens2 = layeredSearchTokens(chunk, chunk.lexicalLayer ?? "chunk");
|
|
179482
179600
|
const frequencies2 = /* @__PURE__ */ new Map();
|
|
179483
|
-
for (const token of
|
|
179484
|
-
const documentLength = chunk.tokenCount ??
|
|
179601
|
+
for (const token of tokens2) frequencies2.set(token, (frequencies2.get(token) ?? 0) + 1);
|
|
179602
|
+
const documentLength = chunk.tokenCount ?? tokens2.length;
|
|
179485
179603
|
const averageLength = Math.max(1, corpus.averageTokenCount);
|
|
179486
179604
|
const documentCount = Math.max(1, corpus.size);
|
|
179487
179605
|
const k1 = 1.2;
|
|
@@ -183308,7 +183426,7 @@ ${pointer}
|
|
|
183308
183426
|
var require_resolve_props = __commonJS({
|
|
183309
183427
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js"(exports2) {
|
|
183310
183428
|
"use strict";
|
|
183311
|
-
function resolveProps(
|
|
183429
|
+
function resolveProps(tokens2, { flow: flow3, indicator, next, offset, onError, parentIndent, startOnNewline }) {
|
|
183312
183430
|
let spaceBefore = false;
|
|
183313
183431
|
let atNewline = startOnNewline;
|
|
183314
183432
|
let hasSpace = startOnNewline;
|
|
@@ -183323,7 +183441,7 @@ var require_resolve_props = __commonJS({
|
|
|
183323
183441
|
let comma = null;
|
|
183324
183442
|
let found2 = null;
|
|
183325
183443
|
let start = null;
|
|
183326
|
-
for (const token of
|
|
183444
|
+
for (const token of tokens2) {
|
|
183327
183445
|
if (reqSpace) {
|
|
183328
183446
|
if (token.type !== "space" && token.type !== "newline" && token.type !== "comma")
|
|
183329
183447
|
onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -183414,7 +183532,7 @@ var require_resolve_props = __commonJS({
|
|
|
183414
183532
|
hasSpace = false;
|
|
183415
183533
|
}
|
|
183416
183534
|
}
|
|
183417
|
-
const last =
|
|
183535
|
+
const last = tokens2[tokens2.length - 1];
|
|
183418
183536
|
const end = last ? last.offset + last.source.length : offset;
|
|
183419
183537
|
if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) {
|
|
183420
183538
|
onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -184753,8 +184871,8 @@ ${cb}` : comment;
|
|
|
184753
184871
|
* @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
|
|
184754
184872
|
* @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
|
|
184755
184873
|
*/
|
|
184756
|
-
*compose(
|
|
184757
|
-
for (const token of
|
|
184874
|
+
*compose(tokens2, forceDoc = false, endOffset = -1) {
|
|
184875
|
+
for (const token of tokens2)
|
|
184758
184876
|
yield* this.next(token);
|
|
184759
184877
|
yield* this.end(forceDoc, endOffset);
|
|
184760
184878
|
}
|
|
@@ -192924,8 +193042,8 @@ var init_governance_service = __esm({
|
|
|
192924
193042
|
return false;
|
|
192925
193043
|
};
|
|
192926
193044
|
const addFragment = (source, content3) => {
|
|
192927
|
-
const
|
|
192928
|
-
if (usedTokens +
|
|
193045
|
+
const tokens2 = estimateKnowledgeTokens(content3);
|
|
193046
|
+
if (usedTokens + tokens2 > selectedPolicy.tokenBudget) return false;
|
|
192929
193047
|
const fragment = this.snapshot(ctx, "context_pack", content3, trustedProjectId, void 0);
|
|
192930
193048
|
snapshots2.push(fragment);
|
|
192931
193049
|
entries.push({
|
|
@@ -192941,12 +193059,12 @@ var init_governance_service = __esm({
|
|
|
192941
193059
|
...source.score !== void 0 ? { relevanceScore: source.score } : {},
|
|
192942
193060
|
...source.evidenceRole ? { evidenceRole: source.evidenceRole } : {},
|
|
192943
193061
|
contentHash: fragment.contentHash,
|
|
192944
|
-
tokenCount:
|
|
193062
|
+
tokenCount: tokens2,
|
|
192945
193063
|
ordinal: entries.length,
|
|
192946
193064
|
renderedFragmentRef: fragment.ref
|
|
192947
193065
|
});
|
|
192948
193066
|
fragments.push(content3);
|
|
192949
|
-
usedTokens +=
|
|
193067
|
+
usedTokens += tokens2;
|
|
192950
193068
|
return true;
|
|
192951
193069
|
};
|
|
192952
193070
|
const taskFacts = [...request2.facts];
|
|
@@ -203190,9 +203308,9 @@ function lexicalMatchRatio(query, value2) {
|
|
|
203190
203308
|
const actual = new Set(lexicalTerms(value2));
|
|
203191
203309
|
return expected.filter((term) => actual.has(term)).length / expected.length;
|
|
203192
203310
|
}
|
|
203193
|
-
function frequencies(
|
|
203311
|
+
function frequencies(tokens2) {
|
|
203194
203312
|
const values = /* @__PURE__ */ new Map();
|
|
203195
|
-
for (const token of
|
|
203313
|
+
for (const token of tokens2) values.set(token, (values.get(token) ?? 0) + 1);
|
|
203196
203314
|
return values;
|
|
203197
203315
|
}
|
|
203198
203316
|
function bm25Scores(query, documents, options = {}) {
|
|
@@ -203200,21 +203318,21 @@ function bm25Scores(query, documents, options = {}) {
|
|
|
203200
203318
|
const queryTokens = [...new Set(typeof query === "string" ? lexicalTerms(query) : query)];
|
|
203201
203319
|
if (queryTokens.length === 0) return documents.map(() => 0);
|
|
203202
203320
|
const tokenized = documents.map((document4) => lexicalTerms(document4));
|
|
203203
|
-
const averageLength = tokenized.reduce((total,
|
|
203321
|
+
const averageLength = tokenized.reduce((total, tokens2) => total + tokens2.length, 0) / Math.max(1, tokenized.length);
|
|
203204
203322
|
const documentFrequencies = /* @__PURE__ */ new Map();
|
|
203205
203323
|
for (const term of queryTokens) {
|
|
203206
|
-
documentFrequencies.set(term, tokenized.filter((
|
|
203324
|
+
documentFrequencies.set(term, tokenized.filter((tokens2) => tokens2.includes(term)).length);
|
|
203207
203325
|
}
|
|
203208
203326
|
const k1 = options.k1 ?? 1.2;
|
|
203209
203327
|
const b2 = options.b ?? 0.75;
|
|
203210
|
-
const raw = tokenized.map((
|
|
203211
|
-
const counts2 = frequencies(
|
|
203328
|
+
const raw = tokenized.map((tokens2) => {
|
|
203329
|
+
const counts2 = frequencies(tokens2);
|
|
203212
203330
|
return queryTokens.reduce((score, term) => {
|
|
203213
203331
|
const tf = counts2.get(term) ?? 0;
|
|
203214
203332
|
if (tf === 0) return score;
|
|
203215
203333
|
const df = documentFrequencies.get(term) ?? 0;
|
|
203216
203334
|
const idf = Math.log(1 + (documents.length - df + 0.5) / (df + 0.5));
|
|
203217
|
-
const lengthNormalization = 1 - b2 + b2 *
|
|
203335
|
+
const lengthNormalization = 1 - b2 + b2 * tokens2.length / Math.max(1, averageLength);
|
|
203218
203336
|
return score + idf * tf * (k1 + 1) / (tf + k1 * lengthNormalization);
|
|
203219
203337
|
}, 0);
|
|
203220
203338
|
});
|
|
@@ -207589,12 +207707,9 @@ async function startOasisServer(opts) {
|
|
|
207589
207707
|
}));
|
|
207590
207708
|
return;
|
|
207591
207709
|
}
|
|
207592
|
-
|
|
207593
|
-
|
|
207594
|
-
|
|
207595
|
-
url,
|
|
207596
|
-
await resolveEngine(company?.kind === "ok" ? company.companyId : void 0)
|
|
207597
|
-
);
|
|
207710
|
+
const companyId = company?.kind === "ok" ? company.companyId : void 0;
|
|
207711
|
+
const limits = await opts.fileLimits?.get(companyId) ?? DEFAULT_FILE_LIMITS;
|
|
207712
|
+
await withFileLimits(limits, async () => serveFileRequest(req, res, url, await resolveEngine(companyId)));
|
|
207598
207713
|
return;
|
|
207599
207714
|
}
|
|
207600
207715
|
if (url.pathname === "/api/whoami" && req.method === "GET") {
|
|
@@ -207621,17 +207736,18 @@ async function startOasisServer(opts) {
|
|
|
207621
207736
|
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
207622
207737
|
const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
|
|
207623
207738
|
const fileLimits = await opts.fileLimits?.get(currentCompanyId) ?? { ...DEFAULT_FILE_LIMITS };
|
|
207739
|
+
const requestMaxBytes = fileUploadRequestMaxBytes(fileLimits);
|
|
207624
207740
|
const chunks = [];
|
|
207625
207741
|
let requestBytes = 0;
|
|
207626
207742
|
const declared = Number(req.headers["content-length"] ?? 0);
|
|
207627
|
-
if (declared >
|
|
207743
|
+
if (declared > requestMaxBytes) {
|
|
207628
207744
|
req.resume();
|
|
207629
207745
|
res.writeHead(413, { "content-type": "application/json" }).end(JSON.stringify({ error: { code: "UPLOAD_TOO_LARGE", message: "\u4E0A\u4F20\u8BF7\u6C42\u8D85\u8FC7\u901A\u9053\u5BB9\u91CF" } }));
|
|
207630
207746
|
return;
|
|
207631
207747
|
}
|
|
207632
207748
|
for await (const chunk of req) {
|
|
207633
207749
|
requestBytes += chunk.length;
|
|
207634
|
-
if (requestBytes >
|
|
207750
|
+
if (requestBytes > requestMaxBytes) {
|
|
207635
207751
|
res.writeHead(413, { "content-type": "application/json" }).end(JSON.stringify({ error: { code: "UPLOAD_TOO_LARGE", message: "\u4E0A\u4F20\u8BF7\u6C42\u8D85\u8FC7\u901A\u9053\u5BB9\u91CF" } }));
|
|
207636
207752
|
return;
|
|
207637
207753
|
}
|
|
@@ -207658,9 +207774,9 @@ async function startOasisServer(opts) {
|
|
|
207658
207774
|
return;
|
|
207659
207775
|
}
|
|
207660
207776
|
await opts.fileLimits.put(currentCompanyId, limits);
|
|
207661
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits,
|
|
207777
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits, canManage }));
|
|
207662
207778
|
} else {
|
|
207663
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits: fileLimits,
|
|
207779
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits: fileLimits, canManage }));
|
|
207664
207780
|
}
|
|
207665
207781
|
return;
|
|
207666
207782
|
}
|
|
@@ -221679,6 +221795,15 @@ var init_handshake_throttle = __esm({
|
|
|
221679
221795
|
});
|
|
221680
221796
|
|
|
221681
221797
|
// ../server/src/daemon-hub.ts
|
|
221798
|
+
function legacyMessage(msg, maxBytes = FILE_TRANSFER_MAX_BYTES) {
|
|
221799
|
+
try {
|
|
221800
|
+
const json = JSON.stringify(msg);
|
|
221801
|
+
if (Buffer.byteLength(json) <= maxBytes) return json;
|
|
221802
|
+
} catch (error2) {
|
|
221803
|
+
if (!(error2 instanceof RangeError)) throw error2;
|
|
221804
|
+
}
|
|
221805
|
+
throw new Error("\u5F53\u524D\u6267\u884C\u8282\u70B9\u6216\u4F1A\u8BDD\u4E0D\u652F\u6301\u5927\u6587\u4EF6\u5206\u5757\u4F20\u8F93\uFF0C\u8BF7\u5347\u7EA7\u8282\u70B9\u5E76\u91CD\u65B0\u5F00\u59CB\u672C\u8F6E\u5BF9\u8BDD");
|
|
221806
|
+
}
|
|
221682
221807
|
function clientIpOf(req) {
|
|
221683
221808
|
const fwd = req.headers["x-forwarded-for"];
|
|
221684
221809
|
const raw = Array.isArray(fwd) ? fwd[0] : fwd;
|
|
@@ -221941,11 +222066,15 @@ var init_daemon_hub = __esm({
|
|
|
221941
222066
|
handleSessionConnection(ws, auth) {
|
|
221942
222067
|
const { nodeId, dispatchId } = auth;
|
|
221943
222068
|
let registered = false;
|
|
222069
|
+
const decoder = new ChunkedMessageDecoder();
|
|
221944
222070
|
ws.on("message", (raw) => {
|
|
221945
222071
|
let msg;
|
|
221946
222072
|
try {
|
|
221947
|
-
|
|
222073
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222074
|
+
if (decoded === void 0) return;
|
|
222075
|
+
msg = decoded;
|
|
221948
222076
|
} catch {
|
|
222077
|
+
ws.close(1007, "Invalid message framing");
|
|
221949
222078
|
return;
|
|
221950
222079
|
}
|
|
221951
222080
|
if (msg.type === "session_hello") {
|
|
@@ -221962,6 +222091,7 @@ var init_daemon_hub = __esm({
|
|
|
221962
222091
|
sessionId: msg.sessionId,
|
|
221963
222092
|
connectedAt: Date.now(),
|
|
221964
222093
|
supportsInputConsumptionReceipts: msg.supportsInputConsumptionReceipts === true,
|
|
222094
|
+
supportsChunkedMessages: msg.supportsChunkedMessages === true,
|
|
221965
222095
|
...msg.jobArtifactId ? { jobArtifactId: msg.jobArtifactId } : {}
|
|
221966
222096
|
});
|
|
221967
222097
|
for (const l of this.sessionConnectListeners) l({ dispatchId, sessionId: msg.sessionId, nodeId });
|
|
@@ -222158,7 +222288,7 @@ var init_daemon_hub = __esm({
|
|
|
222158
222288
|
sendToSession(dispatchId, msg) {
|
|
222159
222289
|
const ws = this.sessionSockets.get(dispatchId);
|
|
222160
222290
|
if (!ws || ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222161
|
-
|
|
222291
|
+
for (const frame of this.sessionMeta.get(dispatchId)?.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg, 100 * MIB)]) ws.send(frame);
|
|
222162
222292
|
return true;
|
|
222163
222293
|
}
|
|
222164
222294
|
/**
|
|
@@ -222219,16 +222349,20 @@ var init_daemon_hub = __esm({
|
|
|
222219
222349
|
sourceIp: clientIpOf(req),
|
|
222220
222350
|
send: (msg) => {
|
|
222221
222351
|
if (ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222222
|
-
|
|
222352
|
+
for (const frame of daemon.meta.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg)]) ws.send(frame);
|
|
222223
222353
|
return true;
|
|
222224
222354
|
},
|
|
222225
222355
|
close: () => ws.close()
|
|
222226
222356
|
};
|
|
222357
|
+
const decoder = new ChunkedMessageDecoder();
|
|
222227
222358
|
ws.on("message", (raw) => {
|
|
222228
222359
|
let msg;
|
|
222229
222360
|
try {
|
|
222230
|
-
|
|
222361
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222362
|
+
if (decoded === void 0) return;
|
|
222363
|
+
msg = decoded;
|
|
222231
222364
|
} catch {
|
|
222365
|
+
ws.close(1007, "Invalid message framing");
|
|
222232
222366
|
return;
|
|
222233
222367
|
}
|
|
222234
222368
|
this.lastSeen.set(daemonId, Date.now());
|
|
@@ -222266,7 +222400,7 @@ var init_daemon_hub = __esm({
|
|
|
222266
222400
|
ws.on("error", (err) => {
|
|
222267
222401
|
console.error(`[hub] daemon ${daemonId} error:`, err.message);
|
|
222268
222402
|
});
|
|
222269
|
-
daemon.send({ type: "ping" });
|
|
222403
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222270
222404
|
}
|
|
222271
222405
|
/**
|
|
222272
222406
|
* 周期性活性 sweep:
|
|
@@ -222289,7 +222423,7 @@ var init_daemon_hub = __esm({
|
|
|
222289
222423
|
this.sockets.get(id)?.terminate();
|
|
222290
222424
|
continue;
|
|
222291
222425
|
}
|
|
222292
|
-
daemon.send({ type: "ping" });
|
|
222426
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222293
222427
|
}
|
|
222294
222428
|
}
|
|
222295
222429
|
/** 关闭 hub:停 liveness 定时器并断开所有 daemon。serve 关停时调用。 */
|
|
@@ -222547,17 +222681,11 @@ var init_skill_fetcher = __esm({
|
|
|
222547
222681
|
SKILL_DESCRIPTION_MAX = 600;
|
|
222548
222682
|
Bundle = class {
|
|
222549
222683
|
files = {};
|
|
222550
|
-
totalBytes = 0;
|
|
222551
|
-
fileCount = 0;
|
|
222552
222684
|
add(path40, content3) {
|
|
222553
222685
|
const bytes2 = new TextEncoder().encode(content3).length;
|
|
222554
|
-
if (
|
|
222555
|
-
throw new Error(`
|
|
222556
|
-
if (this.totalBytes + bytes2 > currentFileLimits().skillBundleBytes)
|
|
222557
|
-
throw new Error(`Import bundle exceeds ${currentFileLimits().skillBundleBytes} byte limit`);
|
|
222686
|
+
if (bytes2 > currentFileLimits().skillFileBytes)
|
|
222687
|
+
throw new Error(`Skill file exceeds ${currentFileLimits().skillFileBytes} byte limit: ${path40}`);
|
|
222558
222688
|
this.files[path40] = content3;
|
|
222559
|
-
this.totalBytes += bytes2;
|
|
222560
|
-
this.fileCount++;
|
|
222561
222689
|
}
|
|
222562
222690
|
};
|
|
222563
222691
|
}
|
|
@@ -223330,7 +223458,7 @@ ${input.description}
|
|
|
223330
223458
|
const file = this.buildSkillFile(skillId, path40, content3, now);
|
|
223331
223459
|
const existing = await this.opts.store.listSkillFiles(skillId);
|
|
223332
223460
|
const next = [...existing.filter((f2) => f2.path !== path40), file];
|
|
223333
|
-
assertSkillFileLimits(
|
|
223461
|
+
assertSkillFileLimits([file]);
|
|
223334
223462
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
223335
223463
|
if (path40 === "SKILL.md") {
|
|
223336
223464
|
const { name, description } = parseSkillFrontmatter(content3);
|
|
@@ -224379,17 +224507,14 @@ function unpackSkillBundle(bytes2) {
|
|
|
224379
224507
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u7F3A\u5C11 files \u5BF9\u8C61");
|
|
224380
224508
|
}
|
|
224381
224509
|
const out = [];
|
|
224382
|
-
let total = 0;
|
|
224383
224510
|
for (const [path40, content3] of Object.entries(files)) {
|
|
224384
224511
|
if (typeof content3 !== "string") throw new SkillPackageInvalidError(`\u6587\u4EF6 ${path40} \u4E0D\u662F\u6587\u672C`);
|
|
224385
224512
|
if (!isCanonicalRelativePath(path40)) throw new SkillPackageInvalidError(`\u975E\u6CD5\u6280\u80FD\u6587\u4EF6\u8DEF\u5F84\uFF1A${path40}`);
|
|
224386
224513
|
const size = Buffer.byteLength(content3, "utf8");
|
|
224387
224514
|
if (size > currentFileLimits().skillFileBytes) throw new SkillPackageInvalidError(`\u6587\u4EF6\u8FC7\u5927\uFF1A${path40}`);
|
|
224388
|
-
total += size;
|
|
224389
|
-
if (total > currentFileLimits().skillBundleBytes) throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u603B\u5927\u5C0F\u8D85\u9650");
|
|
224390
224515
|
out.push({ path: path40, content: content3 });
|
|
224391
224516
|
}
|
|
224392
|
-
if (out.length === 0
|
|
224517
|
+
if (out.length === 0) {
|
|
224393
224518
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u6587\u4EF6\u6570\u91CF\u975E\u6CD5");
|
|
224394
224519
|
}
|
|
224395
224520
|
if (!out.some((f2) => f2.path === "SKILL.md")) {
|
|
@@ -240049,7 +240174,7 @@ function createChatSessionsDomain(opts) {
|
|
|
240049
240174
|
const outcome = await bridge.read(
|
|
240050
240175
|
loc.nodeId,
|
|
240051
240176
|
{ workdirKey: loc.workdirKey, runtimeKind: loc.runtimeKind, rtId: loc.rtId, path: req.query?.get("path") ?? "" },
|
|
240052
|
-
|
|
240177
|
+
currentFileReadMaxBytes()
|
|
240053
240178
|
);
|
|
240054
240179
|
if (outcome.ok) {
|
|
240055
240180
|
const buf = Buffer.from(outcome.contentBase64, "base64");
|
|
@@ -244477,7 +244602,13 @@ var init_daemon_adapter = __esm({
|
|
|
244477
244602
|
};
|
|
244478
244603
|
this.pending.set(dispatchId, entry);
|
|
244479
244604
|
const sessionAuth = this.sessionAuth ? { ...this.sessionAuth.issue({ nodeId, dispatchId }), gatewayUrl: this.sessionAuth.gatewayUrl } : void 0;
|
|
244480
|
-
|
|
244605
|
+
let sent;
|
|
244606
|
+
try {
|
|
244607
|
+
sent = this.hub.dispatch(nodeId, { type: "dispatch", dispatchId, job, ...sessionAuth ? { sessionAuth } : {} });
|
|
244608
|
+
} catch (error2) {
|
|
244609
|
+
this.pending.delete(dispatchId);
|
|
244610
|
+
throw error2;
|
|
244611
|
+
}
|
|
244481
244612
|
if (!sent) {
|
|
244482
244613
|
queueMicrotask(() => this.settle(dispatchId, { code: null, reason: "server-unreachable", errorMessage: `\u6D3E\u53D1\u65F6\u8282\u70B9 ${nodeId} \u4E0D\u5728\u7EBF\uFF08socket \u975E OPEN\uFF09\uFF0C\u5E27\u672A\u9001\u8FBE` }));
|
|
244483
244614
|
} else if (this.ackTimeoutMs > 0) {
|
|
@@ -263233,6 +263364,7 @@ var init_trajectory = __esm({
|
|
|
263233
263364
|
|
|
263234
263365
|
// src/index.ts
|
|
263235
263366
|
var fs44 = __toESM(require("node:fs"));
|
|
263367
|
+
init_src();
|
|
263236
263368
|
var os14 = __toESM(require("node:os"));
|
|
263237
263369
|
var path39 = __toESM(require("node:path"));
|
|
263238
263370
|
var import_node_child_process22 = require("node:child_process");
|
|
@@ -271572,6 +271704,7 @@ var SessionManager = class {
|
|
|
271572
271704
|
// ../cli/src/daemon/session-process.ts
|
|
271573
271705
|
var fs35 = __toESM(require("node:fs"), 1);
|
|
271574
271706
|
var path30 = __toESM(require("node:path"), 1);
|
|
271707
|
+
var import_node_readline = require("node:readline");
|
|
271575
271708
|
init_wrapper();
|
|
271576
271709
|
init_src();
|
|
271577
271710
|
|
|
@@ -271754,7 +271887,7 @@ var OUTBOX_MAX_FRAMES = 8e3;
|
|
|
271754
271887
|
var isKeyFrame = (m2) => m2.type === "session_started" || m2.type === "session_exited";
|
|
271755
271888
|
async function runSessionProcess(specFile, adapter) {
|
|
271756
271889
|
process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] = "1";
|
|
271757
|
-
const spec = readSpec(specFile);
|
|
271890
|
+
const spec = await readSpec(specFile);
|
|
271758
271891
|
const { dispatchId, job, auth, sessionDir } = spec;
|
|
271759
271892
|
const lock = acquireSessionLock(path30.join(sessionDir, "lock"));
|
|
271760
271893
|
if (!lock && hasFlock()) {
|
|
@@ -271767,13 +271900,24 @@ async function runSessionProcess(specFile, adapter) {
|
|
|
271767
271900
|
const state = new SessionProcessState(spec, adapter, lock);
|
|
271768
271901
|
await state.run();
|
|
271769
271902
|
}
|
|
271770
|
-
function readSpec(specFile) {
|
|
271771
|
-
const
|
|
271903
|
+
async function readSpec(specFile) {
|
|
271904
|
+
const decoder = new ChunkedMessageDecoder();
|
|
271905
|
+
const source = fs35.createReadStream(specFile, { encoding: "utf8" });
|
|
271906
|
+
const lines = (0, import_node_readline.createInterface)({ input: source, crlfDelay: Infinity });
|
|
271772
271907
|
try {
|
|
271773
|
-
|
|
271774
|
-
|
|
271908
|
+
for await (const line of lines) {
|
|
271909
|
+
const spec = decoder.accept(JSON.parse(line));
|
|
271910
|
+
if (spec !== void 0) return spec;
|
|
271911
|
+
}
|
|
271912
|
+
throw new Error("Incomplete session specification");
|
|
271913
|
+
} finally {
|
|
271914
|
+
lines.close();
|
|
271915
|
+
source.destroy();
|
|
271916
|
+
try {
|
|
271917
|
+
fs35.unlinkSync(specFile);
|
|
271918
|
+
} catch {
|
|
271919
|
+
}
|
|
271775
271920
|
}
|
|
271776
|
-
return spec;
|
|
271777
271921
|
}
|
|
271778
271922
|
var SessionProcessState = class {
|
|
271779
271923
|
constructor(spec, adapter, lock) {
|
|
@@ -271880,16 +272024,21 @@ var SessionProcessState = class {
|
|
|
271880
272024
|
...this.spec.job.artifactId ? { jobArtifactId: this.spec.job.artifactId } : {},
|
|
271881
272025
|
// ADR 0300 D2:自报支持帧号;新服务端据此回带 ackSeq 的 hello-ack,届时才把 serverSupportsDedup 置真。
|
|
271882
272026
|
supportsFrameSeq: true,
|
|
272027
|
+
supportsChunkedMessages: true,
|
|
271883
272028
|
supportsInputConsumptionReceipts: true
|
|
271884
272029
|
});
|
|
271885
272030
|
const toResend = this.serverSupportsDedup ? this.outbox : this.outbox.filter(isKeyFrame);
|
|
271886
272031
|
for (const m2 of toResend) this.rawSend(m2);
|
|
271887
272032
|
});
|
|
272033
|
+
const decoder = new ChunkedMessageDecoder();
|
|
271888
272034
|
ws.on("message", (raw) => {
|
|
271889
272035
|
let msg;
|
|
271890
272036
|
try {
|
|
271891
|
-
|
|
272037
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272038
|
+
if (decoded === void 0) return;
|
|
272039
|
+
msg = decoded;
|
|
271892
272040
|
} catch {
|
|
272041
|
+
ws.close(1007, "Invalid message framing");
|
|
271893
272042
|
return;
|
|
271894
272043
|
}
|
|
271895
272044
|
void this.onServerMessage(msg);
|
|
@@ -272576,6 +272725,7 @@ var DaemonWsClient = class {
|
|
|
272576
272725
|
else log2("[node-cli]", "\u505C\u673A\u6392\u7A7A\u5B8C\u6210\uFF1A\u5728\u9014\u4F1A\u8BDD\u7684\u9000\u51FA\u5E27\u5747\u5DF2\u786E\u8BA4\u9001\u8FBE");
|
|
272577
272726
|
this.stop();
|
|
272578
272727
|
}
|
|
272728
|
+
serverSupportsChunkedMessages = false;
|
|
272579
272729
|
connect() {
|
|
272580
272730
|
if (this.stopped) return;
|
|
272581
272731
|
const ws = new import_websocket.default(this.serverUrl, {
|
|
@@ -272589,6 +272739,7 @@ var DaemonWsClient = class {
|
|
|
272589
272739
|
handshakeTimeout: this.handshakeTimeoutMs
|
|
272590
272740
|
});
|
|
272591
272741
|
this.ws = ws;
|
|
272742
|
+
this.serverSupportsChunkedMessages = false;
|
|
272592
272743
|
ws.on("open", () => {
|
|
272593
272744
|
log2("[node-cli]", `connected id=${this.daemonId}`);
|
|
272594
272745
|
this.authRejectStreak = 0;
|
|
@@ -272606,12 +272757,16 @@ var DaemonWsClient = class {
|
|
|
272606
272757
|
}
|
|
272607
272758
|
}, this.pingIntervalMs);
|
|
272608
272759
|
});
|
|
272760
|
+
const decoder = new ChunkedMessageDecoder();
|
|
272609
272761
|
ws.on("message", (raw) => {
|
|
272610
272762
|
this.lastReceivedAt = Date.now();
|
|
272611
272763
|
let msg;
|
|
272612
272764
|
try {
|
|
272613
|
-
|
|
272765
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272766
|
+
if (decoded === void 0) return;
|
|
272767
|
+
msg = decoded;
|
|
272614
272768
|
} catch {
|
|
272769
|
+
ws.close(1007, "Invalid message framing");
|
|
272615
272770
|
return;
|
|
272616
272771
|
}
|
|
272617
272772
|
void this.handleMessage(msg);
|
|
@@ -272728,6 +272883,7 @@ var DaemonWsClient = class {
|
|
|
272728
272883
|
break;
|
|
272729
272884
|
}
|
|
272730
272885
|
case "ping":
|
|
272886
|
+
this.serverSupportsChunkedMessages = msg.supportsChunkedMessages === true;
|
|
272731
272887
|
this.send({ type: "pong" });
|
|
272732
272888
|
break;
|
|
272733
272889
|
case "ack":
|
|
@@ -272833,7 +272989,9 @@ var DaemonWsClient = class {
|
|
|
272833
272989
|
});
|
|
272834
272990
|
}
|
|
272835
272991
|
send(msg) {
|
|
272836
|
-
if (this.ws?.readyState === import_websocket.default.OPEN)
|
|
272992
|
+
if (this.ws?.readyState === import_websocket.default.OPEN) {
|
|
272993
|
+
for (const frame of this.serverSupportsChunkedMessages && msg.type === "workdir_read_result" ? encodeChunkedMessage(msg) : [JSON.stringify(msg)]) this.ws.send(frame);
|
|
272994
|
+
}
|
|
272837
272995
|
}
|
|
272838
272996
|
/**
|
|
272839
272997
|
* 待补发流帧数(观测/测试用)。
|
|
@@ -272958,6 +273116,7 @@ var DaemonWsClient = class {
|
|
|
272958
273116
|
// ADR 0554:本 daemon 认 `workdir_walk`。恒 true——handler 随包发,装了这版就一定有。
|
|
272959
273117
|
supportsWorkdirWalk: true,
|
|
272960
273118
|
supportsFileRestore: true,
|
|
273119
|
+
supportsChunkedMessages: true,
|
|
272961
273120
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
272962
273121
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
272963
273122
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -277580,8 +277739,6 @@ ${res.warning}`);
|
|
|
277580
277739
|
const SKIP2 = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store"]);
|
|
277581
277740
|
const limits = await loadFileLimits();
|
|
277582
277741
|
const MAX_FILE_BYTES3 = limits.skillFileBytes;
|
|
277583
|
-
const MAX_FILE_COUNT = limits.skillFileCount;
|
|
277584
|
-
let totalBytes = 0;
|
|
277585
277742
|
const local = {};
|
|
277586
277743
|
const binary = [];
|
|
277587
277744
|
const walk = (abs, rel) => {
|
|
@@ -277595,8 +277752,6 @@ ${res.warning}`);
|
|
|
277595
277752
|
}
|
|
277596
277753
|
const size = fs39.statSync(childAbs).size;
|
|
277597
277754
|
if (size > MAX_FILE_BYTES3) throw new Error(`\u6280\u80FD\u6587\u4EF6\u8D85\u8FC7 ${MAX_FILE_BYTES3 / 1024 / 1024} MiB\uFF1A${childRel}`);
|
|
277598
|
-
totalBytes += size;
|
|
277599
|
-
if (totalBytes > limits.skillBundleBytes) throw new Error(`\u6280\u80FD\u6574\u5305\u8D85\u8FC7 ${limits.skillBundleBytes / 1024 / 1024} MiB`);
|
|
277600
277755
|
const buf = fs39.readFileSync(childAbs);
|
|
277601
277756
|
if (buf.includes(0)) {
|
|
277602
277757
|
binary.push(childRel);
|
|
@@ -277612,7 +277767,6 @@ ${res.warning}`);
|
|
|
277612
277767
|
}
|
|
277613
277768
|
const paths = Object.keys(local);
|
|
277614
277769
|
if (paths.length === 0) throw new Error(`\u76EE\u5F55\u91CC\u6CA1\u6709\u53EF\u4E0A\u4F20\u7684\u6587\u4EF6\uFF1A${dir2}`);
|
|
277615
|
-
if (paths.length > MAX_FILE_COUNT) throw new Error(`\u6280\u80FD\u6587\u4EF6\u6570\u8D85\u8FC7 ${MAX_FILE_COUNT} \u4E2A\uFF1A${paths.length}`);
|
|
277616
277770
|
const skillMd = local["SKILL.md"];
|
|
277617
277771
|
if (skillMd === void 0) {
|
|
277618
277772
|
throw new Error(`${dir2} \u6839\u76EE\u5F55\u4E0B\u6CA1\u6709 SKILL.md\u2014\u2014\u6280\u80FD\u5FC5\u987B\u6709\u5B83\uFF08frontmatter \u5199 name \u548C description\uFF0C\u6B63\u6587\u5199\u505A\u6CD5\uFF09\u3002`);
|
|
@@ -278883,7 +279037,7 @@ function shimScript() {
|
|
|
278883
279037
|
}
|
|
278884
279038
|
|
|
278885
279039
|
// src/index.ts
|
|
278886
|
-
var PKG_VERSION = true ? "2.2.
|
|
279040
|
+
var PKG_VERSION = true ? "2.2.47" : "dev";
|
|
278887
279041
|
var LOCAL_BIN = localBin();
|
|
278888
279042
|
var NPM_PREFIX = npmPrefix();
|
|
278889
279043
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -279294,13 +279448,19 @@ function spawnSessionProcess(spec) {
|
|
|
279294
279448
|
fs44.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
279295
279449
|
const specFile = path39.join(dir, "spec.json");
|
|
279296
279450
|
const cfg = readConfig();
|
|
279297
|
-
fs44.
|
|
279298
|
-
|
|
279299
|
-
|
|
279300
|
-
|
|
279301
|
-
|
|
279302
|
-
|
|
279303
|
-
|
|
279451
|
+
const fd = fs44.openSync(specFile, "w", 384);
|
|
279452
|
+
try {
|
|
279453
|
+
for (const frame of encodeChunkedMessage({
|
|
279454
|
+
...spec,
|
|
279455
|
+
sessionDir: dir,
|
|
279456
|
+
nodeId: cfg?.nodeId ?? INSTANCE,
|
|
279457
|
+
daemonVersion: PKG_VERSION,
|
|
279458
|
+
daemonPkg: PKG_NAME
|
|
279459
|
+
})) fs44.writeFileSync(fd, `${frame}
|
|
279460
|
+
`);
|
|
279461
|
+
} finally {
|
|
279462
|
+
fs44.closeSync(fd);
|
|
279463
|
+
}
|
|
279304
279464
|
let pinnedDir = INST.currentLink;
|
|
279305
279465
|
try {
|
|
279306
279466
|
pinnedDir = fs44.realpathSync(INST.currentLink);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.47",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "98d67615dd3606fcebb19d6561d2a5e7abe5ae31"
|
|
30
30
|
}
|
|
31
31
|
}
|