@kvman/kvcoder 0.1.11 → 0.1.13
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/api.d.ts +45 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/calls/call-name.d.ts.map +1 -1
- package/dist/calls/call-name.js +10 -1
- package/dist/calls/call-name.js.map +1 -1
- package/dist/calls/run-tool.d.ts.map +1 -1
- package/dist/calls/run-tool.js +2 -0
- package/dist/calls/run-tool.js.map +1 -1
- package/dist/connector-call.d.ts +2 -2
- package/dist/connector-call.d.ts.map +1 -1
- package/dist/connector-call.js +5 -3
- package/dist/connector-call.js.map +1 -1
- package/dist/connectors/artifact.d.ts +1 -0
- package/dist/connectors/artifact.d.ts.map +1 -1
- package/dist/connectors/background.d.ts.map +1 -1
- package/dist/connectors/background.js +8 -4
- package/dist/connectors/background.js.map +1 -1
- package/dist/connectors/builtin-connectors.d.ts +38 -0
- package/dist/connectors/builtin-connectors.d.ts.map +1 -1
- package/dist/connectors/builtin-connectors.js +4 -1
- package/dist/connectors/builtin-connectors.js.map +1 -1
- package/dist/connectors/delegate.d.ts.map +1 -1
- package/dist/connectors/delegate.js +3 -0
- package/dist/connectors/delegate.js.map +1 -1
- package/dist/connectors/execution-map.d.ts +1 -1
- package/dist/connectors/execution-map.d.ts.map +1 -1
- package/dist/connectors/execution-map.js +1 -1
- package/dist/connectors/execution-map.js.map +1 -1
- package/dist/connectors/fs.d.ts +29 -1
- package/dist/connectors/fs.d.ts.map +1 -1
- package/dist/connectors/fs.js +46 -9
- package/dist/connectors/fs.js.map +1 -1
- package/dist/connectors/payload-fields.d.ts +3 -0
- package/dist/connectors/payload-fields.d.ts.map +1 -1
- package/dist/connectors/payload-fields.js +8 -2
- package/dist/connectors/payload-fields.js.map +1 -1
- package/dist/connectors/web.d.ts +16 -0
- package/dist/connectors/web.d.ts.map +1 -0
- package/dist/connectors/web.js +22 -0
- package/dist/connectors/web.js.map +1 -0
- package/dist/delegate/permission.d.ts +6 -0
- package/dist/delegate/permission.d.ts.map +1 -1
- package/dist/files/change-diff.d.ts +17 -0
- package/dist/files/change-diff.d.ts.map +1 -0
- package/dist/files/change-diff.js +59 -0
- package/dist/files/change-diff.js.map +1 -0
- package/dist/files/edit-places.d.ts +11 -0
- package/dist/files/edit-places.d.ts.map +1 -0
- package/dist/files/edit-places.js +105 -0
- package/dist/files/edit-places.js.map +1 -0
- package/dist/files/edit-text.d.ts +1 -0
- package/dist/files/edit-text.d.ts.map +1 -1
- package/dist/files/edit-text.js +22 -10
- package/dist/files/edit-text.js.map +1 -1
- package/dist/files/file-change.d.ts.map +1 -1
- package/dist/files/file-change.js +12 -0
- package/dist/files/file-change.js.map +1 -1
- package/dist/files/find-paths.d.ts +9 -0
- package/dist/files/find-paths.d.ts.map +1 -0
- package/dist/files/find-paths.js +38 -0
- package/dist/files/find-paths.js.map +1 -0
- package/dist/files/read-file.d.ts +3 -1
- package/dist/files/read-file.d.ts.map +1 -1
- package/dist/files/read-file.js +7 -6
- package/dist/files/read-file.js.map +1 -1
- package/dist/files/read-files.d.ts +11 -0
- package/dist/files/read-files.d.ts.map +1 -0
- package/dist/files/read-files.js +35 -0
- package/dist/files/read-files.js.map +1 -0
- package/dist/files/read-text.d.ts +63 -0
- package/dist/files/read-text.d.ts.map +1 -0
- package/dist/files/read-text.js +67 -0
- package/dist/files/read-text.js.map +1 -0
- package/dist/files/register-changes.d.ts +3 -0
- package/dist/files/register-changes.d.ts.map +1 -0
- package/dist/files/register-changes.js +78 -0
- package/dist/files/register-changes.js.map +1 -0
- package/dist/files/search-text.d.ts +10 -1
- package/dist/files/search-text.d.ts.map +1 -1
- package/dist/files/search-text.js +32 -57
- package/dist/files/search-text.js.map +1 -1
- package/dist/files/workspace-files.d.ts +5 -0
- package/dist/files/workspace-files.d.ts.map +1 -0
- package/dist/files/workspace-files.js +66 -0
- package/dist/files/workspace-files.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/prompt/build-prompt.d.ts +4 -0
- package/dist/prompt/build-prompt.d.ts.map +1 -1
- package/dist/prompt/build-prompt.js +6 -2
- package/dist/prompt/build-prompt.js.map +1 -1
- package/dist/prompt/person-preferences.d.ts +5 -0
- package/dist/prompt/person-preferences.d.ts.map +1 -0
- package/dist/prompt/person-preferences.js +14 -0
- package/dist/prompt/person-preferences.js.map +1 -0
- package/dist/prompt/session-grants.d.ts +4 -0
- package/dist/prompt/session-grants.d.ts.map +1 -1
- package/dist/prompt/session-grants.js +3 -2
- package/dist/prompt/session-grants.js.map +1 -1
- package/dist/prompt/session-prompt.d.ts.map +1 -1
- package/dist/prompt/session-prompt.js +15 -6
- package/dist/prompt/session-prompt.js.map +1 -1
- package/dist/prompt/working-method.d.ts +2 -2
- package/dist/prompt/working-method.d.ts.map +1 -1
- package/dist/prompt/working-method.js +49 -43
- package/dist/prompt/working-method.js.map +1 -1
- package/dist/register-settings.d.ts +23 -0
- package/dist/register-settings.d.ts.map +1 -1
- package/dist/register-settings.js +13 -0
- package/dist/register-settings.js.map +1 -1
- package/dist/schemas/approval-rule.d.ts +9 -0
- package/dist/schemas/approval-rule.d.ts.map +1 -0
- package/dist/schemas/approval-rule.js +7 -0
- package/dist/schemas/approval-rule.js.map +1 -0
- package/dist/schemas/check.d.ts +7 -0
- package/dist/schemas/check.d.ts.map +1 -0
- package/dist/schemas/check.js +9 -0
- package/dist/schemas/check.js.map +1 -0
- package/dist/schemas/records.d.ts +10 -0
- package/dist/schemas/records.d.ts.map +1 -1
- package/dist/schemas/records.js +8 -0
- package/dist/schemas/records.js.map +1 -1
- package/dist/sessions/new-session.d.ts.map +1 -1
- package/dist/sessions/new-session.js +4 -1
- package/dist/sessions/new-session.js.map +1 -1
- package/dist/sessions/register-fork-export.d.ts.map +1 -1
- package/dist/sessions/register-fork-export.js +3 -2
- package/dist/sessions/register-fork-export.js.map +1 -1
- package/dist/sessions/register-sessions.d.ts.map +1 -1
- package/dist/sessions/register-sessions.js +17 -9
- package/dist/sessions/register-sessions.js.map +1 -1
- package/dist/sessions/session-view.d.ts +8 -1
- package/dist/sessions/session-view.d.ts.map +1 -1
- package/dist/sessions/session-view.js +6 -1
- package/dist/sessions/session-view.js.map +1 -1
- package/dist/sessions/waiting-on.d.ts +7 -0
- package/dist/sessions/waiting-on.d.ts.map +1 -0
- package/dist/sessions/waiting-on.js +20 -0
- package/dist/sessions/waiting-on.js.map +1 -0
- package/dist/store/collections.d.ts +18 -0
- package/dist/store/collections.d.ts.map +1 -1
- package/dist/store/collections.js +3 -1
- package/dist/store/collections.js.map +1 -1
- package/dist/turns/answer-extras.d.ts +21 -0
- package/dist/turns/answer-extras.d.ts.map +1 -0
- package/dist/turns/answer-extras.js +43 -0
- package/dist/turns/answer-extras.js.map +1 -0
- package/dist/turns/answer-fingerprint.d.ts +6 -2
- package/dist/turns/answer-fingerprint.d.ts.map +1 -1
- package/dist/turns/answer-fingerprint.js +9 -3
- package/dist/turns/answer-fingerprint.js.map +1 -1
- package/dist/turns/apply-answer.d.ts +2 -1
- package/dist/turns/apply-answer.d.ts.map +1 -1
- package/dist/turns/apply-answer.js +10 -4
- package/dist/turns/apply-answer.js.map +1 -1
- package/dist/turns/approval-rules.d.ts +13 -0
- package/dist/turns/approval-rules.d.ts.map +1 -0
- package/dist/turns/approval-rules.js +65 -0
- package/dist/turns/approval-rules.js.map +1 -0
- package/dist/turns/check-after-edits.d.ts +8 -0
- package/dist/turns/check-after-edits.d.ts.map +1 -0
- package/dist/turns/check-after-edits.js +23 -0
- package/dist/turns/check-after-edits.js.map +1 -0
- package/dist/turns/clear-results.d.ts +15 -0
- package/dist/turns/clear-results.d.ts.map +1 -0
- package/dist/turns/clear-results.js +58 -0
- package/dist/turns/clear-results.js.map +1 -0
- package/dist/turns/cleared-results.d.ts +17 -0
- package/dist/turns/cleared-results.d.ts.map +1 -0
- package/dist/turns/cleared-results.js +46 -0
- package/dist/turns/cleared-results.js.map +1 -0
- package/dist/turns/compaction.js +6 -6
- package/dist/turns/compaction.js.map +1 -1
- package/dist/turns/file-results.d.ts +15 -0
- package/dist/turns/file-results.d.ts.map +1 -0
- package/dist/turns/file-results.js +39 -0
- package/dist/turns/file-results.js.map +1 -0
- package/dist/turns/lost-reply.js +2 -2
- package/dist/turns/lost-reply.js.map +1 -1
- package/dist/turns/model-context.d.ts +2 -0
- package/dist/turns/model-context.d.ts.map +1 -1
- package/dist/turns/model-context.js +28 -5
- package/dist/turns/model-context.js.map +1 -1
- package/dist/turns/read-again.d.ts +11 -5
- package/dist/turns/read-again.d.ts.map +1 -1
- package/dist/turns/read-again.js +39 -10
- package/dist/turns/read-again.js.map +1 -1
- package/dist/turns/register-turns.d.ts.map +1 -1
- package/dist/turns/register-turns.js +12 -4
- package/dist/turns/register-turns.js.map +1 -1
- package/dist/turns/run-calls.d.ts +4 -0
- package/dist/turns/run-calls.d.ts.map +1 -1
- package/dist/turns/run-calls.js +35 -5
- package/dist/turns/run-calls.js.map +1 -1
- package/dist/turns/run-command.d.ts.map +1 -1
- package/dist/turns/run-command.js +4 -4
- package/dist/turns/run-command.js.map +1 -1
- package/dist/turns/step.d.ts.map +1 -1
- package/dist/turns/step.js +43 -8
- package/dist/turns/step.js.map +1 -1
- package/dist/ui/register-ui.js +2 -2
- package/dist/ui/register-ui.js.map +1 -1
- package/dist/web/components/approval.css +1 -1
- package/dist/web/components/approval.js +122 -89
- package/dist/web/components/call.css +1 -1
- package/dist/web/components/call.js +403 -305
- package/dist/web/components/connectors.css +1 -1
- package/dist/web/components/connectors.js +440 -427
- package/dist/web/components/conversation.css +1 -1
- package/dist/web/components/conversation.js +2532 -1503
- package/dist/web/components/mcp-sign-in.css +1 -1
- package/dist/web/components/model.css +1 -1
- package/dist/web/components/model.js +138 -126
- package/dist/web/components/preferences.css +2 -0
- package/dist/web/components/preferences.js +151 -0
- package/dist/web/components/question.css +1 -1
- package/dist/web/components/sessions.css +1 -1
- package/dist/web/components/sessions.js +44 -21
- package/dist/web-fetch/fetch-page.d.ts +28 -0
- package/dist/web-fetch/fetch-page.d.ts.map +1 -0
- package/dist/web-fetch/fetch-page.js +108 -0
- package/dist/web-fetch/fetch-page.js.map +1 -0
- package/dist/web-fetch/private-address.d.ts +3 -0
- package/dist/web-fetch/private-address.d.ts.map +1 -0
- package/dist/web-fetch/private-address.js +69 -0
- package/dist/web-fetch/private-address.js.map +1 -0
- package/dist/web-fetch/web-hosts.d.ts +7 -0
- package/dist/web-fetch/web-hosts.d.ts.map +1 -0
- package/dist/web-fetch/web-hosts.js +19 -0
- package/dist/web-fetch/web-hosts.js.map +1 -0
- package/docs/connectors.md +2 -2
- package/locales/ar.json +80 -14
- package/locales/en.json +81 -15
- package/package.json +20 -6
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { lookup } from 'node:dns/promises';
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import https from 'node:https';
|
|
4
|
+
import { isIP } from 'node:net';
|
|
5
|
+
import { ProblemError } from '@kvman/sdk';
|
|
6
|
+
import { invalid } from "../problems.js";
|
|
7
|
+
import { truncate } from "../result-text.js";
|
|
8
|
+
import { isPrivateAddress } from "./private-address.js";
|
|
9
|
+
// `web fetch` (plan 08 §8.5, ADR 0095): a page by its address, as Markdown or text. Every host is resolved and checked
|
|
10
|
+
// before each request and each redirect, and the connection goes to the address that was checked.
|
|
11
|
+
export const bodyLimit = 5 * 1024 * 1024;
|
|
12
|
+
const redirectLimit = 5;
|
|
13
|
+
const pageTimeoutMs = 30_000;
|
|
14
|
+
const textTypes = new Set(['application/json', 'application/xml', 'application/javascript']);
|
|
15
|
+
export const webFailed = (url, fields) => new ProblemError({ code: 'kvcoder/WEB_FAILED', message: `${url} couldn't be read: ${fields.status === undefined ? fields.reason ?? 'it failed' : `status ${String(fields.status)}`}.`, params: { url, ...fields } });
|
|
16
|
+
// Reads at most the body limit; the rest of a larger body is left unread.
|
|
17
|
+
function readBody(response) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const chunks = [];
|
|
20
|
+
let size = 0;
|
|
21
|
+
response.on('data', (chunk) => {
|
|
22
|
+
chunks.push(chunk);
|
|
23
|
+
size += chunk.length;
|
|
24
|
+
if (size >= bodyLimit)
|
|
25
|
+
response.destroy();
|
|
26
|
+
});
|
|
27
|
+
response.on('close', () => resolve(Buffer.concat(chunks).subarray(0, bodyLimit)));
|
|
28
|
+
response.on('error', reject);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** The network: Node's resolver, and a request pinned to the checked address. */
|
|
32
|
+
export const networkTransport = {
|
|
33
|
+
resolve: async (host) => (isIP(host) !== 0 ? [host] : (await lookup(host, { all: true, verbatim: true })).map((found) => found.address)),
|
|
34
|
+
request: (url, address, signal) => new Promise((resolve, reject) => {
|
|
35
|
+
const client = url.protocol === 'https:' ? https : http;
|
|
36
|
+
// Every lookup of this request answers the checked address, so a second resolution can't move it.
|
|
37
|
+
const pinned = (_host, options, done) => {
|
|
38
|
+
if (options.all === true)
|
|
39
|
+
done(null, [{ address, family: isIP(address) }]);
|
|
40
|
+
else
|
|
41
|
+
done(null, address, isIP(address));
|
|
42
|
+
};
|
|
43
|
+
const request = client.request(url, { method: 'GET', signal, lookup: pinned, headers: { accept: 'text/html, text/markdown, text/plain, application/json;q=0.9, */*;q=0.1', 'user-agent': 'kvman' } }, (response) => {
|
|
44
|
+
readBody(response).then((body) => resolve({ status: response.statusCode ?? 0, type: String(response.headers['content-type'] ?? ''), location: response.headers.location, body }), reject);
|
|
45
|
+
});
|
|
46
|
+
request.on('error', reject);
|
|
47
|
+
request.end();
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
// turndown brings a whole DOM, about 14 MB, so a worker loads it with its first page, not at start (plan 12 §12.3).
|
|
51
|
+
async function markdownOf(html) {
|
|
52
|
+
const { default: TurndownService } = await import('turndown');
|
|
53
|
+
const turndown = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' });
|
|
54
|
+
turndown.remove(['script', 'style', 'noscript']);
|
|
55
|
+
return turndown.turndown(html);
|
|
56
|
+
}
|
|
57
|
+
// A checked address of the host, or a refusal naming it.
|
|
58
|
+
async function checkedAddress(transport, url) {
|
|
59
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
60
|
+
const addresses = await transport.resolve(host);
|
|
61
|
+
const [first] = addresses;
|
|
62
|
+
if (first === undefined || addresses.some(isPrivateAddress))
|
|
63
|
+
throw invalid(`${url.hostname} is a private or local address, which web fetch doesn't reach.`, { url: url.href });
|
|
64
|
+
return first;
|
|
65
|
+
}
|
|
66
|
+
function parsed(given) {
|
|
67
|
+
const url = URL.canParse(given) ? new URL(given) : undefined;
|
|
68
|
+
if (url === undefined || (url.protocol !== 'http:' && url.protocol !== 'https:'))
|
|
69
|
+
throw invalid('The address must start with http:// or https://.', { url: given });
|
|
70
|
+
if (url.username !== '' || url.password !== '')
|
|
71
|
+
throw invalid("The address can't hold a name or a password.", { url: given });
|
|
72
|
+
return url;
|
|
73
|
+
}
|
|
74
|
+
async function contentOf(type, body, url) {
|
|
75
|
+
const text = body.toString('utf8');
|
|
76
|
+
if (type === 'text/html' || type === 'application/xhtml+xml')
|
|
77
|
+
return markdownOf(text);
|
|
78
|
+
if (type.startsWith('text/') || textTypes.has(type) || type.endsWith('+json'))
|
|
79
|
+
return text;
|
|
80
|
+
throw invalid(`${url} is ${type === '' ? 'of no stated type' : type}, which web fetch doesn't read; only pages and text.`, { url, type });
|
|
81
|
+
}
|
|
82
|
+
/** Fetches a page, following redirects, each checked again. */
|
|
83
|
+
export async function fetchPage(given, transport, signal) {
|
|
84
|
+
let url = parsed(given);
|
|
85
|
+
const timeout = AbortSignal.any([signal, AbortSignal.timeout(pageTimeoutMs)]);
|
|
86
|
+
for (let redirects = 0;; redirects += 1) {
|
|
87
|
+
const address = await checkedAddress(transport, url);
|
|
88
|
+
let response;
|
|
89
|
+
try {
|
|
90
|
+
response = await transport.request(url, address, timeout);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
signal.throwIfAborted();
|
|
94
|
+
throw webFailed(url.href, { reason: timeout.aborted ? 'it took longer than 30 s' : error instanceof Error ? error.message : 'the connection failed' });
|
|
95
|
+
}
|
|
96
|
+
if (response.status >= 300 && response.status < 400 && response.location !== undefined) {
|
|
97
|
+
if (redirects === redirectLimit)
|
|
98
|
+
throw webFailed(url.href, { reason: `more than ${String(redirectLimit)} redirects` });
|
|
99
|
+
url = parsed(new URL(response.location, url).href);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (response.status >= 400)
|
|
103
|
+
throw webFailed(url.href, { status: response.status });
|
|
104
|
+
const type = (response.type.split(';')[0] ?? '').trim().toLowerCase();
|
|
105
|
+
return { url: url.href, status: response.status, type, content: truncate(await contentOf(type, response.body, url.href)) };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=fetch-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-page.js","sourceRoot":"","sources":["../../src/web-fetch/fetch-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAuB,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,uHAAuH;AACvH,kGAAkG;AAElG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AACzC,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,aAAa,GAAG,MAAM,CAAC;AAC7B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,iBAAiB,EAAE,wBAAwB,CAAC,CAAC,CAAC;AAY7F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,MAA4C,EAAgB,EAAE,CACnG,IAAI,YAAY,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,GAAG,GAAG,sBAAsB,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAC;AAEvN,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,QAA8B;IAC9C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,IAAI,SAAS;gBAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAClF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxI,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAChC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,kGAAkG;QAClG,MAAM,MAAM,GAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;YACtD,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI;gBAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;;gBACtE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,yEAAyE,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE;YACjN,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5L,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC,CAAC;CACL,CAAC;AAEF,oHAAoH;AACpH,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxF,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,yDAAyD;AACzD,KAAK,UAAU,cAAc,CAAC,SAAuB,EAAE,GAAQ;IAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC;QAAE,MAAM,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,gEAAgE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/K,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAAE,MAAM,OAAO,CAAC,kDAAkD,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACpK,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QAAE,MAAM,OAAO,CAAC,8CAA8C,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9H,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY,EAAE,GAAW;IAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,uBAAuB;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IACtF,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3F,MAAM,OAAO,CAAC,GAAG,GAAG,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,sDAAsD,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5I,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,SAAuB,EAAE,MAAmB;IACzF,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC9E,KAAK,IAAI,SAAS,GAAG,CAAC,GAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,QAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC;QACzJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACvF,IAAI,SAAS,KAAK,aAAa;gBAAE,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,aAAa,MAAM,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC,CAAC;YACvH,GAAG,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACnD,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG;YAAE,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnF,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACtE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAC7H,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-address.d.ts","sourceRoot":"","sources":["../../src/web-fetch/private-address.ts"],"names":[],"mappings":"AA2DA,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAKzD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { isIP } from 'node:net';
|
|
2
|
+
// The addresses `web fetch` never reaches (plan 08 §8.5, ADR 0095, 3): loopback, private, link-local, unique-local,
|
|
3
|
+
// unspecified, and multicast, in IPv4 and IPv6, and IPv4 carried inside IPv6. Addresses are compared as numbers, so
|
|
4
|
+
// every spelling of one address (`::ffff:127.0.0.1`, `::ffff:7f00:1`) is judged the same.
|
|
5
|
+
const v4Blocks = [
|
|
6
|
+
[0x00000000, 8], // 0.0.0.0/8, unspecified
|
|
7
|
+
[0x0a000000, 8], // 10/8
|
|
8
|
+
[0x64400000, 10], // 100.64/10, shared
|
|
9
|
+
[0x7f000000, 8], // 127/8, loopback
|
|
10
|
+
[0xa9fe0000, 16], // 169.254/16, link-local
|
|
11
|
+
[0xac100000, 12], // 172.16/12
|
|
12
|
+
[0xc0a80000, 16], // 192.168/16
|
|
13
|
+
[0xe0000000, 4], // 224/4, multicast
|
|
14
|
+
[0xf0000000, 4], // 240/4, reserved
|
|
15
|
+
];
|
|
16
|
+
function privateV4(value) {
|
|
17
|
+
return v4Blocks.some(([base, bits]) => Math.floor(value / 2 ** (32 - bits)) === Math.floor(base / 2 ** (32 - bits)));
|
|
18
|
+
}
|
|
19
|
+
function v4Number(address) {
|
|
20
|
+
return address.split('.').reduce((total, part) => total * 256 + Number(part), 0);
|
|
21
|
+
}
|
|
22
|
+
/** The eight 16-bit groups of an IPv6 address, or nothing when it doesn't expand to exactly eight. */
|
|
23
|
+
function hextets(address) {
|
|
24
|
+
const dotted = /^(.*:)(\d+\.\d+\.\d+\.\d+)$/.exec(address);
|
|
25
|
+
const v4 = dotted?.[2] === undefined ? undefined : v4Number(dotted[2]);
|
|
26
|
+
const text = dotted?.[1] === undefined || v4 === undefined ? address : `${dotted[1]}${(v4 >>> 16).toString(16)}:${(v4 & 0xffff).toString(16)}`;
|
|
27
|
+
const halves = text.split('::');
|
|
28
|
+
if (halves.length > 2)
|
|
29
|
+
return undefined;
|
|
30
|
+
const groups = (half) => (half === undefined || half === '' ? [] : half.split(':').map((group) => (/^[\da-f]{1,4}$/i.test(group) ? Number.parseInt(group, 16) : Number.NaN)));
|
|
31
|
+
const head = groups(halves[0]), tail = groups(halves[1]);
|
|
32
|
+
const missing = 8 - head.length - tail.length;
|
|
33
|
+
if (halves.length === 1 ? missing !== 0 : missing < 1)
|
|
34
|
+
return undefined;
|
|
35
|
+
const all = [...head, ...Array(halves.length === 1 ? 0 : missing).fill(0), ...tail];
|
|
36
|
+
return all.some(Number.isNaN) ? undefined : all;
|
|
37
|
+
}
|
|
38
|
+
const v4Of = (high, low) => high * 0x10000 + low;
|
|
39
|
+
const zeros = (groups) => groups.every((group) => group === 0);
|
|
40
|
+
function privateV6(address) {
|
|
41
|
+
const groups = hextets(address);
|
|
42
|
+
if (groups === undefined)
|
|
43
|
+
return true;
|
|
44
|
+
const [first = 0, second = 0, third = 0, , , sixth = 0, seventh = 0, eighth = 0] = groups;
|
|
45
|
+
// ::/96 holds :: and ::1 and the old IPv4-compatible form; ::ffff:0:0/96 is IPv4 mapped into IPv6.
|
|
46
|
+
if (zeros(groups.slice(0, 6)))
|
|
47
|
+
return true;
|
|
48
|
+
if (zeros(groups.slice(0, 5)) && sixth === 0xffff)
|
|
49
|
+
return privateV4(v4Of(seventh, eighth));
|
|
50
|
+
// 64:ff9b::/96 is NAT64 and 2002::/16 is 6to4: each carries an IPv4 address, judged as one.
|
|
51
|
+
if (first === 0x64 && second === 0xff9b && zeros(groups.slice(2, 6)))
|
|
52
|
+
return privateV4(v4Of(seventh, eighth));
|
|
53
|
+
if (first === 0x64 && second === 0xff9b && third === 1)
|
|
54
|
+
return true; // 64:ff9b:1::/48, NAT64 for local use
|
|
55
|
+
if (first === 0x2002)
|
|
56
|
+
return privateV4(v4Of(second, third));
|
|
57
|
+
// fc00::/7 unique-local, fe80::/10 link-local, fec0::/10 site-local, ff00::/8 multicast.
|
|
58
|
+
return (first & 0xfe00) === 0xfc00 || (first & 0xffc0) === 0xfe80 || (first & 0xffc0) === 0xfec0 || (first & 0xff00) === 0xff00;
|
|
59
|
+
}
|
|
60
|
+
/** Whether an address is one `web fetch` must not reach; something that isn't an address counts as one. */
|
|
61
|
+
export function isPrivateAddress(address) {
|
|
62
|
+
const kind = isIP(address);
|
|
63
|
+
if (kind === 4)
|
|
64
|
+
return privateV4(v4Number(address));
|
|
65
|
+
if (kind === 6)
|
|
66
|
+
return privateV6(address.split('%')[0] ?? address);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=private-address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-address.js","sourceRoot":"","sources":["../../src/web-fetch/private-address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,oHAAoH;AACpH,oHAAoH;AACpH,0FAA0F;AAE1F,MAAM,QAAQ,GAAgC;IAC5C,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,yBAAyB;IAC1C,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,OAAO;IACxB,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,oBAAoB;IACtC,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,kBAAkB;IACnC,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,yBAAyB;IAC3C,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,YAAY;IAC9B,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,aAAa;IAC/B,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,mBAAmB;IACpC,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,kBAAkB;CACpC,CAAC;AAEF,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AACvH,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACnF,CAAC;AAED,sGAAsG;AACtG,SAAS,OAAO,CAAC,OAAe;IAC9B,MAAM,MAAM,GAAG,6BAA6B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IAC/I,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,IAAwB,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACxE,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,CAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC5F,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;AAClD,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,GAAG,GAAG,CAAC;AACjE,MAAM,KAAK,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;AAElF,SAAS,SAAS,CAAC,OAAe;IAChC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,AAAD,EAAG,AAAD,EAAG,KAAK,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC1F,mGAAmG;IACnG,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3F,4FAA4F;IAC5F,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9G,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,sCAAsC;IAC3G,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5D,yFAAyF;IACzF,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,MAAM,CAAC;AAClI,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RunCall } from '../calls/run-tool.ts';
|
|
2
|
+
import type { TxRecords } from '../store/collections.ts';
|
|
3
|
+
/** The host a `web fetch` call names, lowercase, or nothing for another call or an address that doesn't parse. */
|
|
4
|
+
export declare function hostOf(call: RunCall): string | undefined;
|
|
5
|
+
/** Adds the host of an allowed `web fetch` to the chat at the root, in the transaction that applies the answer. */
|
|
6
|
+
export declare function allowHostInTx(store: TxRecords, sessionId: string, call: RunCall): void;
|
|
7
|
+
//# sourceMappingURL=web-hosts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-hosts.d.ts","sourceRoot":"","sources":["../../src/web-fetch/web-hosts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAKzD,kHAAkH;AAClH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIxD;AAED,mHAAmH;AACnH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAKtF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { executionRootInTx } from "../sessions/execution-root.js";
|
|
2
|
+
// The hosts a chat let `web fetch` reach (plan 08 §8.5, ADR 0095, 4): the first fetch from a host asks, and an allowed
|
|
3
|
+
// one is kept on the chat at the root, so its helpers share it.
|
|
4
|
+
/** The host a `web fetch` call names, lowercase, or nothing for another call or an address that doesn't parse. */
|
|
5
|
+
export function hostOf(call) {
|
|
6
|
+
if (call.connector !== 'web' || call.command !== 'fetch')
|
|
7
|
+
return undefined;
|
|
8
|
+
const given = call.payload['url'];
|
|
9
|
+
return typeof given === 'string' && URL.canParse(given) ? new URL(given).hostname.toLowerCase() : undefined;
|
|
10
|
+
}
|
|
11
|
+
/** Adds the host of an allowed `web fetch` to the chat at the root, in the transaction that applies the answer. */
|
|
12
|
+
export function allowHostInTx(store, sessionId, call) {
|
|
13
|
+
const host = hostOf(call);
|
|
14
|
+
const root = executionRootInTx(store, sessionId);
|
|
15
|
+
if (host === undefined || root === undefined || root.webHosts.includes(host))
|
|
16
|
+
return;
|
|
17
|
+
store.sessions.update(root.id, { webHosts: [...root.webHosts, host] });
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=web-hosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-hosts.js","sourceRoot":"","sources":["../../src/web-fetch/web-hosts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGlE,uHAAuH;AACvH,gEAAgE;AAEhE,kHAAkH;AAClH,MAAM,UAAU,MAAM,CAAC,IAAa;IAClC,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9G,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,aAAa,CAAC,KAAgB,EAAE,SAAiB,EAAE,IAAa;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACjD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO;IACrF,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC"}
|
package/docs/connectors.md
CHANGED
|
@@ -36,7 +36,7 @@ ctx.registerHandler('kernel.started', {
|
|
|
36
36
|
- `commands`: each command's `name`, the public `command` it runs, and optional `examples` (`{ description, input }`). `help` shows the registered descriptions, JSON Schemas, and examples, so give every input field a `.describe()`.
|
|
37
37
|
- `asks: true` on a command makes the person approve every call of it first (see **A command that asks** below). The field takes only `true`; leave it out for a command that runs at once.
|
|
38
38
|
- Each `command` must be a public command or query of the registering extension, or registration fails `VALIDATION_FAILED`. The command runs through `ctx.exec` with the payload as its input, so validation, cancel, and timeouts are the kernel's, and it runs to its end inside the agent's step.
|
|
39
|
-
- The result the agent reads is the output as JSON on one line, or `error <code>: <message>`. A payload that doesn't fit returns each problem and then the payload's signature, such as `{ text, done? }`, so the agent can correct it in one try; a payload that isn't a plain object returns its JSON Schema on one line instead.
|
|
39
|
+
- The result the agent reads is the output as JSON on one line, or `error <code>: <message>`. A payload that doesn't fit returns each problem and then the payload's signature, such as `{ text (≤200), done? }`, where `(≤N)` is a string's `max` length from your zod schema, so the agent can correct it in one try; a payload that isn't a plain object returns its JSON Schema on one line instead.
|
|
40
40
|
- `binary`: a program on the system, with `{ check, install?, help? }`. `check` is a line whose exit code 0 means the program is usable; the connector is listed, and can be called, only while its check passes.
|
|
41
41
|
|
|
42
42
|
## A command that asks
|
|
@@ -101,7 +101,7 @@ Register a connector with `optIn: true`, the only value the field takes, when it
|
|
|
101
101
|
|
|
102
102
|
## Built-in connectors
|
|
103
103
|
|
|
104
|
-
kvcoder's own connectors are `shell` (one line in the real shell), `fs` (read, list, search, write, and edit files in the workspace folder), `artifact` (a document shown beside the chat), `background` (follow up on what was started with `background: true`), `ask` (a question that suspends the turn), `delegate` (`delegate run { worker, title, task, background? }` hands a task to a worker, which runs it in a helper session, and `delegate continue { id, message, background? }` sends a follow-up to a helper that has ended, which goes on with its own history; the workers are the setting `kvcoder.delegate.workers`, and it is a connector of a session only while a worker is turned on), and `mcp` (the tools of the MCP servers the person added; it is a connector of a session only while the workspace has a server). Their names are taken: registering one fails `kvcoder/NAME_TAKEN`.
|
|
104
|
+
kvcoder's own connectors are `shell` (one line in the real shell), `fs` (read, list, find, search, write, and edit files in the workspace folder; `read-files` reads several files in one call, and the model reads a file as numbered lines), `artifact` (a document shown beside the chat), `background` (follow up on what was started with `background: true`), `ask` (a question that suspends the turn), `delegate` (`delegate run { worker, title, task, background? }` hands a task to a worker, which runs it in a helper session, and `delegate continue { id, message, background? }` sends a follow-up to a helper that has ended, which goes on with its own history; the workers are the setting `kvcoder.delegate.workers`, and it is a connector of a session only while a worker is turned on), and `mcp` (the tools of the MCP servers the person added; it is a connector of a session only while the workspace has a server). Their names are taken: registering one fails `kvcoder/NAME_TAKEN`.
|
|
105
105
|
|
|
106
106
|
`shell exec`, a binary's `exec`, `fs write`, `fs edit`, and `mcp call` ask the person first when the payload says `risky: true`, or always when `kvcoder.approval` is `ask`, and never when it is `never`. A registered command asks only when its entry has `asks: true`, and then always, except on `never`. `risky` is required: a call that leaves it out fails `VALIDATION_FAILED` and asks nobody. Only `shell exec`, a binary's `exec`, `delegate run`, and `delegate continue` take `background: true`; every other command runs to its end. A background helper's approvals show in the chat, and while it waits on the person its status is `waiting`.
|
|
107
107
|
|
package/locales/ar.json
CHANGED
|
@@ -15,20 +15,38 @@
|
|
|
15
15
|
"kvcoder.errors.JOB_NOT_FOUND": "لا توجد في هذه المحادثة مهمة خلفية بهذا المعرّف.",
|
|
16
16
|
"kvcoder.errors.MCP_SERVER_NOT_FOUND": "لا يوجد خادم MCP باسم {server}.",
|
|
17
17
|
"kvcoder.errors.WORKER_NOT_FOUND": "لا يوجد مساعد باسم {worker}.",
|
|
18
|
+
"kvcoder.errors.WEB_FAILED": "تعذّرت قراءة {url}.",
|
|
18
19
|
"kvcoder.errors.MCP_CONNECT_FAILED": "فشل خادم MCP {server}: {reason}",
|
|
19
20
|
"kvcoder.errors.MCP_SIGN_IN_NEEDED": "خادم MCP {server} يحتاج إلى تسجيل دخولك.",
|
|
20
21
|
"kvcoder.errors.MCP_SIGN_IN_FAILED": "لم ينجح تسجيل الدخول: {reason}",
|
|
21
22
|
"kvcoder.notices.CANCELLED": "أوقفتَ هذه الجولة.",
|
|
22
23
|
"kvcoder.notices.INTERRUPTED": "انقطعت هذه الجولة. قد تكون آثارها غير معروفة؛ لن تُعاد الخطوة القديمة تلقائيًا. أرسل رسالة جديدة للمتابعة.",
|
|
23
24
|
"kvcoder.notices.STEP_FAILED": "توقفت الجولة: {error}",
|
|
25
|
+
"kvcoder.notices.MODEL_SWITCHED": "بلغ {from} حده، فانتقلت هذه المحادثة إلى النموذج البديل {to}.",
|
|
24
26
|
"kvcoder.notices.MAX_STEPS": "توقفت الجولة بعد بلوغ الحد الأقصى للخطوات ({steps}).",
|
|
25
27
|
"kvcoder.notices.SUMMARY_FAILED": "تعذّر تلخيص الرسائل السابقة: {error}",
|
|
26
28
|
"kvcoder.notices.REPLY_LOST": "لم يصل رد النموذج كاملًا بعد عدة محاولات (ضاع نحو {tokens} توكن). اكتب «تابع» للمحاولة من جديد، أو اختر نموذجًا آخر.",
|
|
27
29
|
"kvcoder.notices.REPLY_INCOMPLETE": "جاء رد النموذج فارغًا أو مقطوعًا عند حد الطول مرتين متتاليتين. أعد المحاولة، أو اختر نموذجًا آخر.",
|
|
28
30
|
"kvcoder.ui.newChat": "محادثة جديدة",
|
|
31
|
+
"kvcoder.ui.changes.title": "التغييرات",
|
|
32
|
+
"kvcoder.ui.changes.toggle": "التغييرات ({count})",
|
|
33
|
+
"kvcoder.ui.changes.loading": "جارٍ قراءة التغييرات…",
|
|
34
|
+
"kvcoder.ui.changes.note": "الملفات التي غيّرتها هذه المحادثة، مقارنةً بآخر حفظ أو بالنسخة التي احتفظت بها. تغييرات أسطر الطرفية لا تظهر هنا.",
|
|
35
|
+
"kvcoder.ui.changes.noGit": "تعذّر تشغيل Git، فتظهر التغييرات بلا فروقها. تغييرات أسطر الطرفية لا تظهر هنا.",
|
|
36
|
+
"kvcoder.ui.changes.commit": "احفظ في Git",
|
|
37
|
+
"kvcoder.ui.changes.commitMessage": "احفظ هذه التغييرات في Git.",
|
|
38
|
+
"kvcoder.ui.changes.undo": "تراجع",
|
|
39
|
+
"kvcoder.ui.changes.none": "لم يبقَ أي تغيير.",
|
|
40
|
+
"kvcoder.ui.changes.state.changed": "مُعدَّل",
|
|
41
|
+
"kvcoder.ui.changes.state.created": "جديد",
|
|
42
|
+
"kvcoder.ui.changes.state.deleted": "محذوف",
|
|
29
43
|
"kvcoder.ui.chats": "المحادثات",
|
|
30
44
|
"kvcoder.ui.today": "اليوم",
|
|
31
45
|
"kvcoder.ui.earlier": "الأقدم",
|
|
46
|
+
"kvcoder.ui.notify.title": "محادثة تحتاجك",
|
|
47
|
+
"kvcoder.ui.notify.ask": "احصل على تنبيه عندما تحتاجك محادثة بينما kvman في الخلفية.",
|
|
48
|
+
"kvcoder.ui.notify.on": "تفعيل",
|
|
49
|
+
"kvcoder.ui.notify.later": "ليس الآن",
|
|
32
50
|
"kvcoder.ui.needsYou": "بانتظار ردّك",
|
|
33
51
|
"kvcoder.ui.status.idle": "جاهزة",
|
|
34
52
|
"kvcoder.ui.status.running": "قيد العمل…",
|
|
@@ -49,7 +67,7 @@
|
|
|
49
67
|
"kvcoder.ui.costParts": "منها: التلخيص {summary}، العنوان {title}، المساعدون {helpers}",
|
|
50
68
|
"kvcoder.ui.costEstimate": "التكلفة تقدير من كتالوج النماذج",
|
|
51
69
|
"kvcoder.ui.memoryDetail": "يحمل النموذج الآن {tokens} من {window} توكن. تُلخَّص الرسائل الأقدم عند {at}%.",
|
|
52
|
-
"kvcoder.ui.turns": "
|
|
70
|
+
"kvcoder.ui.turns": "لا جولات | جولة واحدة | جولتان | {count} جولات | {count} جولة | {count} جولة",
|
|
53
71
|
"kvcoder.ui.exitCode": "رمز الخروج {code}",
|
|
54
72
|
"kvcoder.ui.retry": "إعادة المحاولة",
|
|
55
73
|
"kvcoder.ui.loadFailed": "تعذّر تحميل هذه المحادثة: {error}",
|
|
@@ -71,8 +89,13 @@
|
|
|
71
89
|
"kvcoder.ui.other": "إجابة أخرى",
|
|
72
90
|
"kvcoder.ui.yes": "نعم",
|
|
73
91
|
"kvcoder.ui.no": "لا",
|
|
74
|
-
"kvcoder.ui.allowCommands": "هل تسمح بتنفيذ هذه الأوامر؟
|
|
92
|
+
"kvcoder.ui.allowCommands": "هل تسمح بتنفيذ هذه الأوامر؟ | هل تسمح بتنفيذ هذا الأمر؟ | هل تسمح بتنفيذ هذين الأمرين؟ | هل تسمح بتنفيذ هذه الأوامر الـ{count}؟ | هل تسمح بتنفيذ هذه الأوامر الـ{count}؟ | هل تسمح بتنفيذ هذه الأوامر الـ{count}؟",
|
|
75
93
|
"kvcoder.ui.allow": "سماح",
|
|
94
|
+
"kvcoder.ui.approval.denyWhy": "ارفض واذكر السبب…",
|
|
95
|
+
"kvcoder.ui.approval.reason": "ماذا يفعل الوكيل بدلًا من ذلك؟",
|
|
96
|
+
"kvcoder.ui.approval.alwaysLine": "اسمح دائمًا بالأسطر التي تبدأ بـ",
|
|
97
|
+
"kvcoder.ui.approval.always": "اسمح دائمًا",
|
|
98
|
+
"kvcoder.ui.approval.alwaysFiles": "اسمح دائمًا بتغيير الملفات هنا",
|
|
76
99
|
"kvcoder.ui.deny": "رفض",
|
|
77
100
|
"kvcoder.ui.allowAll": "سماح للكل",
|
|
78
101
|
"kvcoder.ui.denyAll": "رفض الكل",
|
|
@@ -96,7 +119,7 @@
|
|
|
96
119
|
"kvcoder.ui.preparing": "جارٍ تجهيز أمر…",
|
|
97
120
|
"kvcoder.ui.searchModels": "ابحث في النماذج",
|
|
98
121
|
"kvcoder.ui.noModels": "لا توجد نماذج مطابقة",
|
|
99
|
-
"kvcoder.ui.modelsCount": "{shown} من أصل {
|
|
122
|
+
"kvcoder.ui.modelsCount": "{shown} من أصل {count} | {shown} من أصل نموذج واحد | {shown} من أصل نموذجين | {shown} من أصل {count} نماذج | {shown} من أصل {count} نموذجًا | {shown} من أصل {count} نموذج",
|
|
100
123
|
"kvcoder.ui.activity.waiting": "بانتظار النموذج…",
|
|
101
124
|
"kvcoder.ui.activity.thinking": "يفكر…",
|
|
102
125
|
"kvcoder.ui.activity.writing": "يكتب…",
|
|
@@ -129,8 +152,8 @@
|
|
|
129
152
|
"kvcoder.ui.approvalLine.change": "تغيير",
|
|
130
153
|
"kvcoder.ui.homeWorkspace": "الرئيسية",
|
|
131
154
|
"kvcoder.ui.chatNotHere": "هذه المحادثة ليست في مساحة العمل هذه.",
|
|
132
|
-
"kvcoder.ui.showEarlier": "عرض {count} رسالة أقدم",
|
|
133
|
-
"kvcoder.ui.earlierMessages": "رسائل
|
|
155
|
+
"kvcoder.ui.showEarlier": "عرض الرسائل الأقدم | عرض رسالة أقدم | عرض رسالتين أقدم | عرض {count} رسائل أقدم | عرض {count} رسالة أقدم | عرض {count} رسالة أقدم",
|
|
156
|
+
"kvcoder.ui.earlierMessages": "لا رسائل أقدم · تصدير | رسالة أقدم · تصدير | رسالتان أقدم · تصدير | {count} رسائل أقدم · تصدير | {count} رسالة أقدم · تصدير | {count} رسالة أقدم · تصدير",
|
|
134
157
|
"kvcoder.ui.messageDismisses": "إرسال رسالة الآن يتخطى الأسئلة ويرفض الأوامر المعلّقة.",
|
|
135
158
|
"kvcoder.ui.promptTitle": "تعليمات النظام كما ستُرسل في الخطوة التالية",
|
|
136
159
|
"kvcoder.ui.copy": "نسخ",
|
|
@@ -141,6 +164,8 @@
|
|
|
141
164
|
"kvcoder.ui.reach.session": "هذه المحادثة",
|
|
142
165
|
"kvcoder.ui.leftOut": "مستبعد: يتجاوز 64 كيلوبايت",
|
|
143
166
|
"kvcoder.ui.model": "النموذج",
|
|
167
|
+
"kvcoder.ui.decideForMe": "قرّر عني",
|
|
168
|
+
"kvcoder.ui.decideForMeHint": "يتخذ الوكيل كل قرار بنفسه، بالخيار الذي يوصي به، ولا يسألك أسئلة في هذه المحادثة. طلبات الموافقة تبقى كما هي.",
|
|
144
169
|
"kvcoder.ui.thinking": "التفكير",
|
|
145
170
|
"kvcoder.ui.thinkingLevels.off": "بدون",
|
|
146
171
|
"kvcoder.ui.thinkingLevels.minimal": "أدنى",
|
|
@@ -182,7 +207,11 @@
|
|
|
182
207
|
"kvcoder.shell.run.description": "ينفّذ سطرًا واحدًا في الطرفية الفعلية، داخل مجلد مساحة العمل.",
|
|
183
208
|
"kvcoder.binary.run.description": "يشغّل البرنامج بالوسائط المعطاة في الطرفية الفعلية، داخل مجلد مساحة العمل.",
|
|
184
209
|
"kvcoder.fs.file.get.description": "يقرأ أسطرًا من ملف نصي.",
|
|
210
|
+
"kvcoder.fs.files.get.description": "يقرأ عدة ملفات نصية في استدعاء واحد، بالترتيب، كلًّا كما يقرؤه read.",
|
|
211
|
+
"kvcoder.change.list.description": "يسرد الملفات التي غيّرتها محادثة عبر fs، الأحدث أولًا، مع فرق كل منها.",
|
|
212
|
+
"kvcoder.change.undo.description": "يتراجع عن آخر تغيير أجرته المحادثة على ملف، كما يفعل fs undo؛ للشخص.",
|
|
185
213
|
"kvcoder.fs.entry.list.description": "يسرد ملفات ومجلدات مجلد واحد.",
|
|
214
|
+
"kvcoder.fs.path.list.description": "يجد الملفات التي يطابق مسارها نمطًا، داخل مجلد، الأحدث أولًا.",
|
|
186
215
|
"kvcoder.fs.text.search.description": "يجد الأسطر التي تطابق تعبيرًا نمطيًا، في ملف أو داخل مجلد.",
|
|
187
216
|
"kvcoder.fs.write.description": "ينشئ ملفًا مع مجلداته الأصلية، أو يستبدل محتوى الملف.",
|
|
188
217
|
"kvcoder.fs.edit.description": "يستبدل مقاطع نصية محددة في ملف موجود؛ وإذا فشل أحد الاستبدالات لا يُكتب شيء.",
|
|
@@ -202,6 +231,7 @@
|
|
|
202
231
|
"kvcoder.background.wait.description": "ينتظر حتى تنتهي عملية في الخلفية أو ينقضي الوقت، ثم يعطي حالتها ومخرجاتها كما يفعل output.",
|
|
203
232
|
"kvcoder.background.stop.description": "يوقف عملية في الخلفية أو تشغيل برنامج مساعد، أو يلغي وكيلًا فرعيًا في الخلفية.",
|
|
204
233
|
"kvcoder.mcp.tool.describe.description": "يسرد أدوات خادم MCP، أو يعطي وصف أداة واحدة ومُدخلاتها.",
|
|
234
|
+
"kvcoder.web.page.get.description": "يقرأ صفحة على الويب بصيغة Markdown أو نصًا.",
|
|
205
235
|
"kvcoder.mcp.tool.call.description": "يستدعي أداة من خادم MCP ويعيد نصّها.",
|
|
206
236
|
"kvcoder.mcp.steps.run.description": "يستدعي عدة أدوات من خادم MCP على اتصال واحد بالترتيب، فيحتفظ الخادم بحالته بينها، ويتوقف عند أول أداة تُبلغ عن خطأ.",
|
|
207
237
|
"kvcoder.mcp.server.check.description": "يتصل بخادم MCP ويخبر هل هو جاهز، أم يحتاج إلى تسجيل دخول، أم فشل.",
|
|
@@ -241,8 +271,26 @@
|
|
|
241
271
|
"kvcoder.thinking.description": "مقدار تفكير النموذج في المحادثة الجديدة.",
|
|
242
272
|
"kvcoder.maxSteps.title": "الخطوات في كل جولة",
|
|
243
273
|
"kvcoder.maxSteps.description": "أقصى عدد من الخطوات تنفّذه الجولة قبل أن تتوقف. اتركه فارغًا لتبقى الجولة بلا حدّ.",
|
|
274
|
+
"kvcoder.preferences.title": "تفضيلاتك",
|
|
275
|
+
"kvcoder.preferences.description": "ما يجب أن تعرفه كل محادثة عن طريقتك في العمل، مثل لغة تطبيقاتك أو ألا يسألك الوكيل. يقرؤها الوكيل في كل محادثة.",
|
|
276
|
+
"kvcoder.config.preferences.placeholder": "ابنِ التطبيقات بالعربية أولًا.\nلا تطلب مني الاختيار: اختر ما توصي به.",
|
|
277
|
+
"kvcoder.config.preferences.save": "حفظ",
|
|
278
|
+
"kvcoder.ui.remember.this": "تذكّر هذا",
|
|
279
|
+
"kvcoder.ui.remember.question": "أتضيف هذا إلى تفضيلاتك؟ كل محادثة تقرؤها.",
|
|
280
|
+
"kvcoder.ui.remember.add": "أضف",
|
|
281
|
+
"kvcoder.ui.remember.added": "أُضيف إلى تفضيلاتك.",
|
|
282
|
+
"kvcoder.check.title": "فحص بعد التغييرات",
|
|
283
|
+
"kvcoder.check.description": "سطر يشغّله kvman بعد أن يغيّر الوكيل ملفات، مثل فحص الأنواع في المشروع؛ تُضاف نتيجته ومخرجاته إلى التغيير ليرى الوكيل الخطأ فورًا. فارغ لعدم التشغيل.",
|
|
284
|
+
"kvcoder.fallbackModel.title": "نموذج بديل",
|
|
285
|
+
"kvcoder.fallbackModel.description": "النموذج الذي تنتقل إليه المحادثة عندما يبلغ نموذجها حد الاستخدام، أو حد الطلبات بعد كل المحاولات. فارغ لعدم الانتقال.",
|
|
244
286
|
"kvcoder.approval.title": "الموافقة",
|
|
245
287
|
"kvcoder.approval.description": "متى يطلب الوكيل موافقتك قبل تنفيذ أمر أو تعديل ملف أو أي شيء آخر يحتاج إلى إذنك.",
|
|
288
|
+
"kvcoder.approval.allowed.title": "مسموح دائمًا",
|
|
289
|
+
"kvcoder.approval.allowed.description": "أوامر وتغييرات تعمل دون سؤالك: سطر يبدأ كل أمر فيه بأحد هذه البدايات، أو تغيير ملف في هذا المجلد.",
|
|
290
|
+
"kvcoder.config.approval.rules.line": "مسموح دائمًا: {prefix} …",
|
|
291
|
+
"kvcoder.config.approval.rules.files": "مسموح دائمًا: تغيير الملفات",
|
|
292
|
+
"kvcoder.config.approval.rules.none": "لا توجد أوامر مسموحة دائمًا.",
|
|
293
|
+
"kvcoder.config.approval.rules.remove": "إزالة",
|
|
246
294
|
"kvcoder.config.approval.never.title": "عدم السؤال قبل أي عملية؟",
|
|
247
295
|
"kvcoder.config.approval.never.text": "سينفّذ الوكيل الأوامر ويعدّل الملفات ويغيّر kvman نفسه ويشغّل برامج المساعدين دون أن يسألك. وما يقرؤه قد يوجّهه.",
|
|
248
296
|
"kvcoder.config.approval.never.confirm": "أوقف السؤال",
|
|
@@ -307,7 +355,9 @@
|
|
|
307
355
|
"kvcoder.ui.map.evidence": "الدليل",
|
|
308
356
|
"kvcoder.ui.map.note": "ملاحظة",
|
|
309
357
|
"kvcoder.ui.map.noted": "مؤجَّل لوقت لاحق ({count})",
|
|
310
|
-
"kvcoder.ui.map.remaining": "{count} من
|
|
358
|
+
"kvcoder.ui.map.remaining": "كل خطوات خريطة التنفيذ أُنجزت. | خطوة واحدة من خريطة التنفيذ لم تُنجز. | خطوتان من خريطة التنفيذ لم تُنجزا. | {count} خطوات من خريطة التنفيذ لم تُنجز. | {count} خطوة من خريطة التنفيذ لم تُنجز. | {count} خطوة من خريطة التنفيذ لم تُنجز.",
|
|
359
|
+
"kvcoder.ui.map.continue": "تابع",
|
|
360
|
+
"kvcoder.ui.map.continueMessage": "تابع.",
|
|
311
361
|
"kvcoder.ui.map.show": "عرض الخريطة",
|
|
312
362
|
"kvcoder.ui.map.close": "إغلاق",
|
|
313
363
|
"kvcoder.ui.artifacts.frameLabel": "معاينة {title}",
|
|
@@ -346,6 +396,7 @@
|
|
|
346
396
|
"kvcoder.config.connector.background": "يسرد ما يعمل في الخلفية ويقرأ ناتجه ويوقفه.",
|
|
347
397
|
"kvcoder.config.connector.ask": "يطرح عليك سؤالًا وينتظر إجابتك.",
|
|
348
398
|
"kvcoder.config.connector.delegate": "يسند جزءًا من المهمة إلى مساعد: وكيل آخر له تعليماته.",
|
|
399
|
+
"kvcoder.config.connector.web": "يقرأ صفحات على الويب، مثل التوثيق الحالي، ويسألك قبل أول صفحة من كل موقع.",
|
|
349
400
|
"kvcoder.config.connector.mcp": "يستخدم أدوات خوادم MCP التي تضيفها.",
|
|
350
401
|
"kvcoder.config.connectors.use": "استخدام {name}",
|
|
351
402
|
"kvcoder.config.connectors.configure": "إعداد {name}",
|
|
@@ -363,7 +414,7 @@
|
|
|
363
414
|
"kvcoder.config.mcp.empty": "لا توجد خوادم بعد. أضف خادمًا ليستخدم الوكيل أدواته.",
|
|
364
415
|
"kvcoder.config.mcp.add": "إضافة خادم",
|
|
365
416
|
"kvcoder.config.mcp.checking": "جارٍ الفحص…",
|
|
366
|
-
"kvcoder.config.mcp.ready": "جاهز · {count} أداة",
|
|
417
|
+
"kvcoder.config.mcp.ready": "جاهز · لا أدوات | جاهز · أداة واحدة | جاهز · أداتان | جاهز · {count} أدوات | جاهز · {count} أداة | جاهز · {count} أداة",
|
|
367
418
|
"kvcoder.config.mcp.signInNeeded": "يحتاج إلى تسجيل الدخول",
|
|
368
419
|
"kvcoder.config.mcp.failed": "تعذّر الاتصال",
|
|
369
420
|
"kvcoder.config.mcp.recheck": "افحص مجددًا",
|
|
@@ -498,6 +549,7 @@
|
|
|
498
549
|
"kvcoder.config.model.reset.workspace": "استخدام قيمة كل مساحات العمل",
|
|
499
550
|
"kvcoder.config.model.ownValue": "لمساحة العمل {name} قيمة خاصة بها. انتقل إلى {name} لتغييرها.",
|
|
500
551
|
"kvcoder.ui.milliseconds": "{count} مللي ث",
|
|
552
|
+
"kvcoder.ui.hoursMinutes": "{hours} س {minutes} د",
|
|
501
553
|
"kvcoder.ui.minutesSeconds": "{minutes} د {seconds} ث",
|
|
502
554
|
"kvcoder.ui.callFailed": "فشل",
|
|
503
555
|
"kvcoder.ui.callParts": "كُتب في {written} · نُفّذ في {ran}",
|
|
@@ -506,6 +558,19 @@
|
|
|
506
558
|
"kvcoder.ui.call.write": "كتابة",
|
|
507
559
|
"kvcoder.ui.call.read": "قراءة",
|
|
508
560
|
"kvcoder.ui.call.list": "عرض",
|
|
561
|
+
"kvcoder.ui.fold.read": "قراءة {count} ملف | قراءة ملف واحد | قراءة ملفين | قراءة {count} ملفات | قراءة {count} ملفًا | قراءة {count} ملف",
|
|
562
|
+
"kvcoder.ui.fold.searched": "بحث {count} مرة | بحث مرة واحدة | بحث مرتين | بحث {count} مرات | بحث {count} مرة | بحث {count} مرة",
|
|
563
|
+
"kvcoder.ui.fold.changed": "تعديل {count} ملف | تعديل ملف واحد | تعديل ملفين | تعديل {count} ملفات | تعديل {count} ملفًا | تعديل {count} ملف",
|
|
564
|
+
"kvcoder.ui.fold.ran": "تشغيل {count} أمر | تشغيل أمر واحد | تشغيل أمرين | تشغيل {count} أوامر | تشغيل {count} أمرًا | تشغيل {count} أمر",
|
|
565
|
+
"kvcoder.ui.fold.other": "استخدام {count} أداة أخرى | استخدام أداة أخرى | استخدام أداتين أخريين | استخدام {count} أدوات أخرى | استخدام {count} أداة أخرى | استخدام {count} أداة أخرى",
|
|
566
|
+
"kvcoder.ui.fold.failed": "فشل {count} خطوة | فشلت خطوة واحدة | فشلت خطوتان | فشلت {count} خطوات | فشلت {count} خطوة | فشلت {count} خطوة",
|
|
567
|
+
"kvcoder.ui.fold.list": "{first}، {next}",
|
|
568
|
+
"kvcoder.ui.call.fetch": "جلب",
|
|
569
|
+
"kvcoder.ui.call.find": "إيجاد",
|
|
570
|
+
"kvcoder.ui.call.files": "لا ملفات | ملف واحد | ملفان | {count} ملفات | {count} ملفًا | {count} ملف",
|
|
571
|
+
"kvcoder.ui.call.fileNotRead": "لم يُقرأ: استهلكت الملفات التي قبله حدّ هذا الاستدعاء (30 KB).",
|
|
572
|
+
"kvcoder.ui.call.fileUnchanged": "لم يتغيّر منذ قراءة سابقة في هذه المحادثة.",
|
|
573
|
+
"kvcoder.ui.call.filesFirst": "لا ملفات | الملف الأول | أول ملفين | أول {count} ملفات | أول {count} ملفًا | أول {count} ملف",
|
|
509
574
|
"kvcoder.ui.call.search": "بحث",
|
|
510
575
|
"kvcoder.ui.call.tools": "الأدوات",
|
|
511
576
|
"kvcoder.ui.call.delegate": "تفويض",
|
|
@@ -525,17 +590,18 @@
|
|
|
525
590
|
"kvcoder.ui.call.created": "أُنشئ · {size}",
|
|
526
591
|
"kvcoder.ui.call.replaced": "استُبدل · {size}",
|
|
527
592
|
"kvcoder.ui.call.lines": "الأسطر {from}–{to} من {total}",
|
|
528
|
-
"kvcoder.ui.call.entries": "{count} عنصر",
|
|
529
|
-
"kvcoder.ui.call.entriesFirst": "أول {count} عنصر",
|
|
530
|
-
"kvcoder.ui.call.
|
|
531
|
-
"kvcoder.ui.call.
|
|
532
|
-
"kvcoder.ui.call.
|
|
533
|
-
"kvcoder.ui.call.
|
|
593
|
+
"kvcoder.ui.call.entries": "لا عناصر | عنصر واحد | عنصران | {count} عناصر | {count} عنصرًا | {count} عنصر",
|
|
594
|
+
"kvcoder.ui.call.entriesFirst": "لا عناصر | العنصر الأول | أول عنصرين | أول {count} عناصر | أول {count} عنصرًا | أول {count} عنصر",
|
|
595
|
+
"kvcoder.ui.call.matchCount": "لا نتائج | نتيجة واحدة | نتيجتان | {count} نتائج | {count} نتيجة | {count} نتيجة",
|
|
596
|
+
"kvcoder.ui.call.matches": "{matches} في {files}",
|
|
597
|
+
"kvcoder.ui.call.matchesFirst": "لا نتائج | النتيجة الأولى | أول نتيجتين | أول {count} نتائج | أول {count} نتيجة | أول {count} نتيجة",
|
|
598
|
+
"kvcoder.ui.call.toolCount": "لا أدوات | أداة واحدة | أداتان | {count} أدوات | {count} أداة | {count} أداة",
|
|
599
|
+
"kvcoder.ui.call.runCount": "لا مهام | مهمة واحدة | مهمتان | {count} مهام | {count} مهمة | {count} مهمة",
|
|
534
600
|
"kvcoder.ui.call.bytes": "{count} بايت",
|
|
535
601
|
"kvcoder.ui.call.kilobytes": "{count} ك.ب",
|
|
536
602
|
"kvcoder.ui.call.megabytes": "{count} م.ب",
|
|
537
603
|
"kvcoder.ui.call.risky": "خطِر",
|
|
538
|
-
"kvcoder.ui.call.replacements": "{count} استبدال · من السطر {line}",
|
|
604
|
+
"kvcoder.ui.call.replacements": "لا استبدالات · من السطر {line} | استبدال واحد · من السطر {line} | استبدالان · من السطر {line} | {count} استبدالات · من السطر {line} | {count} استبدالًا · من السطر {line} | {count} استبدال · من السطر {line}",
|
|
539
605
|
"kvcoder.ui.call.showAll": "عرض كل الأسطر ({count})",
|
|
540
606
|
"kvcoder.ui.call.showFewer": "عرض أقل",
|
|
541
607
|
"kvcoder.ui.call.error": "الخطأ",
|