@nexrall/code-core 1.4.46 → 1.4.48

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 (38) hide show
  1. package/dist/agent/agentTypes.d.ts.map +1 -1
  2. package/dist/agent/agentTypes.js +12 -15
  3. package/dist/agent/loop.d.ts.map +1 -1
  4. package/dist/agent/loop.js +14 -1
  5. package/dist/agent/memory.d.ts +38 -10
  6. package/dist/agent/memory.d.ts.map +1 -1
  7. package/dist/agent/memory.js +223 -67
  8. package/dist/agent/skills.d.ts +34 -4
  9. package/dist/agent/skills.d.ts.map +1 -1
  10. package/dist/agent/skills.js +111 -38
  11. package/dist/agent/trust.d.ts +7 -0
  12. package/dist/agent/trust.d.ts.map +1 -0
  13. package/dist/agent/trust.js +163 -0
  14. package/dist/api/client.d.ts +30 -0
  15. package/dist/api/client.d.ts.map +1 -1
  16. package/dist/api/client.js +52 -0
  17. package/dist/checkpoint/manager.d.ts.map +1 -1
  18. package/dist/checkpoint/manager.js +6 -0
  19. package/dist/commands/loader.d.ts.map +1 -1
  20. package/dist/commands/loader.js +2 -13
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/permissions/modePolicy.d.ts.map +1 -1
  25. package/dist/permissions/modePolicy.js +1 -0
  26. package/dist/permissions/rules.js +1 -1
  27. package/dist/plugins/index.d.ts +31 -4
  28. package/dist/plugins/index.d.ts.map +1 -1
  29. package/dist/plugins/index.js +72 -5
  30. package/dist/plugins/installer.d.ts +47 -0
  31. package/dist/plugins/installer.d.ts.map +1 -1
  32. package/dist/plugins/installer.js +173 -0
  33. package/dist/tools/executor.d.ts.map +1 -1
  34. package/dist/tools/executor.js +196 -5
  35. package/dist/util/frontmatter.d.ts +79 -0
  36. package/dist/util/frontmatter.d.ts.map +1 -0
  37. package/dist/util/frontmatter.js +172 -0
  38. package/package.json +5 -2
