ysagc-agent 0.2.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.
Files changed (58) hide show
  1. package/README.md +36 -66
  2. package/dist/agent.d.ts +17 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +293 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/cli.d.ts +14 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +267 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +52 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +135 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/executor.d.ts +46 -0
  15. package/dist/executor.d.ts.map +1 -0
  16. package/dist/executor.js +397 -0
  17. package/dist/executor.js.map +1 -0
  18. package/dist/index.d.ts +19 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +34 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/logger.d.ts +37 -0
  23. package/dist/logger.d.ts.map +1 -0
  24. package/dist/logger.js +121 -0
  25. package/dist/logger.js.map +1 -0
  26. package/dist/path-utils.d.ts +44 -0
  27. package/dist/path-utils.d.ts.map +1 -0
  28. package/dist/path-utils.js +206 -0
  29. package/dist/path-utils.js.map +1 -0
  30. package/dist/protocol.d.ts +77 -0
  31. package/dist/protocol.d.ts.map +1 -0
  32. package/dist/protocol.js +94 -0
  33. package/dist/protocol.js.map +1 -0
  34. package/dist/security.d.ts +32 -0
  35. package/dist/security.d.ts.map +1 -0
  36. package/dist/security.js +228 -0
  37. package/dist/security.js.map +1 -0
  38. package/dist/tools.d.ts +36 -0
  39. package/dist/tools.d.ts.map +1 -0
  40. package/dist/tools.js +498 -0
  41. package/dist/tools.js.map +1 -0
  42. package/package.json +36 -21
  43. package/src/config.js +0 -94
  44. package/src/http-fs.js +0 -178
  45. package/src/index.js +0 -439
  46. package/src/logger.js +0 -84
  47. package/src/methods/dialog.js +0 -84
  48. package/src/methods/fs.js +0 -674
  49. package/src/methods/git.js +0 -391
  50. package/src/methods/project.js +0 -57
  51. package/src/methods/scaffold.js +0 -131
  52. package/src/methods/skill.js +0 -347
  53. package/src/methods/system.js +0 -82
  54. package/src/methods/terminal.js +0 -234
  55. package/src/origin.js +0 -38
  56. package/src/pairing.js +0 -168
  57. package/src/rpc.js +0 -62
  58. package/src/sandbox.js +0 -178
