ysagc-agent 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -67
- package/dist/agent.d.ts +17 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +293 -0
- package/dist/agent.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +267 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +52 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +135 -0
- package/dist/config.js.map +1 -0
- package/dist/executor.d.ts +46 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +397 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +37 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +121 -0
- package/dist/logger.js.map +1 -0
- package/dist/path-utils.d.ts +44 -0
- package/dist/path-utils.d.ts.map +1 -0
- package/dist/path-utils.js +206 -0
- package/dist/path-utils.js.map +1 -0
- package/dist/protocol.d.ts +77 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +94 -0
- package/dist/protocol.js.map +1 -0
- package/dist/security.d.ts +32 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +228 -0
- package/dist/security.js.map +1 -0
- package/dist/tools.d.ts +36 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +498 -0
- package/dist/tools.js.map +1 -0
- package/package.json +36 -21
- package/src/config.js +0 -94
- package/src/http-fs.js +0 -178
- package/src/index.js +0 -442
- package/src/logger.js +0 -84
- package/src/methods/browse.js +0 -91
- package/src/methods/dialog.js +0 -84
- package/src/methods/fs.js +0 -674
- package/src/methods/git.js +0 -391
- package/src/methods/project.js +0 -57
- package/src/methods/scaffold.js +0 -131
- package/src/methods/skill.js +0 -472
- package/src/methods/system.js +0 -82
- package/src/methods/terminal.js +0 -234
- package/src/origin.js +0 -38
- package/src/pairing.js +0 -168
- package/src/rpc.js +0 -62
- package/src/sandbox.js +0 -178
package/dist/cli.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.runSelfTest = runSelfTest;
|
|
38
|
+
const commander_1 = require("commander");
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const os = __importStar(require("node:os"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const agent_1 = require("./agent");
|
|
43
|
+
const config_1 = require("./config");
|
|
44
|
+
const logger_1 = require("./logger");
|
|
45
|
+
const path_utils_1 = require("./path-utils");
|
|
46
|
+
const security_1 = require("./security");
|
|
47
|
+
const tools_1 = require("./tools");
|
|
48
|
+
const program = new commander_1.Command();
|
|
49
|
+
program
|
|
50
|
+
.name('ysagc-agent')
|
|
51
|
+
.description('Local execution agent for ysagc (state-agnostic, safety-bounded)')
|
|
52
|
+
.version(agent_1.AGENT_VERSION)
|
|
53
|
+
.option('--server <url>', 'platform WebSocket URL for the agent channel')
|
|
54
|
+
.option('--token <token>', 'device/agent auth token')
|
|
55
|
+
.option('--device-id <id>', 'stable device identifier')
|
|
56
|
+
.option('--root <dir>', 'authorisation root for all file operations')
|
|
57
|
+
.option('--mode <mode>', 'permission mode: supervise | smart | auto', 'smart')
|
|
58
|
+
.option('--web', 'enable the local web_search (stub) tool')
|
|
59
|
+
.option('--timeout <ms>', 'command timeout in milliseconds')
|
|
60
|
+
.option('--max-bytes <n>', 'per-stream output cap in bytes')
|
|
61
|
+
.option('--log-level <level>', 'silent | error | warn | info | debug', 'info')
|
|
62
|
+
.option('--selftest', 'run a local self-test and exit');
|
|
63
|
+
program.parse(process.argv);
|
|
64
|
+
const opts = program.opts();
|
|
65
|
+
function toInt(value) {
|
|
66
|
+
if (value === undefined || value === null)
|
|
67
|
+
return undefined;
|
|
68
|
+
const n = Number(value);
|
|
69
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : undefined;
|
|
70
|
+
}
|
|
71
|
+
function asStr(value) {
|
|
72
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
73
|
+
}
|
|
74
|
+
function shutdown(handle, signal) {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.log(`\n${signal} received; shutting down`);
|
|
77
|
+
handle?.stop();
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
async function main() {
|
|
81
|
+
if (opts.selftest) {
|
|
82
|
+
const results = await runSelfTest();
|
|
83
|
+
runAndPrintSelfTest(results);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const config = (0, config_1.loadConfig)({
|
|
88
|
+
server: asStr(opts.server),
|
|
89
|
+
token: asStr(opts.token),
|
|
90
|
+
deviceId: asStr(opts.deviceId),
|
|
91
|
+
root: asStr(opts.root),
|
|
92
|
+
mode: asStr(opts.mode),
|
|
93
|
+
web: opts.web === true ? true : undefined,
|
|
94
|
+
timeoutMs: toInt(opts.timeout),
|
|
95
|
+
maxBytes: toInt(opts.maxBytes),
|
|
96
|
+
logLevel: asStr(opts.logLevel),
|
|
97
|
+
});
|
|
98
|
+
const log = new logger_1.Logger({ level: config.logLevel, name: 'cli' });
|
|
99
|
+
log.info('agent config', (0, config_1.describeConfig)(config));
|
|
100
|
+
const handle = (0, agent_1.startAgent)(config);
|
|
101
|
+
process.on('SIGINT', () => shutdown(handle, 'SIGINT'));
|
|
102
|
+
process.on('SIGTERM', () => shutdown(handle, 'SIGTERM'));
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err instanceof config_1.ConfigError) {
|
|
106
|
+
// eslint-disable-next-line no-console
|
|
107
|
+
console.error(`\nConfiguration error: ${err.message}\n`);
|
|
108
|
+
// eslint-disable-next-line no-console
|
|
109
|
+
console.error('Run `ysagc-agent --help` for usage, or set the matching environment variables.');
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function runAndPrintSelfTest(results) {
|
|
116
|
+
let failed = 0;
|
|
117
|
+
for (const r of results) {
|
|
118
|
+
const status = r.ok ? 'PASS' : 'FAIL';
|
|
119
|
+
const detail = [r.details, r.error].filter(Boolean).join(' — ');
|
|
120
|
+
// eslint-disable-next-line no-console
|
|
121
|
+
console.log(`[${status}] ${r.name}${detail ? ` — ${detail}` : ''}`);
|
|
122
|
+
if (!r.ok)
|
|
123
|
+
failed += 1;
|
|
124
|
+
}
|
|
125
|
+
// eslint-disable-next-line no-console
|
|
126
|
+
console.log(`\nSelf-test: ${results.length - failed}/${results.length} passed.`);
|
|
127
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Run a local smoke test of path safety, danger-command detection, sensitive
|
|
131
|
+
* path detection, secret masking and the tool registry. Returns structured
|
|
132
|
+
* PASS/FAIL results; the CLI prints them and picks the exit code.
|
|
133
|
+
*/
|
|
134
|
+
async function runSelfTest() {
|
|
135
|
+
const results = [];
|
|
136
|
+
const add = (name, ok, details, error) => {
|
|
137
|
+
results.push({ name, ok, details, error });
|
|
138
|
+
};
|
|
139
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ysagc-test-'));
|
|
140
|
+
const outside = fs.mkdtempSync(path.join(os.tmpdir(), 'ysagc-outside-'));
|
|
141
|
+
const sync = (name, fn) => {
|
|
142
|
+
try {
|
|
143
|
+
add(name, fn());
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
add(name, false, undefined, err instanceof Error ? err.message : String(err));
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const asyncCheck = async (name, fn) => {
|
|
150
|
+
try {
|
|
151
|
+
add(name, await fn());
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
add(name, false, undefined, err instanceof Error ? err.message : String(err));
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
try {
|
|
158
|
+
// --- path safety ------------------------------------------------------
|
|
159
|
+
sync('canonicalize resolves ..', () => {
|
|
160
|
+
const cwd = dir;
|
|
161
|
+
const resolved = (0, path_utils_1.canonicalize)('sub/dir/../file.txt', cwd);
|
|
162
|
+
return resolved === path.resolve(dir, 'sub', 'file.txt');
|
|
163
|
+
});
|
|
164
|
+
sync('isWithinRoot: child inside root', () => (0, path_utils_1.isWithinRoot)(dir, path.join(dir, 'a', 'b')));
|
|
165
|
+
sync('isWithinRoot: .. escape rejected', () => !(0, path_utils_1.isWithinRoot)(dir, path.join(dir, '..', 'escape')));
|
|
166
|
+
sync('isWithinRoot: equal root rejected when writing', () => !(0, path_utils_1.isWithinRoot)(dir, dir));
|
|
167
|
+
sync('isWithinRoot: equal root allowed when reading', () => (0, path_utils_1.isWithinRoot)(dir, dir, { allowEqual: true }));
|
|
168
|
+
sync('windows reserved name detected', () => (0, path_utils_1.isWindowsReservedName)('CON'));
|
|
169
|
+
sync('non-reserved name ok', () => !(0, path_utils_1.isWindowsReservedName)('hello'));
|
|
170
|
+
sync('symlink escape rejected', () => {
|
|
171
|
+
try {
|
|
172
|
+
const link = path.join(dir, 'linkdir');
|
|
173
|
+
fs.symlinkSync(outside, link, 'junction');
|
|
174
|
+
return !(0, path_utils_1.isWithinRoot)(dir, path.join(link, 'file.txt'));
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return true; // skipped when symlinks are unsupported (e.g. unprivileged Windows)
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// --- danger detection -------------------------------------------------
|
|
181
|
+
const dangerCases = [
|
|
182
|
+
['rm -rf /tmp/foo', true],
|
|
183
|
+
['sudo apt-get update', true],
|
|
184
|
+
['git reset --hard', true],
|
|
185
|
+
['format d:', true],
|
|
186
|
+
['echo hello world', false],
|
|
187
|
+
['ls -la', false],
|
|
188
|
+
['cat package.json', false],
|
|
189
|
+
];
|
|
190
|
+
for (const [cmd, shouldBlock] of dangerCases) {
|
|
191
|
+
const a = (0, security_1.isDangerCommand)(cmd);
|
|
192
|
+
add(`danger: ${cmd}`, a.danger === shouldBlock, `severity=${a.severity}`);
|
|
193
|
+
}
|
|
194
|
+
// --- sensitive path ---------------------------------------------------
|
|
195
|
+
sync('sensitive /etc/passwd blocked', () => (0, security_1.isSensitivePath)('/etc/passwd'));
|
|
196
|
+
sync('sensitive .env blocked', () => (0, security_1.isSensitivePath)('/some/root/.env'));
|
|
197
|
+
sync('normal file allowed', () => !(0, security_1.isSensitivePath)(path.join(dir, 'x.txt')));
|
|
198
|
+
// --- secret masking ---------------------------------------------------
|
|
199
|
+
sync('maskSecrets redacts sk- keys', () => {
|
|
200
|
+
const masked = (0, security_1.maskSecrets)('key=sk-abcdefghijklmnopqrstuvwxyz123456 extra');
|
|
201
|
+
return !/sk-[a-f0-9]{6,}/i.test(masked) && masked.includes('***');
|
|
202
|
+
});
|
|
203
|
+
sync('maskSecrets redacts bearer/JWT', () => {
|
|
204
|
+
const masked = (0, security_1.maskSecrets)('Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.sig');
|
|
205
|
+
return !masked.includes('eyJhbGci') && masked.includes('***');
|
|
206
|
+
});
|
|
207
|
+
// --- tools ------------------------------------------------------------
|
|
208
|
+
const logger = new logger_1.Logger({ level: 'error', name: 'selftest' });
|
|
209
|
+
const registry = (0, tools_1.createToolRegistry)({
|
|
210
|
+
root: dir,
|
|
211
|
+
mode: 'smart',
|
|
212
|
+
webEnabled: false,
|
|
213
|
+
timeoutMs: 10000,
|
|
214
|
+
maxBytes: 8000,
|
|
215
|
+
logger,
|
|
216
|
+
});
|
|
217
|
+
await asyncCheck('write_file', async () => {
|
|
218
|
+
const w = await registry.dispatch('write_file', { path: 'hello.txt', content: 'hello world' });
|
|
219
|
+
return w.ok && w.result?.bytesWritten === 11;
|
|
220
|
+
});
|
|
221
|
+
await asyncCheck('read_file', async () => {
|
|
222
|
+
const r = await registry.dispatch('read_file', { path: 'hello.txt', maxBytes: 100 });
|
|
223
|
+
return r.ok && String(r.result?.content ?? '').includes('hello world');
|
|
224
|
+
});
|
|
225
|
+
await asyncCheck('list_dir', async () => {
|
|
226
|
+
const l = await registry.dispatch('list_dir', { path: '.', depth: 1 });
|
|
227
|
+
const entries = l.result?.entries ?? [];
|
|
228
|
+
return l.ok && entries.some((entry) => entry.name === 'hello.txt');
|
|
229
|
+
});
|
|
230
|
+
await asyncCheck('edit_file', async () => {
|
|
231
|
+
const e = await registry.dispatch('edit_file', { path: 'hello.txt', oldText: 'world', newText: 'there' });
|
|
232
|
+
return e.ok && e.result?.replacements === 1;
|
|
233
|
+
});
|
|
234
|
+
await asyncCheck('write_file rejects outside root', async () => {
|
|
235
|
+
const out = await registry.dispatch('write_file', { path: '../escape.txt', content: 'nope' });
|
|
236
|
+
return !out.ok;
|
|
237
|
+
});
|
|
238
|
+
await asyncCheck('generate', async () => {
|
|
239
|
+
const g = await registry.dispatch('generate', { template: 'node', name: 'myproj' });
|
|
240
|
+
const files = g.result?.files ?? [];
|
|
241
|
+
return g.ok && files.some((f) => f.path.includes('myproj/package.json'));
|
|
242
|
+
});
|
|
243
|
+
await asyncCheck('run_command echo', async () => {
|
|
244
|
+
const c = await registry.dispatch('run_command', { cmd: 'echo hello from selftest' });
|
|
245
|
+
const stdout = String(c.result?.stdout ?? '');
|
|
246
|
+
return c.ok && stdout.includes('hello from selftest');
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
try {
|
|
251
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
252
|
+
fs.rmSync(outside, { recursive: true, force: true });
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
/* best-effort cleanup */
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return results;
|
|
259
|
+
}
|
|
260
|
+
if (require.main === module) {
|
|
261
|
+
main().catch((err) => {
|
|
262
|
+
// eslint-disable-next-line no-console
|
|
263
|
+
console.error(`Fatal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHA,kCA0IC;AAzPD,yCAAoC;AACpC,4CAA8B;AAC9B,4CAA8B;AAC9B,gDAAkC;AAClC,mCAAsE;AACtE,qCAAmE;AACnE,qCAAkC;AAClC,6CAAiF;AACjF,yCAA2E;AAC3E,mCAA6C;AAS7C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,kEAAkE,CAAC;KAC/E,OAAO,CAAC,qBAAa,CAAC;KACtB,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;KACxE,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;KACtD,MAAM,CAAC,cAAc,EAAE,4CAA4C,CAAC;KACpE,MAAM,CAAC,eAAe,EAAE,2CAA2C,EAAE,OAAO,CAAC;KAC7E,MAAM,CAAC,OAAO,EAAE,yCAAyC,CAAC;KAC1D,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;KAC3D,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;KAC3D,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,EAAE,MAAM,CAAC;KAC7E,MAAM,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;AAE1D,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAA2B,CAAC;AAErD,SAAS,KAAK,CAAC,KAAc;IAC3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC;AAED,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACrF,CAAC;AAED,SAAS,QAAQ,CAAC,MAA+B,EAAE,MAAc;IAC/D,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,0BAA0B,CAAC,CAAC;IACnD,MAAM,EAAE,IAAI,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;QACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC;YACxB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAC1B,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YACxB,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC9B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACtB,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACzC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;YAC9B,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC9B,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;SAC/B,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,eAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,IAAA,uBAAc,EAAC,MAAM,CAAC,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAW,EAAE,CAAC;YAC/B,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,0BAA0B,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YACzD,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;YAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAmB;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,MAAM,GAAG,MAAM,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IACjF,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,WAAW;IAC/B,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAW,EAAE,OAAgB,EAAE,KAAc,EAAQ,EAAE;QAChF,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEzE,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAiB,EAAQ,EAAE;QACrD,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,EAAE,IAAY,EAAE,EAA0B,EAAiB,EAAE;QACnF,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,yEAAyE;QACzE,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE;YACpC,MAAM,GAAG,GAAG,GAAG,CAAC;YAChB,MAAM,QAAQ,GAAG,IAAA,yBAAY,EAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;YAC1D,OAAO,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,IAAA,yBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE,CAAC,CAAC,IAAA,yBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnG,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE,CAAC,CAAC,IAAA,yBAAY,EAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE,CAAC,IAAA,yBAAY,EAAC,GAAG,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,IAAA,kCAAqB,EAAC,KAAK,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC,IAAA,kCAAqB,EAAC,OAAO,CAAC,CAAC,CAAC;QAEpE,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACnC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBACvC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;gBAC1C,OAAO,CAAC,IAAA,yBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC,CAAC,oEAAoE;YACnF,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,MAAM,WAAW,GAA6B;YAC5C,CAAC,iBAAiB,EAAE,IAAI,CAAC;YACzB,CAAC,qBAAqB,EAAE,IAAI,CAAC;YAC7B,CAAC,kBAAkB,EAAE,IAAI,CAAC;YAC1B,CAAC,WAAW,EAAE,IAAI,CAAC;YACnB,CAAC,kBAAkB,EAAE,KAAK,CAAC;YAC3B,CAAC,QAAQ,EAAE,KAAK,CAAC;YACjB,CAAC,kBAAkB,EAAE,KAAK,CAAC;SAC5B,CAAC;QACF,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,IAAA,0BAAe,EAAC,GAAG,CAAC,CAAC;YAC/B,GAAG,CAAC,WAAW,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,WAAW,EAAE,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,yEAAyE;QACzE,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE,CAAC,IAAA,0BAAe,EAAC,aAAa,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,IAAA,0BAAe,EAAC,iBAAiB,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC,IAAA,0BAAe,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAE7E,yEAAyE;QACzE,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACxC,MAAM,MAAM,GAAG,IAAA,sBAAW,EAAC,+CAA+C,CAAC,CAAC;YAC5E,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAA,sBAAW,EAAC,iDAAiD,CAAC,CAAC;YAC9E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,IAAA,0BAAkB,EAAC;YAClC,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,KAAM;YACjB,QAAQ,EAAE,IAAK;YACf,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;YAC/F,OAAO,CAAC,CAAC,EAAE,IAAK,CAAC,CAAC,MAAoC,EAAE,YAAY,KAAK,EAAE,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACrF,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,CAAE,CAAC,CAAC,MAA+B,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACnG,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;YACtC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YACvE,MAAM,OAAO,GAAI,CAAC,CAAC,MAAgD,EAAE,OAAO,IAAI,EAAE,CAAC;YACnF,OAAO,CAAC,CAAC,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1G,OAAO,CAAC,CAAC,EAAE,IAAK,CAAC,CAAC,MAAoC,EAAE,YAAY,KAAK,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;YACtC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpF,MAAM,KAAK,GAAI,CAAC,CAAC,MAA8C,EAAE,KAAK,IAAI,EAAE,CAAC;YAC7E,OAAO,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACtF,MAAM,MAAM,GAAG,MAAM,CAAE,CAAC,CAAC,MAA8B,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;YACvE,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACjD,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Logger, type LogLevel } from './logger';
|
|
2
|
+
export type PermissionMode = 'supervise' | 'smart' | 'auto';
|
|
3
|
+
export interface AgentConfig {
|
|
4
|
+
/** Platform WebSocket URL for the agent channel. */
|
|
5
|
+
server: string;
|
|
6
|
+
/** Device/agent auth token presented in the hello frame. */
|
|
7
|
+
token: string;
|
|
8
|
+
/** Stable device identifier sent in the hello frame. */
|
|
9
|
+
deviceId: string;
|
|
10
|
+
/** Authorisation root; every file operation must stay inside it. */
|
|
11
|
+
root: string;
|
|
12
|
+
/** Permission policy for shell commands. */
|
|
13
|
+
mode: PermissionMode;
|
|
14
|
+
/** Whether the local web_search tool is enabled. */
|
|
15
|
+
web: boolean;
|
|
16
|
+
/** Command timeout in milliseconds. */
|
|
17
|
+
timeoutMs: number;
|
|
18
|
+
/** Per-stream output cap in bytes before it is truncated/spilled. */
|
|
19
|
+
maxBytes: number;
|
|
20
|
+
/** Log verbosity. */
|
|
21
|
+
logLevel: LogLevel;
|
|
22
|
+
/** Passed in the hello frame to let the platform route the agent. */
|
|
23
|
+
platform: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ConfigOverrides {
|
|
26
|
+
server?: string;
|
|
27
|
+
token?: string;
|
|
28
|
+
deviceId?: string;
|
|
29
|
+
root?: string;
|
|
30
|
+
mode?: string;
|
|
31
|
+
web?: boolean;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
maxBytes?: number;
|
|
34
|
+
logLevel?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare class ConfigError extends Error {
|
|
37
|
+
constructor(message: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve an {@link AgentConfig} from defaults, environment variables and CLI
|
|
41
|
+
* overrides (in that order of precedence). Environment variables are read from
|
|
42
|
+
* WS_URL / YSAGC_TOKEN / DEVICE_ID / WORKSPACE_ROOT / PERMISSION_MODE /
|
|
43
|
+
* YSAGC_WEB / YSAGC_TIMEOUT / YSAGC_MAX_BYTES / YSAGC_LOG_LEVEL.
|
|
44
|
+
*/
|
|
45
|
+
export declare function loadConfig(overrides?: ConfigOverrides): AgentConfig;
|
|
46
|
+
/** Validate the subset of config required to start the agent. Throws a
|
|
47
|
+
* {@link ConfigError} with a friendly message for missing values. */
|
|
48
|
+
export declare function validateConfig(config: AgentConfig): void;
|
|
49
|
+
/** Build a logger from a config. */
|
|
50
|
+
export declare function loggerFromConfig(config: AgentConfig): Logger;
|
|
51
|
+
export declare function describeConfig(config: AgentConfig): Record<string, unknown>;
|
|
52
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEjD,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAI5D,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,cAAc,CAAC;IACrB,oDAAoD;IACpD,GAAG,EAAE,OAAO,CAAC;IACb,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AA+CD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,GAAE,eAAoB,GAAG,WAAW,CA0BvE;AAiBD;qEACqE;AACrE,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAYxD;AAED,oCAAoC;AACpC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa3E"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfigError = void 0;
|
|
7
|
+
exports.loadConfig = loadConfig;
|
|
8
|
+
exports.validateConfig = validateConfig;
|
|
9
|
+
exports.loggerFromConfig = loggerFromConfig;
|
|
10
|
+
exports.describeConfig = describeConfig;
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
13
|
+
const logger_1 = require("./logger");
|
|
14
|
+
const VALID_MODES = new Set(['supervise', 'smart', 'auto']);
|
|
15
|
+
class ConfigError extends Error {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'ConfigError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.ConfigError = ConfigError;
|
|
22
|
+
const DEFAULT_TIMEOUT_MS = 120000;
|
|
23
|
+
const DEFAULT_MAX_BYTES = 64000;
|
|
24
|
+
function readEnv(name) {
|
|
25
|
+
const v = process.env[name];
|
|
26
|
+
return v && v.trim() !== '' ? v.trim() : undefined;
|
|
27
|
+
}
|
|
28
|
+
function parseMode(value, fallback) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return fallback;
|
|
31
|
+
const v = value.toLowerCase();
|
|
32
|
+
if (VALID_MODES.has(v))
|
|
33
|
+
return v;
|
|
34
|
+
throw new ConfigError(`Invalid permission mode "${value}". Expected one of: supervise, smart, auto.`);
|
|
35
|
+
}
|
|
36
|
+
function parsePosInt(value, fallback, name) {
|
|
37
|
+
if (!value)
|
|
38
|
+
return fallback;
|
|
39
|
+
const n = Number(value);
|
|
40
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
41
|
+
throw new ConfigError(`Invalid ${name}: "${value}" must be a positive integer.`);
|
|
42
|
+
}
|
|
43
|
+
return Math.floor(n);
|
|
44
|
+
}
|
|
45
|
+
function parseLogLevel(value) {
|
|
46
|
+
if (!value)
|
|
47
|
+
return 'info';
|
|
48
|
+
const v = value.toLowerCase();
|
|
49
|
+
if (v === 'silent' || v === 'error' || v === 'warn' || v === 'info' || v === 'debug') {
|
|
50
|
+
return v;
|
|
51
|
+
}
|
|
52
|
+
throw new ConfigError(`Invalid log level "${value}". Expected: silent, error, warn, info, debug.`);
|
|
53
|
+
}
|
|
54
|
+
function resolveRoot(raw) {
|
|
55
|
+
if (!raw)
|
|
56
|
+
return process.cwd();
|
|
57
|
+
// Expand a leading ~ to the home directory at configuration time only; the
|
|
58
|
+
// path-utils canonicaliser intentionally does not expand `~`.
|
|
59
|
+
const t = raw.trim();
|
|
60
|
+
if (t === '~')
|
|
61
|
+
return node_os_1.default.homedir();
|
|
62
|
+
if (t.startsWith('~/') || t.startsWith('~\\'))
|
|
63
|
+
return node_path_1.default.join(node_os_1.default.homedir(), t.slice(2));
|
|
64
|
+
return node_path_1.default.resolve(t);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve an {@link AgentConfig} from defaults, environment variables and CLI
|
|
68
|
+
* overrides (in that order of precedence). Environment variables are read from
|
|
69
|
+
* WS_URL / YSAGC_TOKEN / DEVICE_ID / WORKSPACE_ROOT / PERMISSION_MODE /
|
|
70
|
+
* YSAGC_WEB / YSAGC_TIMEOUT / YSAGC_MAX_BYTES / YSAGC_LOG_LEVEL.
|
|
71
|
+
*/
|
|
72
|
+
function loadConfig(overrides = {}) {
|
|
73
|
+
const mode = parseMode(overrides.mode ?? readEnv('PERMISSION_MODE'), 'smart');
|
|
74
|
+
return {
|
|
75
|
+
server: overrides.server ?? readEnv('WS_URL') ?? '',
|
|
76
|
+
token: overrides.token ?? readEnv('YSAGC_TOKEN') ?? '',
|
|
77
|
+
deviceId: overrides.deviceId ??
|
|
78
|
+
readEnv('DEVICE_ID') ??
|
|
79
|
+
defaultDeviceId(),
|
|
80
|
+
root: resolveRoot(overrides.root ?? readEnv('WORKSPACE_ROOT')),
|
|
81
|
+
mode,
|
|
82
|
+
web: overrides.web ?? truthy(readEnv('YSAGC_WEB')),
|
|
83
|
+
timeoutMs: parsePosInt(overrides.timeoutMs != null ? String(overrides.timeoutMs) : readEnv('YSAGC_TIMEOUT'), DEFAULT_TIMEOUT_MS, 'timeout'),
|
|
84
|
+
maxBytes: parsePosInt(overrides.maxBytes != null ? String(overrides.maxBytes) : readEnv('YSAGC_MAX_BYTES'), DEFAULT_MAX_BYTES, 'max-bytes'),
|
|
85
|
+
logLevel: parseLogLevel(overrides.logLevel ?? readEnv('YSAGC_LOG_LEVEL')),
|
|
86
|
+
platform: 'node',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function truthy(value) {
|
|
90
|
+
if (!value)
|
|
91
|
+
return false;
|
|
92
|
+
return /^(1|true|yes|on)$/i.test(value);
|
|
93
|
+
}
|
|
94
|
+
/** A stable-ish default device id derived from the hostname. */
|
|
95
|
+
function defaultDeviceId() {
|
|
96
|
+
try {
|
|
97
|
+
const host = node_os_1.default.hostname();
|
|
98
|
+
return `agent-${host || 'unknown'}-${process.pid}`;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return `agent-${process.pid}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Validate the subset of config required to start the agent. Throws a
|
|
105
|
+
* {@link ConfigError} with a friendly message for missing values. */
|
|
106
|
+
function validateConfig(config) {
|
|
107
|
+
if (!config.server || config.server.trim() === '') {
|
|
108
|
+
throw new ConfigError('Missing platform WebSocket URL. Pass --server <url> or set WS_URL.');
|
|
109
|
+
}
|
|
110
|
+
if (!config.token || config.token.trim() === '') {
|
|
111
|
+
throw new ConfigError('Missing auth token. Pass --token <token> or set YSAGC_TOKEN.');
|
|
112
|
+
}
|
|
113
|
+
if (!config.deviceId || config.deviceId.trim() === '') {
|
|
114
|
+
throw new ConfigError('Missing device id. Pass --device-id <id> or set DEVICE_ID.');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Build a logger from a config. */
|
|
118
|
+
function loggerFromConfig(config) {
|
|
119
|
+
return new logger_1.Logger({ level: config.logLevel, name: 'ysagc-agent' });
|
|
120
|
+
}
|
|
121
|
+
function describeConfig(config) {
|
|
122
|
+
return {
|
|
123
|
+
server: config.server,
|
|
124
|
+
deviceId: config.deviceId,
|
|
125
|
+
root: config.root,
|
|
126
|
+
mode: config.mode,
|
|
127
|
+
web: config.web,
|
|
128
|
+
timeoutMs: config.timeoutMs,
|
|
129
|
+
maxBytes: config.maxBytes,
|
|
130
|
+
logLevel: config.logLevel,
|
|
131
|
+
platform: config.platform,
|
|
132
|
+
// token deliberately omitted — never log it.
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface CommandResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
exitCode: number;
|
|
5
|
+
durationMs: number;
|
|
6
|
+
/** True when the process was killed because the timeout elapsed. */
|
|
7
|
+
timedOut: boolean;
|
|
8
|
+
/** True when a stream was truncated to the max-bytes cap. */
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
/** Path to a temp file holding the full stdout when truncated. */
|
|
11
|
+
stdoutFile?: string;
|
|
12
|
+
/** Path to a temp file holding the full stderr when truncated. */
|
|
13
|
+
stderrFile?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface RunCommandOptions {
|
|
16
|
+
command: string;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
maxBytes?: number;
|
|
20
|
+
/** Extra environment variables (merged over the default, sanitised env). */
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
/** Abort signal; aborting kills the process tree. */
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
/** Force shell mode (default: auto-detect per platform / metacharacters). */
|
|
25
|
+
shell?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Split a simple command string into argv (respects single/double quotes and
|
|
29
|
+
* backslash escape). Do not use for commands with shell metacharacters.
|
|
30
|
+
*/
|
|
31
|
+
export declare function tokenize(input: string): string[];
|
|
32
|
+
/** Decide whether a command must run through a shell. On Windows the shell is
|
|
33
|
+
* always used because many common commands are cmd builtins. */
|
|
34
|
+
export declare function shouldUseShell(command: string, override?: boolean): boolean;
|
|
35
|
+
/** Build a sanitised env so agent/platform credentials never reach child
|
|
36
|
+
* processes. Essential environment (PATH, HOME, LANG, ...) is preserved. */
|
|
37
|
+
export declare function sanitizeEnv(base: NodeJS.ProcessEnv, extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
38
|
+
/**
|
|
39
|
+
* Run a command, capturing stdout/stderr (spilled to a temp file when it
|
|
40
|
+
* exceeds `maxBytes`), enforcing a timeout, and killing the process tree on
|
|
41
|
+
* timeout or abort. Non-zero exit codes are returned, not thrown. Output is
|
|
42
|
+
* captured through file-descriptor redirection rather than a pipe so it is
|
|
43
|
+
* robust on constrained platforms and for very large outputs.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runCommand(opts: RunCommandOptions): Promise<CommandResult>;
|
|
46
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qDAAqD;IACrD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoCD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsChD;AAED;gEACgE;AAChE,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAI3E;AAED;4EAC4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAiBjG;AA2DD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkM1E"}
|