@@ -1,3 +1,10 @@
1
+ export interface SkillWarning {
2
+ /** Absolute path of the SKILL.md / command file the problem was found in. */
3
+ file: string;
4
+ /** Skill name, when one could be determined. */
5
+ name: string;
6
+ message: string;
7
+ }
1
8
  export interface Skill {
2
9
  name: string;
3
10
  description: string;
@@ -11,10 +18,33 @@ export interface Skill {
11
18
  disableModelInvocation: boolean;
12
19
  /** false → only the model may invoke it (auto-load only, not meant to be typed as a command). */
13
20
  userInvocable: boolean;
21
+ /** agentskills.io spec field — license name or reference to a bundled license file. Informational only. */
22
+ license?: string;
23
+ /** agentskills.io spec field — environment requirements (e.g. "Requires git, docker"). Informational only. */
24
+ compatibility?: string;
25
+ /** agentskills.io spec field — arbitrary author-supplied key/value metadata (from a nested `metadata:` block). */
26
+ metadata?: Record<string, string>;
27
+ /** agentskills.io spec field (experimental) — space-separated tool names the skill declares it needs. Not yet enforced as an allowlist; informational. */
28
+ allowedTools?: string[];
14
29
  }
15
- /** Discover all skills (project overrides global overrides plugin overrides builtin).
16
- * Directory-style `.nexrall/skills/<name>/SKILL.md` beats a flat `.nexrall/commands/<name>.md`
17
- * of the same name within the same precedence tier. */
30
+ /**
31
+ * Discover all skills, with diagnostics.
32
+ *
33
+ * Precedence, most to least authoritative: project `.nexrall/skills` >
34
+ * project `.nexrall/commands` > project `.agents/skills` (cross-client) >
35
+ * global `.nexrall/commands` > global `.nexrall/skills` > global
36
+ * `.agents/skills` (cross-client) > plugin > builtin.
37
+ *
38
+ * The `.agents/skills` scans are always the weakest source within their tier
39
+ * — see the module comment above for why. Directory-style
40
+ * `.nexrall/skills/<name>/SKILL.md` beats a flat `.nexrall/commands/<name>.md`
41
+ * of the same name within the same precedence tier.
42
+ */
43
+ export declare function loadSkillsWithWarnings(workDir: string): {
44
+ skills: Skill[];
45
+ warnings: SkillWarning[];
46
+ };
47
+ /** Discover all skills (project overrides global overrides plugin overrides builtin). See loadSkillsWithWarnings for the full precedence rule and diagnostics. */
18
48
  export declare function loadSkills(workDir: string): Skill[];
19
49
  export declare function findSkill(skills: Skill[], name: string): Skill | undefined;
20
50
  /** Skills the MODEL may auto-invoke via the use_skill tool (excludes disable-model-invocation:true ones). */
@@ -28,7 +58,7 @@ export declare function summariseSkills(skills: Skill[]): string;
28
58
  * substitution as slash commands — see commands/loader.ts#expandBody), then
29
59
  * prepend a short header pointing at the skill's own directory (if any) so
30
60
  * the model knows where to find supporting files it may need to read_file
31
- * on demand, mirroring Claude Code's "reference files from your SKILL.md"
61
+ * on demand, mirroring the spec's "reference files from your SKILL.md"
32
62
  * guidance without loading them into context up front.
33
63
  */
34
64
  export declare function expandSkill(skill: Skill, argString: string, workDir: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/agent/skills.ts"],"names":[],"mappings":"AA2CA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpD,0IAA0I;IAC1I,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kHAAkH;IAClH,sBAAsB,EAAE,OAAO,CAAC;IAChC,iGAAiG;IACjG,aAAa,EAAE,OAAO,CAAC;CACxB;AAyID;;wDAEwD;AACxD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,CAanD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAG1E;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAE5D;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAE5D;AAED,oHAAoH;AACpH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAIvD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAcpF"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/agent/skills.ts"],"names":[],"mappings":"AAyEA,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpD,0IAA0I;IAC1I,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kHAAkH;IAClH,sBAAsB,EAAE,OAAO,CAAC;IAChC,iGAAiG;IACjG,aAAa,EAAE,OAAO,CAAC;IACvB,2GAA2G;IAC3G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kHAAkH;IAClH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,0JAA0J;IAC1J,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AA8LD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAsBrG;AAED,kKAAkK;AAClK,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,CAEnD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAG1E;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAE5D;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAE5D;AAED,oHAAoH;AACpH,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAIvD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAcpF"}
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadSkillsWithWarnings = loadSkillsWithWarnings;
36
37
  exports.loadSkills = loadSkills;
37
38
  exports.findSkill = findSkill;
38
39
  exports.autoInvokableSkills = autoInvokableSkills;
@@ -44,18 +45,19 @@ const path = __importStar(require("path"));
44
45
  const os = __importStar(require("os"));
45
46
  const index_1 = require("../plugins/index");
46
47
  const loader_1 = require("../commands/loader");