@@ -0,0 +1,44 @@
1
+ /** Thrown when a path is empty, escapes the allowed root, or targets a
2
+ * Windows-reserved / sensitive location. */
3
+ export declare class PathError extends Error {
4
+ readonly code: string;
5
+ constructor(code: string, message: string);
6
+ }
7
+ /** True when a single path segment (ignoring its extension) is a Windows
8
+ * reserved device name such as CON or COM1. */
9
+ export declare function isWindowsReservedName(segment: string): boolean;
10
+ /**
11
+ * Resolve the longest existing ancestor's real path and re-append the
12
+ * not-yet-existing tail. This keeps canonicalisation correct for both files
13
+ * that already exist (symlinks resolved) and files about to be created
14
+ * (their existing parent's symlinks resolved), which prevents escaping the
15
+ * root through a symlink.
16
+ */
17
+ export declare function realpathSafe(p: string): string;
18
+ /**
19
+ * Produce a canonical, absolute, symlink-aware path. Resolves `..`, normalises
20
+ * separators, resolves symlinks on the existing prefix, strips the Windows
21
+ * `\\?\` prefix, and (on Windows) detects reserved device names and trailing
22
+ * dot/space aliases. `~` and environment variables are NOT expanded.
23
+ */
24
+ export declare function canonicalize(p: string, cwd?: string): string;
25
+ export interface WithinRootOptions {
26
+ /** Allow the candidate to be exactly equal to the root (e.g. listing the
27
+ * root itself). Defaults to false so writes to the root are rejected. */
28
+ allowEqual?: boolean;
29
+ }
30
+ /**
31
+ * Strictly check that `candidate` is under `root`. Both are canonicalised
32
+ * first, so `..` escapes and symlink escapes are detected regardless of the
33
+ * original spelling. By default a candidate equal to the root is rejected.
34
+ */
35
+ export declare function isWithinRoot(root: string, candidate: string, opts?: WithinRootOptions): boolean;
36
+ /**
37
+ * Assert that `candidate` is inside `root`. Returns the canonical candidate
38
+ * path, or throws a {@link PathError} if it is outside the root.
39
+ */
40
+ export declare function assertInsideRoot(root: string, candidate: string, opts?: WithinRootOptions): string;
41
+ /** Resolve a tool-provided relative path against `cwd` and validate it stays
42
+ * inside the root. */
43
+ export declare function safeResolve(root: string, p: string, cwd?: string, opts?: WithinRootOptions): string;
44
+ //# sourceMappingURL=path-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAGA;4CAC4C;AAC5C,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AA8BD;+CAC+C;AAC/C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA0B9C;AAaD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAyB5D;AAED,MAAM,WAAW,iBAAiB;IAChC;6EACyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAenG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAUtG;AAED;sBACsB;AACtB,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAGvG"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PathError = void 0;
37
+ exports.isWindowsReservedName = isWindowsReservedName;
38
+ exports.realpathSafe = realpathSafe;
39
+ exports.canonicalize = canonicalize;
40
+ exports.isWithinRoot = isWithinRoot;
41
+ exports.assertInsideRoot = assertInsideRoot;
42
+ exports.safeResolve = safeResolve;
43
+ const path = __importStar(require("node:path"));
44
+ const fs = __importStar(require("node:fs"));
45
+ /** Thrown when a path is empty, escapes the allowed root, or targets a
46
+ * Windows-reserved / sensitive location. */
47
+ class PathError extends Error {
48
+ constructor(code, message) {
49
+ super(message);
50
+ this.name = 'PathError';
51
+ this.code = code;
52
+ }
53
+ }
54
+ exports.PathError = PathError;
55
+ /** Windows reserved device names (base name, case-insensitive). */
56
+ const WINDOWS_RESERVED = new Set([
57
+ 'CON',
58
+ 'PRN',
59
+ 'AUX',
60
+ 'NUL',
61
+ 'COM1',
62
+ 'COM2',
63
+ 'COM3',
64
+ 'COM4',
65
+ 'COM5',
66
+ 'COM6',
67
+ 'COM7',
68
+ 'COM8',
69
+ 'COM9',
70
+ 'LPT1',
71
+ 'LPT2',
72
+ 'LPT3',
73
+ 'LPT4',
74
+ 'LPT5',
75
+ 'LPT6',
76
+ 'LPT7',
77
+ 'LPT8',
78
+ 'LPT9',
79
+ ]);
80
+ const IS_WINDOWS = process.platform === 'win32';
81
+ /** True when a single path segment (ignoring its extension) is a Windows
82
+ * reserved device name such as CON or COM1. */
83
+ function isWindowsReservedName(segment) {
84
+ const base = String(segment ?? '').trim().split('.')[0].toUpperCase();
85
+ return WINDOWS_RESERVED.has(base);
86
+ }
87
+ /**
88
+ * Resolve the longest existing ancestor's real path and re-append the
89
+ * not-yet-existing tail. This keeps canonicalisation correct for both files
90
+ * that already exist (symlinks resolved) and files about to be created
91
+ * (their existing parent's symlinks resolved), which prevents escaping the
92
+ * root through a symlink.
93
+ */
94
+ function realpathSafe(p) {
95
+ const abs = path.resolve(p);
96
+ try {
97
+ const real = fs.realpathSync(abs);
98
+ return real;
99
+ }
100
+ catch {
101
+ // The path does not fully exist; walk up to the deepest existing ancestor.
102
+ let existing = abs;
103
+ const tail = [];
104
+ // Guard against non-finite loops.
105
+ for (let i = 0; i < 4096; i++) {
106
+ const parent = path.dirname(existing);
107
+ if (existing === parent)
108
+ break;
109
+ if (fs.existsSync(existing)) {
110
+ try {
111
+ const real = fs.realpathSync(existing);
112
+ return tail.length ? path.resolve(real, ...tail) : real;
113
+ }
114
+ catch {
115
+ // parent was removed between check and realpath; continue upward
116
+ }
117
+ }
118
+ tail.unshift(path.basename(existing));
119
+ existing = parent;
120
+ }
121
+ }
122
+ return abs;
123
+ }
124
+ /** Strip trailing dots and spaces from each path segment (Windows aliases). */
125
+ function stripWindowsTrailing(p) {
126
+ const parts = p.split(path.sep);
127
+ const cleaned = parts.map((part, idx) => {
128
+ if (idx === 0)
129
+ return part; // drive/root prefix
130
+ const stripped = part.replace(/[ \t.\u00A0]+$/u, '');
131
+ return stripped === '' ? part : stripped;
132
+ });
133
+ return cleaned.join(path.sep);
134
+ }
135
+ /**
136
+ * Produce a canonical, absolute, symlink-aware path. Resolves `..`, normalises
137
+ * separators, resolves symlinks on the existing prefix, strips the Windows
138
+ * `\\?\` prefix, and (on Windows) detects reserved device names and trailing
139
+ * dot/space aliases. `~` and environment variables are NOT expanded.
140
+ */
141
+ function canonicalize(p, cwd) {
142
+ let raw = String(p ?? '').trim();
143
+ if (raw === '') {
144
+ throw new PathError('ERR_EMPTY_PATH', 'Path is empty');
145
+ }
146
+ // Strip the Windows long-path prefix `\\?\`.
147
+ raw = raw.replace(/^\\\\\?\\/, '');
148
+ // Some shells pass `\\?\UNC\`; collapse to a UNC path.
149
+ raw = raw.replace(/^\\\\\?\\UNC\\/, '\\\\');
150
+ const base = cwd && cwd.trim() !== '' ? cwd : process.cwd();
151
+ const abs = path.resolve(base, raw);
152
+ let normalized = path.normalize(abs);
153
+ if (IS_WINDOWS) {
154
+ normalized = stripWindowsTrailing(normalized);
155
+ for (const segment of normalized.split(path.sep)) {
156
+ if (segment && isWindowsReservedName(segment)) {
157
+ throw new PathError('ERR_RESERVED_NAME', `Path uses a reserved Windows name: ${segment}`);
158
+ }
159
+ }
160
+ }
161
+ return realpathSafe(normalized);
162
+ }
163
+ /**
164
+ * Strictly check that `candidate` is under `root`. Both are canonicalised
165
+ * first, so `..` escapes and symlink escapes are detected regardless of the
166
+ * original spelling. By default a candidate equal to the root is rejected.
167
+ */
168
+ function isWithinRoot(root, candidate, opts = {}) {
169
+ const allowEqual = opts.allowEqual ?? false;
170
+ let rootC;
171
+ let candC;
172
+ try {
173
+ rootC = canonicalize(root);
174
+ candC = canonicalize(candidate);
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ const rel = path.relative(rootC, candC);
180
+ if (rel === '')
181
+ return allowEqual;
182
+ if (rel === '..' || rel.startsWith('..' + path.sep))
183
+ return false;
184
+ if (path.isAbsolute(rel))
185
+ return false;
186
+ return true;
187
+ }
188
+ /**
189
+ * Assert that `candidate` is inside `root`. Returns the canonical candidate
190
+ * path, or throws a {@link PathError} if it is outside the root.
191
+ */
192
+ function assertInsideRoot(root, candidate, opts = {}) {
193
+ const rootC = canonicalize(root);
194
+ const candC = canonicalize(candidate);
195
+ if (!isWithinRoot(rootC, candC, opts)) {
196
+ throw new PathError('ERR_OUTSIDE_ROOT', `Path is outside the authorised root: ${candidate} (root: ${rootC})`);
197
+ }
198
+ return candC;
199
+ }
200
+ /** Resolve a tool-provided relative path against `cwd` and validate it stays
201
+ * inside the root. */
202
+ function safeResolve(root, p, cwd, opts = {}) {
203
+ const resolved = canonicalize(p, cwd);
204
+ return assertInsideRoot(root, resolved, opts);
205
+ }
206
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,sDAGC;AASD,oCA0BC;AAmBD,oCAyBC;AAaD,oCAeC;AAMD,4CAUC;AAID,kCAGC;AAjLD,gDAAkC;AAClC,4CAA8B;AAE9B;4CAC4C;AAC5C,MAAa,SAAU,SAAQ,KAAK;IAElC,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAPD,8BAOC;AAED,mEAAmE;AACnE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAEhD;+CAC+C;AAC/C,SAAgB,qBAAqB,CAAC,OAAe;IACnD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACtE,OAAO,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,CAAS;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,IAAI,QAAQ,GAAG,GAAG,CAAC;QACnB,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,kCAAkC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACtC,IAAI,QAAQ,KAAK,MAAM;gBAAE,MAAM;YAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACvC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC1D,CAAC;gBAAC,MAAM,CAAC;oBACP,iEAAiE;gBACnE,CAAC;YACH,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtC,QAAQ,GAAG,MAAM,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,SAAS,oBAAoB,CAAC,CAAS;IACrC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACtC,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,oBAAoB;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,CAAS,EAAE,GAAY;IAClD,IAAI,GAAG,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjC,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;IACzD,CAAC;IAED,6CAA6C;IAC7C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACnC,uDAAuD;IACvD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAE5C,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,IAAI,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC9C,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,IAAI,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,SAAS,CAAC,mBAAmB,EAAE,sCAAsC,OAAO,EAAE,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC;AAQD;;;;GAIG;AACH,SAAgB,YAAY,CAAC,IAAY,EAAE,SAAiB,EAAE,OAA0B,EAAE;IACxF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC;IAC5C,IAAI,KAAa,CAAC;IAClB,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,IAAY,EAAE,SAAiB,EAAE,OAA0B,EAAE;IAC5F,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,SAAS,CACjB,kBAAkB,EAClB,wCAAwC,SAAS,WAAW,KAAK,GAAG,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;sBACsB;AACtB,SAAgB,WAAW,CAAC,IAAY,EAAE,CAAS,EAAE,GAAY,EAAE,OAA0B,EAAE;IAC7F,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtC,OAAO,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Wire protocol for the ysagc platform agent channel. Messages are JSON text
3
+ * frames. Client-to-server and server-to-client message sets are kept
4
+ * separate so unknown or miscast frames are rejected as malformed.
5
+ */
6
+ export type ClientState = 'online' | 'busy' | 'error';
7
+ export interface HelloMessage {
8
+ type: 'hello';
9
+ token: string;
10
+ deviceId: string;
11
+ version: string;
12
+ platform: string;
13
+ }
14
+ export interface PongMessage {
15
+ type: 'pong';
16
+ t?: number;
17
+ }
18
+ export interface ToolResultMessage {
19
+ type: 'tool_result';
20
+ jobId: string;
21
+ ok: boolean;
22
+ result?: unknown;
23
+ error?: string;
24
+ durationMs: number;
25
+ /** Set when the idempotency cache was the source of the result. */
26
+ cached?: boolean;
27
+ }
28
+ export interface StatusMessage {
29
+ type: 'status';
30
+ state: ClientState;
31
+ sessionId?: string;
32
+ jobId?: string;
33
+ ts?: number;
34
+ }
35
+ export interface WelcomeMessage {
36
+ type: 'welcome';
37
+ sessionId: string;
38
+ }
39
+ export interface PingMessage {
40
+ type: 'ping';
41
+ t?: number;
42
+ }
43
+ export interface ToolCallMessage {
44
+ type: 'tool_call';
45
+ jobId: string;
46
+ idempotencyKey?: string;
47
+ tool: string;
48
+ args: Record<string, unknown>;
49
+ }
50
+ export interface CancelMessage {
51
+ type: 'cancel';
52
+ jobId: string;
53
+ }
54
+ export type ClientMessage = HelloMessage | PongMessage | ToolResultMessage | StatusMessage;
55
+ export type ServerMessage = WelcomeMessage | PingMessage | ToolCallMessage | CancelMessage;
56
+ export type PlatformMessage = ClientMessage | ServerMessage;
57
+ /** Serialise a message to a JSON wire frame. */
58
+ export declare function encodeMessage(msg: PlatformMessage): string;
59
+ /** Convert raw frame bytes/strings into a parsed server message. Returns null
60
+ * when the frame is not a well-formed, known server message. */
61
+ export declare function decodeMessage(data: string | Buffer | ArrayBuffer | DataView | Uint8Array): ServerMessage | null;
62
+ export declare function isToolCall(msg: ServerMessage): msg is ToolCallMessage;
63
+ export declare function isPing(msg: ServerMessage): msg is PingMessage;
64
+ export declare function isCancel(msg: ServerMessage): msg is CancelMessage;
65
+ export declare function isWelcome(msg: ServerMessage): msg is WelcomeMessage;
66
+ /**
67
+ * Canonical, deterministic JSON serialisation (object keys are sorted) so the
68
+ * same tool/args always produce the same cache key irrespective of key order.
69
+ */
70
+ export declare function stableStringify(value: unknown): string;
71
+ /**
72
+ * Compute a stable idempotency key for a tool invocation. When the platform
73
+ * supplies a key (for the same job retried after a crash) it is combined with
74
+ * the tool + arguments so two logically different jobs never collide.
75
+ */
76
+ export declare function computeIdempotencyKey(tool: string, args: Record<string, unknown>, idempotencyKey?: string): string;
77
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAC3F,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,WAAW,GAAG,eAAe,GAAG,aAAa,CAAC;AAC3F,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,aAAa,CAAC;AAI5D,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAE1D;AAED;gEACgE;AAChE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAC1D,aAAa,GAAG,IAAI,CAwBtB;AAQD,wBAAgB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,eAAe,CAErE;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,WAAW,CAE7D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,aAAa,CAEjE;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,cAAc,CAEnE;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWtD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAOR"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeMessage = encodeMessage;
4
+ exports.decodeMessage = decodeMessage;
5
+ exports.isToolCall = isToolCall;
6
+ exports.isPing = isPing;
7
+ exports.isCancel = isCancel;
8
+ exports.isWelcome = isWelcome;
9
+ exports.stableStringify = stableStringify;
10
+ exports.computeIdempotencyKey = computeIdempotencyKey;
11
+ const node_crypto_1 = require("node:crypto");
12
+ const SERVER_TYPES = new Set(['welcome', 'ping', 'tool_call', 'cancel']);
13
+ /** Serialise a message to a JSON wire frame. */
14
+ function encodeMessage(msg) {
15
+ return JSON.stringify(msg);
16
+ }
17
+ /** Convert raw frame bytes/strings into a parsed server message. Returns null
18
+ * when the frame is not a well-formed, known server message. */
19
+ function decodeMessage(data) {
20
+ let buf;
21
+ if (typeof data === 'string') {
22
+ buf = Buffer.from(data, 'utf8');
23
+ }
24
+ else if (data instanceof ArrayBuffer) {
25
+ buf = Buffer.from(new Uint8Array(data));
26
+ }
27
+ else if (data instanceof DataView) {
28
+ buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
29
+ }
30
+ else {
31
+ buf = Buffer.from(data);
32
+ }
33
+ const text = buf.toString('utf8');
34
+ let parsed;
35
+ try {
36
+ parsed = JSON.parse(text);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ if (!isRecord(parsed))
42
+ return null;
43
+ const type = parsed.type;
44
+ if (typeof type !== 'string' || !SERVER_TYPES.has(type))
45
+ return null;
46
+ return parsed;
47
+ }
48
+ function isRecord(value) {
49
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
50
+ }
51
+ // --- type guards -----------------------------------------------------------
52
+ function isToolCall(msg) {
53
+ return msg.type === 'tool_call';
54
+ }
55
+ function isPing(msg) {
56
+ return msg.type === 'ping';
57
+ }
58
+ function isCancel(msg) {
59
+ return msg.type === 'cancel';
60
+ }
61
+ function isWelcome(msg) {
62
+ return msg.type === 'welcome';
63
+ }
64
+ // --- idempotency -----------------------------------------------------------
65
+ /**
66
+ * Canonical, deterministic JSON serialisation (object keys are sorted) so the
67
+ * same tool/args always produce the same cache key irrespective of key order.
68
+ */
69
+ function stableStringify(value) {
70
+ if (value === null || typeof value !== 'object') {
71
+ return JSON.stringify(value) ?? 'null';
72
+ }
73
+ if (Array.isArray(value)) {
74
+ return '[' + value.map((v) => stableStringify(v)).join(',') + ']';
75
+ }
76
+ const obj = value;
77
+ const keys = Object.keys(obj).sort();
78
+ const parts = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
79
+ return '{' + parts.join(',') + '}';
80
+ }
81
+ /**
82
+ * Compute a stable idempotency key for a tool invocation. When the platform
83
+ * supplies a key (for the same job retried after a crash) it is combined with
84
+ * the tool + arguments so two logically different jobs never collide.
85
+ */
86
+ function computeIdempotencyKey(tool, args, idempotencyKey) {
87
+ const payload = stableStringify({
88
+ tool,
89
+ args,
90
+ ...(idempotencyKey ? { idempotencyKey } : {}),
91
+ });
92
+ return (0, node_crypto_1.createHash)('sha256').update(payload).digest('hex');
93
+ }
94
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Security helpers: dangerous-command detection, sensitive-path detection and
3
+ * secret masking. These are intentionally conservative — when in doubt the
4
+ * path/command is treated as unsafe.
5
+ */
6
+ export type DangerSeverity = 'none' | 'danger' | 'critical';
7
+ export interface DangerAssessment {
8
+ /** True when the command must never be executed automatically. */
9
+ danger: boolean;
10
+ severity: DangerSeverity;
11
+ /** Human-readable reason for the assessment. */
12
+ reason: string;
13
+ }
14
+ /**
15
+ * Assess whether a shell command is too dangerous to run automatically.
16
+ * Cross-platform (bash / powershell / cmd). Returns a severity and reason.
17
+ */
18
+ export declare function isDangerCommand(command: string): DangerAssessment;
19
+ /**
20
+ * Whether a (canonical absolute) path should never be read/written by a tool.
21
+ * These are blocked no matter what permission mode is in effect.
22
+ */
23
+ export declare function isSensitivePath(p: string): boolean;
24
+ /** Emitted value when any secret has been redacted. */
25
+ export declare const MASK = "***";
26
+ /**
27
+ * Redact secrets from a string: provider keys, bearer tokens, JWTs, private
28
+ * keys, and `key=value` / `key: value` pairs for obvious secret names. Used
29
+ * before logging or returning tool output so internal keys never leak.
30
+ */
31
+ export declare function maskSecrets(text: string): string;
32
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;CAChB;AA8HD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAejE;AA8BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED,uDAAuD;AACvD,eAAO,MAAM,IAAI,QAAQ,CAAC;AAE1B;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwChD"}