oasis_test_v2 2.2.45 → 2.2.46
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 +282 -123
- 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
|
}
|
|
@@ -10140,14 +10265,14 @@ function accountUsage(model, usage) {
|
|
|
10140
10265
|
const input = nonNegative(usage.inputTokens);
|
|
10141
10266
|
const output = nonNegative(usage.outputTokens);
|
|
10142
10267
|
const cache = nonNegative(usage.cacheReadTokens) + nonNegative(usage.cacheCreationTokens);
|
|
10143
|
-
const
|
|
10268
|
+
const tokens2 = { input, cache, output, total: input + cache + output };
|
|
10144
10269
|
const estimated = estimateUsageCostBreakdown(resolved, usage);
|
|
10145
10270
|
const weights = estimated ? { input: estimated.inputMicros, cache: estimated.cacheMicros, output: estimated.outputMicros } : null;
|
|
10146
10271
|
const reported = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
10147
10272
|
if (reported > 0) {
|
|
10148
10273
|
const parts = weights && estimated?.currency === "USD" ? splitByWeight(reported, weights) : { input: 0, cache: 0, output: reported };
|
|
10149
10274
|
return {
|
|
10150
|
-
tokens,
|
|
10275
|
+
tokens: tokens2,
|
|
10151
10276
|
currency: "USD",
|
|
10152
10277
|
amountMicros: reported,
|
|
10153
10278
|
parts,
|
|
@@ -10160,7 +10285,7 @@ function accountUsage(model, usage) {
|
|
|
10160
10285
|
const amount = weights.input + weights.cache + weights.output;
|
|
10161
10286
|
const displayUsdMicros = toDisplayUsd(estimated.currency, amount);
|
|
10162
10287
|
return {
|
|
10163
|
-
tokens,
|
|
10288
|
+
tokens: tokens2,
|
|
10164
10289
|
currency: estimated.currency,
|
|
10165
10290
|
amountMicros: amount,
|
|
10166
10291
|
parts: weights,
|
|
@@ -10170,7 +10295,7 @@ function accountUsage(model, usage) {
|
|
|
10170
10295
|
};
|
|
10171
10296
|
}
|
|
10172
10297
|
return {
|
|
10173
|
-
tokens,
|
|
10298
|
+
tokens: tokens2,
|
|
10174
10299
|
currency: "USD",
|
|
10175
10300
|
amountMicros: 0,
|
|
10176
10301
|
parts: { input: 0, cache: 0, output: 0 },
|
|
@@ -10195,8 +10320,8 @@ function estimateSubagentCostUsdMicros(usage) {
|
|
|
10195
10320
|
const models = Object.entries(usage.byModel);
|
|
10196
10321
|
if (models.length === 0) return void 0;
|
|
10197
10322
|
let total = 0;
|
|
10198
|
-
for (const [model,
|
|
10199
|
-
const account = accountUsage(model, { ...
|
|
10323
|
+
for (const [model, tokens2] of models) {
|
|
10324
|
+
const account = accountUsage(model, { ...tokens2, costUsdMicros: null });
|
|
10200
10325
|
if (!account || account.source !== "estimated") return void 0;
|
|
10201
10326
|
total += account.displayUsdMicros;
|
|
10202
10327
|
}
|
|
@@ -24975,13 +25100,13 @@ var require_axios = __commonJS({
|
|
|
24975
25100
|
return utils$1.isArray(value2) ? value2.map(normalizeValue) : String(value2);
|
|
24976
25101
|
}
|
|
24977
25102
|
function parseTokens(str5) {
|
|
24978
|
-
const
|
|
25103
|
+
const tokens2 = /* @__PURE__ */ Object.create(null);
|
|
24979
25104
|
const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;
|
|
24980
25105
|
let match;
|
|
24981
25106
|
while (match = tokensRE.exec(str5)) {
|
|
24982
|
-
|
|
25107
|
+
tokens2[match[1]] = match[2];
|
|
24983
25108
|
}
|
|
24984
|
-
return
|
|
25109
|
+
return tokens2;
|
|
24985
25110
|
}
|
|
24986
25111
|
var isValidHeaderName = (str5) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str5.trim());
|
|
24987
25112
|
function matchHeaderValue(context2, value2, header, filter, isHeaderNameFilter) {
|
|
@@ -166604,8 +166729,6 @@ async function prepareSessionFileRestore(input) {
|
|
|
166604
166729
|
}
|
|
166605
166730
|
if (input.fresh) issues.push(...saveIssues.map((i) => ({ ...i, phase: "restore", message: `\u539F\u6587\u4EF6\u5C1A\u672A\u4FDD\u5B58\uFF1A${i.message}` })));
|
|
166606
166731
|
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
166732
|
const seen = /* @__PURE__ */ new Set();
|
|
166610
166733
|
const add = async (name, ref2, path40, replace2) => {
|
|
166611
166734
|
if (seen.has(path40)) return;
|
|
@@ -166615,12 +166738,9 @@ async function prepareSessionFileRestore(input) {
|
|
|
166615
166738
|
return;
|
|
166616
166739
|
}
|
|
166617
166740
|
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
166741
|
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
166742
|
const hash3 = (0, import_node_crypto24.createHash)("sha256").update(bytes2).digest("hex");
|
|
166622
166743
|
if (hash3 !== ref2.replace(/^blob:/, "")) throw new Error("\u539F\u4EF6\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
166623
|
-
total += bytes2.byteLength;
|
|
166624
166744
|
restoreFiles[path40] = { contentBase64: Buffer.from(bytes2).toString("base64"), sha256: hash3, overwrite: replace2 };
|
|
166625
166745
|
lines.push(`- ${JSON.stringify(name)} \u2192 ${JSON.stringify(path40)}`);
|
|
166626
166746
|
} catch (error2) {
|
|
@@ -166652,17 +166772,14 @@ async function prepareSessionFileRestore(input) {
|
|
|
166652
166772
|
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
166773
|
return { restoreFiles, index: lines.join("\n") };
|
|
166654
166774
|
}
|
|
166655
|
-
var import_node_crypto24
|
|
166775
|
+
var import_node_crypto24;
|
|
166656
166776
|
var init_file_restore = __esm({
|
|
166657
166777
|
"../server/src/domains/chat-sessions/file-restore.ts"() {
|
|
166658
166778
|
"use strict";
|
|
166659
166779
|
import_node_crypto24 = require("node:crypto");
|
|
166660
|
-
init_src();
|
|
166661
166780
|
init_chat_attachment_files();
|
|
166662
166781
|
init_router();
|
|
166663
166782
|
init_persistent_files();
|
|
166664
|
-
RESTORE_INLINE_MAX_BYTES = FILE_TRANSFER_INPUT_MAX_BYTES;
|
|
166665
|
-
RESTORE_MAX_FILES = 500;
|
|
166666
166783
|
}
|
|
166667
166784
|
});
|
|
166668
166785
|
|
|
@@ -179356,20 +179473,20 @@ function knowledgeSearchTokenStream(value2) {
|
|
|
179356
179473
|
raw.push(token);
|
|
179357
179474
|
}
|
|
179358
179475
|
}
|
|
179359
|
-
const
|
|
179476
|
+
const tokens2 = [];
|
|
179360
179477
|
for (let index2 = 0; index2 < raw.length; index2++) {
|
|
179361
179478
|
const token = raw[index2];
|
|
179362
179479
|
const next = raw[index2 + 1];
|
|
179363
179480
|
const merged = new RegExp("^\\p{Script=Han}$", "u").test(token) && next && new RegExp("^\\p{Script=Han}$", "u").test(next) ? `${token}${next}` : token;
|
|
179364
179481
|
if (merged !== token) index2++;
|
|
179365
179482
|
if (LEXICAL_STOPWORDS.has(merged)) continue;
|
|
179366
|
-
|
|
179483
|
+
tokens2.push(merged);
|
|
179367
179484
|
const chars = [...merged];
|
|
179368
179485
|
if (new RegExp("^\\p{Script=Han}+$", "u").test(merged) && chars.length > 2) {
|
|
179369
|
-
for (let index3 = 0; index3 < chars.length - 1; index3++)
|
|
179486
|
+
for (let index3 = 0; index3 < chars.length - 1; index3++) tokens2.push(`${chars[index3]}${chars[index3 + 1]}`);
|
|
179370
179487
|
}
|
|
179371
179488
|
}
|
|
179372
|
-
return
|
|
179489
|
+
return tokens2;
|
|
179373
179490
|
}
|
|
179374
179491
|
function knowledgeSearchTerms(value2) {
|
|
179375
179492
|
return [...new Set(knowledgeSearchTokenStream(value2))];
|
|
@@ -179381,20 +179498,20 @@ function documentSearchTokens(chunk) {
|
|
|
179381
179498
|
[chunk.logicalPath, 2]
|
|
179382
179499
|
];
|
|
179383
179500
|
return fields.flatMap(([value2, repeats]) => {
|
|
179384
|
-
const
|
|
179385
|
-
return Array.from({ length: repeats }, () =>
|
|
179501
|
+
const tokens2 = knowledgeSearchTokenStream(value2);
|
|
179502
|
+
return Array.from({ length: repeats }, () => tokens2).flat();
|
|
179386
179503
|
});
|
|
179387
179504
|
}
|
|
179388
179505
|
function layeredSearchTokens(chunk, lexicalLayer) {
|
|
179389
179506
|
return lexicalLayer === "document" ? documentSearchTokens(chunk) : knowledgeSearchTokenStream(chunk.text);
|
|
179390
179507
|
}
|
|
179391
179508
|
function knowledgeSearchIndexFields(chunk, lexicalLayer) {
|
|
179392
|
-
const
|
|
179509
|
+
const tokens2 = layeredSearchTokens(chunk, lexicalLayer);
|
|
179393
179510
|
return {
|
|
179394
|
-
terms: [...new Set(
|
|
179511
|
+
terms: [...new Set(tokens2)],
|
|
179395
179512
|
lexicalIndexVersion: KNOWLEDGE_LEXICAL_INDEX_VERSION,
|
|
179396
179513
|
lexicalLayer,
|
|
179397
|
-
tokenCount:
|
|
179514
|
+
tokenCount: tokens2.length
|
|
179398
179515
|
};
|
|
179399
179516
|
}
|
|
179400
179517
|
function knowledgeSearchIndexEntries(input) {
|
|
@@ -179478,10 +179595,10 @@ function splitKnowledgeChunks(content3, maxChars = 1600) {
|
|
|
179478
179595
|
function scoreKnowledgeChunk(query, chunk, corpus) {
|
|
179479
179596
|
const queryTerms = knowledgeSearchTerms(query);
|
|
179480
179597
|
if (queryTerms.length === 0) return 0;
|
|
179481
|
-
const
|
|
179598
|
+
const tokens2 = layeredSearchTokens(chunk, chunk.lexicalLayer ?? "chunk");
|
|
179482
179599
|
const frequencies2 = /* @__PURE__ */ new Map();
|
|
179483
|
-
for (const token of
|
|
179484
|
-
const documentLength = chunk.tokenCount ??
|
|
179600
|
+
for (const token of tokens2) frequencies2.set(token, (frequencies2.get(token) ?? 0) + 1);
|
|
179601
|
+
const documentLength = chunk.tokenCount ?? tokens2.length;
|
|
179485
179602
|
const averageLength = Math.max(1, corpus.averageTokenCount);
|
|
179486
179603
|
const documentCount = Math.max(1, corpus.size);
|
|
179487
179604
|
const k1 = 1.2;
|
|
@@ -183308,7 +183425,7 @@ ${pointer}
|
|
|
183308
183425
|
var require_resolve_props = __commonJS({
|
|
183309
183426
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js"(exports2) {
|
|
183310
183427
|
"use strict";
|
|
183311
|
-
function resolveProps(
|
|
183428
|
+
function resolveProps(tokens2, { flow: flow3, indicator, next, offset, onError, parentIndent, startOnNewline }) {
|
|
183312
183429
|
let spaceBefore = false;
|
|
183313
183430
|
let atNewline = startOnNewline;
|
|
183314
183431
|
let hasSpace = startOnNewline;
|
|
@@ -183323,7 +183440,7 @@ var require_resolve_props = __commonJS({
|
|
|
183323
183440
|
let comma = null;
|
|
183324
183441
|
let found2 = null;
|
|
183325
183442
|
let start = null;
|
|
183326
|
-
for (const token of
|
|
183443
|
+
for (const token of tokens2) {
|
|
183327
183444
|
if (reqSpace) {
|
|
183328
183445
|
if (token.type !== "space" && token.type !== "newline" && token.type !== "comma")
|
|
183329
183446
|
onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -183414,7 +183531,7 @@ var require_resolve_props = __commonJS({
|
|
|
183414
183531
|
hasSpace = false;
|
|
183415
183532
|
}
|
|
183416
183533
|
}
|
|
183417
|
-
const last =
|
|
183534
|
+
const last = tokens2[tokens2.length - 1];
|
|
183418
183535
|
const end = last ? last.offset + last.source.length : offset;
|
|
183419
183536
|
if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) {
|
|
183420
183537
|
onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -184753,8 +184870,8 @@ ${cb}` : comment;
|
|
|
184753
184870
|
* @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
184871
|
* @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
|
|
184755
184872
|
*/
|
|
184756
|
-
*compose(
|
|
184757
|
-
for (const token of
|
|
184873
|
+
*compose(tokens2, forceDoc = false, endOffset = -1) {
|
|
184874
|
+
for (const token of tokens2)
|
|
184758
184875
|
yield* this.next(token);
|
|
184759
184876
|
yield* this.end(forceDoc, endOffset);
|
|
184760
184877
|
}
|
|
@@ -192924,8 +193041,8 @@ var init_governance_service = __esm({
|
|
|
192924
193041
|
return false;
|
|
192925
193042
|
};
|
|
192926
193043
|
const addFragment = (source, content3) => {
|
|
192927
|
-
const
|
|
192928
|
-
if (usedTokens +
|
|
193044
|
+
const tokens2 = estimateKnowledgeTokens(content3);
|
|
193045
|
+
if (usedTokens + tokens2 > selectedPolicy.tokenBudget) return false;
|
|
192929
193046
|
const fragment = this.snapshot(ctx, "context_pack", content3, trustedProjectId, void 0);
|
|
192930
193047
|
snapshots2.push(fragment);
|
|
192931
193048
|
entries.push({
|
|
@@ -192941,12 +193058,12 @@ var init_governance_service = __esm({
|
|
|
192941
193058
|
...source.score !== void 0 ? { relevanceScore: source.score } : {},
|
|
192942
193059
|
...source.evidenceRole ? { evidenceRole: source.evidenceRole } : {},
|
|
192943
193060
|
contentHash: fragment.contentHash,
|
|
192944
|
-
tokenCount:
|
|
193061
|
+
tokenCount: tokens2,
|
|
192945
193062
|
ordinal: entries.length,
|
|
192946
193063
|
renderedFragmentRef: fragment.ref
|
|
192947
193064
|
});
|
|
192948
193065
|
fragments.push(content3);
|
|
192949
|
-
usedTokens +=
|
|
193066
|
+
usedTokens += tokens2;
|
|
192950
193067
|
return true;
|
|
192951
193068
|
};
|
|
192952
193069
|
const taskFacts = [...request2.facts];
|
|
@@ -203190,9 +203307,9 @@ function lexicalMatchRatio(query, value2) {
|
|
|
203190
203307
|
const actual = new Set(lexicalTerms(value2));
|
|
203191
203308
|
return expected.filter((term) => actual.has(term)).length / expected.length;
|
|
203192
203309
|
}
|
|
203193
|
-
function frequencies(
|
|
203310
|
+
function frequencies(tokens2) {
|
|
203194
203311
|
const values = /* @__PURE__ */ new Map();
|
|
203195
|
-
for (const token of
|
|
203312
|
+
for (const token of tokens2) values.set(token, (values.get(token) ?? 0) + 1);
|
|
203196
203313
|
return values;
|
|
203197
203314
|
}
|
|
203198
203315
|
function bm25Scores(query, documents, options = {}) {
|
|
@@ -203200,21 +203317,21 @@ function bm25Scores(query, documents, options = {}) {
|
|
|
203200
203317
|
const queryTokens = [...new Set(typeof query === "string" ? lexicalTerms(query) : query)];
|
|
203201
203318
|
if (queryTokens.length === 0) return documents.map(() => 0);
|
|
203202
203319
|
const tokenized = documents.map((document4) => lexicalTerms(document4));
|
|
203203
|
-
const averageLength = tokenized.reduce((total,
|
|
203320
|
+
const averageLength = tokenized.reduce((total, tokens2) => total + tokens2.length, 0) / Math.max(1, tokenized.length);
|
|
203204
203321
|
const documentFrequencies = /* @__PURE__ */ new Map();
|
|
203205
203322
|
for (const term of queryTokens) {
|
|
203206
|
-
documentFrequencies.set(term, tokenized.filter((
|
|
203323
|
+
documentFrequencies.set(term, tokenized.filter((tokens2) => tokens2.includes(term)).length);
|
|
203207
203324
|
}
|
|
203208
203325
|
const k1 = options.k1 ?? 1.2;
|
|
203209
203326
|
const b2 = options.b ?? 0.75;
|
|
203210
|
-
const raw = tokenized.map((
|
|
203211
|
-
const counts2 = frequencies(
|
|
203327
|
+
const raw = tokenized.map((tokens2) => {
|
|
203328
|
+
const counts2 = frequencies(tokens2);
|
|
203212
203329
|
return queryTokens.reduce((score, term) => {
|
|
203213
203330
|
const tf = counts2.get(term) ?? 0;
|
|
203214
203331
|
if (tf === 0) return score;
|
|
203215
203332
|
const df = documentFrequencies.get(term) ?? 0;
|
|
203216
203333
|
const idf = Math.log(1 + (documents.length - df + 0.5) / (df + 0.5));
|
|
203217
|
-
const lengthNormalization = 1 - b2 + b2 *
|
|
203334
|
+
const lengthNormalization = 1 - b2 + b2 * tokens2.length / Math.max(1, averageLength);
|
|
203218
203335
|
return score + idf * tf * (k1 + 1) / (tf + k1 * lengthNormalization);
|
|
203219
203336
|
}, 0);
|
|
203220
203337
|
});
|
|
@@ -207589,12 +207706,9 @@ async function startOasisServer(opts) {
|
|
|
207589
207706
|
}));
|
|
207590
207707
|
return;
|
|
207591
207708
|
}
|
|
207592
|
-
|
|
207593
|
-
|
|
207594
|
-
|
|
207595
|
-
url,
|
|
207596
|
-
await resolveEngine(company?.kind === "ok" ? company.companyId : void 0)
|
|
207597
|
-
);
|
|
207709
|
+
const companyId = company?.kind === "ok" ? company.companyId : void 0;
|
|
207710
|
+
const limits = await opts.fileLimits?.get(companyId) ?? DEFAULT_FILE_LIMITS;
|
|
207711
|
+
await withFileLimits(limits, async () => serveFileRequest(req, res, url, await resolveEngine(companyId)));
|
|
207598
207712
|
return;
|
|
207599
207713
|
}
|
|
207600
207714
|
if (url.pathname === "/api/whoami" && req.method === "GET") {
|
|
@@ -207621,17 +207735,18 @@ async function startOasisServer(opts) {
|
|
|
207621
207735
|
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
207622
207736
|
const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
|
|
207623
207737
|
const fileLimits = await opts.fileLimits?.get(currentCompanyId) ?? { ...DEFAULT_FILE_LIMITS };
|
|
207738
|
+
const requestMaxBytes = fileUploadRequestMaxBytes(fileLimits);
|
|
207624
207739
|
const chunks = [];
|
|
207625
207740
|
let requestBytes = 0;
|
|
207626
207741
|
const declared = Number(req.headers["content-length"] ?? 0);
|
|
207627
|
-
if (declared >
|
|
207742
|
+
if (declared > requestMaxBytes) {
|
|
207628
207743
|
req.resume();
|
|
207629
207744
|
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
207745
|
return;
|
|
207631
207746
|
}
|
|
207632
207747
|
for await (const chunk of req) {
|
|
207633
207748
|
requestBytes += chunk.length;
|
|
207634
|
-
if (requestBytes >
|
|
207749
|
+
if (requestBytes > requestMaxBytes) {
|
|
207635
207750
|
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
207751
|
return;
|
|
207637
207752
|
}
|
|
@@ -207658,9 +207773,9 @@ async function startOasisServer(opts) {
|
|
|
207658
207773
|
return;
|
|
207659
207774
|
}
|
|
207660
207775
|
await opts.fileLimits.put(currentCompanyId, limits);
|
|
207661
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits,
|
|
207776
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits, canManage }));
|
|
207662
207777
|
} else {
|
|
207663
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits: fileLimits,
|
|
207778
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits: fileLimits, canManage }));
|
|
207664
207779
|
}
|
|
207665
207780
|
return;
|
|
207666
207781
|
}
|
|
@@ -221679,6 +221794,15 @@ var init_handshake_throttle = __esm({
|
|
|
221679
221794
|
});
|
|
221680
221795
|
|
|
221681
221796
|
// ../server/src/daemon-hub.ts
|
|
221797
|
+
function legacyMessage(msg, maxBytes = FILE_TRANSFER_MAX_BYTES) {
|
|
221798
|
+
try {
|
|
221799
|
+
const json = JSON.stringify(msg);
|
|
221800
|
+
if (Buffer.byteLength(json) <= maxBytes) return json;
|
|
221801
|
+
} catch (error2) {
|
|
221802
|
+
if (!(error2 instanceof RangeError)) throw error2;
|
|
221803
|
+
}
|
|
221804
|
+
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");
|
|
221805
|
+
}
|
|
221682
221806
|
function clientIpOf(req) {
|
|
221683
221807
|
const fwd = req.headers["x-forwarded-for"];
|
|
221684
221808
|
const raw = Array.isArray(fwd) ? fwd[0] : fwd;
|
|
@@ -221941,11 +222065,15 @@ var init_daemon_hub = __esm({
|
|
|
221941
222065
|
handleSessionConnection(ws, auth) {
|
|
221942
222066
|
const { nodeId, dispatchId } = auth;
|
|
221943
222067
|
let registered = false;
|
|
222068
|
+
const decoder = new ChunkedMessageDecoder();
|
|
221944
222069
|
ws.on("message", (raw) => {
|
|
221945
222070
|
let msg;
|
|
221946
222071
|
try {
|
|
221947
|
-
|
|
222072
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222073
|
+
if (decoded === void 0) return;
|
|
222074
|
+
msg = decoded;
|
|
221948
222075
|
} catch {
|
|
222076
|
+
ws.close(1007, "Invalid message framing");
|
|
221949
222077
|
return;
|
|
221950
222078
|
}
|
|
221951
222079
|
if (msg.type === "session_hello") {
|
|
@@ -221962,6 +222090,7 @@ var init_daemon_hub = __esm({
|
|
|
221962
222090
|
sessionId: msg.sessionId,
|
|
221963
222091
|
connectedAt: Date.now(),
|
|
221964
222092
|
supportsInputConsumptionReceipts: msg.supportsInputConsumptionReceipts === true,
|
|
222093
|
+
supportsChunkedMessages: msg.supportsChunkedMessages === true,
|
|
221965
222094
|
...msg.jobArtifactId ? { jobArtifactId: msg.jobArtifactId } : {}
|
|
221966
222095
|
});
|
|
221967
222096
|
for (const l of this.sessionConnectListeners) l({ dispatchId, sessionId: msg.sessionId, nodeId });
|
|
@@ -222158,7 +222287,7 @@ var init_daemon_hub = __esm({
|
|
|
222158
222287
|
sendToSession(dispatchId, msg) {
|
|
222159
222288
|
const ws = this.sessionSockets.get(dispatchId);
|
|
222160
222289
|
if (!ws || ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222161
|
-
|
|
222290
|
+
for (const frame of this.sessionMeta.get(dispatchId)?.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg, 100 * MIB)]) ws.send(frame);
|
|
222162
222291
|
return true;
|
|
222163
222292
|
}
|
|
222164
222293
|
/**
|
|
@@ -222219,16 +222348,20 @@ var init_daemon_hub = __esm({
|
|
|
222219
222348
|
sourceIp: clientIpOf(req),
|
|
222220
222349
|
send: (msg) => {
|
|
222221
222350
|
if (ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222222
|
-
|
|
222351
|
+
for (const frame of daemon.meta.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg)]) ws.send(frame);
|
|
222223
222352
|
return true;
|
|
222224
222353
|
},
|
|
222225
222354
|
close: () => ws.close()
|
|
222226
222355
|
};
|
|
222356
|
+
const decoder = new ChunkedMessageDecoder();
|
|
222227
222357
|
ws.on("message", (raw) => {
|
|
222228
222358
|
let msg;
|
|
222229
222359
|
try {
|
|
222230
|
-
|
|
222360
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222361
|
+
if (decoded === void 0) return;
|
|
222362
|
+
msg = decoded;
|
|
222231
222363
|
} catch {
|
|
222364
|
+
ws.close(1007, "Invalid message framing");
|
|
222232
222365
|
return;
|
|
222233
222366
|
}
|
|
222234
222367
|
this.lastSeen.set(daemonId, Date.now());
|
|
@@ -222266,7 +222399,7 @@ var init_daemon_hub = __esm({
|
|
|
222266
222399
|
ws.on("error", (err) => {
|
|
222267
222400
|
console.error(`[hub] daemon ${daemonId} error:`, err.message);
|
|
222268
222401
|
});
|
|
222269
|
-
daemon.send({ type: "ping" });
|
|
222402
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222270
222403
|
}
|
|
222271
222404
|
/**
|
|
222272
222405
|
* 周期性活性 sweep:
|
|
@@ -222289,7 +222422,7 @@ var init_daemon_hub = __esm({
|
|
|
222289
222422
|
this.sockets.get(id)?.terminate();
|
|
222290
222423
|
continue;
|
|
222291
222424
|
}
|
|
222292
|
-
daemon.send({ type: "ping" });
|
|
222425
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222293
222426
|
}
|
|
222294
222427
|
}
|
|
222295
222428
|
/** 关闭 hub:停 liveness 定时器并断开所有 daemon。serve 关停时调用。 */
|
|
@@ -222547,17 +222680,11 @@ var init_skill_fetcher = __esm({
|
|
|
222547
222680
|
SKILL_DESCRIPTION_MAX = 600;
|
|
222548
222681
|
Bundle = class {
|
|
222549
222682
|
files = {};
|
|
222550
|
-
totalBytes = 0;
|
|
222551
|
-
fileCount = 0;
|
|
222552
222683
|
add(path40, content3) {
|
|
222553
222684
|
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`);
|
|
222685
|
+
if (bytes2 > currentFileLimits().skillFileBytes)
|
|
222686
|
+
throw new Error(`Skill file exceeds ${currentFileLimits().skillFileBytes} byte limit: ${path40}`);
|
|
222558
222687
|
this.files[path40] = content3;
|
|
222559
|
-
this.totalBytes += bytes2;
|
|
222560
|
-
this.fileCount++;
|
|
222561
222688
|
}
|
|
222562
222689
|
};
|
|
222563
222690
|
}
|
|
@@ -223330,7 +223457,7 @@ ${input.description}
|
|
|
223330
223457
|
const file = this.buildSkillFile(skillId, path40, content3, now);
|
|
223331
223458
|
const existing = await this.opts.store.listSkillFiles(skillId);
|
|
223332
223459
|
const next = [...existing.filter((f2) => f2.path !== path40), file];
|
|
223333
|
-
assertSkillFileLimits(
|
|
223460
|
+
assertSkillFileLimits([file]);
|
|
223334
223461
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
223335
223462
|
if (path40 === "SKILL.md") {
|
|
223336
223463
|
const { name, description } = parseSkillFrontmatter(content3);
|
|
@@ -224379,17 +224506,14 @@ function unpackSkillBundle(bytes2) {
|
|
|
224379
224506
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u7F3A\u5C11 files \u5BF9\u8C61");
|
|
224380
224507
|
}
|
|
224381
224508
|
const out = [];
|
|
224382
|
-
let total = 0;
|
|
224383
224509
|
for (const [path40, content3] of Object.entries(files)) {
|
|
224384
224510
|
if (typeof content3 !== "string") throw new SkillPackageInvalidError(`\u6587\u4EF6 ${path40} \u4E0D\u662F\u6587\u672C`);
|
|
224385
224511
|
if (!isCanonicalRelativePath(path40)) throw new SkillPackageInvalidError(`\u975E\u6CD5\u6280\u80FD\u6587\u4EF6\u8DEF\u5F84\uFF1A${path40}`);
|
|
224386
224512
|
const size = Buffer.byteLength(content3, "utf8");
|
|
224387
224513
|
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
224514
|
out.push({ path: path40, content: content3 });
|
|
224391
224515
|
}
|
|
224392
|
-
if (out.length === 0
|
|
224516
|
+
if (out.length === 0) {
|
|
224393
224517
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u6587\u4EF6\u6570\u91CF\u975E\u6CD5");
|
|
224394
224518
|
}
|
|
224395
224519
|
if (!out.some((f2) => f2.path === "SKILL.md")) {
|
|
@@ -240049,7 +240173,7 @@ function createChatSessionsDomain(opts) {
|
|
|
240049
240173
|
const outcome = await bridge.read(
|
|
240050
240174
|
loc.nodeId,
|
|
240051
240175
|
{ workdirKey: loc.workdirKey, runtimeKind: loc.runtimeKind, rtId: loc.rtId, path: req.query?.get("path") ?? "" },
|
|
240052
|
-
|
|
240176
|
+
currentFileReadMaxBytes()
|
|
240053
240177
|
);
|
|
240054
240178
|
if (outcome.ok) {
|
|
240055
240179
|
const buf = Buffer.from(outcome.contentBase64, "base64");
|
|
@@ -244477,7 +244601,13 @@ var init_daemon_adapter = __esm({
|
|
|
244477
244601
|
};
|
|
244478
244602
|
this.pending.set(dispatchId, entry);
|
|
244479
244603
|
const sessionAuth = this.sessionAuth ? { ...this.sessionAuth.issue({ nodeId, dispatchId }), gatewayUrl: this.sessionAuth.gatewayUrl } : void 0;
|
|
244480
|
-
|
|
244604
|
+
let sent;
|
|
244605
|
+
try {
|
|
244606
|
+
sent = this.hub.dispatch(nodeId, { type: "dispatch", dispatchId, job, ...sessionAuth ? { sessionAuth } : {} });
|
|
244607
|
+
} catch (error2) {
|
|
244608
|
+
this.pending.delete(dispatchId);
|
|
244609
|
+
throw error2;
|
|
244610
|
+
}
|
|
244481
244611
|
if (!sent) {
|
|
244482
244612
|
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
244613
|
} else if (this.ackTimeoutMs > 0) {
|
|
@@ -263233,6 +263363,7 @@ var init_trajectory = __esm({
|
|
|
263233
263363
|
|
|
263234
263364
|
// src/index.ts
|
|
263235
263365
|
var fs44 = __toESM(require("node:fs"));
|
|
263366
|
+
init_src();
|
|
263236
263367
|
var os14 = __toESM(require("node:os"));
|
|
263237
263368
|
var path39 = __toESM(require("node:path"));
|
|
263238
263369
|
var import_node_child_process22 = require("node:child_process");
|
|
@@ -271572,6 +271703,7 @@ var SessionManager = class {
|
|
|
271572
271703
|
// ../cli/src/daemon/session-process.ts
|
|
271573
271704
|
var fs35 = __toESM(require("node:fs"), 1);
|
|
271574
271705
|
var path30 = __toESM(require("node:path"), 1);
|
|
271706
|
+
var import_node_readline = require("node:readline");
|
|
271575
271707
|
init_wrapper();
|
|
271576
271708
|
init_src();
|
|
271577
271709
|
|
|
@@ -271754,7 +271886,7 @@ var OUTBOX_MAX_FRAMES = 8e3;
|
|
|
271754
271886
|
var isKeyFrame = (m2) => m2.type === "session_started" || m2.type === "session_exited";
|
|
271755
271887
|
async function runSessionProcess(specFile, adapter) {
|
|
271756
271888
|
process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] = "1";
|
|
271757
|
-
const spec = readSpec(specFile);
|
|
271889
|
+
const spec = await readSpec(specFile);
|
|
271758
271890
|
const { dispatchId, job, auth, sessionDir } = spec;
|
|
271759
271891
|
const lock = acquireSessionLock(path30.join(sessionDir, "lock"));
|
|
271760
271892
|
if (!lock && hasFlock()) {
|
|
@@ -271767,13 +271899,24 @@ async function runSessionProcess(specFile, adapter) {
|
|
|
271767
271899
|
const state = new SessionProcessState(spec, adapter, lock);
|
|
271768
271900
|
await state.run();
|
|
271769
271901
|
}
|
|
271770
|
-
function readSpec(specFile) {
|
|
271771
|
-
const
|
|
271902
|
+
async function readSpec(specFile) {
|
|
271903
|
+
const decoder = new ChunkedMessageDecoder();
|
|
271904
|
+
const source = fs35.createReadStream(specFile, { encoding: "utf8" });
|
|
271905
|
+
const lines = (0, import_node_readline.createInterface)({ input: source, crlfDelay: Infinity });
|
|
271772
271906
|
try {
|
|
271773
|
-
|
|
271774
|
-
|
|
271907
|
+
for await (const line of lines) {
|
|
271908
|
+
const spec = decoder.accept(JSON.parse(line));
|
|
271909
|
+
if (spec !== void 0) return spec;
|
|
271910
|
+
}
|
|
271911
|
+
throw new Error("Incomplete session specification");
|
|
271912
|
+
} finally {
|
|
271913
|
+
lines.close();
|
|
271914
|
+
source.destroy();
|
|
271915
|
+
try {
|
|
271916
|
+
fs35.unlinkSync(specFile);
|
|
271917
|
+
} catch {
|
|
271918
|
+
}
|
|
271775
271919
|
}
|
|
271776
|
-
return spec;
|
|
271777
271920
|
}
|
|
271778
271921
|
var SessionProcessState = class {
|
|
271779
271922
|
constructor(spec, adapter, lock) {
|
|
@@ -271880,16 +272023,21 @@ var SessionProcessState = class {
|
|
|
271880
272023
|
...this.spec.job.artifactId ? { jobArtifactId: this.spec.job.artifactId } : {},
|
|
271881
272024
|
// ADR 0300 D2:自报支持帧号;新服务端据此回带 ackSeq 的 hello-ack,届时才把 serverSupportsDedup 置真。
|
|
271882
272025
|
supportsFrameSeq: true,
|
|
272026
|
+
supportsChunkedMessages: true,
|
|
271883
272027
|
supportsInputConsumptionReceipts: true
|
|
271884
272028
|
});
|
|
271885
272029
|
const toResend = this.serverSupportsDedup ? this.outbox : this.outbox.filter(isKeyFrame);
|
|
271886
272030
|
for (const m2 of toResend) this.rawSend(m2);
|
|
271887
272031
|
});
|
|
272032
|
+
const decoder = new ChunkedMessageDecoder();
|
|
271888
272033
|
ws.on("message", (raw) => {
|
|
271889
272034
|
let msg;
|
|
271890
272035
|
try {
|
|
271891
|
-
|
|
272036
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272037
|
+
if (decoded === void 0) return;
|
|
272038
|
+
msg = decoded;
|
|
271892
272039
|
} catch {
|
|
272040
|
+
ws.close(1007, "Invalid message framing");
|
|
271893
272041
|
return;
|
|
271894
272042
|
}
|
|
271895
272043
|
void this.onServerMessage(msg);
|
|
@@ -272576,6 +272724,7 @@ var DaemonWsClient = class {
|
|
|
272576
272724
|
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
272725
|
this.stop();
|
|
272578
272726
|
}
|
|
272727
|
+
serverSupportsChunkedMessages = false;
|
|
272579
272728
|
connect() {
|
|
272580
272729
|
if (this.stopped) return;
|
|
272581
272730
|
const ws = new import_websocket.default(this.serverUrl, {
|
|
@@ -272589,6 +272738,7 @@ var DaemonWsClient = class {
|
|
|
272589
272738
|
handshakeTimeout: this.handshakeTimeoutMs
|
|
272590
272739
|
});
|
|
272591
272740
|
this.ws = ws;
|
|
272741
|
+
this.serverSupportsChunkedMessages = false;
|
|
272592
272742
|
ws.on("open", () => {
|
|
272593
272743
|
log2("[node-cli]", `connected id=${this.daemonId}`);
|
|
272594
272744
|
this.authRejectStreak = 0;
|
|
@@ -272606,12 +272756,16 @@ var DaemonWsClient = class {
|
|
|
272606
272756
|
}
|
|
272607
272757
|
}, this.pingIntervalMs);
|
|
272608
272758
|
});
|
|
272759
|
+
const decoder = new ChunkedMessageDecoder();
|
|
272609
272760
|
ws.on("message", (raw) => {
|
|
272610
272761
|
this.lastReceivedAt = Date.now();
|
|
272611
272762
|
let msg;
|
|
272612
272763
|
try {
|
|
272613
|
-
|
|
272764
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272765
|
+
if (decoded === void 0) return;
|
|
272766
|
+
msg = decoded;
|
|
272614
272767
|
} catch {
|
|
272768
|
+
ws.close(1007, "Invalid message framing");
|
|
272615
272769
|
return;
|
|
272616
272770
|
}
|
|
272617
272771
|
void this.handleMessage(msg);
|
|
@@ -272728,6 +272882,7 @@ var DaemonWsClient = class {
|
|
|
272728
272882
|
break;
|
|
272729
272883
|
}
|
|
272730
272884
|
case "ping":
|
|
272885
|
+
this.serverSupportsChunkedMessages = msg.supportsChunkedMessages === true;
|
|
272731
272886
|
this.send({ type: "pong" });
|
|
272732
272887
|
break;
|
|
272733
272888
|
case "ack":
|
|
@@ -272833,7 +272988,9 @@ var DaemonWsClient = class {
|
|
|
272833
272988
|
});
|
|
272834
272989
|
}
|
|
272835
272990
|
send(msg) {
|
|
272836
|
-
if (this.ws?.readyState === import_websocket.default.OPEN)
|
|
272991
|
+
if (this.ws?.readyState === import_websocket.default.OPEN) {
|
|
272992
|
+
for (const frame of this.serverSupportsChunkedMessages && msg.type === "workdir_read_result" ? encodeChunkedMessage(msg) : [JSON.stringify(msg)]) this.ws.send(frame);
|
|
272993
|
+
}
|
|
272837
272994
|
}
|
|
272838
272995
|
/**
|
|
272839
272996
|
* 待补发流帧数(观测/测试用)。
|
|
@@ -272958,6 +273115,7 @@ var DaemonWsClient = class {
|
|
|
272958
273115
|
// ADR 0554:本 daemon 认 `workdir_walk`。恒 true——handler 随包发,装了这版就一定有。
|
|
272959
273116
|
supportsWorkdirWalk: true,
|
|
272960
273117
|
supportsFileRestore: true,
|
|
273118
|
+
supportsChunkedMessages: true,
|
|
272961
273119
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
272962
273120
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
272963
273121
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -277580,8 +277738,6 @@ ${res.warning}`);
|
|
|
277580
277738
|
const SKIP2 = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store"]);
|
|
277581
277739
|
const limits = await loadFileLimits();
|
|
277582
277740
|
const MAX_FILE_BYTES3 = limits.skillFileBytes;
|
|
277583
|
-
const MAX_FILE_COUNT = limits.skillFileCount;
|
|
277584
|
-
let totalBytes = 0;
|
|
277585
277741
|
const local = {};
|
|
277586
277742
|
const binary = [];
|
|
277587
277743
|
const walk = (abs, rel) => {
|
|
@@ -277595,8 +277751,6 @@ ${res.warning}`);
|
|
|
277595
277751
|
}
|
|
277596
277752
|
const size = fs39.statSync(childAbs).size;
|
|
277597
277753
|
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
277754
|
const buf = fs39.readFileSync(childAbs);
|
|
277601
277755
|
if (buf.includes(0)) {
|
|
277602
277756
|
binary.push(childRel);
|
|
@@ -277612,7 +277766,6 @@ ${res.warning}`);
|
|
|
277612
277766
|
}
|
|
277613
277767
|
const paths = Object.keys(local);
|
|
277614
277768
|
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
277769
|
const skillMd = local["SKILL.md"];
|
|
277617
277770
|
if (skillMd === void 0) {
|
|
277618
277771
|
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 +279036,7 @@ function shimScript() {
|
|
|
278883
279036
|
}
|
|
278884
279037
|
|
|
278885
279038
|
// src/index.ts
|
|
278886
|
-
var PKG_VERSION = true ? "2.2.
|
|
279039
|
+
var PKG_VERSION = true ? "2.2.46" : "dev";
|
|
278887
279040
|
var LOCAL_BIN = localBin();
|
|
278888
279041
|
var NPM_PREFIX = npmPrefix();
|
|
278889
279042
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -279294,13 +279447,19 @@ function spawnSessionProcess(spec) {
|
|
|
279294
279447
|
fs44.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
279295
279448
|
const specFile = path39.join(dir, "spec.json");
|
|
279296
279449
|
const cfg = readConfig();
|
|
279297
|
-
fs44.
|
|
279298
|
-
|
|
279299
|
-
|
|
279300
|
-
|
|
279301
|
-
|
|
279302
|
-
|
|
279303
|
-
|
|
279450
|
+
const fd = fs44.openSync(specFile, "w", 384);
|
|
279451
|
+
try {
|
|
279452
|
+
for (const frame of encodeChunkedMessage({
|
|
279453
|
+
...spec,
|
|
279454
|
+
sessionDir: dir,
|
|
279455
|
+
nodeId: cfg?.nodeId ?? INSTANCE,
|
|
279456
|
+
daemonVersion: PKG_VERSION,
|
|
279457
|
+
daemonPkg: PKG_NAME
|
|
279458
|
+
})) fs44.writeFileSync(fd, `${frame}
|
|
279459
|
+
`);
|
|
279460
|
+
} finally {
|
|
279461
|
+
fs44.closeSync(fd);
|
|
279462
|
+
}
|
|
279304
279463
|
let pinnedDir = INST.currentLink;
|
|
279305
279464
|
try {
|
|
279306
279465
|
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.46",
|
|
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": "71593b93fa3ef6950c616a185e2ed7b0ee7b88e7"
|
|
30
30
|
}
|
|
31
31
|
}
|