47
- function parseFrontmatter(raw) {
48
- const m = /^\s*---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(raw);
49
- if (!m)
50
- return { meta: {}, body: raw.trim() };
51
- const meta = {};
52
- for (const line of m[1].split(/\r?\n/)) {
53
- const kv = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line.trim());
54
- if (kv)
55
- meta[kv[1].toLowerCase()] = kv[2].trim().replace(/^["']|["']$/g, '');
56
- }
57
- return { meta, body: (m[2] ?? '').trim() };
58
- }
48
+ const frontmatter_1 = require("../util/frontmatter");
49
+ /** Frontmatter keys this parser understands, for typo/unrecognised-key detection (see SkillWarning). */
50
+ const KNOWN_META_KEYS = new Set([
51
+ 'name', 'description', 'model', 'mode',
52
+ 'disable-model-invocation', 'user-invocable',
53
+ 'license', 'compatibility', 'metadata', 'allowed-tools',
54
+ ]);
55
+ // agentskills.io's `name` constraint: 1-64 chars, lowercase alphanumeric and
56
+ // hyphens, no leading/trailing/consecutive hyphens. Validated LENIENTLY here
57
+ // (warn, still load) per the spec's own client-implementation guidance —
58
+ // rejecting a skill outright over a cosmetic name issue would be a worse
59
+ // failure mode than a slightly-off name that still works.
60
+ const SPEC_NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
59
61
  function parseBool(v, fallback) {
60
62
  if (v === undefined)
61
63
  return fallback;
@@ -66,7 +68,14 @@ function parseBool(v, fallback) {
66
68
  return false;
67
69
  return fallback;
68
70
  }
69
- function toSkill(meta, body, name, source, dir) {
71
+ /** Space- (or comma-) separated tool list, same leniency as agentTypes.ts's parseToolList. */
72
+ function parseSpaceList(v) {
73
+ if (!v)
74
+ return undefined;
75
+ const items = v.split(/[,\s]+/).map((t) => t.trim()).filter(Boolean);
76
+ return items.length ? items : undefined;
77
+ }
78
+ function toSkill(meta, body, name, source, dir, nested) {
70
79
  const model = ['turbo', 'pro', 'ultra'].find((x) => x === (meta.model ?? '').toLowerCase());
71
80
  return {
72
81
  name,
@@ -78,13 +87,51 @@ function toSkill(meta, body, name, source, dir) {
78
87
  dir,
79
88
  disableModelInvocation: parseBool(meta['disable-model-invocation'], false),
80
89
  userInvocable: parseBool(meta['user-invocable'], true),
90
+ license: meta.license || undefined,
91
+ compatibility: meta.compatibility || undefined,
92
+ metadata: nested?.metadata,
93
+ allowedTools: parseSpaceList(meta['allowed-tools']),
81
94
  };
82
95
  }
96
+ /**
97
+ * Lenient validation warnings for a skill's frontmatter — never blocks loading, only reported.
98
+ *
99
+ * `rawName` is the name BEFORE lowercasing (whatever the frontmatter or the
100
+ * directory/file actually said) — validated against the spec's naming rule,
101
+ * which is itself case-sensitive ("lowercase ... only" is a real constraint,
102
+ * not cosmetic). `effectiveName` is the lowercased name used as the map key
103
+ * and `Skill.name` — using it here instead would make an uppercase name
104
+ * always "pass" validation simply because it had already been normalised
105
+ * away by the time this function saw it.
106
+ */
107
+ function validateSkillMeta(meta, rawName, effectiveName, dirName, file, warnings) {
108
+ if (!warnings)
109
+ return;
110
+ if (!SPEC_NAME_RE.test(rawName)) {
111
+ warnings.push({
112
+ file, name: effectiveName,
113
+ message: `name "${rawName}" does not match the agentskills.io convention (lowercase letters, numbers, and single hyphens only) — loaded anyway, but other clients reading this skill may warn or reject it.`,
114
+ });
115
+ }
116
+ else if (rawName.length > 64) {
117
+ warnings.push({ file, name: effectiveName, message: `name is ${rawName.length} characters — the spec caps this at 64. Loaded anyway.` });
118
+ }
119
+ if (dirName !== undefined && meta.name && meta.name.trim().toLowerCase() !== dirName.toLowerCase()) {
120
+ warnings.push({
121
+ file, name: effectiveName,
122
+ message: `frontmatter name "${meta.name}" does not match its directory name "${dirName}" — the spec requires them to match for cross-client compatibility. Loaded anyway, using the frontmatter name.`,
123
+ });
124
+ }
125
+ const strayKeys = Object.keys(meta).filter((k) => !KNOWN_META_KEYS.has(k));
126
+ if (strayKeys.length) {
127
+ warnings.push({ file, name: effectiveName, message: `has unrecognised frontmatter key(s): ${strayKeys.join(', ')} — these are ignored.` });
128
+ }
129
+ }
83
130
  // Legacy flat-file skills: .nexrall/commands/<name>.md (and plugin commands/).
84
131
  // Kept as its own loader (rather than merged into loadSkillDir below) since the
85
132
  // naming/precedence rule ("skill directory wins over a same-name flat command")
86
133
  // requires knowing about both shapes before the caller merges them.
87
- function loadFlatCommandDir(dir, source, into) {
134
+ function loadFlatCommandDir(dir, source, into, warnings) {
88
135
  let files;
89
136
  try {
90
137
  files = fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
@@ -93,23 +140,27 @@ function loadFlatCommandDir(dir, source, into) {
93
140
  return;
94
141
  }
95
142
  for (const file of files) {
143
+ const full = path.join(dir, file);
96
144
  try {
97
- const raw = fs.readFileSync(path.join(dir, file), 'utf-8');
98
- const { meta, body } = parseFrontmatter(raw);
99
- const name = (meta.name || path.basename(file, '.md')).trim().toLowerCase();
145
+ const raw = fs.readFileSync(full, 'utf-8');
146
+ const { meta, body } = (0, frontmatter_1.parseFrontmatter)(raw);
147
+ const rawName = (meta.name || path.basename(file, '.md')).trim();
148
+ const name = rawName.toLowerCase();
100
149
  if (!name)
101
150
  continue;
102
151
  if (source !== 'project' && into.has(name))
103
152
  continue; // earlier tiers win
153
+ validateSkillMeta(meta, rawName, name, undefined, full, warnings);
104
154
  into.set(name, toSkill(meta, body, name, source));
105
155
  }
106
- catch {
107
- /* skip malformed */
156
+ catch (err) {
157
+ warnings?.push({ file: full, name: path.basename(file, '.md'), message: `could not be read or parsed (${err.message}) — skipped.` });
108
158
  }
109
159
  }
110
160
  }
111
161
  // Directory-style skills: .nexrall/skills/<name>/SKILL.md (+ optional supporting files).
112
- function loadSkillDir(root, source, into) {
162
+ // Also used for the cross-client `.agents/skills/<name>/SKILL.md` convention — same shape.
163
+ function loadSkillDir(root, source, into, warnings) {
113
164
  let entries;
114
165
  try {
115
166
  entries = fs.readdirSync(root, { withFileTypes: true });
@@ -131,8 +182,9 @@ function loadSkillDir(root, source, into) {
131
182
  }
132
183
  try {
133
184
  const raw = fs.readFileSync(skillFile, 'utf-8');
134
- const { meta, body } = parseFrontmatter(raw);
135
- const name = (meta.name || entry.name).trim().toLowerCase();
185
+ const { meta, body, nested } = (0, frontmatter_1.parseFrontmatter)(raw);
186
+ const rawName = (meta.name || entry.name).trim();
187
+ const name = rawName.toLowerCase();
136
188
  if (!name)
137
189
  continue;
138
190
  // A directory-style skill always wins over an earlier flat command of
@@ -140,10 +192,11 @@ function loadSkillDir(root, source, into) {
140
192
  // project tier always wins outright regardless of load order.
141
193
  if (source !== 'project' && into.has(name))
142
194
  continue;
143
- into.set(name, toSkill(meta, body, name, source, skillDir));
195
+ validateSkillMeta(meta, rawName, name, entry.name, skillFile, warnings);
196
+ into.set(name, toSkill(meta, body, name, source, skillDir, nested));
144
197
  }
145
- catch {
146
- /* skip malformed */
198
+ catch (err) {
199
+ warnings?.push({ file: skillFile, name: entry.name, message: `could not be read or parsed (${err.message}) — skipped.` });
147
200
  }
148
201
  }
149
202
  }
@@ -187,25 +240,45 @@ const BUILTIN_SKILLS = [
187
240
  ].join('\n'),
188
241
  },
189
242
  ];
190
- /** Discover all skills (project overrides global overrides plugin overrides builtin).
191
- * Directory-style `.nexrall/skills/<name>/SKILL.md` beats a flat `.nexrall/commands/<name>.md`
192
- * of the same name within the same precedence tier. */
193
- function loadSkills(workDir) {
243
+ /**
244
+ * Discover all skills, with diagnostics.
245
+ *
246
+ * Precedence, most to least authoritative: project `.nexrall/skills` >
247
+ * project `.nexrall/commands` > project `.agents/skills` (cross-client) >
248
+ * global `.nexrall/commands` > global `.nexrall/skills` > global
249
+ * `.agents/skills` (cross-client) > plugin > builtin.
250
+ *
251
+ * The `.agents/skills` scans are always the weakest source within their tier
252
+ * — see the module comment above for why. Directory-style
253
+ * `.nexrall/skills/<name>/SKILL.md` beats a flat `.nexrall/commands/<name>.md`
254
+ * of the same name within the same precedence tier.
255
+ */
256
+ function loadSkillsWithWarnings(workDir) {
194
257
  const out = new Map();
195
- // Flat commands first (so a same-tier skill directory below can override them).
196
- loadFlatCommandDir(path.join(workDir, '.nexrall', 'commands'), 'project', out);
197
- loadSkillDir(path.join(workDir, '.nexrall', 'skills'), 'project', out);
198
- loadFlatCommandDir(path.join(os.homedir(), '.nexrall', 'commands'), 'global', out);
199
- loadSkillDir(path.join(os.homedir(), '.nexrall', 'skills'), 'global', out);
258
+ const warnings = [];
259
+ // Project tier is last-write-wins (see loadSkillDir/loadFlatCommandDir's
260
+ // `source !== 'project'` guard), so the WEAKEST project source loads first.
261
+ loadSkillDir(path.join(workDir, '.agents', 'skills'), 'project', out, warnings);
262
+ loadFlatCommandDir(path.join(workDir, '.nexrall', 'commands'), 'project', out, warnings);
263
+ loadSkillDir(path.join(workDir, '.nexrall', 'skills'), 'project', out, warnings);
264
+ // Global tier is first-write-wins (the guard skips a repeat name), so the
265
+ // STRONGEST global source loads first, and .agents/skills loads last.
266
+ loadFlatCommandDir(path.join(os.homedir(), '.nexrall', 'commands'), 'global', out, warnings);
267
+ loadSkillDir(path.join(os.homedir(), '.nexrall', 'skills'), 'global', out, warnings);
268
+ loadSkillDir(path.join(os.homedir(), '.agents', 'skills'), 'global', out, warnings);
200
269
  for (const dir of (0, index_1.pluginAssetDirs)(workDir, 'commands'))
201
- loadFlatCommandDir(dir, 'plugin', out);
270
+ loadFlatCommandDir(dir, 'plugin', out, warnings);
202
271
  for (const dir of (0, index_1.pluginAssetDirs)(workDir, 'skills'))
203
- loadSkillDir(dir, 'plugin', out);
272
+ loadSkillDir(dir, 'plugin', out, warnings);
204
273
  for (const skill of BUILTIN_SKILLS) {
205
274
  if (!out.has(skill.name))
206
275
  out.set(skill.name, skill);
207
276
  }
208
- return [...out.values()];
277
+ return { skills: [...out.values()], warnings };
278
+ }
279
+ /** Discover all skills (project overrides global overrides plugin overrides builtin). See loadSkillsWithWarnings for the full precedence rule and diagnostics. */
280
+ function loadSkills(workDir) {
281
+ return loadSkillsWithWarnings(workDir).skills;
209
282
  }
210
283
  function findSkill(skills, name) {
211
284
  const want = name.replace(/^\//, '').trim().toLowerCase();
@@ -231,7 +304,7 @@ function summariseSkills(skills) {
231
304
  * substitution as slash commands — see commands/loader.ts#expandBody), then
232
305
  * prepend a short header pointing at the skill's own directory (if any) so
233
306
  * the model knows where to find supporting files it may need to read_file
234
- * on demand, mirroring Claude Code's "reference files from your SKILL.md"
307
+ * on demand, mirroring the spec's "reference files from your SKILL.md"
235
308
  * guidance without loading them into context up front.
236
309
  */
237
310
  function expandSkill(skill, argString, workDir) {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Which trust-sensitive files actually exist in `dir`, so a confirmation
3
+ * prompt can tell the user what THIS folder will do rather than describing
4
+ * risks in the abstract. Ordered most- to least-dangerous.
5
+ */
6
+ export declare function detectTrustSignals(dir: string): string[];
7
+ //# sourceMappingURL=trust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/agent/trust.ts"],"names":[],"mappings":"AAqDA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAkExD"}
@@ -0,0 +1,163 @@
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.detectTrustSignals = detectTrustSignals;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ // ─── Workspace Trust Signals (shared) ─────────────────────────────────────
40
+ //
41
+ // Opening a folder for an agent to work in is not a passive act. Before the
42
+ // user types anything, a session can already read and act on files found in
43
+ // that folder:
44
+ //
45
+ // • `.nexrall/mcp.json` declares MCP servers, and connecting to a stdio
46
+ // server runs `spawn(server.command, server.args)` — arbitrary command
47
+ // execution, straight from a file in the repo (see mcp/manager.ts /
48
+ // mcp/client.ts).
49
+ // • `.nexrall/plugins/` may contribute their OWN `mcp.json`/`hooks.json`
50
+ // (see plugins/index.ts's pluginMcpServers/pluginHooks) — same risk
51
+ // class as a bare mcp.json, just one hop further away.
52
+ // • `nexrall.md` is injected into the system prompt as trusted project
53
+ // instructions, so its contents steer the agent for the whole session.
54
+ // • `.nexrall/{skills,commands}` define playbooks the agent will follow,
55
+ // and `.nexrall/permissions.json` can pre-approve tool calls that would
56
+ // otherwise prompt.
57
+ // • `.agents/skills/` is the same kind of playbook, discovered from the
58
+ // agentskills.io cross-client convention (see agent/skills.ts) rather
59
+ // than a Nexrall-specific path — worth its own line since it may have
60
+ // been authored for a different client entirely.
61
+ //
62
+ // So `git clone` of a hostile repo followed by pointing an agent at it is
63
+ // enough to execute attacker-chosen commands before a human reviews anything.
64
+ //
65
+ // This module is the shared, pure "what would this folder do" detector. The
66
+ // CLI has its own longstanding copy (packages/cli/src/trust.ts) — kept
67
+ // independent there rather than migrated onto this one, so a change here
68
+ // can never silently alter the CLI's own trust-prompt wording/behaviour or
69
+ // its own dedicated test suite. Any NEW client (e.g. the desktop app) should
70
+ // use this shared copy instead of hand-rolling a third one.
71
+ //
72
+ // Deliberately stateless: nothing here reads or writes any trust STORE.
73
+ // Whether/how a client remembers "already confirmed this session" is the
74
+ // caller's job (see e.g. desktop's main/trustGate.ts) — this function only
75
+ // ever reports what is true of the folder RIGHT NOW.
76
+ /** Does the project settings file bind plugin aliases to remote repos? */
77
+ function declaresPluginSources(dir) {
78
+ try {
79
+ const raw = fs.readFileSync(path.join(dir, '.nexrall', 'settings.json'), 'utf-8');
80
+ const obj = JSON.parse(raw);
81
+ const s = obj.pluginSources;
82
+ return Boolean(s && typeof s === 'object' && !Array.isArray(s) && Object.keys(s).length > 0);
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ /**
89
+ * Which trust-sensitive files actually exist in `dir`, so a confirmation
90
+ * prompt can tell the user what THIS folder will do rather than describing
91
+ * risks in the abstract. Ordered most- to least-dangerous.
92
+ */
93
+ function detectTrustSignals(dir) {
94
+ const signals = [];
95
+ const exists = (...p) => {
96
+ try {
97
+ return fs.existsSync(path.join(dir, ...p));
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ };
103
+ // Code-executing first — these can run local commands before the user
104
+ // types anything, so they are what the decision really hinges on.
105
+ if (exists('.nexrall', 'mcp.json')) {
106
+ signals.push('.nexrall/mcp.json — can start MCP servers (runs local commands)');
107
+ }
108
+ if (exists('.nexrall', 'plugins')) {
109
+ // Plugins are scanned from the workspace and may contribute their own MCP
110
+ // servers/hooks (see plugins/index.ts → pluginMcpServers/pluginHooks), so
111
+ // this is in the same risk class as mcp.json rather than a cosmetic add-on.
112
+ signals.push('.nexrall/plugins/ — project plugins (may add MCP servers or hooks)');
113
+ }
114
+ // Then things that widen what the agent may do without asking.
115
+ if (exists('.nexrall', 'permissions.json')) {
116
+ signals.push('.nexrall/permissions.json — pre-approved tool permissions');
117
+ }
118
+ if (exists('.nexrall', 'settings.json')) {
119
+ // Called out separately when the file declares plugin sources: those bind
120
+ // a short alias to a remote repo, so installing that alias would fetch
121
+ // whatever the REPOSITORY chose. Installing still needs a human and its
122
+ // own confirmation — nothing is fetched from a declaration alone — but the
123
+ // user should know the repo is trying to name what they install. A
124
+ // settings.json can also carry a project's own `hooks` config, which runs
125
+ // shell commands automatically around tool calls — worth flagging here too.
126
+ let hasHooks = false;
127
+ try {
128
+ const raw = fs.readFileSync(path.join(dir, '.nexrall', 'settings.json'), 'utf-8');
129
+ const obj = JSON.parse(raw);
130
+ hasHooks = Boolean(obj.hooks && typeof obj.hooks === 'object' && Object.keys(obj.hooks).length > 0);
131
+ }
132
+ catch { /* absent or malformed — treated as no hooks declared */ }
133
+ const bits = ['.nexrall/settings.json — project settings and permission rules'];
134
+ if (declaresPluginSources(dir))
135
+ bits.push('declares plugin sources (aliases for remote plugin repos)');
136
+ if (hasHooks)
137
+ bits.push('runs hooks (shell commands) automatically around tool calls');
138
+ signals.push(bits.join(', '));
139
+ }
140
+ // Then things that steer the agent's behaviour.
141
+ if (exists('nexrall.md')) {
142
+ signals.push('nexrall.md — project instructions added to the agent\u2019s prompt');
143
+ }
144
+ if (exists('.nexrall', 'skills')) {
145
+ signals.push('.nexrall/skills/ — custom agent playbooks');
146
+ }
147
+ if (exists('.nexrall', 'commands')) {
148
+ signals.push('.nexrall/commands/ — custom slash commands');
149
+ }
150
+ if (exists('.nexrall', 'agents')) {
151
+ signals.push('.nexrall/agents/ — custom sub-agent definitions');
152
+ }
153
+ if (exists('.agents', 'skills')) {
154
+ // Same risk class as .nexrall/skills/ (a playbook is instructions the
155
+ // agent follows, not code it executes) — called out separately because
156
+ // this path is the agentskills.io cross-client convention, so a skill
157
+ // here may have been authored for/by a DIFFERENT tool than the one
158
+ // asking to trust this folder right now.
159
+ signals.push('.agents/skills/ — cross-client agent playbooks (agentskills.io convention)');
160
+ }
161
+ return signals;
162
+ }
163
+ //# sourceMappingURL=trust.js.map
@@ -131,6 +131,36 @@ export interface DescribeAttachmentResult {
131
131
  }
132
132
  export declare function describeAttachment(kind: 'image' | 'pdf', data: string, mediaType?: string, name?: string): Promise<DescribeAttachmentResult>;
133
133
  export declare function getBalance(): Promise<number>;
134
+ export interface UsageDailyDay {
135
+ date: string;
136
+ total: number;
137
+ byType: Record<string, number>;
138
+ }
139
+ export interface UsageDailyResult {
140
+ days: UsageDailyDay[];
141
+ totalSpent: number;
142
+ }
143
+ /**
144
+ * Day-by-day spend breakdown, same endpoint the web app's Settings > Usage
145
+ * chart reads (backend/routes/user.js's /usage-daily). Used by Nexrall Work's
146
+ * own Settings > Usage panel so both surfaces show the identical numbers.
147
+ */
148
+ export declare function getUsageDaily(days?: number): Promise<UsageDailyResult>;
134
149
  export declare function exchangeVscodeCode(code: string): Promise<AuthConfig>;
135
150
  export declare function login(email: string, password: string): Promise<AuthConfig>;
151
+ export interface UserProfile {
152
+ id: string | number;
153
+ email: string;
154
+ name?: string;
155
+ phone?: string;
156
+ avatar_url?: string;
157
+ username?: string;
158
+ bio?: string;
159
+ }
160
+ /**
161
+ * Same GET /api/user/profile the web app's Settings > Profile section reads.
162
+ * Used by Nexrall Work's own Settings > Profile panel so both surfaces show
163
+ * identical account data.
164
+ */
165
+ export declare function getUserProfile(): Promise<UserProfile>;
136
166
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA8B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiErH,eAAO,MAAM,QAAQ,QAAmB,CAAC;AAIzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GACtD,CAAC,EAAE,CAeL;AAiGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6IAA6I;IAC7I,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AA8ID,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,GAC7B,OAAO,CAAC,OAAO,CAAC,CAkmClB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9D;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYxD;AAeD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,OAAO,GAAG,KAAK,EACrB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,wBAAwB,CAAC,CAmCnC;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BlD;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA+B1E;AAID,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BhF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -10,8 +10,10 @@ exports.cancelTurn = cancelTurn;
10
10
  exports.revokeRefreshToken = revokeRefreshToken;
11
11
  exports.describeAttachment = describeAttachment;
12
12
  exports.getBalance = getBalance;
13
+ exports.getUsageDaily = getUsageDaily;
13
14
  exports.exchangeVscodeCode = exchangeVscodeCode;
14
15
  exports.login = login;
16
+ exports.getUserProfile = getUserProfile;
15
17
  const eventsource_parser_1 = require("eventsource-parser");
16
18
  const node_fetch_1 = __importDefault(require("node-fetch"));
17
19
  const crypto_1 = require("crypto");
@@ -1544,6 +1546,33 @@ async function getBalance() {
1544
1546
  const data = (await response.json());
1545
1547
  return typeof data.balance === 'number' ? data.balance : 0;
1546
1548
  }
1549
+ /**
1550
+ * Day-by-day spend breakdown, same endpoint the web app's Settings > Usage
1551
+ * chart reads (backend/routes/user.js's /usage-daily). Used by Nexrall Work's
1552
+ * own Settings > Usage panel so both surfaces show the identical numbers.
1553
+ */
1554
+ async function getUsageDaily(days = 30) {
1555
+ const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/usage-daily?days=${days}`, { method: 'GET', headers: authHeaders() });
1556
+ let response = await fetchOnce();
1557
+ if (response.status === 401 || response.status === 403) {
1558
+ const body = await response.text().catch(() => '');
1559
+ if (isExpiredTokenResponse(response.status, body) && await refreshAccessToken()) {
1560
+ response = await fetchOnce();
1561
+ }
1562
+ else {
1563
+ throw new Error(`API error ${response.status}: ${body}`);
1564
+ }
1565
+ }
1566
+ if (!response.ok) {
1567
+ const errText = await response.text();
1568
+ throw new Error(`API error ${response.status}: ${errText}`);
1569
+ }
1570
+ const data = (await response.json());
1571
+ return {
1572
+ days: Array.isArray(data.days) ? data.days : [],
1573
+ totalSpent: typeof data.totalSpent === 'number' ? data.totalSpent : 0,
1574
+ };
1575
+ }
1547
1576
  // ─── VSCode OAuth ─────────────────────────────────────────────────────────────
1548
1577
  async function exchangeVscodeCode(code) {
1549
1578
  const response = await (0, node_fetch_1.default)(`${exports.API_BASE}/api/auth/vscode-exchange`, {
@@ -1596,4 +1625,27 @@ async function login(email, password) {
1596
1625
  email: data.email ?? email,
1597
1626
  };
1598
1627
  }
1628
+ /**
1629
+ * Same GET /api/user/profile the web app's Settings > Profile section reads.
1630
+ * Used by Nexrall Work's own Settings > Profile panel so both surfaces show
1631
+ * identical account data.
1632
+ */
1633
+ async function getUserProfile() {
1634
+ const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/profile`, { method: 'GET', headers: authHeaders() });
1635
+ let response = await fetchOnce();
1636
+ if (response.status === 401 || response.status === 403) {
1637
+ const body = await response.text().catch(() => '');
1638
+ if (isExpiredTokenResponse(response.status, body) && await refreshAccessToken()) {
1639
+ response = await fetchOnce();
1640
+ }
1641
+ else {
1642
+ throw new Error(`API error ${response.status}: ${body}`);
1643
+ }
1644
+ }
1645
+ if (!response.ok) {
1646
+ const errText = await response.text();
1647
+ throw new Error(`API error ${response.status}: ${errText}`);
1648
+ }
1649
+ return (await response.json());
1650
+ }
1599
1651
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/checkpoint/manager.ts"],"names":[],"mappings":"AA4CA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAQD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMlE;AAyBD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA6BD,qBAAa,iBAAiB;IAWhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC;;;;OAIG;gBAC0B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAa5D,OAAO,CAAC,OAAO;IAIf;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAcpD;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA8BxE;;;;;;;OAOG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQxC,OAAO,CAAC,iBAAiB;IAiBzB,0FAA0F;IAC1F,UAAU,IAAI,IAAI;IAWlB,IAAI,IAAI,iBAAiB,EAAE;IAY3B,cAAc,IAAI,OAAO;IAIzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IA0BnD,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,YAAY;CAkCrB"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/checkpoint/manager.ts"],"names":[],"mappings":"AA+CA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAQD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMlE;AA4BD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA6BD,qBAAa,iBAAiB;IAWhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC;;;;OAIG;gBAC0B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAa5D,OAAO,CAAC,OAAO;IAIf;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAcpD;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA8BxE;;;;;;;OAOG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQxC,OAAO,CAAC,iBAAiB;IAiBzB,0FAA0F;IAC1F,UAAU,IAAI,IAAI;IAWlB,IAAI,IAAI,iBAAiB,EAAE;IAY3B,cAAc,IAAI,OAAO;IAIzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IA0BnD,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,YAAY;CAkCrB"}
@@ -68,6 +68,9 @@ const MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024; // 2 MB/file — larger files are no
68
68
  const MAX_PERSISTED_TURNS = 50; // pruned oldest-first on commit
69
69
  const MUTATING_TOOLS = new Set([
70
70
  'write_file',
71
+ 'write_docx',
72
+ 'write_xlsx',
73
+ 'write_pptx',
71
74
  'edit_file',
72
75
  'multi_edit',
73
76
  'delete_file',
@@ -99,6 +102,9 @@ function str(v) {
99
102
  function affectedPaths(name, input) {
100
103
  switch (name) {
101
104
  case 'write_file':
105
+ case 'write_docx':
106
+ case 'write_xlsx':
107
+ case 'write_pptx':
102
108
  case 'edit_file':
103
109
  case 'multi_edit':
104
110
  case 'delete_file':
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/commands/loader.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACrD;AAiFD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CASjE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAG7F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAuCnF;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3F"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/commands/loader.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACrD;AAsED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CASjE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAG7F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAuCnF;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3F"}