oasis_test_v2 2.2.44 → 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 +455 -148
- 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
|
}
|
|
@@ -4880,7 +5005,7 @@ async function listModels(runtime, executablePath) {
|
|
|
4880
5005
|
case "claude-code":
|
|
4881
5006
|
return claudeStaticModels();
|
|
4882
5007
|
case "codex":
|
|
4883
|
-
return
|
|
5008
|
+
return discoverCodexCatalog(executablePath);
|
|
4884
5009
|
case "gemini":
|
|
4885
5010
|
return withFallback(runtime, executablePath, async () => await discoverACPModels(executablePath ?? "gemini", "gemini", ["--acp"]) ?? [], geminiStaticModels);
|
|
4886
5011
|
case "copilot":
|
|
@@ -5024,22 +5149,9 @@ function codebuddyStaticModels() {
|
|
|
5024
5149
|
function cursorStaticModels() {
|
|
5025
5150
|
return [{ id: "default[]", label: "Auto", provider: "cursor", default: true }];
|
|
5026
5151
|
}
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
if (models.length === 0) return true;
|
|
5031
|
-
return models.some((m2) => m2.id === modelId);
|
|
5032
|
-
} catch {
|
|
5033
|
-
return true;
|
|
5034
|
-
}
|
|
5035
|
-
}
|
|
5036
|
-
async function defaultModelFor(runtime, executablePath) {
|
|
5037
|
-
try {
|
|
5038
|
-
const models = await listModels(runtime, executablePath);
|
|
5039
|
-
return models.find((m2) => m2.default)?.id;
|
|
5040
|
-
} catch {
|
|
5041
|
-
return void 0;
|
|
5042
|
-
}
|
|
5152
|
+
function resolveDispatchModel(candidate, catalog) {
|
|
5153
|
+
if (catalog.length === 0 || catalog.some((m2) => m2.id === candidate)) return { model: candidate, replaced: false };
|
|
5154
|
+
return { model: catalog.find((m2) => m2.default)?.id, replaced: true };
|
|
5043
5155
|
}
|
|
5044
5156
|
async function discoverOpenCodeModels(bin) {
|
|
5045
5157
|
const out = await runCapture(bin ?? "opencode", ["models"]);
|
|
@@ -5055,7 +5167,163 @@ async function discoverOpenCodeModels(bin) {
|
|
|
5055
5167
|
}
|
|
5056
5168
|
return models;
|
|
5057
5169
|
}
|
|
5058
|
-
async function
|
|
5170
|
+
async function discoverCodexCatalog(bin) {
|
|
5171
|
+
const probed = { customProvider: false };
|
|
5172
|
+
const models = await cachedDiscovery(discoveryCacheKey("codex", bin), async () => {
|
|
5173
|
+
const catalog = codexCatalogFromAppServer(await probeCodexAppServer(bin ?? "codex"));
|
|
5174
|
+
if (!catalog) return discoverCodexBundledModels(bin);
|
|
5175
|
+
probed.customProvider = catalog.customProvider;
|
|
5176
|
+
return catalog.models;
|
|
5177
|
+
});
|
|
5178
|
+
return models.length > 0 || probed.customProvider ? models : codexStaticModels();
|
|
5179
|
+
}
|
|
5180
|
+
function codexCatalogFromAppServer(probe) {
|
|
5181
|
+
const config2 = probe?.config;
|
|
5182
|
+
if (!probe || !config2) return null;
|
|
5183
|
+
const providerId = config2.modelProvider?.trim() || "openai";
|
|
5184
|
+
const customProvider = providerId.toLowerCase() !== "openai";
|
|
5185
|
+
if (!customProvider && !probe.models) return null;
|
|
5186
|
+
const provider = customProvider ? config2.providerName?.trim() || providerId : "OpenAI";
|
|
5187
|
+
const listApplies = !customProvider || Boolean(config2.modelCatalogJson);
|
|
5188
|
+
const listed = listApplies ? probe.models ?? [] : [];
|
|
5189
|
+
const configured = config2.model?.trim();
|
|
5190
|
+
const defaultId = configured || listed.find((m2) => m2.isDefault)?.id;
|
|
5191
|
+
const models = listed.map((m2) => ({ id: m2.id, label: m2.label, provider }));
|
|
5192
|
+
if (configured && !models.some((m2) => m2.id === configured)) models.push({ id: configured, label: configured, provider });
|
|
5193
|
+
return { models: models.map((m2) => m2.id === defaultId ? { ...m2, default: true } : m2), customProvider };
|
|
5194
|
+
}
|
|
5195
|
+
async function probeCodexAppServer(bin, timeoutMs = 15e3) {
|
|
5196
|
+
let dir;
|
|
5197
|
+
try {
|
|
5198
|
+
dir = (0, import_node_fs2.mkdtempSync)((0, import_node_path3.join)((0, import_node_os2.tmpdir)(), "oasis-codex-models-"));
|
|
5199
|
+
} catch {
|
|
5200
|
+
return null;
|
|
5201
|
+
}
|
|
5202
|
+
let child;
|
|
5203
|
+
try {
|
|
5204
|
+
child = (0, import_node_child_process5.spawn)(bin, ["app-server", "--stdio", "-c", "allow_login_shell=false"], {
|
|
5205
|
+
cwd: dir,
|
|
5206
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
5207
|
+
env: { ...process.env }
|
|
5208
|
+
});
|
|
5209
|
+
} catch {
|
|
5210
|
+
(0, import_node_fs2.rmSync)(dir, { recursive: true, force: true });
|
|
5211
|
+
return null;
|
|
5212
|
+
}
|
|
5213
|
+
return await new Promise((resolve10) => {
|
|
5214
|
+
let settled = false;
|
|
5215
|
+
let config2;
|
|
5216
|
+
const listed = [];
|
|
5217
|
+
let listState = "pending";
|
|
5218
|
+
let nextId = 3;
|
|
5219
|
+
const MAX_PAGES = 20;
|
|
5220
|
+
let pages = 0;
|
|
5221
|
+
const finish = (value2) => {
|
|
5222
|
+
if (settled) return;
|
|
5223
|
+
settled = true;
|
|
5224
|
+
clearTimeout(timer);
|
|
5225
|
+
try {
|
|
5226
|
+
child.stdin?.end();
|
|
5227
|
+
} catch {
|
|
5228
|
+
}
|
|
5229
|
+
try {
|
|
5230
|
+
child.kill("SIGKILL");
|
|
5231
|
+
} catch {
|
|
5232
|
+
}
|
|
5233
|
+
try {
|
|
5234
|
+
(0, import_node_fs2.rmSync)(dir, { recursive: true, force: true });
|
|
5235
|
+
} catch {
|
|
5236
|
+
}
|
|
5237
|
+
resolve10(value2);
|
|
5238
|
+
};
|
|
5239
|
+
const maybeFinish = () => {
|
|
5240
|
+
if (config2 === void 0 || listState === "pending") return;
|
|
5241
|
+
finish({ config: config2, models: listState === "done" ? listed : null });
|
|
5242
|
+
};
|
|
5243
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
5244
|
+
const send = (id, method, params) => {
|
|
5245
|
+
try {
|
|
5246
|
+
child.stdin?.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
5247
|
+
`);
|
|
5248
|
+
} catch {
|
|
5249
|
+
finish(null);
|
|
5250
|
+
}
|
|
5251
|
+
};
|
|
5252
|
+
child.on("error", () => finish(null));
|
|
5253
|
+
child.stdin?.on("error", () => finish(null));
|
|
5254
|
+
child.on("close", () => finish(null));
|
|
5255
|
+
let buf = "";
|
|
5256
|
+
child.stdout?.on("data", (chunk) => {
|
|
5257
|
+
if (settled) return;
|
|
5258
|
+
buf += chunk.toString("utf8");
|
|
5259
|
+
let nl;
|
|
5260
|
+
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
5261
|
+
const line = buf.slice(0, nl).trim();
|
|
5262
|
+
buf = buf.slice(nl + 1);
|
|
5263
|
+
if (!line) continue;
|
|
5264
|
+
let msg;
|
|
5265
|
+
try {
|
|
5266
|
+
msg = JSON.parse(line);
|
|
5267
|
+
} catch {
|
|
5268
|
+
continue;
|
|
5269
|
+
}
|
|
5270
|
+
if (typeof msg.id !== "number") continue;
|
|
5271
|
+
if (msg.id === 1) {
|
|
5272
|
+
if (msg.error !== void 0) {
|
|
5273
|
+
finish(null);
|
|
5274
|
+
return;
|
|
5275
|
+
}
|
|
5276
|
+
send(2, "config/read", { cwd: dir });
|
|
5277
|
+
send(nextId, "model/list", {});
|
|
5278
|
+
continue;
|
|
5279
|
+
}
|
|
5280
|
+
if (msg.id === 2) {
|
|
5281
|
+
config2 = msg.error !== void 0 ? null : parseCodexConfigRead(msg.result);
|
|
5282
|
+
maybeFinish();
|
|
5283
|
+
continue;
|
|
5284
|
+
}
|
|
5285
|
+
if (msg.id === nextId && listState === "pending") {
|
|
5286
|
+
if (msg.error !== void 0) {
|
|
5287
|
+
listState = "failed";
|
|
5288
|
+
} else {
|
|
5289
|
+
const page = msg.result ?? {};
|
|
5290
|
+
for (const m2 of page.data ?? []) {
|
|
5291
|
+
const id = typeof m2.model === "string" && m2.model ? m2.model : typeof m2.id === "string" ? m2.id : "";
|
|
5292
|
+
if (!id || m2.hidden === true || listed.some((x2) => x2.id === id)) continue;
|
|
5293
|
+
listed.push({ id, label: typeof m2.displayName === "string" && m2.displayName ? m2.displayName : id, isDefault: m2.isDefault === true });
|
|
5294
|
+
}
|
|
5295
|
+
pages += 1;
|
|
5296
|
+
if (typeof page.nextCursor === "string" && page.nextCursor && pages < MAX_PAGES) {
|
|
5297
|
+
nextId += 1;
|
|
5298
|
+
send(nextId, "model/list", { cursor: page.nextCursor });
|
|
5299
|
+
continue;
|
|
5300
|
+
}
|
|
5301
|
+
listState = "done";
|
|
5302
|
+
}
|
|
5303
|
+
maybeFinish();
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
5306
|
+
});
|
|
5307
|
+
send(1, "initialize", { clientInfo: { name: "oasis-model-discovery", version: "0.1.0" }, capabilities: {} });
|
|
5308
|
+
});
|
|
5309
|
+
}
|
|
5310
|
+
function parseCodexConfigRead(result) {
|
|
5311
|
+
const config2 = (result ?? {}).config ?? {};
|
|
5312
|
+
const str5 = (v2) => typeof v2 === "string" && v2.trim() ? v2.trim() : void 0;
|
|
5313
|
+
const model = str5(config2["model"]);
|
|
5314
|
+
const modelProvider = str5(config2["model_provider"]);
|
|
5315
|
+
const modelCatalogJson = str5(config2["model_catalog_json"]);
|
|
5316
|
+
const providers = config2["model_providers"];
|
|
5317
|
+
const entry = modelProvider && providers && typeof providers === "object" ? providers[modelProvider] : void 0;
|
|
5318
|
+
const providerName = entry && typeof entry === "object" ? str5(entry["name"]) : void 0;
|
|
5319
|
+
return {
|
|
5320
|
+
...model ? { model } : {},
|
|
5321
|
+
...modelProvider ? { modelProvider } : {},
|
|
5322
|
+
...providerName ? { providerName } : {},
|
|
5323
|
+
...modelCatalogJson ? { modelCatalogJson } : {}
|
|
5324
|
+
};
|
|
5325
|
+
}
|
|
5326
|
+
async function discoverCodexBundledModels(bin) {
|
|
5059
5327
|
const out = await runCapture(bin ?? "codex", ["debug", "models", "--bundled"]);
|
|
5060
5328
|
if (out === void 0) return [];
|
|
5061
5329
|
try {
|
|
@@ -5256,6 +5524,7 @@ async function discoverACPModels(bin, provider, args = ["acp"], timeoutMs = 12e3
|
|
|
5256
5524
|
};
|
|
5257
5525
|
const watchdog = setTimeout(fail, timeoutMs);
|
|
5258
5526
|
child.on("error", fail);
|
|
5527
|
+
child.stdin?.on("error", fail);
|
|
5259
5528
|
child.on("exit", () => {
|
|
5260
5529
|
if (!settled) fail();
|
|
5261
5530
|
});
|
|
@@ -9996,14 +10265,14 @@ function accountUsage(model, usage) {
|
|
|
9996
10265
|
const input = nonNegative(usage.inputTokens);
|
|
9997
10266
|
const output = nonNegative(usage.outputTokens);
|
|
9998
10267
|
const cache = nonNegative(usage.cacheReadTokens) + nonNegative(usage.cacheCreationTokens);
|
|
9999
|
-
const
|
|
10268
|
+
const tokens2 = { input, cache, output, total: input + cache + output };
|
|
10000
10269
|
const estimated = estimateUsageCostBreakdown(resolved, usage);
|
|
10001
10270
|
const weights = estimated ? { input: estimated.inputMicros, cache: estimated.cacheMicros, output: estimated.outputMicros } : null;
|
|
10002
10271
|
const reported = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
10003
10272
|
if (reported > 0) {
|
|
10004
10273
|
const parts = weights && estimated?.currency === "USD" ? splitByWeight(reported, weights) : { input: 0, cache: 0, output: reported };
|
|
10005
10274
|
return {
|
|
10006
|
-
tokens,
|
|
10275
|
+
tokens: tokens2,
|
|
10007
10276
|
currency: "USD",
|
|
10008
10277
|
amountMicros: reported,
|
|
10009
10278
|
parts,
|
|
@@ -10016,7 +10285,7 @@ function accountUsage(model, usage) {
|
|
|
10016
10285
|
const amount = weights.input + weights.cache + weights.output;
|
|
10017
10286
|
const displayUsdMicros = toDisplayUsd(estimated.currency, amount);
|
|
10018
10287
|
return {
|
|
10019
|
-
tokens,
|
|
10288
|
+
tokens: tokens2,
|
|
10020
10289
|
currency: estimated.currency,
|
|
10021
10290
|
amountMicros: amount,
|
|
10022
10291
|
parts: weights,
|
|
@@ -10026,7 +10295,7 @@ function accountUsage(model, usage) {
|
|
|
10026
10295
|
};
|
|
10027
10296
|
}
|
|
10028
10297
|
return {
|
|
10029
|
-
tokens,
|
|
10298
|
+
tokens: tokens2,
|
|
10030
10299
|
currency: "USD",
|
|
10031
10300
|
amountMicros: 0,
|
|
10032
10301
|
parts: { input: 0, cache: 0, output: 0 },
|
|
@@ -10051,8 +10320,8 @@ function estimateSubagentCostUsdMicros(usage) {
|
|
|
10051
10320
|
const models = Object.entries(usage.byModel);
|
|
10052
10321
|
if (models.length === 0) return void 0;
|
|
10053
10322
|
let total = 0;
|
|
10054
|
-
for (const [model,
|
|
10055
|
-
const account = accountUsage(model, { ...
|
|
10323
|
+
for (const [model, tokens2] of models) {
|
|
10324
|
+
const account = accountUsage(model, { ...tokens2, costUsdMicros: null });
|
|
10056
10325
|
if (!account || account.source !== "estimated") return void 0;
|
|
10057
10326
|
total += account.displayUsdMicros;
|
|
10058
10327
|
}
|
|
@@ -24831,13 +25100,13 @@ var require_axios = __commonJS({
|
|
|
24831
25100
|
return utils$1.isArray(value2) ? value2.map(normalizeValue) : String(value2);
|
|
24832
25101
|
}
|
|
24833
25102
|
function parseTokens(str5) {
|
|
24834
|
-
const
|
|
25103
|
+
const tokens2 = /* @__PURE__ */ Object.create(null);
|
|
24835
25104
|
const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;
|
|
24836
25105
|
let match;
|
|
24837
25106
|
while (match = tokensRE.exec(str5)) {
|
|
24838
|
-
|
|
25107
|
+
tokens2[match[1]] = match[2];
|
|
24839
25108
|
}
|
|
24840
|
-
return
|
|
25109
|
+
return tokens2;
|
|
24841
25110
|
}
|
|
24842
25111
|
var isValidHeaderName = (str5) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str5.trim());
|
|
24843
25112
|
function matchHeaderValue(context2, value2, header, filter, isHeaderNameFilter) {
|
|
@@ -166460,8 +166729,6 @@ async function prepareSessionFileRestore(input) {
|
|
|
166460
166729
|
}
|
|
166461
166730
|
if (input.fresh) issues.push(...saveIssues.map((i) => ({ ...i, phase: "restore", message: `\u539F\u6587\u4EF6\u5C1A\u672A\u4FDD\u5B58\uFF1A${i.message}` })));
|
|
166462
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", ""];
|
|
166463
|
-
let total = 0;
|
|
166464
|
-
const inlineMax = input.inlineMaxBytes ?? RESTORE_INLINE_MAX_BYTES;
|
|
166465
166732
|
const seen = /* @__PURE__ */ new Set();
|
|
166466
166733
|
const add = async (name, ref2, path40, replace2) => {
|
|
166467
166734
|
if (seen.has(path40)) return;
|
|
@@ -166471,12 +166738,9 @@ async function prepareSessionFileRestore(input) {
|
|
|
166471
166738
|
return;
|
|
166472
166739
|
}
|
|
166473
166740
|
try {
|
|
166474
|
-
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");
|
|
166475
166741
|
const bytes2 = await input.readBlob(ref2);
|
|
166476
|
-
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`);
|
|
166477
166742
|
const hash3 = (0, import_node_crypto24.createHash)("sha256").update(bytes2).digest("hex");
|
|
166478
166743
|
if (hash3 !== ref2.replace(/^blob:/, "")) throw new Error("\u539F\u4EF6\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
166479
|
-
total += bytes2.byteLength;
|
|
166480
166744
|
restoreFiles[path40] = { contentBase64: Buffer.from(bytes2).toString("base64"), sha256: hash3, overwrite: replace2 };
|
|
166481
166745
|
lines.push(`- ${JSON.stringify(name)} \u2192 ${JSON.stringify(path40)}`);
|
|
166482
166746
|
} catch (error2) {
|
|
@@ -166508,17 +166772,14 @@ async function prepareSessionFileRestore(input) {
|
|
|
166508
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")}`);
|
|
166509
166773
|
return { restoreFiles, index: lines.join("\n") };
|
|
166510
166774
|
}
|
|
166511
|
-
var import_node_crypto24
|
|
166775
|
+
var import_node_crypto24;
|
|
166512
166776
|
var init_file_restore = __esm({
|
|
166513
166777
|
"../server/src/domains/chat-sessions/file-restore.ts"() {
|
|
166514
166778
|
"use strict";
|
|
166515
166779
|
import_node_crypto24 = require("node:crypto");
|
|
166516
|
-
init_src();
|
|
166517
166780
|
init_chat_attachment_files();
|
|
166518
166781
|
init_router();
|
|
166519
166782
|
init_persistent_files();
|
|
166520
|
-
RESTORE_INLINE_MAX_BYTES = FILE_TRANSFER_INPUT_MAX_BYTES;
|
|
166521
|
-
RESTORE_MAX_FILES = 500;
|
|
166522
166783
|
}
|
|
166523
166784
|
});
|
|
166524
166785
|
|
|
@@ -179212,20 +179473,20 @@ function knowledgeSearchTokenStream(value2) {
|
|
|
179212
179473
|
raw.push(token);
|
|
179213
179474
|
}
|
|
179214
179475
|
}
|
|
179215
|
-
const
|
|
179476
|
+
const tokens2 = [];
|
|
179216
179477
|
for (let index2 = 0; index2 < raw.length; index2++) {
|
|
179217
179478
|
const token = raw[index2];
|
|
179218
179479
|
const next = raw[index2 + 1];
|
|
179219
179480
|
const merged = new RegExp("^\\p{Script=Han}$", "u").test(token) && next && new RegExp("^\\p{Script=Han}$", "u").test(next) ? `${token}${next}` : token;
|
|
179220
179481
|
if (merged !== token) index2++;
|
|
179221
179482
|
if (LEXICAL_STOPWORDS.has(merged)) continue;
|
|
179222
|
-
|
|
179483
|
+
tokens2.push(merged);
|
|
179223
179484
|
const chars = [...merged];
|
|
179224
179485
|
if (new RegExp("^\\p{Script=Han}+$", "u").test(merged) && chars.length > 2) {
|
|
179225
|
-
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]}`);
|
|
179226
179487
|
}
|
|
179227
179488
|
}
|
|
179228
|
-
return
|
|
179489
|
+
return tokens2;
|
|
179229
179490
|
}
|
|
179230
179491
|
function knowledgeSearchTerms(value2) {
|
|
179231
179492
|
return [...new Set(knowledgeSearchTokenStream(value2))];
|
|
@@ -179237,20 +179498,20 @@ function documentSearchTokens(chunk) {
|
|
|
179237
179498
|
[chunk.logicalPath, 2]
|
|
179238
179499
|
];
|
|
179239
179500
|
return fields.flatMap(([value2, repeats]) => {
|
|
179240
|
-
const
|
|
179241
|
-
return Array.from({ length: repeats }, () =>
|
|
179501
|
+
const tokens2 = knowledgeSearchTokenStream(value2);
|
|
179502
|
+
return Array.from({ length: repeats }, () => tokens2).flat();
|
|
179242
179503
|
});
|
|
179243
179504
|
}
|
|
179244
179505
|
function layeredSearchTokens(chunk, lexicalLayer) {
|
|
179245
179506
|
return lexicalLayer === "document" ? documentSearchTokens(chunk) : knowledgeSearchTokenStream(chunk.text);
|
|
179246
179507
|
}
|
|
179247
179508
|
function knowledgeSearchIndexFields(chunk, lexicalLayer) {
|
|
179248
|
-
const
|
|
179509
|
+
const tokens2 = layeredSearchTokens(chunk, lexicalLayer);
|
|
179249
179510
|
return {
|
|
179250
|
-
terms: [...new Set(
|
|
179511
|
+
terms: [...new Set(tokens2)],
|
|
179251
179512
|
lexicalIndexVersion: KNOWLEDGE_LEXICAL_INDEX_VERSION,
|
|
179252
179513
|
lexicalLayer,
|
|
179253
|
-
tokenCount:
|
|
179514
|
+
tokenCount: tokens2.length
|
|
179254
179515
|
};
|
|
179255
179516
|
}
|
|
179256
179517
|
function knowledgeSearchIndexEntries(input) {
|
|
@@ -179334,10 +179595,10 @@ function splitKnowledgeChunks(content3, maxChars = 1600) {
|
|
|
179334
179595
|
function scoreKnowledgeChunk(query, chunk, corpus) {
|
|
179335
179596
|
const queryTerms = knowledgeSearchTerms(query);
|
|
179336
179597
|
if (queryTerms.length === 0) return 0;
|
|
179337
|
-
const
|
|
179598
|
+
const tokens2 = layeredSearchTokens(chunk, chunk.lexicalLayer ?? "chunk");
|
|
179338
179599
|
const frequencies2 = /* @__PURE__ */ new Map();
|
|
179339
|
-
for (const token of
|
|
179340
|
-
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;
|
|
179341
179602
|
const averageLength = Math.max(1, corpus.averageTokenCount);
|
|
179342
179603
|
const documentCount = Math.max(1, corpus.size);
|
|
179343
179604
|
const k1 = 1.2;
|
|
@@ -183164,7 +183425,7 @@ ${pointer}
|
|
|
183164
183425
|
var require_resolve_props = __commonJS({
|
|
183165
183426
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js"(exports2) {
|
|
183166
183427
|
"use strict";
|
|
183167
|
-
function resolveProps(
|
|
183428
|
+
function resolveProps(tokens2, { flow: flow3, indicator, next, offset, onError, parentIndent, startOnNewline }) {
|
|
183168
183429
|
let spaceBefore = false;
|
|
183169
183430
|
let atNewline = startOnNewline;
|
|
183170
183431
|
let hasSpace = startOnNewline;
|
|
@@ -183179,7 +183440,7 @@ var require_resolve_props = __commonJS({
|
|
|
183179
183440
|
let comma = null;
|
|
183180
183441
|
let found2 = null;
|
|
183181
183442
|
let start = null;
|
|
183182
|
-
for (const token of
|
|
183443
|
+
for (const token of tokens2) {
|
|
183183
183444
|
if (reqSpace) {
|
|
183184
183445
|
if (token.type !== "space" && token.type !== "newline" && token.type !== "comma")
|
|
183185
183446
|
onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -183270,7 +183531,7 @@ var require_resolve_props = __commonJS({
|
|
|
183270
183531
|
hasSpace = false;
|
|
183271
183532
|
}
|
|
183272
183533
|
}
|
|
183273
|
-
const last =
|
|
183534
|
+
const last = tokens2[tokens2.length - 1];
|
|
183274
183535
|
const end = last ? last.offset + last.source.length : offset;
|
|
183275
183536
|
if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) {
|
|
183276
183537
|
onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
|
|
@@ -184609,8 +184870,8 @@ ${cb}` : comment;
|
|
|
184609
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.
|
|
184610
184871
|
* @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
|
|
184611
184872
|
*/
|
|
184612
|
-
*compose(
|
|
184613
|
-
for (const token of
|
|
184873
|
+
*compose(tokens2, forceDoc = false, endOffset = -1) {
|
|
184874
|
+
for (const token of tokens2)
|
|
184614
184875
|
yield* this.next(token);
|
|
184615
184876
|
yield* this.end(forceDoc, endOffset);
|
|
184616
184877
|
}
|
|
@@ -192780,8 +193041,8 @@ var init_governance_service = __esm({
|
|
|
192780
193041
|
return false;
|
|
192781
193042
|
};
|
|
192782
193043
|
const addFragment = (source, content3) => {
|
|
192783
|
-
const
|
|
192784
|
-
if (usedTokens +
|
|
193044
|
+
const tokens2 = estimateKnowledgeTokens(content3);
|
|
193045
|
+
if (usedTokens + tokens2 > selectedPolicy.tokenBudget) return false;
|
|
192785
193046
|
const fragment = this.snapshot(ctx, "context_pack", content3, trustedProjectId, void 0);
|
|
192786
193047
|
snapshots2.push(fragment);
|
|
192787
193048
|
entries.push({
|
|
@@ -192797,12 +193058,12 @@ var init_governance_service = __esm({
|
|
|
192797
193058
|
...source.score !== void 0 ? { relevanceScore: source.score } : {},
|
|
192798
193059
|
...source.evidenceRole ? { evidenceRole: source.evidenceRole } : {},
|
|
192799
193060
|
contentHash: fragment.contentHash,
|
|
192800
|
-
tokenCount:
|
|
193061
|
+
tokenCount: tokens2,
|
|
192801
193062
|
ordinal: entries.length,
|
|
192802
193063
|
renderedFragmentRef: fragment.ref
|
|
192803
193064
|
});
|
|
192804
193065
|
fragments.push(content3);
|
|
192805
|
-
usedTokens +=
|
|
193066
|
+
usedTokens += tokens2;
|
|
192806
193067
|
return true;
|
|
192807
193068
|
};
|
|
192808
193069
|
const taskFacts = [...request2.facts];
|
|
@@ -203046,9 +203307,9 @@ function lexicalMatchRatio(query, value2) {
|
|
|
203046
203307
|
const actual = new Set(lexicalTerms(value2));
|
|
203047
203308
|
return expected.filter((term) => actual.has(term)).length / expected.length;
|
|
203048
203309
|
}
|
|
203049
|
-
function frequencies(
|
|
203310
|
+
function frequencies(tokens2) {
|
|
203050
203311
|
const values = /* @__PURE__ */ new Map();
|
|
203051
|
-
for (const token of
|
|
203312
|
+
for (const token of tokens2) values.set(token, (values.get(token) ?? 0) + 1);
|
|
203052
203313
|
return values;
|
|
203053
203314
|
}
|
|
203054
203315
|
function bm25Scores(query, documents, options = {}) {
|
|
@@ -203056,21 +203317,21 @@ function bm25Scores(query, documents, options = {}) {
|
|
|
203056
203317
|
const queryTokens = [...new Set(typeof query === "string" ? lexicalTerms(query) : query)];
|
|
203057
203318
|
if (queryTokens.length === 0) return documents.map(() => 0);
|
|
203058
203319
|
const tokenized = documents.map((document4) => lexicalTerms(document4));
|
|
203059
|
-
const averageLength = tokenized.reduce((total,
|
|
203320
|
+
const averageLength = tokenized.reduce((total, tokens2) => total + tokens2.length, 0) / Math.max(1, tokenized.length);
|
|
203060
203321
|
const documentFrequencies = /* @__PURE__ */ new Map();
|
|
203061
203322
|
for (const term of queryTokens) {
|
|
203062
|
-
documentFrequencies.set(term, tokenized.filter((
|
|
203323
|
+
documentFrequencies.set(term, tokenized.filter((tokens2) => tokens2.includes(term)).length);
|
|
203063
203324
|
}
|
|
203064
203325
|
const k1 = options.k1 ?? 1.2;
|
|
203065
203326
|
const b2 = options.b ?? 0.75;
|
|
203066
|
-
const raw = tokenized.map((
|
|
203067
|
-
const counts2 = frequencies(
|
|
203327
|
+
const raw = tokenized.map((tokens2) => {
|
|
203328
|
+
const counts2 = frequencies(tokens2);
|
|
203068
203329
|
return queryTokens.reduce((score, term) => {
|
|
203069
203330
|
const tf = counts2.get(term) ?? 0;
|
|
203070
203331
|
if (tf === 0) return score;
|
|
203071
203332
|
const df = documentFrequencies.get(term) ?? 0;
|
|
203072
203333
|
const idf = Math.log(1 + (documents.length - df + 0.5) / (df + 0.5));
|
|
203073
|
-
const lengthNormalization = 1 - b2 + b2 *
|
|
203334
|
+
const lengthNormalization = 1 - b2 + b2 * tokens2.length / Math.max(1, averageLength);
|
|
203074
203335
|
return score + idf * tf * (k1 + 1) / (tf + k1 * lengthNormalization);
|
|
203075
203336
|
}, 0);
|
|
203076
203337
|
});
|
|
@@ -207445,12 +207706,9 @@ async function startOasisServer(opts) {
|
|
|
207445
207706
|
}));
|
|
207446
207707
|
return;
|
|
207447
207708
|
}
|
|
207448
|
-
|
|
207449
|
-
|
|
207450
|
-
|
|
207451
|
-
url,
|
|
207452
|
-
await resolveEngine(company?.kind === "ok" ? company.companyId : void 0)
|
|
207453
|
-
);
|
|
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)));
|
|
207454
207712
|
return;
|
|
207455
207713
|
}
|
|
207456
207714
|
if (url.pathname === "/api/whoami" && req.method === "GET") {
|
|
@@ -207477,17 +207735,18 @@ async function startOasisServer(opts) {
|
|
|
207477
207735
|
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
207478
207736
|
const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
|
|
207479
207737
|
const fileLimits = await opts.fileLimits?.get(currentCompanyId) ?? { ...DEFAULT_FILE_LIMITS };
|
|
207738
|
+
const requestMaxBytes = fileUploadRequestMaxBytes(fileLimits);
|
|
207480
207739
|
const chunks = [];
|
|
207481
207740
|
let requestBytes = 0;
|
|
207482
207741
|
const declared = Number(req.headers["content-length"] ?? 0);
|
|
207483
|
-
if (declared >
|
|
207742
|
+
if (declared > requestMaxBytes) {
|
|
207484
207743
|
req.resume();
|
|
207485
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" } }));
|
|
207486
207745
|
return;
|
|
207487
207746
|
}
|
|
207488
207747
|
for await (const chunk of req) {
|
|
207489
207748
|
requestBytes += chunk.length;
|
|
207490
|
-
if (requestBytes >
|
|
207749
|
+
if (requestBytes > requestMaxBytes) {
|
|
207491
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" } }));
|
|
207492
207751
|
return;
|
|
207493
207752
|
}
|
|
@@ -207514,9 +207773,9 @@ async function startOasisServer(opts) {
|
|
|
207514
207773
|
return;
|
|
207515
207774
|
}
|
|
207516
207775
|
await opts.fileLimits.put(currentCompanyId, limits);
|
|
207517
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits,
|
|
207776
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ limits, canManage }));
|
|
207518
207777
|
} else {
|
|
207519
|
-
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 }));
|
|
207520
207779
|
}
|
|
207521
207780
|
return;
|
|
207522
207781
|
}
|
|
@@ -221535,6 +221794,15 @@ var init_handshake_throttle = __esm({
|
|
|
221535
221794
|
});
|
|
221536
221795
|
|
|
221537
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
|
+
}
|
|
221538
221806
|
function clientIpOf(req) {
|
|
221539
221807
|
const fwd = req.headers["x-forwarded-for"];
|
|
221540
221808
|
const raw = Array.isArray(fwd) ? fwd[0] : fwd;
|
|
@@ -221797,11 +222065,15 @@ var init_daemon_hub = __esm({
|
|
|
221797
222065
|
handleSessionConnection(ws, auth) {
|
|
221798
222066
|
const { nodeId, dispatchId } = auth;
|
|
221799
222067
|
let registered = false;
|
|
222068
|
+
const decoder = new ChunkedMessageDecoder();
|
|
221800
222069
|
ws.on("message", (raw) => {
|
|
221801
222070
|
let msg;
|
|
221802
222071
|
try {
|
|
221803
|
-
|
|
222072
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222073
|
+
if (decoded === void 0) return;
|
|
222074
|
+
msg = decoded;
|
|
221804
222075
|
} catch {
|
|
222076
|
+
ws.close(1007, "Invalid message framing");
|
|
221805
222077
|
return;
|
|
221806
222078
|
}
|
|
221807
222079
|
if (msg.type === "session_hello") {
|
|
@@ -221818,6 +222090,7 @@ var init_daemon_hub = __esm({
|
|
|
221818
222090
|
sessionId: msg.sessionId,
|
|
221819
222091
|
connectedAt: Date.now(),
|
|
221820
222092
|
supportsInputConsumptionReceipts: msg.supportsInputConsumptionReceipts === true,
|
|
222093
|
+
supportsChunkedMessages: msg.supportsChunkedMessages === true,
|
|
221821
222094
|
...msg.jobArtifactId ? { jobArtifactId: msg.jobArtifactId } : {}
|
|
221822
222095
|
});
|
|
221823
222096
|
for (const l of this.sessionConnectListeners) l({ dispatchId, sessionId: msg.sessionId, nodeId });
|
|
@@ -222014,7 +222287,7 @@ var init_daemon_hub = __esm({
|
|
|
222014
222287
|
sendToSession(dispatchId, msg) {
|
|
222015
222288
|
const ws = this.sessionSockets.get(dispatchId);
|
|
222016
222289
|
if (!ws || ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222017
|
-
|
|
222290
|
+
for (const frame of this.sessionMeta.get(dispatchId)?.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg, 100 * MIB)]) ws.send(frame);
|
|
222018
222291
|
return true;
|
|
222019
222292
|
}
|
|
222020
222293
|
/**
|
|
@@ -222075,16 +222348,20 @@ var init_daemon_hub = __esm({
|
|
|
222075
222348
|
sourceIp: clientIpOf(req),
|
|
222076
222349
|
send: (msg) => {
|
|
222077
222350
|
if (ws.readyState !== import_websocket.default.OPEN) return false;
|
|
222078
|
-
|
|
222351
|
+
for (const frame of daemon.meta.supportsChunkedMessages ? encodeChunkedMessage(msg) : [legacyMessage(msg)]) ws.send(frame);
|
|
222079
222352
|
return true;
|
|
222080
222353
|
},
|
|
222081
222354
|
close: () => ws.close()
|
|
222082
222355
|
};
|
|
222356
|
+
const decoder = new ChunkedMessageDecoder();
|
|
222083
222357
|
ws.on("message", (raw) => {
|
|
222084
222358
|
let msg;
|
|
222085
222359
|
try {
|
|
222086
|
-
|
|
222360
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
222361
|
+
if (decoded === void 0) return;
|
|
222362
|
+
msg = decoded;
|
|
222087
222363
|
} catch {
|
|
222364
|
+
ws.close(1007, "Invalid message framing");
|
|
222088
222365
|
return;
|
|
222089
222366
|
}
|
|
222090
222367
|
this.lastSeen.set(daemonId, Date.now());
|
|
@@ -222122,7 +222399,7 @@ var init_daemon_hub = __esm({
|
|
|
222122
222399
|
ws.on("error", (err) => {
|
|
222123
222400
|
console.error(`[hub] daemon ${daemonId} error:`, err.message);
|
|
222124
222401
|
});
|
|
222125
|
-
daemon.send({ type: "ping" });
|
|
222402
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222126
222403
|
}
|
|
222127
222404
|
/**
|
|
222128
222405
|
* 周期性活性 sweep:
|
|
@@ -222145,7 +222422,7 @@ var init_daemon_hub = __esm({
|
|
|
222145
222422
|
this.sockets.get(id)?.terminate();
|
|
222146
222423
|
continue;
|
|
222147
222424
|
}
|
|
222148
|
-
daemon.send({ type: "ping" });
|
|
222425
|
+
daemon.send({ type: "ping", supportsChunkedMessages: true });
|
|
222149
222426
|
}
|
|
222150
222427
|
}
|
|
222151
222428
|
/** 关闭 hub:停 liveness 定时器并断开所有 daemon。serve 关停时调用。 */
|
|
@@ -222403,17 +222680,11 @@ var init_skill_fetcher = __esm({
|
|
|
222403
222680
|
SKILL_DESCRIPTION_MAX = 600;
|
|
222404
222681
|
Bundle = class {
|
|
222405
222682
|
files = {};
|
|
222406
|
-
totalBytes = 0;
|
|
222407
|
-
fileCount = 0;
|
|
222408
222683
|
add(path40, content3) {
|
|
222409
222684
|
const bytes2 = new TextEncoder().encode(content3).length;
|
|
222410
|
-
if (
|
|
222411
|
-
throw new Error(`
|
|
222412
|
-
if (this.totalBytes + bytes2 > currentFileLimits().skillBundleBytes)
|
|
222413
|
-
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}`);
|
|
222414
222687
|
this.files[path40] = content3;
|
|
222415
|
-
this.totalBytes += bytes2;
|
|
222416
|
-
this.fileCount++;
|
|
222417
222688
|
}
|
|
222418
222689
|
};
|
|
222419
222690
|
}
|
|
@@ -223186,7 +223457,7 @@ ${input.description}
|
|
|
223186
223457
|
const file = this.buildSkillFile(skillId, path40, content3, now);
|
|
223187
223458
|
const existing = await this.opts.store.listSkillFiles(skillId);
|
|
223188
223459
|
const next = [...existing.filter((f2) => f2.path !== path40), file];
|
|
223189
|
-
assertSkillFileLimits(
|
|
223460
|
+
assertSkillFileLimits([file]);
|
|
223190
223461
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
223191
223462
|
if (path40 === "SKILL.md") {
|
|
223192
223463
|
const { name, description } = parseSkillFrontmatter(content3);
|
|
@@ -224235,17 +224506,14 @@ function unpackSkillBundle(bytes2) {
|
|
|
224235
224506
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u7F3A\u5C11 files \u5BF9\u8C61");
|
|
224236
224507
|
}
|
|
224237
224508
|
const out = [];
|
|
224238
|
-
let total = 0;
|
|
224239
224509
|
for (const [path40, content3] of Object.entries(files)) {
|
|
224240
224510
|
if (typeof content3 !== "string") throw new SkillPackageInvalidError(`\u6587\u4EF6 ${path40} \u4E0D\u662F\u6587\u672C`);
|
|
224241
224511
|
if (!isCanonicalRelativePath(path40)) throw new SkillPackageInvalidError(`\u975E\u6CD5\u6280\u80FD\u6587\u4EF6\u8DEF\u5F84\uFF1A${path40}`);
|
|
224242
224512
|
const size = Buffer.byteLength(content3, "utf8");
|
|
224243
224513
|
if (size > currentFileLimits().skillFileBytes) throw new SkillPackageInvalidError(`\u6587\u4EF6\u8FC7\u5927\uFF1A${path40}`);
|
|
224244
|
-
total += size;
|
|
224245
|
-
if (total > currentFileLimits().skillBundleBytes) throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u603B\u5927\u5C0F\u8D85\u9650");
|
|
224246
224514
|
out.push({ path: path40, content: content3 });
|
|
224247
224515
|
}
|
|
224248
|
-
if (out.length === 0
|
|
224516
|
+
if (out.length === 0) {
|
|
224249
224517
|
throw new SkillPackageInvalidError("\u6280\u80FD\u5305\u6587\u4EF6\u6570\u91CF\u975E\u6CD5");
|
|
224250
224518
|
}
|
|
224251
224519
|
if (!out.some((f2) => f2.path === "SKILL.md")) {
|
|
@@ -239905,7 +240173,7 @@ function createChatSessionsDomain(opts) {
|
|
|
239905
240173
|
const outcome = await bridge.read(
|
|
239906
240174
|
loc.nodeId,
|
|
239907
240175
|
{ workdirKey: loc.workdirKey, runtimeKind: loc.runtimeKind, rtId: loc.rtId, path: req.query?.get("path") ?? "" },
|
|
239908
|
-
|
|
240176
|
+
currentFileReadMaxBytes()
|
|
239909
240177
|
);
|
|
239910
240178
|
if (outcome.ok) {
|
|
239911
240179
|
const buf = Buffer.from(outcome.contentBase64, "base64");
|
|
@@ -244333,7 +244601,13 @@ var init_daemon_adapter = __esm({
|
|
|
244333
244601
|
};
|
|
244334
244602
|
this.pending.set(dispatchId, entry);
|
|
244335
244603
|
const sessionAuth = this.sessionAuth ? { ...this.sessionAuth.issue({ nodeId, dispatchId }), gatewayUrl: this.sessionAuth.gatewayUrl } : void 0;
|
|
244336
|
-
|
|
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
|
+
}
|
|
244337
244611
|
if (!sent) {
|
|
244338
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` }));
|
|
244339
244613
|
} else if (this.ackTimeoutMs > 0) {
|
|
@@ -263089,6 +263363,7 @@ var init_trajectory = __esm({
|
|
|
263089
263363
|
|
|
263090
263364
|
// src/index.ts
|
|
263091
263365
|
var fs44 = __toESM(require("node:fs"));
|
|
263366
|
+
init_src();
|
|
263092
263367
|
var os14 = __toESM(require("node:os"));
|
|
263093
263368
|
var path39 = __toESM(require("node:path"));
|
|
263094
263369
|
var import_node_child_process22 = require("node:child_process");
|
|
@@ -270097,6 +270372,9 @@ async function startServe(opts) {
|
|
|
270097
270372
|
// actor→runtime→default 模型解析(内部字段;非用户 per-session 选择)。
|
|
270098
270373
|
// 决策 0032 预派发校验:候选 model 不在该 runtime 的模型目录里 → 不烧会话,
|
|
270099
270374
|
// 回退目录默认并留 warn(曾因 actor 存了残缺 id "claude-sonnet",CLI 秒拒、节点熔断卡死)。
|
|
270375
|
+
// 目录用**绑定那台节点**的(resolveRuntimeModels,与控制台下拉、会话级校验同一份):控制面本机
|
|
270376
|
+
// 的 isModelValid 看的是控制面自己的 CLI 配置,跨机时回落静态 GPT 目录,会把节点上配好的
|
|
270377
|
+
// deepseek-flash 判无效、悄悄换成 gpt-6-astra 派出去(Bug 0209)。
|
|
270100
270378
|
resolveModel: async (actorId) => {
|
|
270101
270379
|
const actors2 = await runActors();
|
|
270102
270380
|
const binding = await actors2.service.resolveBinding()(actorId);
|
|
@@ -270107,13 +270385,14 @@ async function startServe(opts) {
|
|
|
270107
270385
|
candidate = runtimeCfg?.model;
|
|
270108
270386
|
}
|
|
270109
270387
|
if (!candidate) return void 0;
|
|
270110
|
-
|
|
270111
|
-
|
|
270112
|
-
|
|
270113
|
-
|
|
270114
|
-
|
|
270115
|
-
|
|
270116
|
-
|
|
270388
|
+
if (!binding || traceRuntimeKind(binding.runtimeKind) === "custom") return candidate;
|
|
270389
|
+
const runtimeId = `runtime:${binding.nodeId}:${binding.runtimeKind}`;
|
|
270390
|
+
const catalog = await resolveRuntimeModels({ nodeStore, registry: registryStore, nodeReportedModels }, runtimeId).catch(() => []);
|
|
270391
|
+
const checked = resolveDispatchModel(candidate, catalog);
|
|
270392
|
+
if (checked.replaced) {
|
|
270393
|
+
console.warn(`[dispatch] ${actorId} \u914D\u7F6E\u7684\u6A21\u578B '${candidate}' \u4E0D\u5728 ${runtimeId} \u7684\u5019\u9009\u91CC\uFF0C\u56DE\u9000 ${checked.model ?? "CLI \u9ED8\u8BA4"}\uFF08\u51B3\u7B56 0032\uFF09`);
|
|
270394
|
+
}
|
|
270395
|
+
return checked.model;
|
|
270117
270396
|
},
|
|
270118
270397
|
// ADR「agent CLI 启动参数员工级可配置化」:每次派发解析员工 actor_configs.extraArgs 下发(形态同 resolveModel)。
|
|
270119
270398
|
// 只读员工配置,不叠 runtime 默认、不做「没有员工就找 runtime」回退(ADR §3.3 / §4-A)。
|
|
@@ -271424,6 +271703,7 @@ var SessionManager = class {
|
|
|
271424
271703
|
// ../cli/src/daemon/session-process.ts
|
|
271425
271704
|
var fs35 = __toESM(require("node:fs"), 1);
|
|
271426
271705
|
var path30 = __toESM(require("node:path"), 1);
|
|
271706
|
+
var import_node_readline = require("node:readline");
|
|
271427
271707
|
init_wrapper();
|
|
271428
271708
|
init_src();
|
|
271429
271709
|
|
|
@@ -271606,7 +271886,7 @@ var OUTBOX_MAX_FRAMES = 8e3;
|
|
|
271606
271886
|
var isKeyFrame = (m2) => m2.type === "session_started" || m2.type === "session_exited";
|
|
271607
271887
|
async function runSessionProcess(specFile, adapter) {
|
|
271608
271888
|
process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] = "1";
|
|
271609
|
-
const spec = readSpec(specFile);
|
|
271889
|
+
const spec = await readSpec(specFile);
|
|
271610
271890
|
const { dispatchId, job, auth, sessionDir } = spec;
|
|
271611
271891
|
const lock = acquireSessionLock(path30.join(sessionDir, "lock"));
|
|
271612
271892
|
if (!lock && hasFlock()) {
|
|
@@ -271619,13 +271899,24 @@ async function runSessionProcess(specFile, adapter) {
|
|
|
271619
271899
|
const state = new SessionProcessState(spec, adapter, lock);
|
|
271620
271900
|
await state.run();
|
|
271621
271901
|
}
|
|
271622
|
-
function readSpec(specFile) {
|
|
271623
|
-
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 });
|
|
271624
271906
|
try {
|
|
271625
|
-
|
|
271626
|
-
|
|
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
|
+
}
|
|
271627
271919
|
}
|
|
271628
|
-
return spec;
|
|
271629
271920
|
}
|
|
271630
271921
|
var SessionProcessState = class {
|
|
271631
271922
|
constructor(spec, adapter, lock) {
|
|
@@ -271732,16 +272023,21 @@ var SessionProcessState = class {
|
|
|
271732
272023
|
...this.spec.job.artifactId ? { jobArtifactId: this.spec.job.artifactId } : {},
|
|
271733
272024
|
// ADR 0300 D2:自报支持帧号;新服务端据此回带 ackSeq 的 hello-ack,届时才把 serverSupportsDedup 置真。
|
|
271734
272025
|
supportsFrameSeq: true,
|
|
272026
|
+
supportsChunkedMessages: true,
|
|
271735
272027
|
supportsInputConsumptionReceipts: true
|
|
271736
272028
|
});
|
|
271737
272029
|
const toResend = this.serverSupportsDedup ? this.outbox : this.outbox.filter(isKeyFrame);
|
|
271738
272030
|
for (const m2 of toResend) this.rawSend(m2);
|
|
271739
272031
|
});
|
|
272032
|
+
const decoder = new ChunkedMessageDecoder();
|
|
271740
272033
|
ws.on("message", (raw) => {
|
|
271741
272034
|
let msg;
|
|
271742
272035
|
try {
|
|
271743
|
-
|
|
272036
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272037
|
+
if (decoded === void 0) return;
|
|
272038
|
+
msg = decoded;
|
|
271744
272039
|
} catch {
|
|
272040
|
+
ws.close(1007, "Invalid message framing");
|
|
271745
272041
|
return;
|
|
271746
272042
|
}
|
|
271747
272043
|
void this.onServerMessage(msg);
|
|
@@ -272428,6 +272724,7 @@ var DaemonWsClient = class {
|
|
|
272428
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");
|
|
272429
272725
|
this.stop();
|
|
272430
272726
|
}
|
|
272727
|
+
serverSupportsChunkedMessages = false;
|
|
272431
272728
|
connect() {
|
|
272432
272729
|
if (this.stopped) return;
|
|
272433
272730
|
const ws = new import_websocket.default(this.serverUrl, {
|
|
@@ -272441,6 +272738,7 @@ var DaemonWsClient = class {
|
|
|
272441
272738
|
handshakeTimeout: this.handshakeTimeoutMs
|
|
272442
272739
|
});
|
|
272443
272740
|
this.ws = ws;
|
|
272741
|
+
this.serverSupportsChunkedMessages = false;
|
|
272444
272742
|
ws.on("open", () => {
|
|
272445
272743
|
log2("[node-cli]", `connected id=${this.daemonId}`);
|
|
272446
272744
|
this.authRejectStreak = 0;
|
|
@@ -272458,12 +272756,16 @@ var DaemonWsClient = class {
|
|
|
272458
272756
|
}
|
|
272459
272757
|
}, this.pingIntervalMs);
|
|
272460
272758
|
});
|
|
272759
|
+
const decoder = new ChunkedMessageDecoder();
|
|
272461
272760
|
ws.on("message", (raw) => {
|
|
272462
272761
|
this.lastReceivedAt = Date.now();
|
|
272463
272762
|
let msg;
|
|
272464
272763
|
try {
|
|
272465
|
-
|
|
272764
|
+
const decoded = decoder.accept(JSON.parse(raw.toString()));
|
|
272765
|
+
if (decoded === void 0) return;
|
|
272766
|
+
msg = decoded;
|
|
272466
272767
|
} catch {
|
|
272768
|
+
ws.close(1007, "Invalid message framing");
|
|
272467
272769
|
return;
|
|
272468
272770
|
}
|
|
272469
272771
|
void this.handleMessage(msg);
|
|
@@ -272580,6 +272882,7 @@ var DaemonWsClient = class {
|
|
|
272580
272882
|
break;
|
|
272581
272883
|
}
|
|
272582
272884
|
case "ping":
|
|
272885
|
+
this.serverSupportsChunkedMessages = msg.supportsChunkedMessages === true;
|
|
272583
272886
|
this.send({ type: "pong" });
|
|
272584
272887
|
break;
|
|
272585
272888
|
case "ack":
|
|
@@ -272685,7 +272988,9 @@ var DaemonWsClient = class {
|
|
|
272685
272988
|
});
|
|
272686
272989
|
}
|
|
272687
272990
|
send(msg) {
|
|
272688
|
-
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
|
+
}
|
|
272689
272994
|
}
|
|
272690
272995
|
/**
|
|
272691
272996
|
* 待补发流帧数(观测/测试用)。
|
|
@@ -272810,6 +273115,7 @@ var DaemonWsClient = class {
|
|
|
272810
273115
|
// ADR 0554:本 daemon 认 `workdir_walk`。恒 true——handler 随包发,装了这版就一定有。
|
|
272811
273116
|
supportsWorkdirWalk: true,
|
|
272812
273117
|
supportsFileRestore: true,
|
|
273118
|
+
supportsChunkedMessages: true,
|
|
272813
273119
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
272814
273120
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
272815
273121
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -277432,8 +277738,6 @@ ${res.warning}`);
|
|
|
277432
277738
|
const SKIP2 = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store"]);
|
|
277433
277739
|
const limits = await loadFileLimits();
|
|
277434
277740
|
const MAX_FILE_BYTES3 = limits.skillFileBytes;
|
|
277435
|
-
const MAX_FILE_COUNT = limits.skillFileCount;
|
|
277436
|
-
let totalBytes = 0;
|
|
277437
277741
|
const local = {};
|
|
277438
277742
|
const binary = [];
|
|
277439
277743
|
const walk = (abs, rel) => {
|
|
@@ -277447,8 +277751,6 @@ ${res.warning}`);
|
|
|
277447
277751
|
}
|
|
277448
277752
|
const size = fs39.statSync(childAbs).size;
|
|
277449
277753
|
if (size > MAX_FILE_BYTES3) throw new Error(`\u6280\u80FD\u6587\u4EF6\u8D85\u8FC7 ${MAX_FILE_BYTES3 / 1024 / 1024} MiB\uFF1A${childRel}`);
|
|
277450
|
-
totalBytes += size;
|
|
277451
|
-
if (totalBytes > limits.skillBundleBytes) throw new Error(`\u6280\u80FD\u6574\u5305\u8D85\u8FC7 ${limits.skillBundleBytes / 1024 / 1024} MiB`);
|
|
277452
277754
|
const buf = fs39.readFileSync(childAbs);
|
|
277453
277755
|
if (buf.includes(0)) {
|
|
277454
277756
|
binary.push(childRel);
|
|
@@ -277464,7 +277766,6 @@ ${res.warning}`);
|
|
|
277464
277766
|
}
|
|
277465
277767
|
const paths = Object.keys(local);
|
|
277466
277768
|
if (paths.length === 0) throw new Error(`\u76EE\u5F55\u91CC\u6CA1\u6709\u53EF\u4E0A\u4F20\u7684\u6587\u4EF6\uFF1A${dir2}`);
|
|
277467
|
-
if (paths.length > MAX_FILE_COUNT) throw new Error(`\u6280\u80FD\u6587\u4EF6\u6570\u8D85\u8FC7 ${MAX_FILE_COUNT} \u4E2A\uFF1A${paths.length}`);
|
|
277468
277769
|
const skillMd = local["SKILL.md"];
|
|
277469
277770
|
if (skillMd === void 0) {
|
|
277470
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`);
|
|
@@ -278735,7 +279036,7 @@ function shimScript() {
|
|
|
278735
279036
|
}
|
|
278736
279037
|
|
|
278737
279038
|
// src/index.ts
|
|
278738
|
-
var PKG_VERSION = true ? "2.2.
|
|
279039
|
+
var PKG_VERSION = true ? "2.2.46" : "dev";
|
|
278739
279040
|
var LOCAL_BIN = localBin();
|
|
278740
279041
|
var NPM_PREFIX = npmPrefix();
|
|
278741
279042
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -279146,13 +279447,19 @@ function spawnSessionProcess(spec) {
|
|
|
279146
279447
|
fs44.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
279147
279448
|
const specFile = path39.join(dir, "spec.json");
|
|
279148
279449
|
const cfg = readConfig();
|
|
279149
|
-
fs44.
|
|
279150
|
-
|
|
279151
|
-
|
|
279152
|
-
|
|
279153
|
-
|
|
279154
|
-
|
|
279155
|
-
|
|
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
|
+
}
|
|
279156
279463
|
let pinnedDir = INST.currentLink;
|
|
279157
279464
|
try {
|
|
279158
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
|
}
|