@sema-agent/client-core 0.82.7 → 0.83.0
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/CHANGELOG.md +55 -0
- package/README.md +11 -6
- package/dist/adapt/arms.d.ts +3 -2
- package/dist/adapt/arms.js +16 -11
- package/dist/adapt/ids.js +12 -8
- package/dist/adapt/textStream.d.ts +3 -2
- package/dist/adapt/toolCards.d.ts +2 -3
- package/dist/adapt/toolCards.js +1 -1
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +13 -6
- package/dist/adapter/activeRunSelfHeal.js +34 -17
- package/dist/adapter/downstream/eventToSdkMessage.js +1 -1
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -4
- package/dist/adapter/downstream/terminalToSdkResult.js +43 -5
- package/dist/adapter/runStream.js +6 -6
- package/dist/clientSlice.d.ts +0 -5
- package/dist/engineNoticeCodes.js +4 -0
- package/dist/fleet/fleetRowAgentType.d.ts +0 -1
- package/dist/fleet/fleetRowAgentType.js +0 -3
- package/dist/hitl/approvalResolution.js +2 -0
- package/dist/hitl/frameRouter.d.ts +3 -2
- package/dist/hitl/toolApprovalWire.d.ts +1 -0
- package/dist/hitl/toolApprovalWire.js +56 -10
- package/dist/hooksWireCaps.js +27 -1
- package/dist/host.d.ts +1 -0
- package/dist/liveInitToolFace.d.ts +4 -2
- package/dist/liveInitToolFace.js +2 -2
- package/dist/model/catalogLoader.d.ts +1 -6
- package/dist/panelRunningHistory.d.ts +3 -2
- package/dist/peerFrames.d.ts +0 -1
- package/dist/printInitToolFace.js +1 -1
- package/dist/request/printNotification.js +26 -26
- package/dist/seam.d.ts +8 -2
- package/dist/seam.js +18 -7
- package/dist/systemReminderTag.d.ts +0 -1
- package/dist/systemReminderTag.js +0 -3
- package/dist/toolResult.js +1 -0
- package/dist/uuidV5.d.ts +3 -0
- package/dist/uuidV5.js +178 -0
- package/dist/webSearchWireCaps.d.ts +0 -3
- package/dist/webSearchWireCaps.js +21 -51
- package/dist/wireFailureShape.d.ts +2 -1
- package/docs/INTEGRATION-CLIENTS.md +421 -11
- package/package.json +2 -2
package/dist/seam.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TRANSCRIPT_ID_NAMESPACE, uuidV5 } from './uuidV5.js';
|
|
1
2
|
const CHROME_ARM_TABLE = {
|
|
2
3
|
retry_status: { required: false, duty: '渲/清 spinner 的重试覆盖层' },
|
|
3
4
|
panel_task: { required: true, duty: 'publishEngineAgentPanelEvent(event) 原样转发' },
|
|
@@ -63,6 +64,13 @@ const CHROME_ARM_TABLE = {
|
|
|
63
64
|
duty: 'CC-08(0.71.0):每个压缩边界一条,按**最后一条**取当前值;`usedTokens > compactAtTokens` 是引擎的 shouldCompact 谓词,别重算;`windowTokens` 是 autocompact 窗,' +
|
|
64
65
|
'别渲成模型上下文大小;🔴 `sections[].tokens` 与 `usedTokens` 不同坐标系,**禁相减**、禁拿一段比 `compactAtTokens`;`sections` 整键缺席 = 没装配出段 IR,不是各段为零。',
|
|
65
66
|
},
|
|
67
|
+
memory_saved: {
|
|
68
|
+
required: true,
|
|
69
|
+
duty: '0.83.0 起记忆写入不再是转录行,只发本臂。`notes` 是记忆**笔记原文、不是路径**(别拼链接 / 判文件存在);' +
|
|
70
|
+
'要保留「Saved N memories」那一行的宿主把本臂还原成一条转录行:行 uuid 用 `id`(由这次写入的 wire 稳定键派生、重投同值,按它幂等;与 0.82.x 旧行 uuid 不相等),N = `notes.length`,时间戳在接收口取;' +
|
|
71
|
+
'落成 CC 形行时不许再造 `writtenPaths` / `isMeta` 这类 CC 在该臂上不声明的键;每次写入一条事件、本包不合并;' +
|
|
72
|
+
'没收到本臂不等于没写记忆(回执不成形时不发,工具卡照常在);laneProof 为 subagent = 子代写的,别渲成主会话的。',
|
|
73
|
+
},
|
|
66
74
|
compaction_outcome: {
|
|
67
75
|
required: false,
|
|
68
76
|
duty: 'CC-89(0.75.0):一次压缩的非 compacted 结局(作废 / 失败等),给用户一条可见提示。`outcome` / `trigger` 是引擎开集原词,按成员渲染必带 default 臂、认不得照原词显示;' +
|
|
@@ -139,12 +147,15 @@ const CHROME_ARM_TABLE = {
|
|
|
139
147
|
},
|
|
140
148
|
};
|
|
141
149
|
export const CHROME_ARMS = Object.entries(CHROME_ARM_TABLE).map(([kind, d]) => ({ kind, required: d.required, duty: d.duty }));
|
|
142
|
-
export function deriveTranscriptId(frame, ctx) {
|
|
143
|
-
if (typeof frame.id === 'string' && frame.id.length > 0)
|
|
144
|
-
return `wid_${frame.id}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
export function deriveTranscriptId(frame, ctx, suffix) {
|
|
151
|
+
if (typeof frame.id === 'string' && frame.id.length > 0) {
|
|
152
|
+
return uuidV5(TRANSCRIPT_ID_NAMESPACE, suffix !== undefined ? `wid_${frame.id}#${suffix}` : `wid_${frame.id}`);
|
|
153
|
+
}
|
|
154
|
+
if (typeof frame.seq === 'number') {
|
|
155
|
+
return uuidV5(TRANSCRIPT_ID_NAMESPACE, suffix !== undefined ? `wseq#${suffix}_${frame.seq}` : `wseq_${frame.seq}`);
|
|
156
|
+
}
|
|
157
|
+
if (typeof frame.toolCallId === 'string' && frame.toolCallId.length > 0) {
|
|
158
|
+
return uuidV5(TRANSCRIPT_ID_NAMESPACE, suffix !== undefined ? `wtc#${suffix}_${frame.toolCallId}` : `wtc_${frame.toolCallId}`);
|
|
159
|
+
}
|
|
149
160
|
return ctx.uuid();
|
|
150
161
|
}
|
|
@@ -7,6 +7,3 @@ export function unwrapSystemReminder(text) {
|
|
|
7
7
|
export function stripSystemReminderBlocks(text) {
|
|
8
8
|
return text.replace(new RegExp(`${OPEN_TAG_SOURCE}[\\s\\S]*?<\\/system-reminder>`, 'g'), '');
|
|
9
9
|
}
|
|
10
|
-
export function startsWithSystemReminderOpenTag(text) {
|
|
11
|
-
return new RegExp(`^\\s*${OPEN_TAG_SOURCE}`).test(text);
|
|
12
|
-
}
|
package/dist/toolResult.js
CHANGED
package/dist/uuidV5.d.ts
ADDED
package/dist/uuidV5.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
export const TRANSCRIPT_ID_NAMESPACE = '5935225a-0f39-4c72-b409-4893196112ab';
|
|
2
|
+
const HEX = '0123456789abcdef';
|
|
3
|
+
export function utf8Encode(s) {
|
|
4
|
+
let n = 0;
|
|
5
|
+
for (let i = 0; i < s.length; i++) {
|
|
6
|
+
const c = s.charCodeAt(i);
|
|
7
|
+
if (c < 0x80)
|
|
8
|
+
n += 1;
|
|
9
|
+
else if (c < 0x800)
|
|
10
|
+
n += 2;
|
|
11
|
+
else if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length) {
|
|
12
|
+
const d = s.charCodeAt(i + 1);
|
|
13
|
+
if (d >= 0xdc00 && d <= 0xdfff) {
|
|
14
|
+
n += 4;
|
|
15
|
+
i++;
|
|
16
|
+
}
|
|
17
|
+
else
|
|
18
|
+
n += 3;
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
n += 3;
|
|
22
|
+
}
|
|
23
|
+
const out = new Uint8Array(n);
|
|
24
|
+
let p = 0;
|
|
25
|
+
for (let i = 0; i < s.length; i++) {
|
|
26
|
+
let c = s.charCodeAt(i);
|
|
27
|
+
if (c >= 0xd800 && c <= 0xdfff) {
|
|
28
|
+
const d = c <= 0xdbff && i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
|
|
29
|
+
if (c <= 0xdbff && d >= 0xdc00 && d <= 0xdfff) {
|
|
30
|
+
c = 0x10000 + ((c - 0xd800) << 10) + (d - 0xdc00);
|
|
31
|
+
i++;
|
|
32
|
+
out[p++] = 0xf0 | (c >>> 18);
|
|
33
|
+
out[p++] = 0x80 | ((c >>> 12) & 0x3f);
|
|
34
|
+
out[p++] = 0x80 | ((c >>> 6) & 0x3f);
|
|
35
|
+
out[p++] = 0x80 | (c & 0x3f);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
c = 0xfffd;
|
|
39
|
+
}
|
|
40
|
+
if (c < 0x80) {
|
|
41
|
+
out[p++] = c;
|
|
42
|
+
}
|
|
43
|
+
else if (c < 0x800) {
|
|
44
|
+
out[p++] = 0xc0 | (c >>> 6);
|
|
45
|
+
out[p++] = 0x80 | (c & 0x3f);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out[p++] = 0xe0 | (c >>> 12);
|
|
49
|
+
out[p++] = 0x80 | ((c >>> 6) & 0x3f);
|
|
50
|
+
out[p++] = 0x80 | (c & 0x3f);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function sha1(msg) {
|
|
56
|
+
const len = msg.length;
|
|
57
|
+
const blocks = ((len + 8) >>> 6) + 1;
|
|
58
|
+
const buf = new Uint8Array(blocks * 64);
|
|
59
|
+
buf.set(msg);
|
|
60
|
+
buf[len] = 0x80;
|
|
61
|
+
const bitsHi = Math.floor(len / 0x20000000);
|
|
62
|
+
const bitsLo = (len << 3) >>> 0;
|
|
63
|
+
const end = buf.length;
|
|
64
|
+
buf[end - 8] = (bitsHi >>> 24) & 0xff;
|
|
65
|
+
buf[end - 7] = (bitsHi >>> 16) & 0xff;
|
|
66
|
+
buf[end - 6] = (bitsHi >>> 8) & 0xff;
|
|
67
|
+
buf[end - 5] = bitsHi & 0xff;
|
|
68
|
+
buf[end - 4] = (bitsLo >>> 24) & 0xff;
|
|
69
|
+
buf[end - 3] = (bitsLo >>> 16) & 0xff;
|
|
70
|
+
buf[end - 2] = (bitsLo >>> 8) & 0xff;
|
|
71
|
+
buf[end - 1] = bitsLo & 0xff;
|
|
72
|
+
let h0 = 0x67452301;
|
|
73
|
+
let h1 = 0xefcdab89;
|
|
74
|
+
let h2 = 0x98badcfe;
|
|
75
|
+
let h3 = 0x10325476;
|
|
76
|
+
let h4 = 0xc3d2e1f0;
|
|
77
|
+
const w = new Int32Array(80);
|
|
78
|
+
for (let off = 0; off < end; off += 64) {
|
|
79
|
+
for (let t = 0; t < 16; t++) {
|
|
80
|
+
const q = off + t * 4;
|
|
81
|
+
w[t] = ((buf[q] ?? 0) << 24) | ((buf[q + 1] ?? 0) << 16) | ((buf[q + 2] ?? 0) << 8) | (buf[q + 3] ?? 0);
|
|
82
|
+
}
|
|
83
|
+
for (let t = 16; t < 80; t++) {
|
|
84
|
+
const x = (w[t - 3] ?? 0) ^ (w[t - 8] ?? 0) ^ (w[t - 14] ?? 0) ^ (w[t - 16] ?? 0);
|
|
85
|
+
w[t] = (x << 1) | (x >>> 31);
|
|
86
|
+
}
|
|
87
|
+
let a = h0;
|
|
88
|
+
let b = h1;
|
|
89
|
+
let c = h2;
|
|
90
|
+
let d = h3;
|
|
91
|
+
let e = h4;
|
|
92
|
+
for (let t = 0; t < 80; t++) {
|
|
93
|
+
let f;
|
|
94
|
+
let k;
|
|
95
|
+
if (t < 20) {
|
|
96
|
+
f = (b & c) | (~b & d);
|
|
97
|
+
k = 0x5a827999;
|
|
98
|
+
}
|
|
99
|
+
else if (t < 40) {
|
|
100
|
+
f = b ^ c ^ d;
|
|
101
|
+
k = 0x6ed9eba1;
|
|
102
|
+
}
|
|
103
|
+
else if (t < 60) {
|
|
104
|
+
f = (b & c) | (b & d) | (c & d);
|
|
105
|
+
k = 0x8f1bbcdc;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
f = b ^ c ^ d;
|
|
109
|
+
k = 0xca62c1d6;
|
|
110
|
+
}
|
|
111
|
+
const tmp = (((a << 5) | (a >>> 27)) + f + e + k + (w[t] ?? 0)) | 0;
|
|
112
|
+
e = d;
|
|
113
|
+
d = c;
|
|
114
|
+
c = (b << 30) | (b >>> 2);
|
|
115
|
+
b = a;
|
|
116
|
+
a = tmp;
|
|
117
|
+
}
|
|
118
|
+
h0 = (h0 + a) | 0;
|
|
119
|
+
h1 = (h1 + b) | 0;
|
|
120
|
+
h2 = (h2 + c) | 0;
|
|
121
|
+
h3 = (h3 + d) | 0;
|
|
122
|
+
h4 = (h4 + e) | 0;
|
|
123
|
+
}
|
|
124
|
+
const out = new Uint8Array(20);
|
|
125
|
+
const hs = [h0, h1, h2, h3, h4];
|
|
126
|
+
for (let i = 0; i < 5; i++) {
|
|
127
|
+
const h = hs[i] ?? 0;
|
|
128
|
+
out[i * 4] = (h >>> 24) & 0xff;
|
|
129
|
+
out[i * 4 + 1] = (h >>> 16) & 0xff;
|
|
130
|
+
out[i * 4 + 2] = (h >>> 8) & 0xff;
|
|
131
|
+
out[i * 4 + 3] = h & 0xff;
|
|
132
|
+
}
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
function hexVal(ch) {
|
|
136
|
+
if (ch >= 0x30 && ch <= 0x39)
|
|
137
|
+
return ch - 0x30;
|
|
138
|
+
if (ch >= 0x61 && ch <= 0x66)
|
|
139
|
+
return ch - 0x61 + 10;
|
|
140
|
+
if (ch >= 0x41 && ch <= 0x46)
|
|
141
|
+
return ch - 0x41 + 10;
|
|
142
|
+
return -1;
|
|
143
|
+
}
|
|
144
|
+
export function uuidV5(namespace, name) {
|
|
145
|
+
if (namespace.length !== 36)
|
|
146
|
+
throw new TypeError('uuidV5: namespace must be a 36-character UUID string');
|
|
147
|
+
const ns = new Uint8Array(16);
|
|
148
|
+
let j = 0;
|
|
149
|
+
for (let i = 0; i < 36; i++) {
|
|
150
|
+
const ch = namespace.charCodeAt(i);
|
|
151
|
+
if (i === 8 || i === 13 || i === 18 || i === 23) {
|
|
152
|
+
if (ch !== 0x2d)
|
|
153
|
+
throw new TypeError('uuidV5: namespace must be a 36-character UUID string');
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const hi = hexVal(ch);
|
|
157
|
+
const lo = hexVal(namespace.charCodeAt(i + 1));
|
|
158
|
+
if (hi < 0 || lo < 0)
|
|
159
|
+
throw new TypeError('uuidV5: namespace must be a 36-character UUID string');
|
|
160
|
+
ns[j++] = (hi << 4) | lo;
|
|
161
|
+
i++;
|
|
162
|
+
}
|
|
163
|
+
const nameBytes = utf8Encode(name);
|
|
164
|
+
const input = new Uint8Array(16 + nameBytes.length);
|
|
165
|
+
input.set(ns);
|
|
166
|
+
input.set(nameBytes, 16);
|
|
167
|
+
const h = sha1(input);
|
|
168
|
+
h[6] = ((h[6] ?? 0) & 0x0f) | 0x50;
|
|
169
|
+
h[8] = ((h[8] ?? 0) & 0x3f) | 0x80;
|
|
170
|
+
let s = '';
|
|
171
|
+
for (let i = 0; i < 16; i++) {
|
|
172
|
+
if (i === 4 || i === 6 || i === 8 || i === 10)
|
|
173
|
+
s += '-';
|
|
174
|
+
const b = h[i] ?? 0;
|
|
175
|
+
s += HEX.charAt(b >>> 4) + HEX.charAt(b & 0x0f);
|
|
176
|
+
}
|
|
177
|
+
return s;
|
|
178
|
+
}
|
|
@@ -13,9 +13,6 @@ export declare const WEBSEARCH_ENV: {
|
|
|
13
13
|
readonly apiKey: "SEMA_WEBSEARCH_API_KEY";
|
|
14
14
|
readonly maxResults: "SEMA_WEBSEARCH_MAX_RESULTS";
|
|
15
15
|
};
|
|
16
|
-
export declare function webSearchFromEnv(env?: EnvLike): WebSearchSettings | undefined;
|
|
17
|
-
export declare function webSearchFromSettings(raw: unknown): WebSearchSettings | undefined;
|
|
18
|
-
export declare function resolveWebSearch(env?: EnvLike, settingsRaw?: unknown): WebSearchSettings | undefined;
|
|
19
16
|
export type WebSearchSettingsField = 'section' | 'provider' | 'apiKey' | 'endpoint' | 'searxngParams' | 'maxResults';
|
|
20
17
|
export type WebSearchSettingsVerdict = {
|
|
21
18
|
kind: 'absent';
|
|
@@ -5,41 +5,6 @@ export const WEBSEARCH_ENV = {
|
|
|
5
5
|
apiKey: 'SEMA_WEBSEARCH_API_KEY',
|
|
6
6
|
maxResults: 'SEMA_WEBSEARCH_MAX_RESULTS',
|
|
7
7
|
};
|
|
8
|
-
function normProvider(v) {
|
|
9
|
-
const p = typeof v === 'string' ? v.trim().toLowerCase() : '';
|
|
10
|
-
return p === 'brave' || p === 'tavily' || p === 'searxng' ? p : undefined;
|
|
11
|
-
}
|
|
12
|
-
function normMax(v) {
|
|
13
|
-
const n = typeof v === 'number' ? v : Number(v);
|
|
14
|
-
return Number.isFinite(n) && n > 0 ? Math.floor(n) : undefined;
|
|
15
|
-
}
|
|
16
|
-
function build(provider, apiKey, endpoint, maxResults) {
|
|
17
|
-
const max = normMax(maxResults);
|
|
18
|
-
return {
|
|
19
|
-
provider,
|
|
20
|
-
...(typeof apiKey === 'string' && apiKey ? { apiKey } : {}),
|
|
21
|
-
...(typeof endpoint === 'string' && endpoint ? { endpoint } : {}),
|
|
22
|
-
...(max ? { maxResults: max } : {}),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function webSearchFromEnv(env = hostEnv()) {
|
|
26
|
-
const provider = normProvider(env[WEBSEARCH_ENV.provider]);
|
|
27
|
-
if (!provider)
|
|
28
|
-
return undefined;
|
|
29
|
-
return build(provider, env[WEBSEARCH_ENV.apiKey], env[WEBSEARCH_ENV.endpoint], env[WEBSEARCH_ENV.maxResults]);
|
|
30
|
-
}
|
|
31
|
-
export function webSearchFromSettings(raw) {
|
|
32
|
-
if (!raw || typeof raw !== 'object')
|
|
33
|
-
return undefined;
|
|
34
|
-
const s = raw;
|
|
35
|
-
const provider = normProvider(s.provider);
|
|
36
|
-
if (!provider)
|
|
37
|
-
return undefined;
|
|
38
|
-
return build(provider, s.apiKey, s.endpoint, s.maxResults);
|
|
39
|
-
}
|
|
40
|
-
export function resolveWebSearch(env = hostEnv(), settingsRaw) {
|
|
41
|
-
return webSearchFromEnv(env) ?? webSearchFromSettings(settingsRaw);
|
|
42
|
-
}
|
|
43
8
|
const isBlankText = (v) => v.trim() === '';
|
|
44
9
|
function isHierarchicalUrl(raw) {
|
|
45
10
|
try {
|
|
@@ -54,12 +19,11 @@ function judgeProvider(raw) {
|
|
|
54
19
|
const word = typeof raw === 'string' ? raw.trim().toLowerCase() : undefined;
|
|
55
20
|
if (word === 'brave' || word === 'tavily' || word === 'searxng')
|
|
56
21
|
return { ok: true, value: word };
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return { ok: false, issue: `must be one of brave | tavily | searxng (${got}); it names where searches go, so an unknown or missing provider is refused rather than replaced` };
|
|
22
|
+
const shape = raw === undefined || raw === null ? 'it is missing' : typeof raw === 'string' ? 'it is not one of them' : 'it is not a string';
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
issue: `must name one of brave | tavily | searxng (${shape}) — it names where this request's searches go, so an unknown or missing provider is refused rather than replaced by this deployment's own backend`,
|
|
26
|
+
};
|
|
63
27
|
}
|
|
64
28
|
function judgeText(raw) {
|
|
65
29
|
if (raw === undefined || raw === null)
|
|
@@ -76,7 +40,12 @@ function judgeEndpoint(raw) {
|
|
|
76
40
|
return { ok: false, issue: ENDPOINT_ISSUE };
|
|
77
41
|
if (isBlankText(raw))
|
|
78
42
|
return { ok: true, value: undefined };
|
|
79
|
-
|
|
43
|
+
if (!isHierarchicalUrl(raw))
|
|
44
|
+
return { ok: false, issue: ENDPOINT_ISSUE };
|
|
45
|
+
const u = new URL(raw);
|
|
46
|
+
return u.username !== '' || u.password !== ''
|
|
47
|
+
? { ok: false, issue: 'must not carry userinfo (user or user:password before the host)' }
|
|
48
|
+
: { ok: true, value: raw };
|
|
80
49
|
}
|
|
81
50
|
const COUNT_ISSUE = 'must be a number ≥ 1';
|
|
82
51
|
function judgeCount(raw) {
|
|
@@ -97,7 +66,7 @@ function judgeSearxngParams(raw) {
|
|
|
97
66
|
continue;
|
|
98
67
|
const eq = seg.indexOf('=');
|
|
99
68
|
if (eq < 0)
|
|
100
|
-
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE}
|
|
69
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — entry #${i + 1} has no "="` };
|
|
101
70
|
pairs.push([seg.slice(0, eq).trim(), seg.slice(eq + 1).trim(), i + 1]);
|
|
102
71
|
}
|
|
103
72
|
}
|
|
@@ -106,22 +75,23 @@ function judgeSearxngParams(raw) {
|
|
|
106
75
|
for (let i = 0; i < entries.length; i++) {
|
|
107
76
|
const [k, v] = entries[i];
|
|
108
77
|
if (typeof v !== 'string')
|
|
109
|
-
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE}
|
|
78
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — entry #${i + 1} has a value that is not a string` };
|
|
110
79
|
pairs.push([k, v.trim(), i + 1]);
|
|
111
80
|
}
|
|
112
81
|
}
|
|
113
82
|
else {
|
|
114
|
-
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE}
|
|
83
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — got ${Array.isArray(raw) ? 'an array' : `a ${typeof raw}`}` };
|
|
115
84
|
}
|
|
116
|
-
const
|
|
85
|
+
const firstEntryOf = new Map();
|
|
117
86
|
for (const [k, v, n] of pairs) {
|
|
118
87
|
if (!/^[A-Za-z0-9_.-]+$/.test(k))
|
|
119
|
-
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE}
|
|
88
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — entry #${n} has a name that is not a parameter name (letters, digits, "_", "-", ".")` };
|
|
120
89
|
if (v === '')
|
|
121
|
-
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
90
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — entry #${n} has an empty value` };
|
|
91
|
+
const first = firstEntryOf.get(k);
|
|
92
|
+
if (first !== undefined)
|
|
93
|
+
return { ok: false, issue: `${SEARXNG_PARAMS_ISSUE} — entry #${n} repeats the name of entry #${first}` };
|
|
94
|
+
firstEntryOf.set(k, n);
|
|
125
95
|
}
|
|
126
96
|
return { ok: true, value: pairs.length === 0 ? undefined : Object.fromEntries(pairs.map(([k, v]) => [k, v])) };
|
|
127
97
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
interface WireFailureShape {
|
|
2
2
|
status?: number;
|
|
3
3
|
errorCode?: string;
|
|
4
4
|
retryAfterSec?: number;
|
|
@@ -9,3 +9,4 @@ export declare function readErrorNumber(o: object, key: string): number | undefi
|
|
|
9
9
|
export declare function readErrorString(o: object, key: string): string | undefined;
|
|
10
10
|
export declare function readErrorStringList(o: object, key: string): readonly string[] | undefined;
|
|
11
11
|
export declare function wireFailureShapeOf(e: unknown): WireFailureShape;
|
|
12
|
+
export {};
|