agents-bridge 0.3.11 → 0.3.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/agents/model-auto-binding.d.ts.map +1 -1
- package/dist/agents/model-auto-binding.js +4 -5
- package/dist/agents/model-auto-binding.js.map +1 -1
- package/dist/agents/model-control-files.d.ts +3 -2
- package/dist/agents/model-control-files.d.ts.map +1 -1
- package/dist/agents/model-control-files.js +52 -11
- package/dist/agents/model-control-files.js.map +1 -1
- package/dist/agents/model-device-secret.d.ts +10 -0
- package/dist/agents/model-device-secret.d.ts.map +1 -0
- package/dist/agents/model-device-secret.js +47 -0
- package/dist/agents/model-device-secret.js.map +1 -0
- package/dist/agents/windows-model-control-security.d.ts +10 -1
- package/dist/agents/windows-model-control-security.d.ts.map +1 -1
- package/dist/agents/windows-model-control-security.js +142 -32
- package/dist/agents/windows-model-control-security.js.map +1 -1
- package/dist/cli/cmd-start.d.ts.map +1 -1
- package/dist/cli/cmd-start.js +9 -4
- package/dist/cli/cmd-start.js.map +1 -1
- package/dist/cli/initialize-agent-runtimes.d.ts +4 -0
- package/dist/cli/initialize-agent-runtimes.d.ts.map +1 -0
- package/dist/cli/initialize-agent-runtimes.js +41 -0
- package/dist/cli/initialize-agent-runtimes.js.map +1 -0
- package/dist/config/zod-schema.d.ts +8 -8
- package/package.json +4 -2
- package/scripts/inspect-model-device-secret.mjs +23 -0
- package/scripts/windows-acl-json-smoke.mjs +54 -0
- package/scripts/windows-smoke.mjs +142 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-auto-binding.d.ts","sourceRoot":"","sources":["../../src/agents/model-auto-binding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"model-auto-binding.d.ts","sourceRoot":"","sources":["../../src/agents/model-auto-binding.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxF,OAAO,KAAK,EAAE,MAAM,EAAmB,MAAM,mBAAmB,CAAA;AAIhE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAG/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,2FAA2F;AAC3F,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAqC1J"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { parseModelDeviceSecret } from './model-device-secret.js';
|
|
2
3
|
import { normalizeBotlinkChannelConfigs } from '../config/zod-schema.js';
|
|
3
4
|
import { resolveAgentConfigs } from './agent-resolver.js';
|
|
4
5
|
import { resolveAgent } from './agent-router.js';
|
|
5
6
|
import { resolveOpenApiBaseUrl } from '../cli/botlink-openapi.js';
|
|
6
|
-
import { createSecureModelControlFile,
|
|
7
|
+
import { createSecureModelControlFile, readSecureModelControlFileBuffer } from './model-control-files.js';
|
|
7
8
|
export function modelSwitchAllowed(config, agentId) {
|
|
8
9
|
return config.agents.list?.find(a => a.id === agentId)?.allowModelSwitch ?? config.agents.defaults.allowModelSwitch ?? true;
|
|
9
10
|
}
|
|
@@ -41,7 +42,7 @@ export async function automaticModelControl(config, agentId, statePath, logger)
|
|
|
41
42
|
const path = statePath + '.device';
|
|
42
43
|
let secret;
|
|
43
44
|
try {
|
|
44
|
-
secret = (await
|
|
45
|
+
secret = parseModelDeviceSecret(await readSecureModelControlFileBuffer(path));
|
|
45
46
|
}
|
|
46
47
|
catch (e) {
|
|
47
48
|
if (e.code !== 'ENOENT')
|
|
@@ -53,11 +54,9 @@ export async function automaticModelControl(config, agentId, statePath, logger)
|
|
|
53
54
|
catch (e) {
|
|
54
55
|
if (e.code !== 'EEXIST')
|
|
55
56
|
throw e;
|
|
56
|
-
secret = (await
|
|
57
|
+
secret = parseModelDeviceSecret(await readSecureModelControlFileBuffer(path));
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
if (!/^[a-f0-9]{64}$/.test(secret))
|
|
60
|
-
throw new Error('INVALID_MODEL_DEVICE_SECRET');
|
|
61
60
|
return { endpoint, botToken: account.bot_token, deviceSecret: secret, models: [...new Set([...catalog[provider], initial])], allowModelSwitch: modelSwitchAllowed(config, agentId) };
|
|
62
61
|
}
|
|
63
62
|
//# sourceMappingURL=model-auto-binding.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-auto-binding.js","sourceRoot":"","sources":["../../src/agents/model-auto-binding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,8BAA8B,EAAkB,MAAM,yBAAyB,CAAA;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAAE,4BAA4B,EAAE,
|
|
1
|
+
{"version":3,"file":"model-auto-binding.js","sourceRoot":"","sources":["../../src/agents/model-auto-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export declare function createModelControlFileAccess({ platform, windowsSecurity, }?: {
|
|
2
2
|
platform?: NodeJS.Platform;
|
|
3
|
-
windowsSecurity?: (path: string, kind: 'directory' | 'file') => Promise<void>;
|
|
3
|
+
windowsSecurity?: (path: string, kind: 'directory' | 'file', privateDirectory?: boolean) => Promise<void>;
|
|
4
4
|
}): {
|
|
5
5
|
ensureSecureModelControlDirectory: (path: string) => Promise<void>;
|
|
6
|
+
readSecureModelControlFileBuffer: (path: string) => Promise<Buffer<ArrayBufferLike>>;
|
|
6
7
|
readSecureModelControlFile: (path: string) => Promise<string>;
|
|
7
8
|
createSecureModelControlFile: (path: string, contents: string) => Promise<void>;
|
|
8
9
|
writeSecureModelControlFile: (path: string, contents: string) => Promise<void>;
|
|
9
10
|
};
|
|
10
|
-
export declare const ensureSecureModelControlDirectory: (path: string) => Promise<void>, readSecureModelControlFile: (path: string) => Promise<string>, createSecureModelControlFile: (path: string, contents: string) => Promise<void>, writeSecureModelControlFile: (path: string, contents: string) => Promise<void>;
|
|
11
|
+
export declare const ensureSecureModelControlDirectory: (path: string) => Promise<void>, readSecureModelControlFile: (path: string) => Promise<string>, readSecureModelControlFileBuffer: (path: string) => Promise<Buffer<ArrayBufferLike>>, createSecureModelControlFile: (path: string, contents: string) => Promise<void>, writeSecureModelControlFile: (path: string, contents: string) => Promise<void>;
|
|
11
12
|
//# sourceMappingURL=model-control-files.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-control-files.d.ts","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"model-control-files.d.ts","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"AAgBA,wBAAgB,4BAA4B,CAAC,EAC3C,QAA2B,EAC3B,eAAmD,GACpD,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAAC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO;8CAqBxF,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;6CAqHlC,MAAM;uCACZ,MAAM;yCACJ,MAAM,YAAY,MAAM;wCACzB,MAAM,YAAY,MAAM;EAE/D;AAED,eAAO,MACL,iCAAiC,SA7HsB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,EA6H1C,0BAA0B,SAPxB,MAAM,sBAOoB,gCAAgC,SARpD,MAAM,uCASjD,4BAA4B,SAPW,MAAM,YAAY,MAAM,oBAOjC,2BAA2B,SANnB,MAAM,YAAY,MAAM,kBAO9B,CAAA"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { constants } from 'node:fs';
|
|
2
|
-
import { lstat, mkdir, open, realpath, rename, unlink } from 'node:fs/promises';
|
|
2
|
+
import { link, lstat, mkdir, open, realpath, rename, unlink } from 'node:fs/promises';
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { AGENTS_STATE_DIR } from '../config/paths.js';
|
|
5
6
|
import { ensureWindowsModelControlSecurity, sameWindowsModelControlPath } from './windows-model-control-security.js';
|
|
6
7
|
const MAX_MODEL_CONTROL_FILE_BYTES = 64 * 1024;
|
|
8
|
+
const pendingFileOperations = new Map();
|
|
7
9
|
function expectedUid() {
|
|
8
10
|
return typeof process.geteuid === 'function' ? process.geteuid() : typeof process.getuid === 'function' ? process.getuid() : undefined;
|
|
9
11
|
}
|
|
@@ -12,6 +14,25 @@ function expectedUid() {
|
|
|
12
14
|
export function createModelControlFileAccess({ platform = process.platform, windowsSecurity = ensureWindowsModelControlSecurity, } = {}) {
|
|
13
15
|
const windows = platform === 'win32';
|
|
14
16
|
const noFollow = windows ? 0 : constants.O_NOFOLLOW;
|
|
17
|
+
// Serialize only the same file, including the short exclusive-publish link
|
|
18
|
+
// window. Independent Agent files still run concurrently; no global IO lock.
|
|
19
|
+
async function withFileLock(path, operation) {
|
|
20
|
+
const key = (windows ? 'win32:' + resolve(path).toLowerCase() : 'posix:' + resolve(path));
|
|
21
|
+
const previous = pendingFileOperations.get(key) ?? Promise.resolve();
|
|
22
|
+
let release;
|
|
23
|
+
const gate = new Promise(resolveGate => { release = resolveGate; });
|
|
24
|
+
const tail = previous.then(() => gate);
|
|
25
|
+
pendingFileOperations.set(key, tail);
|
|
26
|
+
await previous;
|
|
27
|
+
try {
|
|
28
|
+
return await operation();
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
release();
|
|
32
|
+
if (pendingFileOperations.get(key) === tail)
|
|
33
|
+
pendingFileOperations.delete(key);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
15
36
|
async function ensureSecureModelControlDirectory(path) {
|
|
16
37
|
const directory = resolve(path);
|
|
17
38
|
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
@@ -26,8 +47,12 @@ export function createModelControlFileAccess({ platform = process.platform, wind
|
|
|
26
47
|
const canonical = await realpath(directory);
|
|
27
48
|
if (windows ? !sameWindowsModelControlPath(canonical, directory) : canonical !== directory)
|
|
28
49
|
throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_PATH');
|
|
29
|
-
if (windows)
|
|
30
|
-
|
|
50
|
+
if (windows) {
|
|
51
|
+
// Only this Bridge's direct per-Agent runtime directory is owned by us.
|
|
52
|
+
// The generic file helper must never rewrite an arbitrary parent's ACL.
|
|
53
|
+
const privateDirectory = sameWindowsModelControlPath(dirname(directory), resolve(AGENTS_STATE_DIR()));
|
|
54
|
+
await windowsSecurity(directory, 'directory', privateDirectory);
|
|
55
|
+
}
|
|
31
56
|
}
|
|
32
57
|
async function validateOpenFile(file, path) {
|
|
33
58
|
const info = await file.stat();
|
|
@@ -60,12 +85,12 @@ export function createModelControlFileAccess({ platform = process.platform, wind
|
|
|
60
85
|
}
|
|
61
86
|
return open(path, constants.O_RDONLY | noFollow);
|
|
62
87
|
}
|
|
63
|
-
async function
|
|
88
|
+
async function readSecureModelControlFileBuffer(path) {
|
|
64
89
|
await ensureSecureModelControlDirectory(dirname(path));
|
|
65
90
|
const file = await openExisting(path);
|
|
66
91
|
try {
|
|
67
92
|
await validateOpenFile(file, path);
|
|
68
|
-
return await file.readFile(
|
|
93
|
+
return await file.readFile();
|
|
69
94
|
}
|
|
70
95
|
finally {
|
|
71
96
|
await file.close();
|
|
@@ -88,19 +113,29 @@ export function createModelControlFileAccess({ platform = process.platform, wind
|
|
|
88
113
|
if (Buffer.byteLength(contents, 'utf8') > MAX_MODEL_CONTROL_FILE_BYTES)
|
|
89
114
|
throw new Error('MODEL_CONTROL_FILE_TOO_LARGE');
|
|
90
115
|
await ensureSecureModelControlDirectory(dirname(path));
|
|
91
|
-
|
|
116
|
+
// Do not expose an empty final .device while preparing its Windows ACL.
|
|
117
|
+
// Only fully written, fsynced private content is published. link() fails
|
|
118
|
+
// with EEXIST instead of replacing an existing device identity.
|
|
119
|
+
const temporaryPath = `${path}.${randomUUID()}.create.tmp`;
|
|
120
|
+
const file = await open(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 0o600);
|
|
92
121
|
try {
|
|
93
|
-
await validateOpenFile(file,
|
|
122
|
+
await validateOpenFile(file, temporaryPath);
|
|
94
123
|
await file.writeFile(contents);
|
|
95
|
-
await validateOpenFile(file,
|
|
124
|
+
await validateOpenFile(file, temporaryPath);
|
|
96
125
|
await file.sync();
|
|
97
126
|
}
|
|
98
127
|
catch (error) {
|
|
99
128
|
await file.close().catch(() => undefined);
|
|
100
|
-
await unlink(
|
|
129
|
+
await unlink(temporaryPath).catch(() => undefined);
|
|
101
130
|
throw error;
|
|
102
131
|
}
|
|
103
132
|
await file.close();
|
|
133
|
+
try {
|
|
134
|
+
await link(temporaryPath, path);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
await unlink(temporaryPath);
|
|
138
|
+
}
|
|
104
139
|
await syncDirectory(dirname(path));
|
|
105
140
|
}
|
|
106
141
|
async function writeSecureModelControlFile(path, contents) {
|
|
@@ -143,7 +178,13 @@ export function createModelControlFileAccess({ platform = process.platform, wind
|
|
|
143
178
|
}
|
|
144
179
|
await syncDirectory(dirname(path));
|
|
145
180
|
}
|
|
146
|
-
return {
|
|
181
|
+
return {
|
|
182
|
+
ensureSecureModelControlDirectory,
|
|
183
|
+
readSecureModelControlFileBuffer: (path) => withFileLock(path, () => readSecureModelControlFileBuffer(path)),
|
|
184
|
+
readSecureModelControlFile: (path) => withFileLock(path, async () => (await readSecureModelControlFileBuffer(path)).toString('utf8')),
|
|
185
|
+
createSecureModelControlFile: (path, contents) => withFileLock(path, () => createSecureModelControlFile(path, contents)),
|
|
186
|
+
writeSecureModelControlFile: (path, contents) => withFileLock(path, () => writeSecureModelControlFile(path, contents)),
|
|
187
|
+
};
|
|
147
188
|
}
|
|
148
|
-
export const { ensureSecureModelControlDirectory, readSecureModelControlFile, createSecureModelControlFile, writeSecureModelControlFile, } = createModelControlFileAccess();
|
|
189
|
+
export const { ensureSecureModelControlDirectory, readSecureModelControlFile, readSecureModelControlFileBuffer, createSecureModelControlFile, writeSecureModelControlFile, } = createModelControlFileAccess();
|
|
149
190
|
//# sourceMappingURL=model-control-files.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-control-files.js","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"model-control-files.js","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Metadata only: callers must never log the credential or a derived hash. */
|
|
2
|
+
export declare function inspectModelDeviceSecret(raw: Buffer): {
|
|
3
|
+
bytes: number;
|
|
4
|
+
encoding: string;
|
|
5
|
+
characters: number;
|
|
6
|
+
reason: string;
|
|
7
|
+
valid: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function parseModelDeviceSecret(raw: Buffer): string;
|
|
10
|
+
//# sourceMappingURL=model-device-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-device-secret.d.ts","sourceRoot":"","sources":["../../src/agents/model-device-secret.ts"],"names":[],"mappings":"AAwBA,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM;;;;;;EAOnD;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM1D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const validSecret = (value) => /^[a-f0-9]{64}$/.test(value);
|
|
2
|
+
function decodedSecret(raw) {
|
|
3
|
+
let encoding = 'utf8';
|
|
4
|
+
// Accept UTF-16 only when there is an explicit BOM or an unambiguous ASCII
|
|
5
|
+
// NUL pattern. Never strip arbitrary NULs or repair/rotate corrupt secrets.
|
|
6
|
+
if (raw.length >= 2 && raw[0] === 0xff && raw[1] === 0xfe)
|
|
7
|
+
encoding = 'utf16le';
|
|
8
|
+
else if (raw.length >= 2 && raw[0] === 0xfe && raw[1] === 0xff)
|
|
9
|
+
encoding = 'utf16be';
|
|
10
|
+
else if (raw.length >= 128 && raw.length % 2 === 0) {
|
|
11
|
+
const isAscii16 = (little) => {
|
|
12
|
+
for (let i = 0; i < raw.length; i += 2) {
|
|
13
|
+
if (raw[i + (little ? 1 : 0)] !== 0 || raw[i + (little ? 0 : 1)] > 0x7f)
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
};
|
|
18
|
+
if (isAscii16(true))
|
|
19
|
+
encoding = 'utf16le';
|
|
20
|
+
else if (isAscii16(false))
|
|
21
|
+
encoding = 'utf16be';
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const label = encoding === 'utf8' ? 'utf-8' : encoding === 'utf16le' ? 'utf-16le' : 'utf-16be';
|
|
25
|
+
return { text: new TextDecoder(label, { fatal: true }).decode(raw).trim(), encoding, validEncoding: true };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { text: '', encoding, validEncoding: false };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Metadata only: callers must never log the credential or a derived hash. */
|
|
32
|
+
export function inspectModelDeviceSecret(raw) {
|
|
33
|
+
const decoded = decodedSecret(raw);
|
|
34
|
+
const reason = !decoded.validEncoding ? 'invalid_encoding'
|
|
35
|
+
: decoded.text.length === 0 ? 'empty'
|
|
36
|
+
: decoded.text.length !== 64 ? 'invalid_length'
|
|
37
|
+
: !validSecret(decoded.text) ? 'invalid_hex' : 'valid';
|
|
38
|
+
return { bytes: raw.length, encoding: decoded.encoding, characters: decoded.text.length, reason, valid: reason === 'valid' };
|
|
39
|
+
}
|
|
40
|
+
export function parseModelDeviceSecret(raw) {
|
|
41
|
+
const metadata = inspectModelDeviceSecret(raw);
|
|
42
|
+
if (!metadata.valid) {
|
|
43
|
+
throw new Error(`INVALID_MODEL_DEVICE_SECRET: reason=${metadata.reason} bytes=${metadata.bytes} encoding=${metadata.encoding} characters=${metadata.characters}; existing file preserved, no identity reset`);
|
|
44
|
+
}
|
|
45
|
+
return decodedSecret(raw).text;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=model-device-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-device-secret.js","sourceRoot":"","sources":["../../src/agents/model-device-secret.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
export declare const WINDOWS_ACL_BATCH_PROTOCOL = "\n$ErrorActionPreference = 'Stop'\n$ProgressPreference = 'SilentlyContinue'\n[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)\n# Windows PowerShell5.1 preserves a JSON array as one pipeline object.\n# Assignment lets foreach enumerate its elements; @() would add a nested array.\n$requests = ConvertFrom-Json -InputObject $env:AGENTS_BRIDGE_ACL_REQUESTS\n$results = @(foreach ($request in $requests) {\n try {\n $snapshot = Inspect-ControlAcl $request.path $request.kind $request.privateDirectory\n @{ index = $request.index; ok = $true; snapshot = $snapshot }\n } catch {\n # Only the Node side's fixed marker allowlist may reach logs.\n @{ index = $request.index; ok = $false; error = $_.Exception.Message }\n }\n})\nConvertTo-Json -InputObject $results -Depth 8 -Compress\n";
|
|
1
2
|
export declare function sameWindowsModelControlPath(left: string, right: string): boolean;
|
|
2
3
|
export declare function validateWindowsModelControlAcl(value: unknown, kind?: 'directory' | 'file'): void;
|
|
3
|
-
|
|
4
|
+
type AclTarget = {
|
|
5
|
+
path: string;
|
|
6
|
+
kind: 'directory' | 'file';
|
|
7
|
+
privateDirectory: boolean;
|
|
8
|
+
};
|
|
9
|
+
/** Coalesce simultaneous checks, never reuse an ACL result or skip a target. */
|
|
10
|
+
export declare function createWindowsModelControlSecurity(runBatch?: (targets: AclTarget[]) => Promise<unknown>): (path: string, kind?: "directory" | "file", privateDirectory?: boolean) => Promise<void>;
|
|
11
|
+
export declare const ensureWindowsModelControlSecurity: (path: string, kind?: "directory" | "file", privateDirectory?: boolean) => Promise<void>;
|
|
12
|
+
export {};
|
|
4
13
|
//# sourceMappingURL=windows-model-control-security.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windows-model-control-security.d.ts","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"windows-model-control-security.d.ts","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,0BAA0B,wyBAiBtC,CAAA;AA8FD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,WAAW,GAAG,MAAe,GAAG,IAAI,CA+BxG;AAED,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAA;AAiBxF,gFAAgF;AAChF,wBAAgB,iCAAiC,CAAC,QAAQ,GAAE,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,CAAC,OAAO,CAAgB,IAsC3G,MAAM,MAAM,EAAE,OAAM,WAAW,GAAG,MAAe,EAAE,0BAAwB,KAAG,OAAO,CAAC,IAAI,CAAC,CAQpG;AAED,eAAO,MAAM,iCAAiC,SAV9B,MAAM,SAAQ,WAAW,GAAG,MAAM,iCAAsC,OAAO,CAAC,IAAI,CAUhB,CAAA"}
|
|
@@ -3,37 +3,98 @@ import { win32 } from 'node:path';
|
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
const execute = promisify(execFile);
|
|
5
5
|
const TRUSTED_SYSTEM_SIDS = new Set(['S-1-5-18', 'S-1-5-32-544']); // SYSTEM, Administrators
|
|
6
|
+
// Shared with the native PowerShell5.1 wire-format regression.
|
|
7
|
+
export const WINDOWS_ACL_BATCH_PROTOCOL = `
|
|
8
|
+
$ErrorActionPreference = 'Stop'
|
|
9
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
10
|
+
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
|
|
11
|
+
# Windows PowerShell5.1 preserves a JSON array as one pipeline object.
|
|
12
|
+
# Assignment lets foreach enumerate its elements; @() would add a nested array.
|
|
13
|
+
$requests = ConvertFrom-Json -InputObject $env:AGENTS_BRIDGE_ACL_REQUESTS
|
|
14
|
+
$results = @(foreach ($request in $requests) {
|
|
15
|
+
try {
|
|
16
|
+
$snapshot = Inspect-ControlAcl $request.path $request.kind $request.privateDirectory
|
|
17
|
+
@{ index = $request.index; ok = $true; snapshot = $snapshot }
|
|
18
|
+
} catch {
|
|
19
|
+
# Only the Node side's fixed marker allowlist may reach logs.
|
|
20
|
+
@{ index = $request.index; ok = $false; error = $_.Exception.Message }
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
ConvertTo-Json -InputObject $results -Depth 8 -Compress
|
|
24
|
+
`;
|
|
6
25
|
// Use SIDs rather than localized account names. Inspect inherited ACEs too; a
|
|
7
26
|
// Unix mode returned by stat on Windows says nothing about the actual DACL.
|
|
8
27
|
const INSPECT_ACL = `
|
|
28
|
+
function Inspect-ControlAcl($target, $kind, $privateDirectory) {
|
|
9
29
|
$ErrorActionPreference = 'Stop'
|
|
10
|
-
$
|
|
30
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
31
|
+
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
|
|
32
|
+
$item = Get-Item -LiteralPath $target -Force
|
|
11
33
|
$cursor = $item
|
|
12
34
|
while ($null -ne $cursor) {
|
|
13
35
|
if (($cursor.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { throw 'MODEL_CONTROL_REPARSE_POINT' }
|
|
14
36
|
if ($cursor -is [IO.DirectoryInfo]) { $cursor = $cursor.Parent } else { $cursor = $cursor.Directory }
|
|
15
37
|
}
|
|
16
|
-
$acl =
|
|
38
|
+
$acl = $item.GetAccessControl([Security.AccessControl.AccessControlSections]'Access,Owner,Group')
|
|
17
39
|
$current = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
|
|
18
40
|
$owner = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
|
|
19
|
-
|
|
41
|
+
function Set-PrivateControlAccess($existing, $kind) {
|
|
42
|
+
# Rebuild only the Access section: preserve owner/group/audit unchanged.
|
|
43
|
+
# preserveInheritance=true retains inherited ACEs in memory, so deleting
|
|
44
|
+
# only explicit Allow entries cannot reliably privatize an inherited DACL.
|
|
45
|
+
if ($kind -eq 'directory') {
|
|
46
|
+
$private = [Security.AccessControl.DirectorySecurity]::new()
|
|
47
|
+
$inheritance = [Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit'
|
|
48
|
+
} else {
|
|
49
|
+
$private = [Security.AccessControl.FileSecurity]::new()
|
|
50
|
+
$inheritance = [Security.AccessControl.InheritanceFlags]::None
|
|
51
|
+
}
|
|
52
|
+
$private.SetAccessRuleProtection($true, $false)
|
|
53
|
+
foreach ($rule in @($existing.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]))) {
|
|
54
|
+
if ($rule.AccessControlType -eq [Security.AccessControl.AccessControlType]::Deny) {
|
|
55
|
+
# Materialize inherited denies as explicit rules with the exact access
|
|
56
|
+
# mask and propagation flags. AccessRuleFactory avoids constructor mask
|
|
57
|
+
# normalization (notably Synchronize on Deny rules).
|
|
58
|
+
$deny = $private.AccessRuleFactory($rule.IdentityReference, [int]$rule.FileSystemRights, $false, $rule.InheritanceFlags, $rule.PropagationFlags, [Security.AccessControl.AccessControlType]::Deny)
|
|
59
|
+
[void]$private.AddAccessRule($deny)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
foreach ($sid in @($current, 'S-1-5-18', 'S-1-5-32-544')) {
|
|
63
|
+
$identity = [Security.Principal.SecurityIdentifier]::new($sid)
|
|
64
|
+
$rule = [Security.AccessControl.FileSystemAccessRule]::new($identity, [Security.AccessControl.FileSystemRights]::FullControl, $inheritance, [Security.AccessControl.PropagationFlags]::None, [Security.AccessControl.AccessControlType]::Allow)
|
|
65
|
+
[void]$private.AddAccessRule($rule)
|
|
66
|
+
}
|
|
67
|
+
# Persist the fresh object directly: only AccessRulesModified is set.
|
|
68
|
+
# Set-Acl copies a complete descriptor and can request SeSecurityPrivilege
|
|
69
|
+
# even when this operation only needs WRITE_DAC on our own state directory.
|
|
70
|
+
$item.SetAccessControl($private)
|
|
71
|
+
}
|
|
72
|
+
$repairAttempted = $false
|
|
73
|
+
if ($kind -eq 'directory' -and $privateDirectory -eq $true) {
|
|
74
|
+
# The caller opts in only for a direct Agent state directory under this
|
|
75
|
+
# Bridge's agents root. Never repair arbitrary parents or workspaces.
|
|
76
|
+
if ($item -isnot [IO.DirectoryInfo]) { throw 'MODEL_CONTROL_INVALID_DIRECTORY' }
|
|
77
|
+
$needsPrivacy = $false
|
|
78
|
+
foreach ($rule in @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]))) {
|
|
79
|
+
if ($rule.AccessControlType -eq [Security.AccessControl.AccessControlType]::Allow -and $rule.IdentityReference.Value -notin @($current, 'S-1-5-18', 'S-1-5-32-544') -and ($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0 -and (([long]$rule.FileSystemRights -band 4294967295) -band 1609432918) -ne 0) { $needsPrivacy = $true }
|
|
80
|
+
}
|
|
81
|
+
if ($needsPrivacy) {
|
|
82
|
+
if ($owner -ne $current) { throw 'MODEL_CONTROL_UNTRUSTED_DIRECTORY_OWNER' }
|
|
83
|
+
$repairAttempted = $true
|
|
84
|
+
Set-PrivateControlAccess $acl 'directory'
|
|
85
|
+
$acl = $item.GetAccessControl([Security.AccessControl.AccessControlSections]'Access,Owner,Group')
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if ($kind -eq 'file') {
|
|
20
89
|
if ($item -isnot [IO.FileInfo] -or $owner -notin @($current, 'S-1-5-18', 'S-1-5-32-544')) { throw 'MODEL_CONTROL_UNTRUSTED_OWNER' }
|
|
21
|
-
# Only model-control files are privatized, before any secret bytes are read
|
|
22
|
-
# or written. Never change a parent directory or a user's workspace ACL.
|
|
23
90
|
$needsPrivacy = $false
|
|
24
91
|
foreach ($rule in @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]))) {
|
|
25
92
|
if ($rule.AccessControlType -eq [Security.AccessControl.AccessControlType]::Allow -and $rule.IdentityReference.Value -notin @($current, 'S-1-5-18', 'S-1-5-32-544') -and [long]$rule.FileSystemRights -ne 0) { $needsPrivacy = $true }
|
|
26
93
|
}
|
|
27
94
|
if ($needsPrivacy) {
|
|
28
|
-
$
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
$identity = [Security.Principal.SecurityIdentifier]::new($sid)
|
|
32
|
-
$rule = [Security.AccessControl.FileSystemAccessRule]::new($identity, [Security.AccessControl.FileSystemRights]::FullControl, [Security.AccessControl.AccessControlType]::Allow)
|
|
33
|
-
[void]$acl.AddAccessRule($rule)
|
|
34
|
-
}
|
|
35
|
-
Set-Acl -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET -AclObject $acl
|
|
36
|
-
$acl = Get-Acl -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET
|
|
95
|
+
$repairAttempted = $true
|
|
96
|
+
Set-PrivateControlAccess $acl 'file'
|
|
97
|
+
$acl = $item.GetAccessControl([Security.AccessControl.AccessControlSections]'Access,Owner,Group')
|
|
37
98
|
}
|
|
38
99
|
}
|
|
39
100
|
$rules = @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]) | ForEach-Object {
|
|
@@ -48,8 +109,10 @@ $rules = @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentif
|
|
|
48
109
|
currentSid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
|
|
49
110
|
ownerSid = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
|
|
50
111
|
rules = $rules
|
|
51
|
-
|
|
52
|
-
|
|
112
|
+
repairAttempted = $repairAttempted
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
` + WINDOWS_ACL_BATCH_PROTOCOL;
|
|
53
116
|
export function sameWindowsModelControlPath(left, right) {
|
|
54
117
|
return win32.normalize(left).toLowerCase() === win32.normalize(right).toLowerCase();
|
|
55
118
|
}
|
|
@@ -94,23 +157,70 @@ export function validateWindowsModelControlAcl(value, kind = 'file') {
|
|
|
94
157
|
if (!effectiveAllow)
|
|
95
158
|
throw invalid();
|
|
96
159
|
}
|
|
97
|
-
|
|
160
|
+
const unavailable = () => new Error('MODEL_CONTROL_WINDOWS_ACL_UNAVAILABLE: Windows PowerShell ACL inspection failed');
|
|
161
|
+
const SAFE_MARKERS = ['MODEL_CONTROL_UNTRUSTED_DIRECTORY_OWNER', 'MODEL_CONTROL_UNTRUSTED_OWNER', 'MODEL_CONTROL_REPARSE_POINT', 'MODEL_CONTROL_INVALID_DIRECTORY'];
|
|
162
|
+
async function inspectBatch(targets) {
|
|
98
163
|
const executable = win32.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
164
|
+
const { stdout } = await execute(executable, [
|
|
165
|
+
'-NoLogo', '-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(INSPECT_ACL, 'utf16le').toString('base64'),
|
|
166
|
+
], {
|
|
167
|
+
env: { ...process.env, AGENTS_BRIDGE_ACL_REQUESTS: JSON.stringify(targets.map((target, index) => ({ ...target, index }))) },
|
|
168
|
+
// One short-lived process, at most three independently checked targets.
|
|
169
|
+
windowsHide: true, timeout: 10_000 * targets.length, maxBuffer: 384 * 1024,
|
|
170
|
+
});
|
|
171
|
+
return JSON.parse(stdout.replace(/^\uFEFF/, '').trim());
|
|
172
|
+
}
|
|
173
|
+
/** Coalesce simultaneous checks, never reuse an ACL result or skip a target. */
|
|
174
|
+
export function createWindowsModelControlSecurity(runBatch = inspectBatch) {
|
|
175
|
+
const queue = [];
|
|
176
|
+
let draining = false;
|
|
177
|
+
async function drain() {
|
|
178
|
+
while (queue.length) {
|
|
179
|
+
// Filesystem callbacks for three Agents need not arrive in the same
|
|
180
|
+
// event-loop turn. A bounded10ms collection window amortizes process
|
|
181
|
+
// startup without caching results or waiting indefinitely for peers.
|
|
182
|
+
if (queue.length < 3)
|
|
183
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
184
|
+
const batch = queue.splice(0, 3);
|
|
185
|
+
try {
|
|
186
|
+
const raw = await runBatch(batch.map(({ path, kind, privateDirectory }) => ({ path, kind, privateDirectory })));
|
|
187
|
+
// Validate correlation/completeness before settling any request.
|
|
188
|
+
if (!Array.isArray(raw) || raw.length !== batch.length || raw.some((entry, index) => !entry || entry.index !== index || typeof entry.ok !== 'boolean' ||
|
|
189
|
+
(!entry.ok && typeof entry.error !== 'string')))
|
|
190
|
+
throw unavailable();
|
|
191
|
+
const results = raw;
|
|
192
|
+
batch.forEach((target, index) => {
|
|
193
|
+
const result = results[index];
|
|
194
|
+
if (!result.ok) {
|
|
195
|
+
const marker = SAFE_MARKERS.find(marker => result.error.includes(marker));
|
|
196
|
+
target.reject(marker ? new Error(marker) : unavailable());
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
validateWindowsModelControlAcl(result.snapshot, target.kind);
|
|
201
|
+
target.resolve();
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
const attempted = result.snapshot?.repairAttempted === true;
|
|
205
|
+
target.reject(new Error(`${error.message}; privateDirectory=${target.privateDirectory} repairAttempted=${attempted}`));
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Never surface shell output, paths, environment or credentials.
|
|
211
|
+
batch.forEach(target => target.reject(unavailable()));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
draining = false;
|
|
113
215
|
}
|
|
114
|
-
|
|
216
|
+
return (path, kind = 'file', privateDirectory = false) => new Promise((resolve, reject) => {
|
|
217
|
+
queue.push({ path, kind, privateDirectory, resolve, reject });
|
|
218
|
+
if (!draining) {
|
|
219
|
+
draining = true;
|
|
220
|
+
// Only one bounded PowerShell process is active at a time.
|
|
221
|
+
setImmediate(() => { void drain(); });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
115
224
|
}
|
|
225
|
+
export const ensureWindowsModelControlSecurity = createWindowsModelControlSecurity();
|
|
116
226
|
//# sourceMappingURL=windows-model-control-security.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windows-model-control-security.js","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AACnC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAA,CAAC,yBAAyB;AAE3F,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,WAAW,GAAG
|
|
1
|
+
{"version":3,"file":"windows-model-control-security.js","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cmd-start.d.ts","sourceRoot":"","sources":["../../src/cli/cmd-start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cmd-start.d.ts","sourceRoot":"","sources":["../../src/cli/cmd-start.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAU5C,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAiB1B,OAAO,EACL,8BAA8B,EAC9B,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAA;AAUhC,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAkBnF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAKzE;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,QAAQ,EAAE,eAAe,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,SAAS,GAAG,cAAc,GAAG,SAAS,CAAA;IAC1E,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,uBAAuB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACpE,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACnE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9C,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAuBlE;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,MAAM,CAAC,CAAA;IAClD,sBAAsB,EAAE,OAAO,CAAA;IAC/B,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,OAAO,CAAC,OAAO,CAAC,CASnB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAopB3D;AAyID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUnE;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAM1F;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAK/D;AAwED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,EAChC,OAAO,CAAC,EAAE;IACR,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;;iBA6IoB,MAAM;wBAqBC,MAAM;mBAiCX,MAAM;EAe9B;AA8BD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASrE;AA0BD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAC7D,QAAQ,EAAE,eAAe,GACxB,oBAAoB,CAetB"}
|