@robota-sdk/agent-preset 3.0.0-beta.79 → 3.0.0-beta.81

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  Preset contract and resolver for the Robota SDK. A preset is a named, pre-tuned bundle of
4
4
  `agent-framework` option overrides (persona, model/effort, permission posture, command-module
5
5
  selection, execution capabilities, autonomy). This package owns the `IPreset` contract, the
6
- built-in `default` preset, and the `resolvePreset` precedence merger.
6
+ built-in `default` preset, and the instance-scoped registry that resolves them.
7
7
 
8
8
  ## Installation
9
9
 
@@ -15,11 +15,9 @@ npm install @robota-sdk/agent-preset
15
15
 
16
16
  ```typescript
17
17
  import {
18
- resolvePreset,
19
- listPresets,
20
- getPreset,
18
+ createPresetRegistry,
19
+ partitionExternalPresets,
21
20
  defaultPreset,
22
- DEFAULT_AGENT_NAME,
23
21
  } from '@robota-sdk/agent-preset';
24
22
  import type {
25
23
  IPreset,
@@ -28,20 +26,28 @@ import type {
28
26
  IResolvePresetContext,
29
27
  } from '@robota-sdk/agent-preset';
30
28
 
29
+ // A registry is per-call and holds its own list: `[built-ins, ...externalPresets]`. With no
30
+ // argument it is the built-ins. Two registries in one process never see each other's presets.
31
+ const registry = createPresetRegistry();
32
+
31
33
  // Resolve a preset into framework option overrides.
32
34
  // Precedence (low → high): preset < cliOverrides < explicit.
33
- const options = resolvePreset('default', {
35
+ const options = registry.resolvePreset('default', {
34
36
  cliOverrides: { model: 'some-model' },
35
37
  explicit: { temperature: 0.2 },
36
38
  });
37
39
 
38
40
  // Discover presets for UX.
39
- const summaries = listPresets(); // [{ id: 'default', title, description }, ...]
41
+ const summaries = registry.listPresets(); // [{ id: 'default', title, description }, ...]
40
42
  ```
41
43
 
42
44
  The `default` preset carries no overrides, so resolving it is a pure no-op that reproduces the
43
45
  standard agent behaviour (no regression).
44
46
 
47
+ When migrating from the implicit Robota defaults, choose the agent name in your product and call
48
+ `loadExternalPresetsFromDir(directory)` with a product-owned directory. The preset package no longer
49
+ exports `DEFAULT_AGENT_NAME`, `defaultExternalPresetDir`, or the no-argument `loadExternalPresets`.
50
+
45
51
  ## Dependency Position
46
52
 
47
53
  ```
@@ -49,7 +55,8 @@ agent-framework ← neutral assembly + option-type SSOT
49
55
  ↑
50
56
  agent-preset ← this package (preset contract + resolver)
51
57
  ↑
52
- agent-cli ← consumes resolvePreset / listPresets
58
+ agent-cli ← consumes createPresetRegistry (per-call resolution, ARCH-008)
59
+ agent-command ← consumes the registry the HOST supplies, through the command-host adapters (ARCH-009)
53
60
  ```
54
61
 
55
62
  This package depends only on `@robota-sdk/agent-framework` and must not re-export it.
@@ -1,4 +1,6 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:fs"),t=require("node:os"),n=require("node:path");const r={id:`default`,title:`Default`,description:`Neutral baseline preset — no overrides; reproduces the standard agent behaviour.`},i={id:`autonomous-builder`,title:`Autonomous Builder`,description:`Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel subagents (proactive autonomous-builder persona; original English wording).`,effort:`high`,autonomy:`act-first`,enableParallelSubagents:!0,selfVerification:!0,persona:[`You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and`,`complete the task — act rather than stop to ask. Keep going through the points where a more`,`hesitant assistant would pause for confirmation, and only check in when something is genuinely`,`ambiguous or risky.`,``,`Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add`,`abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task`,`plainly needs, but resist turning a focused change into a sweeping one.`,``,`After making changes, verify your own work — run the tests, re-read the goal, and confirm the`,`result actually matches what was requested before you call it done.`,``,`Ground your claims in evidence. Before reporting progress, check each claim against an actual`,`tool result from this session; if something is not yet verified, say so plainly rather than`,`implying it is finished.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`,``,`Lead with the outcome. Report results plainly instead of narrating each step, keep formatting`,`light, and stay concise.`].join(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:fs"),t=require("node:path"),n=require("@robota-sdk/agent-framework");const r={id:`default`,title:`Default`,description:`Neutral baseline preset — no overrides; reproduces the standard agent behaviour.`},i={id:`autonomous-builder`,title:`Autonomous Builder`,description:`Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel subagents (proactive autonomous-builder persona; original English wording).`,effort:`high`,autonomy:`act-first`,enableParallelSubagents:!0,selfVerification:!0,persona:[`You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and`,`complete the task — act rather than stop to ask. Keep going through the points where a more`,`hesitant assistant would pause for confirmation, and only check in when something is genuinely`,`ambiguous or risky.`,``,`Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add`,`abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task`,`plainly needs, but resist turning a focused change into a sweeping one.`,``,`After making changes, verify your own work — run the tests, re-read the goal, and confirm the`,`result actually matches what was requested before you call it done.`,``,`Ground your claims in evidence. Before reporting progress, check each claim against an actual`,`tool result from this session; if something is not yet verified, say so plainly rather than`,`implying it is finished.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`,``,`Lead with the outcome. Report results plainly instead of narrating each step, keep formatting`,`light, and stay concise.`].join(`
2
2
  `)},a={id:`careful-reviewer`,title:`Careful Reviewer`,description:`Conservative, ask-first reviewing posture — reads and plans before changing, prompts on write/exec, self-verifies, runs focused (no parallel subagents) at high effort.`,effort:`high`,autonomy:`ask-first`,enableParallelSubagents:!1,selfVerification:!0,persona:[`You are a careful, review-oriented assistant. Read and analyse before you change anything —`,`understand the surrounding code and context first, then lay out a short plan for the change and`,`wait for confirmation before you write or run things that have side effects.`,``,`When you propose a change, explain why — the reasoning behind it and the trade-offs against the`,`alternatives you considered, so the choice can be reviewed rather than taken on trust.`,``,`Stay conservative in scope. Make the change that was asked for and the detail it plainly needs;`,`do not widen the blast radius with unrequested refactors or rewrites.`,``,`Ground your claims in evidence. Before reporting progress or completion, check each claim against`,`an actual tool result from this session; if something is not yet verified, say so plainly rather`,`than implying it is done.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`].join(`
3
3
  `)},o={id:`neutral-executor`,title:`Neutral Executor`,description:`Thin, steerable executor — follows instructions literally, minimal editorialising, strict scope, terse output; balanced autonomy, no parallel subagents, no self-verification, medium effort for predictable scripted use (neutral-alignment work-style; original English wording).`,effort:`medium`,autonomy:`balanced`,enableParallelSubagents:!1,selfVerification:!1,persona:[`Follow the system and user instructions literally. Do what was asked, the way it was asked, and`,`defer to the given instructions over your own preferences.`,``,`Editorialise as little as possible. Skip unrequested commentary, caveats, and asides — give the`,`result, not a narration of it.`,``,`Stay strictly in scope. Make only the change that was requested and the detail it plainly needs;`,`do not add adjacent refactors, comments, or features that were not asked for.`,``,`Keep output terse. Prefer the shortest response that fully answers, so the result is predictable`,`and easy to consume in a script or pipeline.`].join(`
4
- `)},s={"ask-first":`default`,balanced:`default`,"act-first":`acceptEdits`},c=[r,i,a,o],l=[];function u(){return[...c,...l]}function d(e){let t=new Set(c.map(e=>e.id)),n=[],r=[];for(let i of e){if(t.has(i.id)){r.push({id:i.id,reason:`collides with built-in preset`});continue}if(l.some(e=>e.id===i.id)){r.push({id:i.id,reason:`duplicate preset id`});continue}l.push(i),n.push(i.id)}return{registered:n,rejected:r}}function f(){l.length=0}function p(){return u().map(({id:e,title:t,description:n})=>({id:e,title:t,description:n}))}function m(e){return u().find(t=>t.id===e)}function h(e){let{id:t,title:n,description:r,...i}=e;return i}function g(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function _(e,t){return t?{...e,...g(t)}:e}function v(e,t={}){let n=m(e);if(!n){let t=u().map(e=>e.id).join(`, `);throw Error(`Unknown preset: "${e}". Available presets: ${t}.`)}let r=h(n);return r=_(r,t.cliOverrides),r=_(r,t.explicit),y(r)}function y(e){return e.permissionMode===void 0?e.defaultPermissionMode===void 0?e.autonomy===void 0?e:{...e,permissionMode:s[e.autonomy]}:{...e,permissionMode:e.defaultPermissionMode}:e}const b=[`low`,`medium`,`high`,`xhigh`,`max`],x=[`ask-first`,`act-first`,`balanced`],S=[`plan`,`default`,`acceptEdits`,`bypassPermissions`],C=[`safe`,`moderate`,`full`];function w(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function T(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function E(e,t){let n=[[`persona`,e.persona,e=>t.persona=e],[`systemPrompt`,e.systemPrompt,e=>t.systemPrompt=e],[`appendSystemPrompt`,e.appendSystemPrompt,e=>t.appendSystemPrompt=e],[`agentName`,e.agentName,e=>t.agentName=e],[`model`,e.model,e=>t.model=e],[`language`,e.language,e=>t.language=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`string`)return`${e}: expected a string`;r(t)}}function D(e,t){let n=[[`temperature`,e.temperature,e=>t.temperature=e],[`maxOutputTokens`,e.maxOutputTokens,e=>t.maxOutputTokens=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`number`||Number.isNaN(t))return`${e}: expected a number`;r(t)}let r=[[`enableParallelSubagents`,e.enableParallelSubagents,e=>t.enableParallelSubagents=e],[`selfVerification`,e.selfVerification,e=>t.selfVerification=e]];for(let[e,t,n]of r)if(t!==void 0){if(typeof t!=`boolean`)return`${e}: expected a boolean`;n(t)}}function O(e,t){if(e.effort!==void 0){if(!b.includes(e.effort))return`effort: expected one of ${b.join(`, `)}`;t.effort=e.effort}if(e.autonomy!==void 0){if(!x.includes(e.autonomy))return`autonomy: expected one of ${x.join(`, `)}`;t.autonomy=e.autonomy}let n=[[`permissionMode`,e.permissionMode,e=>t.permissionMode=e],[`defaultPermissionMode`,e.defaultPermissionMode,e=>t.defaultPermissionMode=e]];for(let[e,t,r]of n)if(t!==void 0){if(!S.includes(t))return`${e}: expected one of ${S.join(`, `)}`;r(t)}if(e.defaultTrustLevel!==void 0){if(!C.includes(e.defaultTrustLevel))return`defaultTrustLevel: expected one of ${C.join(`, `)}`;t.defaultTrustLevel=e.defaultTrustLevel}}function k(e,t){let n=[[`allowedTools`,e.allowedTools,e=>t.allowedTools=e],[`deniedTools`,e.deniedTools,e=>t.deniedTools=e],[`enabledCommandModules`,e.enabledCommandModules,e=>t.enabledCommandModules=e],[`disabledCommandModules`,e.disabledCommandModules,e=>t.disabledCommandModules=e]];for(let[e,t,r]of n)if(t!==void 0){if(!T(t))return`${e}: expected an array of strings`;r(t)}}function A(e){if(!w(e))return{ok:!1,error:`preset: expected a non-null object`};let t=[[`id`,e.id],[`title`,e.title],[`description`,e.description]];for(let[e,n]of t)if(typeof n!=`string`||n.length===0)return{ok:!1,error:`${e}: expected a non-empty string`};let n={},r=E(e,n)??D(e,n)??O(e,n)??k(e,n);return r===void 0?{ok:!0,preset:{id:e.id,title:e.title,description:e.description,...n}}:{ok:!1,error:r}}function j(){return(0,n.join)((0,t.homedir)(),`.robota`,`presets`)}function M(t){if(!(0,e.existsSync)(t))return{loaded:[],errors:[]};let r=[],i=[],a=new Map,o=(0,e.readdirSync)(t).filter(e=>e.endsWith(`.json`));for(let s of o){let o=(0,n.join)(t,s),c;try{c=JSON.parse((0,e.readFileSync)(o,`utf8`))}catch(e){r.push({file:s,error:e instanceof Error?e.message:String(e)});continue}let l=A(c);if(!l.ok){r.push({file:s,error:l.error});continue}i.push(l.preset),a.set(l.preset.id,s)}let s=d(i);for(let e of s.rejected)r.push({file:a.get(e.id)??e.id,error:e.reason});return{loaded:s.registered,errors:r}}function N(e){return M(e?.dir??j())}exports.DEFAULT_AGENT_NAME=`robota-cli`,exports.autonomousBuilderPreset=i,exports.clearExternalPresets=f,exports.defaultExternalPresetDir=j,exports.defaultPreset=r,exports.getPreset=m,exports.listPresets=p,exports.loadExternalPresets=N,exports.loadExternalPresetsFromDir=M,exports.registerExternalPresets=d,exports.resolvePreset=v,exports.validateExternalPreset=A;
4
+ `)},s={"ask-first":`default`,balanced:`default`,"act-first":`acceptEdits`},c=[r,i,a,o];function l(e){let t=new Set(c.map(e=>e.id)),n=[],r=[];for(let i of e){if(t.has(i.id)){r.push({id:i.id,reason:`collides with built-in preset`});continue}if(n.some(e=>e.id===i.id)){r.push({id:i.id,reason:`duplicate preset id`});continue}n.push(i)}return{accepted:n,rejected:r}}function u(e){let{id:t,title:n,description:r,...i}=e;return i}function d(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function f(e,t){if(!t)return e;let n={...e,...d(t)};return t.deniedTools!==void 0||e.deniedTools!==void 0?{...n,deniedTools:p(e.deniedTools,t.deniedTools)}:n}function p(e,t){return[...new Set([...e??[],...t??[]])]}function m(e,t,n={}){let r=e.find(e=>e.id===t);if(!r){let n=e.map(e=>e.id).join(`, `);throw Error(`Unknown preset: "${t}". Available presets: ${n}.`)}let i=u(r);return i=f(i,n.cliOverrides),i=f(i,n.explicit),g(i)}function h(e=[]){let t=[...c,...l(e).accepted];return{resolvePreset:(e,n={})=>m(t,e,n),getPreset:e=>t.find(t=>t.id===e),listPresets:()=>t.map(({id:e,title:t,description:n})=>({id:e,title:t,description:n}))}}function g(e){return e.permissionMode===void 0?e.defaultPermissionMode===void 0?e.autonomy===void 0?e:{...e,permissionMode:s[e.autonomy]}:{...e,permissionMode:e.defaultPermissionMode}:e}const _=[`ask-first`,`act-first`,`balanced`],v=[`plan`,`default`,`acceptEdits`,`bypassPermissions`];function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function x(e,t){let n=[[`persona`,e.persona,e=>t.persona=e],[`systemPrompt`,e.systemPrompt,e=>t.systemPrompt=e],[`appendSystemPrompt`,e.appendSystemPrompt,e=>t.appendSystemPrompt=e],[`agentName`,e.agentName,e=>t.agentName=e],[`model`,e.model,e=>t.model=e],[`language`,e.language,e=>t.language=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`string`)return`${e}: expected a string`;r(t)}}function S(e,t){let n=[[`temperature`,e.temperature,e=>t.temperature=e],[`maxOutputTokens`,e.maxOutputTokens,e=>t.maxOutputTokens=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`number`||Number.isNaN(t))return`${e}: expected a number`;r(t)}let r=[[`enableParallelSubagents`,e.enableParallelSubagents,e=>t.enableParallelSubagents=e],[`selfVerification`,e.selfVerification,e=>t.selfVerification=e]];for(let[e,t,n]of r)if(t!==void 0){if(typeof t!=`boolean`)return`${e}: expected a boolean`;n(t)}}function C(e,t){if(e.effort!==void 0){if(typeof e.effort!=`string`)return`effort: expected a string`;try{let r=(0,n.parseModelEffort)(e.effort,`effort`);if(r===void 0)return`effort: expected a Core-owned effort selection`;t.effort=r}catch(e){return`effort: ${e instanceof Error?e.message:String(e)}`}}if(e.autonomy!==void 0){if(!_.includes(e.autonomy))return`autonomy: expected one of ${_.join(`, `)}`;t.autonomy=e.autonomy}let r=[[`permissionMode`,e.permissionMode,e=>t.permissionMode=e],[`defaultPermissionMode`,e.defaultPermissionMode,e=>t.defaultPermissionMode=e]];for(let[e,t,n]of r)if(t!==void 0){if(!v.includes(t))return`${e}: expected one of ${v.join(`, `)}`;n(t)}}function w(e,t){let n=[[`allowedTools`,e.allowedTools,e=>t.allowedTools=e],[`deniedTools`,e.deniedTools,e=>t.deniedTools=e],[`enabledCommandModules`,e.enabledCommandModules,e=>t.enabledCommandModules=e],[`disabledCommandModules`,e.disabledCommandModules,e=>t.disabledCommandModules=e]];for(let[e,t,r]of n)if(t!==void 0){if(!b(t))return`${e}: expected an array of strings`;r(t)}}function T(e){if(!y(e))return{ok:!1,error:`preset: expected a non-null object`};let t=[[`id`,e.id],[`title`,e.title],[`description`,e.description]];for(let[e,n]of t)if(typeof n!=`string`||n.length===0)return{ok:!1,error:`${e}: expected a non-empty string`};let n={},r=x(e,n)??S(e,n)??C(e,n)??w(e,n);return r===void 0?{ok:!0,preset:{id:e.id,title:e.title,description:e.description,...n}}:{ok:!1,error:r}}function E(n){if(!(0,e.existsSync)(n))return{presets:[],loaded:[],errors:[]};let r=[],i=[],a=new Map,o=(0,e.readdirSync)(n).filter(e=>e.endsWith(`.json`));for(let s of o){let o=(0,t.join)(n,s),c;try{c=JSON.parse((0,e.readFileSync)(o,`utf8`))}catch(e){r.push({file:s,error:e instanceof Error?e.message:String(e)});continue}let l=T(c);if(!l.ok){r.push({file:s,error:l.error});continue}i.push(l.preset),a.set(l.preset.id,s)}let{accepted:s,rejected:c}=l(i);for(let e of c)r.push({file:a.get(e.id)??e.id,error:e.reason});return{presets:s,loaded:s.map(e=>e.id),errors:r}}const D=[{id:`default`,name:`Default`,description:`The ordinary response style.`,instructions:``,keepCodingInstructions:!0,tokenCost:`baseline`,source:`built-in`},{id:`concise`,name:`Concise`,description:`Lead with the result and keep routine responses short.`,instructions:`Lead with the answer and skip routine preamble or tool narration. Keep responses concise while doing the same engineering work. Expand fully when asked for detail. Always keep error reports, security warnings and destructive-action confirmations complete.`,keepCodingInstructions:!0,tokenCost:`low`,source:`built-in`},{id:`proactive`,name:`Proactive`,description:`Take the next reasonable step without pausing on routine choices.`,instructions:`Act on reasonable routine assumptions and take the next useful step. State assumptions when they matter. The active permission mode remains authoritative; this style never grants, changes, or bypasses permission.`,keepCodingInstructions:!0,tokenCost:`medium`,source:`built-in`},{id:`explanatory`,name:`Explanatory`,description:`Teach the reasoning and trade-offs behind the answer.`,instructions:`Explain the reasoning, important trade-offs, and relevant terminology as you work. Keep the explanation connected to the requested outcome and do not omit complete error, security, or destructive-action guidance.`,keepCodingInstructions:!0,tokenCost:`high`,source:`built-in`},{id:`learning`,name:`Learning`,description:`Teach by marking useful gaps for the human to fill.`,instructions:`Teach the requested subject step by step. Mark a small number of useful gaps with [Your turn:] and invite the human to fill them before revealing the explanation. Never turn safety, security, error, or destructive-action guidance into a gap.`,keepCodingInstructions:!0,tokenCost:`high`,source:`built-in`}],O=new Set([`baseline`,`low`,`medium`,`high`,`unspecified`]);function k(e){return e.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/,`$1$2`)}function A(e,t){if(t===`true`)return!0;if(t===`false`)return!1;throw Error(`${e}: expected boolean, received "${t}"`)}function j(e,t){let n=t.split(`
5
+ `);if(n[0]?.trim()!==`---`)throw Error(`frontmatter: expected an opening --- marker`);let r={},i=-1;for(let e=1;e<n.length;e+=1){let t=n[e];if(t.trim()===`---`){i=e;break}if(t.trim()===``)continue;let a=/^([a-z][a-z0-9-]*):\s*(.*)$/.exec(t);if(!a)throw Error(`frontmatter: invalid entry at line ${e+1}`);let o=a[1];if(r[o]!==void 0)throw Error(`frontmatter.${o}: duplicate field`);r[o]=k(a[2].trim())}if(i<0)throw Error(`frontmatter: expected a closing --- marker`);let a=Object.keys(r).filter(e=>![`name`,`description`,`keep-coding-instructions`,`token-cost`].includes(e));if(a.length>0)throw Error(`frontmatter.${a[0]}: unknown field`);return{values:r,instructions:n.slice(i+1).join(`
6
+ `).trim()}}function M(e){let n=(0,t.basename)(e,(0,t.extname)(e)).trim();if(!/^[a-z0-9][a-z0-9-]*$/i.test(n))throw Error(`id: expected the Markdown filename stem to be a slug, received "${n}"`);return n.toLowerCase()}function N(e,n){if(!e.fileName.endsWith(`.md`))throw Error(`file: expected a .md output-style file`);let r=M(e.fileName),i=j(e.fileName,e.content),a=i.values.name?.trim()||(0,t.basename)(e.fileName,`.md`),o=i.values.description?.trim()||`Custom output style: ${a}`,s=i.values[`keep-coding-instructions`]!==void 0&&A(`frontmatter.keep-coding-instructions`,i.values[`keep-coding-instructions`]),c=i.values[`token-cost`]??`unspecified`;if(!O.has(c))throw Error(`frontmatter.token-cost: expected baseline|low|medium|high|unspecified, received "${c}"`);if(i.instructions.length===0)throw Error(`body: expected non-empty style instructions`);return{id:r,name:a,description:o,instructions:i.instructions,keepCodingInstructions:s,tokenCost:c,source:n}}function P(e){return{id:e.id,name:e.name,description:e.description,tokenCost:e.tokenCost,source:e.source}}function F(e){let t=new Map,n=[];for(let e of D)t.set(e.id,e);let r=[...e].sort((e,t)=>e.precedence-t.precedence);for(let e of r){let r=new Set;for(let i of[...e.files].sort((e,t)=>e.fileName.localeCompare(t.fileName))){let a=`${e.displayName}/${i.fileName}`,o;try{o=N(i,e.scope)}catch(e){n.push({file:a,error:e instanceof Error?e.message:String(e)});continue}if(r.has(o.id)){n.push({file:a,error:`duplicate style id "${o.id}" in source`});continue}if(r.add(o.id),t.get(o.id)?.source===`built-in`){n.push({file:a,error:`style id "${o.id}" collides with a built-in`});continue}t.set(o.id,o)}}return{styles:[...t.values()],loaded:[...t.values()].filter(e=>e.source!==`built-in`).map(e=>e.id),errors:n}}function I(e=[]){let t=F(e),n=new Map(t.styles.map(e=>[e.id,e]));return{listOutputStyles:()=>t.styles.map(P),getOutputStyle:e=>n.get(e)}}exports.autonomousBuilderPreset=i,exports.builtInOutputStyles=D,exports.createOutputStyleRegistry=I,exports.createPresetRegistry=h,exports.defaultPreset=r,exports.loadExternalPresetsFromDir=E,exports.loadOutputStylesFromSources=F,exports.parseOutputStyleFile=N,exports.partitionExternalPresets=l,exports.validateExternalPreset=T;
@@ -0,0 +1,255 @@
1
+ import { ICreateSessionOptions } from "@robota-sdk/agent-framework";
2
+ //#region src/preset-types.d.ts
3
+ /**
4
+ * Effort dial passed through to the model invocation (mechanism, not persona text).
5
+ * `'xhigh'` corresponds to the long-running ("ultra") tier; `'high'` is the neutral default.
6
+ *
7
+ * Reuses the framework's `ICreateSessionOptions['effort']` channel (which is the
8
+ * `agent-core` `TModelEffort` SSOT) so a resolved preset effort threads straight to the
9
+ * provider invocation seam (PRESET-008) without introducing a parallel union.
10
+ */
11
+ type TPresetEffort = NonNullable<ICreateSessionOptions['effort']>;
12
+ /**
13
+ * Behavioural autonomy posture. Drives the permission posture (`permissionMode`) — it is a mechanism
14
+ * mapping, not a display label.
15
+ */
16
+ type TPresetAutonomy = 'ask-first' | 'balanced' | 'act-first';
17
+ /**
18
+ * Permission mode reused from the framework option SSOT (`ICreateSessionOptions`).
19
+ * Reusing the indexed access keeps a single source of truth for the permission-mode union.
20
+ */
21
+ type TPresetPermissionMode = ICreateSessionOptions['permissionMode'];
22
+ /**
23
+ * The framework-facing option subset a preset resolves into. Every field maps to an
24
+ * existing `agent-framework` session/assembly seam; presets never introduce new option types.
25
+ */
26
+ interface IResolvedPresetOptions {
27
+ /**
28
+ * Portable persona/behaviour block (tone, refusal philosophy, output style, proactivity).
29
+ * Composed by the framework as a `source: 'persona'` system-prompt section (priority 5) —
30
+ * never runtime/tool/product-identity text. Empty/undefined adds no section (no regression).
31
+ */
32
+ persona?: string;
33
+ systemPrompt?: string;
34
+ appendSystemPrompt?: string;
35
+ agentName?: string;
36
+ model?: string;
37
+ language?: string;
38
+ effort?: TPresetEffort;
39
+ temperature?: number;
40
+ maxOutputTokens?: number;
41
+ /**
42
+ * Resolved framework permission-mode seam. The end value the assembly applies.
43
+ * Populated either directly, from `defaultPermissionMode`, or from the
44
+ * `autonomy` mapping (precedence: explicit `permissionMode` > `defaultPermissionMode`
45
+ * > `autonomy` mapping).
46
+ */
47
+ permissionMode?: TPresetPermissionMode;
48
+ /**
49
+ * Coarse permission posture declared by a preset. When set (and no explicit
50
+ * `permissionMode`), {@link resolvePreset} promotes it to `permissionMode`.
51
+ */
52
+ defaultPermissionMode?: TPresetPermissionMode;
53
+ allowedTools?: readonly string[];
54
+ deniedTools?: readonly string[];
55
+ enabledCommandModules?: readonly string[];
56
+ disabledCommandModules?: readonly string[];
57
+ enableParallelSubagents?: boolean;
58
+ selfVerification?: boolean;
59
+ autonomy?: TPresetAutonomy;
60
+ }
61
+ /**
62
+ * A named, pre-tuned bundle of framework option overrides plus display identity.
63
+ * Extends `IResolvedPresetOptions` (type SSOT) and adds the identity triple.
64
+ */
65
+ interface IPreset extends IResolvedPresetOptions {
66
+ id: string;
67
+ title: string;
68
+ description: string;
69
+ }
70
+ //#endregion
71
+ //#region src/output-style-types.d.ts
72
+ type TOutputStyleSource = 'built-in' | 'managed' | 'user' | 'project';
73
+ type TOutputStyleTokenCost = 'baseline' | 'low' | 'medium' | 'high' | 'unspecified';
74
+ /** The provider-neutral response-shaping value carried into the framework prompt. */
75
+ interface IOutputStyle {
76
+ readonly id: string;
77
+ readonly name: string;
78
+ readonly description: string;
79
+ readonly instructions: string;
80
+ readonly keepCodingInstructions: boolean;
81
+ readonly tokenCost: TOutputStyleTokenCost;
82
+ readonly source: TOutputStyleSource;
83
+ }
84
+ /** Secret-free discovery projection used by command and UI surfaces. */
85
+ type IOutputStyleSummary = Pick<IOutputStyle, 'id' | 'name' | 'description' | 'tokenCost' | 'source'>;
86
+ interface IOutputStyleFile {
87
+ readonly fileName: string;
88
+ readonly content: string;
89
+ }
90
+ /** A source is already bounded by its owner; this package only decodes the supplied Markdown. */
91
+ interface IOutputStyleSource {
92
+ readonly scope: Exclude<TOutputStyleSource, 'built-in'>;
93
+ readonly displayName: string;
94
+ /** Lower values are applied first. The last scope with an id wins. */
95
+ readonly precedence: number;
96
+ readonly files: readonly IOutputStyleFile[];
97
+ }
98
+ interface IOutputStyleLoadResult {
99
+ readonly styles: readonly IOutputStyle[];
100
+ readonly loaded: readonly string[];
101
+ readonly errors: readonly {
102
+ file: string;
103
+ error: string;
104
+ }[];
105
+ }
106
+ interface IOutputStyleRegistry {
107
+ listOutputStyles(): readonly IOutputStyleSummary[];
108
+ getOutputStyle(id: string): IOutputStyle | undefined;
109
+ }
110
+ //#endregion
111
+ //#region src/presets/default.d.ts
112
+ /**
113
+ * The neutral baseline preset. It carries NO option overrides so that resolving it is a
114
+ * pure no-op — applying `default` reproduces the standard agent behaviour exactly (no regression).
115
+ * The default agent identity is chosen by the product shell, not here,
116
+ * so that this preset stays a true identity element under merging.
117
+ */
118
+ declare const defaultPreset: IPreset;
119
+ //#endregion
120
+ //#region src/presets/autonomous-builder.d.ts
121
+ /**
122
+ * The first opinionated built-in preset: an autonomous, self-verifying builder posture.
123
+ *
124
+ * It both ships a portable persona block AND sets the framework/executor mechanism flags
125
+ * (`effort`, `autonomy`, `enableParallelSubagents`, `selfVerification`) so the style is backed
126
+ * by real, observable behaviour rather than persona text alone. The identifier is generic; the
127
+ * sourcing footnote in `description` is the only place a work-style attribution appears.
128
+ *
129
+ * For long-running tasks the effort dial may be raised to a higher tier; `'high'` is the
130
+ * neutral default carried here.
131
+ */
132
+ declare const autonomousBuilderPreset: IPreset;
133
+ //#endregion
134
+ //#region src/resolve-preset.d.ts
135
+ /** Lightweight `{ id, title, description }` view of a preset for discovery/UX. */
136
+ interface IPresetSummary {
137
+ id: string;
138
+ title: string;
139
+ description: string;
140
+ }
141
+ /** Outcome of {@link partitionExternalPresets}: which presets were accepted and which rejected. */
142
+ interface IPresetRegistrationResult {
143
+ accepted: readonly IPreset[];
144
+ rejected: readonly {
145
+ id: string;
146
+ reason: string;
147
+ }[];
148
+ }
149
+ /**
150
+ * Apply the external-preset conflict policy to one list, reading and mutating NOTHING outside it.
151
+ *
152
+ * Conflict policy: an external preset whose id matches a BUILT-IN preset is rejected
153
+ * (`'collides with built-in preset'`) — built-ins always win. An external preset whose id matches an
154
+ * earlier ACCEPTED external preset is rejected (`'duplicate preset id'`) — first one wins.
155
+ *
156
+ * ARCH-009. This is the whole of what the module-global registry used to be, minus the register:
157
+ * the policy was never the process's to hold, only the list it was applied to was. Both callers —
158
+ * {@link createPresetRegistry} and the external-preset loader — now pass their own list, so two
159
+ * products in one process cannot see each other's presets, and a repeated load cannot accumulate.
160
+ */
161
+ declare function partitionExternalPresets(presets: readonly IPreset[]): IPresetRegistrationResult;
162
+ /**
163
+ * Override layers for {@link resolvePreset}, in increasing precedence.
164
+ * `cliOverrides` model CLI flags; `explicit` models programmatic/SDK options.
165
+ */
166
+ interface IResolvePresetContext {
167
+ cliOverrides?: IResolvedPresetOptions;
168
+ explicit?: IResolvedPresetOptions;
169
+ }
170
+ /**
171
+ * A per-call, instance-scoped preset registry (ARCH-005 R8) — since ARCH-009 the ONLY one there is.
172
+ *
173
+ * A registry holds its own merged list `[built-ins, ...accepted externals]`, so two products in one
174
+ * process do not share one and repeat construction does not accumulate. The
175
+ * `@robota-sdk/agent-product` assembler builds one per `assembleProduct` call and surfaces it on the
176
+ * command-host context, which is how `/preset` inside a live session reaches THIS product's presets
177
+ * rather than the process's.
178
+ */
179
+ interface IPresetRegistry {
180
+ /** Resolve a preset id against this registry's presets. */
181
+ resolvePreset(id: string, context?: IResolvePresetContext): IResolvedPresetOptions;
182
+ /** Look up a preset by id within this registry, or `undefined`. */
183
+ getPreset(id: string): IPreset | undefined;
184
+ /** `{ id, title, description }` summaries of every preset in this registry. */
185
+ listPresets(): readonly IPresetSummary[];
186
+ }
187
+ /**
188
+ * Build an instance-scoped {@link IPresetRegistry} over `[built-ins, ...externalPresets]`.
189
+ *
190
+ * The conflict policy is {@link partitionExternalPresets}, applied to the argument list only: built-ins
191
+ * always win, and among the external presets the first one wins. No module-level state is read or
192
+ * mutated — this is a pure factory, and since ARCH-009 there is no module-level state to read.
193
+ *
194
+ * Called with no argument it is the BUILT-INS, which is the registry a host that supplies none gets.
195
+ */
196
+ declare function createPresetRegistry(externalPresets?: readonly IPreset[]): IPresetRegistry;
197
+ //#endregion
198
+ //#region src/load-external-presets.d.ts
199
+ /**
200
+ * Outcome of an external-preset load: the presets themselves, their ids, and per-file errors.
201
+ *
202
+ * ARCH-009 added `presets`. `loaded` used to be the only way out, because the presets went into a
203
+ * module-global registry and the caller read them back by id — which is what made the global
204
+ * load-bearing at startup. The caller now receives the values it loaded and builds its own registry
205
+ * over them, so nothing has to be looked up from process state.
206
+ */
207
+ interface IExternalPresetLoadResult {
208
+ presets: readonly IPreset[];
209
+ loaded: readonly string[];
210
+ errors: readonly {
211
+ file: string;
212
+ error: string;
213
+ }[];
214
+ }
215
+ /**
216
+ * Load and validate every `*.json` external preset from `dir`.
217
+ *
218
+ * A missing directory yields an empty result (no error). Each file is JSON-parsed and validated;
219
+ * a parse or validation failure is recorded as a per-file error and skipped — the remaining files
220
+ * still load. The surviving presets go through {@link partitionExternalPresets}, whose rejections
221
+ * (built-in id collision or duplicate id) are folded into `errors` against their file.
222
+ *
223
+ * Loading REGISTERS NOTHING. The result is a value the caller owns.
224
+ */
225
+ declare function loadExternalPresetsFromDir(dir: string): IExternalPresetLoadResult;
226
+ //#endregion
227
+ //#region src/preset-validation.d.ts
228
+ /** Result of {@link validateExternalPreset}: the validated preset, or a single error message. */
229
+ type TPresetValidationResult = {
230
+ ok: true;
231
+ preset: IPreset;
232
+ } | {
233
+ ok: false;
234
+ error: string;
235
+ };
236
+ /**
237
+ * Manually validate an unknown value as an {@link IPreset} (no schema library).
238
+ *
239
+ * Required fields: non-empty `id`, `title`, `description` strings. Every other field is
240
+ * optional and is validated only when present; an unrecognised field is dropped (the built
241
+ * preset carries the recognised fields only, never unknown keys). On the first failed check
242
+ * returns `{ ok: false, error: '<field>: <reason>' }`.
243
+ */
244
+ declare function validateExternalPreset(value: unknown): TPresetValidationResult;
245
+ //#endregion
246
+ //#region src/output-styles.d.ts
247
+ declare const builtInOutputStyles: readonly IOutputStyle[];
248
+ //#endregion
249
+ //#region src/output-style-registry.d.ts
250
+ declare function parseOutputStyleFile(file: IOutputStyleFile, source: TOutputStyleSource): IOutputStyle;
251
+ declare function loadOutputStylesFromSources(sources: readonly IOutputStyleSource[]): IOutputStyleLoadResult;
252
+ declare function createOutputStyleRegistry(sources?: readonly IOutputStyleSource[]): IOutputStyleRegistry;
253
+ //#endregion
254
+ export { type IExternalPresetLoadResult, type IOutputStyle, type IOutputStyleFile, type IOutputStyleLoadResult, type IOutputStyleRegistry, type IOutputStyleSource, type IOutputStyleSummary, type IPreset, type IPresetRegistrationResult, type IPresetRegistry, type IPresetSummary, type IResolvePresetContext, type IResolvedPresetOptions, type TOutputStyleSource, type TOutputStyleTokenCost, type TPresetAutonomy, type TPresetEffort, type TPresetPermissionMode, type TPresetValidationResult, autonomousBuilderPreset, builtInOutputStyles, createOutputStyleRegistry, createPresetRegistry, defaultPreset, loadExternalPresetsFromDir, loadOutputStylesFromSources, parseOutputStyleFile, partitionExternalPresets, validateExternalPreset };
255
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/preset-types.ts","../../src/output-style-types.ts","../../src/presets/default.ts","../../src/presets/autonomous-builder.ts","../../src/resolve-preset.ts","../../src/load-external-presets.ts","../../src/preset-validation.ts","../../src/output-styles.ts","../../src/output-style-registry.ts"],"mappings":";;;;;;;;;;KAUY,gBAAgB,YAAY;;;;;KAM5B;;;;;KAMA,wBAAwB;;;;;UAMnB;;;;;;EAOf;EACA;EACA;EACA;EAGA;EACA;EACA,SAAS;EACT;EACA;;;;;;;EASA,iBAAiB;;;;;EAKjB,wBAAwB;EACxB;EACA;EAGA;EACA;EAGA;EACA;EAGA,WAAW;;;;;;UAOI,gBAAgB;EAC/B;EACA;EACA;;;;KClFU;KAEA;;UAGK;WACN;WACA;WACA;WACA;WACA;WACA,WAAW;WACX,QAAQ;;;KAIP,sBAAsB,KAChC;UAIe;WACN;WACA;;;UAIM;WACN,OAAO,QAAQ;WACf;;WAEA;WACA,gBAAgB;;UAGV;WACN,iBAAiB;WACjB;WACA;IAAmB;IAAc;;;UAG3B;EACf,6BAA6B;EAC7B,eAAe,aAAa;;;;;;;;;;cCnCjB,eAAe;;;;;;;;;;;;;;cCsCf,yBAAyB;;;;UCXrB;EACf;EACA;EACA;;;UAIe;EACf,mBAAmB;EACnB;IAAqB;IAAY;;;;;;;;;;;;;;;iBAenB,yBAAyB,kBAAkB,YAAY;;;;;UAwBtD;EACf,eAAe;EACf,WAAW;;;;;;;;;;;UAuFI;;EAEf,cAAc,YAAY,UAAU,wBAAwB;;EAE5D,UAAU,aAAa;;EAEvB,wBAAwB;;;;;;;;;;;iBAYV,qBAAqB,2BAA0B,YAAiB;;;;;;;;;;;UC9K/D;EACf,kBAAkB;EAClB;EACA;IAAmB;IAAc;;;;;;;;;;;;;iBAanB,2BAA2B,cAAc;;;;KCtB7C;EAA4B;EAAU,QAAQ;;EAAc;EAAW;;;;;;;;;;iBA8KnE,uBAAuB,iBAAiB;;;cCpL3C,8BAA8B;;;iBC8E3B,qBACd,MAAM,kBACN,QAAQ,qBACP;iBA6Ca,4BACd,kBAAkB,uBACjB;iBA4Ca,0BACd,mBAAkB,uBACjB"}
@@ -1,5 +1,4 @@
1
1
  import { ICreateSessionOptions } from "@robota-sdk/agent-framework";
2
-
3
2
  //#region src/preset-types.d.ts
4
3
  /**
5
4
  * Effort dial passed through to the model invocation (mechanism, not persona text).
@@ -11,12 +10,10 @@ import { ICreateSessionOptions } from "@robota-sdk/agent-framework";
11
10
  */
12
11
  type TPresetEffort = NonNullable<ICreateSessionOptions['effort']>;
13
12
  /**
14
- * Behavioural autonomy posture. Drives the permission posture
15
- * (`permissionMode` / `defaultTrustLevel`) — it is a mechanism mapping, not a display label.
13
+ * Behavioural autonomy posture. Drives the permission posture (`permissionMode`) — it is a mechanism
14
+ * mapping, not a display label.
16
15
  */
17
16
  type TPresetAutonomy = 'ask-first' | 'balanced' | 'act-first';
18
- /** Default trust level applied when the preset opts into a coarse permission posture. */
19
- type TPresetTrustLevel = 'safe' | 'moderate' | 'full';
20
17
  /**
21
18
  * Permission mode reused from the framework option SSOT (`ICreateSessionOptions`).
22
19
  * Reusing the indexed access keeps a single source of truth for the permission-mode union.
@@ -53,7 +50,6 @@ interface IResolvedPresetOptions {
53
50
  * `permissionMode`), {@link resolvePreset} promotes it to `permissionMode`.
54
51
  */
55
52
  defaultPermissionMode?: TPresetPermissionMode;
56
- defaultTrustLevel?: TPresetTrustLevel;
57
53
  allowedTools?: readonly string[];
58
54
  deniedTools?: readonly string[];
59
55
  enabledCommandModules?: readonly string[];
@@ -72,11 +68,51 @@ interface IPreset extends IResolvedPresetOptions {
72
68
  description: string;
73
69
  }
74
70
  //#endregion
71
+ //#region src/output-style-types.d.ts
72
+ type TOutputStyleSource = 'built-in' | 'managed' | 'user' | 'project';
73
+ type TOutputStyleTokenCost = 'baseline' | 'low' | 'medium' | 'high' | 'unspecified';
74
+ /** The provider-neutral response-shaping value carried into the framework prompt. */
75
+ interface IOutputStyle {
76
+ readonly id: string;
77
+ readonly name: string;
78
+ readonly description: string;
79
+ readonly instructions: string;
80
+ readonly keepCodingInstructions: boolean;
81
+ readonly tokenCost: TOutputStyleTokenCost;
82
+ readonly source: TOutputStyleSource;
83
+ }
84
+ /** Secret-free discovery projection used by command and UI surfaces. */
85
+ type IOutputStyleSummary = Pick<IOutputStyle, 'id' | 'name' | 'description' | 'tokenCost' | 'source'>;
86
+ interface IOutputStyleFile {
87
+ readonly fileName: string;
88
+ readonly content: string;
89
+ }
90
+ /** A source is already bounded by its owner; this package only decodes the supplied Markdown. */
91
+ interface IOutputStyleSource {
92
+ readonly scope: Exclude<TOutputStyleSource, 'built-in'>;
93
+ readonly displayName: string;
94
+ /** Lower values are applied first. The last scope with an id wins. */
95
+ readonly precedence: number;
96
+ readonly files: readonly IOutputStyleFile[];
97
+ }
98
+ interface IOutputStyleLoadResult {
99
+ readonly styles: readonly IOutputStyle[];
100
+ readonly loaded: readonly string[];
101
+ readonly errors: readonly {
102
+ file: string;
103
+ error: string;
104
+ }[];
105
+ }
106
+ interface IOutputStyleRegistry {
107
+ listOutputStyles(): readonly IOutputStyleSummary[];
108
+ getOutputStyle(id: string): IOutputStyle | undefined;
109
+ }
110
+ //#endregion
75
111
  //#region src/presets/default.d.ts
76
112
  /**
77
113
  * The neutral baseline preset. It carries NO option overrides so that resolving it is a
78
114
  * pure no-op — applying `default` reproduces the standard agent behaviour exactly (no regression).
79
- * The default agent identity is owned by `DEFAULT_AGENT_NAME` in `resolve-preset.ts`, not here,
115
+ * The default agent identity is chosen by the product shell, not here,
80
116
  * so that this preset stays a true identity element under merging.
81
117
  */
82
118
  declare const defaultPreset: IPreset;
@@ -96,41 +132,33 @@ declare const defaultPreset: IPreset;
96
132
  declare const autonomousBuilderPreset: IPreset;
97
133
  //#endregion
98
134
  //#region src/resolve-preset.d.ts
99
- /**
100
- * Default agent identity. Owned by `agent-preset` (not baked into `defaultPreset`, which must stay
101
- * a no-op). Consumers apply this when no preset and no explicit override supplies an `agentName`.
102
- */
103
- declare const DEFAULT_AGENT_NAME = "robota-cli";
104
135
  /** Lightweight `{ id, title, description }` view of a preset for discovery/UX. */
105
136
  interface IPresetSummary {
106
137
  id: string;
107
138
  title: string;
108
139
  description: string;
109
140
  }
110
- /** Outcome of {@link registerExternalPresets}: which ids registered and which were rejected. */
141
+ /** Outcome of {@link partitionExternalPresets}: which presets were accepted and which rejected. */
111
142
  interface IPresetRegistrationResult {
112
- registered: readonly string[];
143
+ accepted: readonly IPreset[];
113
144
  rejected: readonly {
114
145
  id: string;
115
146
  reason: string;
116
147
  }[];
117
148
  }
118
149
  /**
119
- * Register user-authored external presets into the module-level registry.
150
+ * Apply the external-preset conflict policy to one list, reading and mutating NOTHING outside it.
120
151
  *
121
152
  * Conflict policy: an external preset whose id matches a BUILT-IN preset is rejected
122
- * (`'collides with built-in preset'`) — built-ins always win. An external preset whose id
123
- * matches an already-registered external preset is rejected (`'duplicate preset id'`) — first
124
- * registration wins. All other presets are appended and counted as registered.
153
+ * (`'collides with built-in preset'`) — built-ins always win. An external preset whose id matches an
154
+ * earlier ACCEPTED external preset is rejected (`'duplicate preset id'`) — first one wins.
125
155
  *
126
- * @returns the ids that registered and the `{ id, reason }` of each rejection.
127
- */
128
- declare function registerExternalPresets(presets: readonly IPreset[]): IPresetRegistrationResult;
129
- /**
130
- * Remove every registered external preset, leaving only the built-ins.
131
- * Used at startup before a fresh re-load and for test isolation.
156
+ * ARCH-009. This is the whole of what the module-global registry used to be, minus the register:
157
+ * the policy was never the process's to hold, only the list it was applied to was. Both callers —
158
+ * {@link createPresetRegistry} and the external-preset loader — now pass their own list, so two
159
+ * products in one process cannot see each other's presets, and a repeated load cannot accumulate.
132
160
  */
133
- declare function clearExternalPresets(): void;
161
+ declare function partitionExternalPresets(presets: readonly IPreset[]): IPresetRegistrationResult;
134
162
  /**
135
163
  * Override layers for {@link resolvePreset}, in increasing precedence.
136
164
  * `cliOverrides` model CLI flags; `explicit` models programmatic/SDK options.
@@ -139,48 +167,62 @@ interface IResolvePresetContext {
139
167
  cliOverrides?: IResolvedPresetOptions;
140
168
  explicit?: IResolvedPresetOptions;
141
169
  }
142
- /** Return the `{ id, title, description }` summary of every registered preset. */
143
- declare function listPresets(): readonly IPresetSummary[];
144
- /** Look up a registered preset by id, or `undefined` if none matches. */
145
- declare function getPreset(id: string): IPreset | undefined;
146
170
  /**
147
- * Resolve a preset id into framework option overrides.
171
+ * A per-call, instance-scoped preset registry (ARCH-005 R8) — since ARCH-009 the ONLY one there is.
148
172
  *
149
- * Precedence LOW → HIGH: preset options < `context.cliOverrides` < `context.explicit`
150
- * (later layers win; `undefined` values are skipped). For the no-op `'default'` preset the
151
- * result equals the merged overrides, guaranteeing no regression.
173
+ * A registry holds its own merged list `[built-ins, ...accepted externals]`, so two products in one
174
+ * process do not share one and repeat construction does not accumulate. The
175
+ * `@robota-sdk/agent-product` assembler builds one per `assembleProduct` call and surfaces it on the
176
+ * command-host context, which is how `/preset` inside a live session reaches THIS product's presets
177
+ * rather than the process's.
178
+ */
179
+ interface IPresetRegistry {
180
+ /** Resolve a preset id against this registry's presets. */
181
+ resolvePreset(id: string, context?: IResolvePresetContext): IResolvedPresetOptions;
182
+ /** Look up a preset by id within this registry, or `undefined`. */
183
+ getPreset(id: string): IPreset | undefined;
184
+ /** `{ id, title, description }` summaries of every preset in this registry. */
185
+ listPresets(): readonly IPresetSummary[];
186
+ }
187
+ /**
188
+ * Build an instance-scoped {@link IPresetRegistry} over `[built-ins, ...externalPresets]`.
152
189
  *
153
- * @throws Error when `id` does not match a registered preset.
190
+ * The conflict policy is {@link partitionExternalPresets}, applied to the argument list only: built-ins
191
+ * always win, and among the external presets the first one wins. No module-level state is read or
192
+ * mutated — this is a pure factory, and since ARCH-009 there is no module-level state to read.
193
+ *
194
+ * Called with no argument it is the BUILT-INS, which is the registry a host that supplies none gets.
154
195
  */
155
- declare function resolvePreset(id: string, context?: IResolvePresetContext): IResolvedPresetOptions;
196
+ declare function createPresetRegistry(externalPresets?: readonly IPreset[]): IPresetRegistry;
156
197
  //#endregion
157
198
  //#region src/load-external-presets.d.ts
158
- /** Outcome of an external-preset load: which ids loaded and per-file load/validation errors. */
199
+ /**
200
+ * Outcome of an external-preset load: the presets themselves, their ids, and per-file errors.
201
+ *
202
+ * ARCH-009 added `presets`. `loaded` used to be the only way out, because the presets went into a
203
+ * module-global registry and the caller read them back by id — which is what made the global
204
+ * load-bearing at startup. The caller now receives the values it loaded and builds its own registry
205
+ * over them, so nothing has to be looked up from process state.
206
+ */
159
207
  interface IExternalPresetLoadResult {
208
+ presets: readonly IPreset[];
160
209
  loaded: readonly string[];
161
210
  errors: readonly {
162
211
  file: string;
163
212
  error: string;
164
213
  }[];
165
214
  }
166
- /** Conventional external-preset directory: `~/.robota/presets`. */
167
- declare function defaultExternalPresetDir(): string;
168
215
  /**
169
- * Load, validate, and register every `*.json` external preset from `dir`.
216
+ * Load and validate every `*.json` external preset from `dir`.
170
217
  *
171
218
  * A missing directory yields an empty result (no error). Each file is JSON-parsed and validated;
172
219
  * a parse or validation failure is recorded as a per-file error and skipped — the remaining files
173
- * still load. Validated presets are registered via {@link registerExternalPresets}; registry
174
- * rejections (built-in id collision or duplicate id) are folded into `errors` against their file.
220
+ * still load. The surviving presets go through {@link partitionExternalPresets}, whose rejections
221
+ * (built-in id collision or duplicate id) are folded into `errors` against their file.
222
+ *
223
+ * Loading REGISTERS NOTHING. The result is a value the caller owns.
175
224
  */
176
225
  declare function loadExternalPresetsFromDir(dir: string): IExternalPresetLoadResult;
177
- /**
178
- * Load external presets from the conventional directory (or `options.dir` when given).
179
- * Thin wrapper over {@link loadExternalPresetsFromDir}.
180
- */
181
- declare function loadExternalPresets(options?: {
182
- dir?: string;
183
- }): IExternalPresetLoadResult;
184
226
  //#endregion
185
227
  //#region src/preset-validation.d.ts
186
228
  /** Result of {@link validateExternalPreset}: the validated preset, or a single error message. */
@@ -201,5 +243,13 @@ type TPresetValidationResult = {
201
243
  */
202
244
  declare function validateExternalPreset(value: unknown): TPresetValidationResult;
203
245
  //#endregion
204
- export { DEFAULT_AGENT_NAME, type IExternalPresetLoadResult, type IPreset, type IPresetRegistrationResult, type IPresetSummary, type IResolvePresetContext, type IResolvedPresetOptions, type TPresetAutonomy, type TPresetEffort, type TPresetPermissionMode, type TPresetTrustLevel, type TPresetValidationResult, autonomousBuilderPreset, clearExternalPresets, defaultExternalPresetDir, defaultPreset, getPreset, listPresets, loadExternalPresets, loadExternalPresetsFromDir, registerExternalPresets, resolvePreset, validateExternalPreset };
246
+ //#region src/output-styles.d.ts
247
+ declare const builtInOutputStyles: readonly IOutputStyle[];
248
+ //#endregion
249
+ //#region src/output-style-registry.d.ts
250
+ declare function parseOutputStyleFile(file: IOutputStyleFile, source: TOutputStyleSource): IOutputStyle;
251
+ declare function loadOutputStylesFromSources(sources: readonly IOutputStyleSource[]): IOutputStyleLoadResult;
252
+ declare function createOutputStyleRegistry(sources?: readonly IOutputStyleSource[]): IOutputStyleRegistry;
253
+ //#endregion
254
+ export { type IExternalPresetLoadResult, type IOutputStyle, type IOutputStyleFile, type IOutputStyleLoadResult, type IOutputStyleRegistry, type IOutputStyleSource, type IOutputStyleSummary, type IPreset, type IPresetRegistrationResult, type IPresetRegistry, type IPresetSummary, type IResolvePresetContext, type IResolvedPresetOptions, type TOutputStyleSource, type TOutputStyleTokenCost, type TPresetAutonomy, type TPresetEffort, type TPresetPermissionMode, type TPresetValidationResult, autonomousBuilderPreset, builtInOutputStyles, createOutputStyleRegistry, createPresetRegistry, defaultPreset, loadExternalPresetsFromDir, loadOutputStylesFromSources, parseOutputStyleFile, partitionExternalPresets, validateExternalPreset };
205
255
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/preset-types.ts","../../src/presets/default.ts","../../src/presets/autonomous-builder.ts","../../src/resolve-preset.ts","../../src/load-external-presets.ts","../../src/preset-validation.ts"],"mappings":";;;;;AAUA;;;;AAA6D;AAM7D;KANY,aAAA,GAAgB,WAAW,CAAC,qBAAA;;;AAMb;AAG3B;KAHY,eAAA;;KAGA,iBAAA;AAAiB;AAM7B;;;AAN6B,KAMjB,qBAAA,GAAwB,qBAAqB;AAAA;AAMzD;;;AANyD,UAMxC,sBAAA;EA0BE;;;;;EAnBjB,OAAA;EACA,YAAA;EACA,kBAAA;EACA,SAAA;EAGA,KAAA;EACA,QAAA;EACA,MAAA,GAAS,aAAA;EACT,WAAA;EACA,eAAA;EADA;;;;;;EAUA,cAAA,GAAiB,qBAAA;EAMG;;;;EADpB,qBAAA,GAAwB,qBAAA;EACxB,iBAAA,GAAoB,iBAAA;EACpB,YAAA;EACA,WAAA;EAGA,qBAAA;EACA,sBAAA;EAGA,uBAAA;EACA,gBAAA;EAGA,QAAA,GAAW,eAAA;AAAA;;;;;UAOI,OAAA,SAAgB,sBAAsB;EACrD,EAAA;EACA,KAAA;EACA,WAAA;AAAA;;;;;AA5EF;;;;cCFa,aAAA,EAAe,OAI3B;;;;;ADFD;;;;AAA6D;AAM7D;;;;cE8Ba,uBAAA,EAAyB,OAWrC;;;;;AF/CD;;cGoBa,kBAAA;;UAuBI,cAAA;EACf,EAAA;EACA,KAAA;EACA,WAAA;AAAA;AHxCyB;AAAA,UG4CV,yBAAA;EACf,UAAA;EACA,QAAA;IAAqB,EAAA;IAAY,MAAA;EAAA;AAAA;;;AHrCsB;AAMzD;;;;;;;iBG4CgB,uBAAA,CAAwB,OAAA,WAAkB,OAAA,KAAY,yBAAyB;;;;;iBAyB/E,oBAAA;;;;;UAQC,qBAAA;EACf,YAAA,GAAe,sBAAA;EACf,QAAA,GAAW,sBAAsB;AAAA;;iBAInB,WAAA,aAAwB,cAAc;;iBAKtC,SAAA,CAAU,EAAA,WAAa,OAAO;;;;;;;;;;iBAmC9B,aAAA,CACd,EAAA,UACA,OAAA,GAAS,qBAAA,GACR,sBAAsB;;;;UCnJR,yBAAA;EACf,MAAA;EACA,MAAA;IAAmB,IAAA;IAAc,KAAA;EAAA;AAAA;AJInC;AAAA,iBIAgB,wBAAA;;;AJAW;AAG3B;;;;AAA6B;iBISb,0BAAA,CAA2B,GAAA,WAAc,yBAAyB;;;;AJHzB;iBI+CzC,mBAAA,CAAoB,OAAA;EAAY,GAAA;AAAA,IAAiB,yBAAyB;;;;KC9D9E,uBAAA;EAA4B,EAAA;EAAU,MAAA,EAAQ,OAAO;AAAA;EAAO,EAAA;EAAW,KAAA;AAAA;;;;ALMxD;AAG3B;;;;iBKyKgB,sBAAA,CAAuB,KAAA,YAAiB,uBAAuB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/preset-types.ts","../../src/output-style-types.ts","../../src/presets/default.ts","../../src/presets/autonomous-builder.ts","../../src/resolve-preset.ts","../../src/load-external-presets.ts","../../src/preset-validation.ts","../../src/output-styles.ts","../../src/output-style-registry.ts"],"mappings":";;;;;;;;;;KAUY,gBAAgB,YAAY;;;;;KAM5B;;;;;KAMA,wBAAwB;;;;;UAMnB;;;;;;EAOf;EACA;EACA;EACA;EAGA;EACA;EACA,SAAS;EACT;EACA;;;;;;;EASA,iBAAiB;;;;;EAKjB,wBAAwB;EACxB;EACA;EAGA;EACA;EAGA;EACA;EAGA,WAAW;;;;;;UAOI,gBAAgB;EAC/B;EACA;EACA;;;;KClFU;KAEA;;UAGK;WACN;WACA;WACA;WACA;WACA;WACA,WAAW;WACX,QAAQ;;;KAIP,sBAAsB,KAChC;UAIe;WACN;WACA;;;UAIM;WACN,OAAO,QAAQ;WACf;;WAEA;WACA,gBAAgB;;UAGV;WACN,iBAAiB;WACjB;WACA;IAAmB;IAAc;;;UAG3B;EACf,6BAA6B;EAC7B,eAAe,aAAa;;;;;;;;;;cCnCjB,eAAe;;;;;;;;;;;;;;cCsCf,yBAAyB;;;;UCXrB;EACf;EACA;EACA;;;UAIe;EACf,mBAAmB;EACnB;IAAqB;IAAY;;;;;;;;;;;;;;;iBAenB,yBAAyB,kBAAkB,YAAY;;;;;UAwBtD;EACf,eAAe;EACf,WAAW;;;;;;;;;;;UAuFI;;EAEf,cAAc,YAAY,UAAU,wBAAwB;;EAE5D,UAAU,aAAa;;EAEvB,wBAAwB;;;;;;;;;;;iBAYV,qBAAqB,2BAA0B,YAAiB;;;;;;;;;;;UC9K/D;EACf,kBAAkB;EAClB;EACA;IAAmB;IAAc;;;;;;;;;;;;;iBAanB,2BAA2B,cAAc;;;;KCtB7C;EAA4B;EAAU,QAAQ;;EAAc;EAAW;;;;;;;;;;iBA8KnE,uBAAuB,iBAAiB;;;cCpL3C,8BAA8B;;;iBC8E3B,qBACd,MAAM,kBACN,QAAQ,qBACP;iBA6Ca,4BACd,kBAAkB,uBACjB;iBA4Ca,0BACd,mBAAkB,uBACjB"}
@@ -1,5 +1,7 @@
1
- import{existsSync as e,readFileSync as t,readdirSync as n}from"node:fs";import{homedir as r}from"node:os";import{join as i}from"node:path";const a={id:`default`,title:`Default`,description:`Neutral baseline preset — no overrides; reproduces the standard agent behaviour.`},o={id:`autonomous-builder`,title:`Autonomous Builder`,description:`Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel subagents (proactive autonomous-builder persona; original English wording).`,effort:`high`,autonomy:`act-first`,enableParallelSubagents:!0,selfVerification:!0,persona:[`You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and`,`complete the task — act rather than stop to ask. Keep going through the points where a more`,`hesitant assistant would pause for confirmation, and only check in when something is genuinely`,`ambiguous or risky.`,``,`Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add`,`abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task`,`plainly needs, but resist turning a focused change into a sweeping one.`,``,`After making changes, verify your own work — run the tests, re-read the goal, and confirm the`,`result actually matches what was requested before you call it done.`,``,`Ground your claims in evidence. Before reporting progress, check each claim against an actual`,`tool result from this session; if something is not yet verified, say so plainly rather than`,`implying it is finished.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`,``,`Lead with the outcome. Report results plainly instead of narrating each step, keep formatting`,`light, and stay concise.`].join(`
2
- `)},s={id:`careful-reviewer`,title:`Careful Reviewer`,description:`Conservative, ask-first reviewing posture — reads and plans before changing, prompts on write/exec, self-verifies, runs focused (no parallel subagents) at high effort.`,effort:`high`,autonomy:`ask-first`,enableParallelSubagents:!1,selfVerification:!0,persona:[`You are a careful, review-oriented assistant. Read and analyse before you change anything —`,`understand the surrounding code and context first, then lay out a short plan for the change and`,`wait for confirmation before you write or run things that have side effects.`,``,`When you propose a change, explain why — the reasoning behind it and the trade-offs against the`,`alternatives you considered, so the choice can be reviewed rather than taken on trust.`,``,`Stay conservative in scope. Make the change that was asked for and the detail it plainly needs;`,`do not widen the blast radius with unrequested refactors or rewrites.`,``,`Ground your claims in evidence. Before reporting progress or completion, check each claim against`,`an actual tool result from this session; if something is not yet verified, say so plainly rather`,`than implying it is done.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`].join(`
3
- `)},c={id:`neutral-executor`,title:`Neutral Executor`,description:`Thin, steerable executor — follows instructions literally, minimal editorialising, strict scope, terse output; balanced autonomy, no parallel subagents, no self-verification, medium effort for predictable scripted use (neutral-alignment work-style; original English wording).`,effort:`medium`,autonomy:`balanced`,enableParallelSubagents:!1,selfVerification:!1,persona:[`Follow the system and user instructions literally. Do what was asked, the way it was asked, and`,`defer to the given instructions over your own preferences.`,``,`Editorialise as little as possible. Skip unrequested commentary, caveats, and asides — give the`,`result, not a narration of it.`,``,`Stay strictly in scope. Make only the change that was requested and the detail it plainly needs;`,`do not add adjacent refactors, comments, or features that were not asked for.`,``,`Keep output terse. Prefer the shortest response that fully answers, so the result is predictable`,`and easy to consume in a script or pipeline.`].join(`
4
- `)},l={"ask-first":`default`,balanced:`default`,"act-first":`acceptEdits`},u=`robota-cli`,d=[a,o,s,c],f=[];function p(){return[...d,...f]}function m(e){let t=new Set(d.map(e=>e.id)),n=[],r=[];for(let i of e){if(t.has(i.id)){r.push({id:i.id,reason:`collides with built-in preset`});continue}if(f.some(e=>e.id===i.id)){r.push({id:i.id,reason:`duplicate preset id`});continue}f.push(i),n.push(i.id)}return{registered:n,rejected:r}}function h(){f.length=0}function g(){return p().map(({id:e,title:t,description:n})=>({id:e,title:t,description:n}))}function _(e){return p().find(t=>t.id===e)}function v(e){let{id:t,title:n,description:r,...i}=e;return i}function y(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function b(e,t){return t?{...e,...y(t)}:e}function x(e,t={}){let n=_(e);if(!n){let t=p().map(e=>e.id).join(`, `);throw Error(`Unknown preset: "${e}". Available presets: ${t}.`)}let r=v(n);return r=b(r,t.cliOverrides),r=b(r,t.explicit),S(r)}function S(e){return e.permissionMode===void 0?e.defaultPermissionMode===void 0?e.autonomy===void 0?e:{...e,permissionMode:l[e.autonomy]}:{...e,permissionMode:e.defaultPermissionMode}:e}const C=[`low`,`medium`,`high`,`xhigh`,`max`],w=[`ask-first`,`act-first`,`balanced`],T=[`plan`,`default`,`acceptEdits`,`bypassPermissions`],E=[`safe`,`moderate`,`full`];function D(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function O(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function k(e,t){let n=[[`persona`,e.persona,e=>t.persona=e],[`systemPrompt`,e.systemPrompt,e=>t.systemPrompt=e],[`appendSystemPrompt`,e.appendSystemPrompt,e=>t.appendSystemPrompt=e],[`agentName`,e.agentName,e=>t.agentName=e],[`model`,e.model,e=>t.model=e],[`language`,e.language,e=>t.language=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`string`)return`${e}: expected a string`;r(t)}}function A(e,t){let n=[[`temperature`,e.temperature,e=>t.temperature=e],[`maxOutputTokens`,e.maxOutputTokens,e=>t.maxOutputTokens=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`number`||Number.isNaN(t))return`${e}: expected a number`;r(t)}let r=[[`enableParallelSubagents`,e.enableParallelSubagents,e=>t.enableParallelSubagents=e],[`selfVerification`,e.selfVerification,e=>t.selfVerification=e]];for(let[e,t,n]of r)if(t!==void 0){if(typeof t!=`boolean`)return`${e}: expected a boolean`;n(t)}}function j(e,t){if(e.effort!==void 0){if(!C.includes(e.effort))return`effort: expected one of ${C.join(`, `)}`;t.effort=e.effort}if(e.autonomy!==void 0){if(!w.includes(e.autonomy))return`autonomy: expected one of ${w.join(`, `)}`;t.autonomy=e.autonomy}let n=[[`permissionMode`,e.permissionMode,e=>t.permissionMode=e],[`defaultPermissionMode`,e.defaultPermissionMode,e=>t.defaultPermissionMode=e]];for(let[e,t,r]of n)if(t!==void 0){if(!T.includes(t))return`${e}: expected one of ${T.join(`, `)}`;r(t)}if(e.defaultTrustLevel!==void 0){if(!E.includes(e.defaultTrustLevel))return`defaultTrustLevel: expected one of ${E.join(`, `)}`;t.defaultTrustLevel=e.defaultTrustLevel}}function M(e,t){let n=[[`allowedTools`,e.allowedTools,e=>t.allowedTools=e],[`deniedTools`,e.deniedTools,e=>t.deniedTools=e],[`enabledCommandModules`,e.enabledCommandModules,e=>t.enabledCommandModules=e],[`disabledCommandModules`,e.disabledCommandModules,e=>t.disabledCommandModules=e]];for(let[e,t,r]of n)if(t!==void 0){if(!O(t))return`${e}: expected an array of strings`;r(t)}}function N(e){if(!D(e))return{ok:!1,error:`preset: expected a non-null object`};let t=[[`id`,e.id],[`title`,e.title],[`description`,e.description]];for(let[e,n]of t)if(typeof n!=`string`||n.length===0)return{ok:!1,error:`${e}: expected a non-empty string`};let n={},r=k(e,n)??A(e,n)??j(e,n)??M(e,n);return r===void 0?{ok:!0,preset:{id:e.id,title:e.title,description:e.description,...n}}:{ok:!1,error:r}}function P(){return i(r(),`.robota`,`presets`)}function F(r){if(!e(r))return{loaded:[],errors:[]};let a=[],o=[],s=new Map,c=n(r).filter(e=>e.endsWith(`.json`));for(let e of c){let n=i(r,e),c;try{c=JSON.parse(t(n,`utf8`))}catch(t){a.push({file:e,error:t instanceof Error?t.message:String(t)});continue}let l=N(c);if(!l.ok){a.push({file:e,error:l.error});continue}o.push(l.preset),s.set(l.preset.id,e)}let l=m(o);for(let e of l.rejected)a.push({file:s.get(e.id)??e.id,error:e.reason});return{loaded:l.registered,errors:a}}function I(e){return F(e?.dir??P())}export{u as DEFAULT_AGENT_NAME,o as autonomousBuilderPreset,h as clearExternalPresets,P as defaultExternalPresetDir,a as defaultPreset,_ as getPreset,g as listPresets,I as loadExternalPresets,F as loadExternalPresetsFromDir,m as registerExternalPresets,x as resolvePreset,N as validateExternalPreset};
1
+ import{existsSync as e,readFileSync as t,readdirSync as n}from"node:fs";import{basename as r,extname as i,join as a}from"node:path";import{parseModelEffort as o}from"@robota-sdk/agent-framework";const s={id:`default`,title:`Default`,description:`Neutral baseline preset — no overrides; reproduces the standard agent behaviour.`},c={id:`autonomous-builder`,title:`Autonomous Builder`,description:`Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel subagents (proactive autonomous-builder persona; original English wording).`,effort:`high`,autonomy:`act-first`,enableParallelSubagents:!0,selfVerification:!0,persona:[`You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and`,`complete the task — act rather than stop to ask. Keep going through the points where a more`,`hesitant assistant would pause for confirmation, and only check in when something is genuinely`,`ambiguous or risky.`,``,`Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add`,`abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task`,`plainly needs, but resist turning a focused change into a sweeping one.`,``,`After making changes, verify your own work — run the tests, re-read the goal, and confirm the`,`result actually matches what was requested before you call it done.`,``,`Ground your claims in evidence. Before reporting progress, check each claim against an actual`,`tool result from this session; if something is not yet verified, say so plainly rather than`,`implying it is finished.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`,``,`Lead with the outcome. Report results plainly instead of narrating each step, keep formatting`,`light, and stay concise.`].join(`
2
+ `)},l={id:`careful-reviewer`,title:`Careful Reviewer`,description:`Conservative, ask-first reviewing posture — reads and plans before changing, prompts on write/exec, self-verifies, runs focused (no parallel subagents) at high effort.`,effort:`high`,autonomy:`ask-first`,enableParallelSubagents:!1,selfVerification:!0,persona:[`You are a careful, review-oriented assistant. Read and analyse before you change anything —`,`understand the surrounding code and context first, then lay out a short plan for the change and`,`wait for confirmation before you write or run things that have side effects.`,``,`When you propose a change, explain why — the reasoning behind it and the trade-offs against the`,`alternatives you considered, so the choice can be reviewed rather than taken on trust.`,``,`Stay conservative in scope. Make the change that was asked for and the detail it plainly needs;`,`do not widen the blast radius with unrequested refactors or rewrites.`,``,`Ground your claims in evidence. Before reporting progress or completion, check each claim against`,`an actual tool result from this session; if something is not yet verified, say so plainly rather`,`than implying it is done.`,``,`Be warm and honest without being sycophantic — tell people what is useful, not just what they`,`want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get`,`something wrong, own it directly, correct it, and move on.`].join(`
3
+ `)},u={id:`neutral-executor`,title:`Neutral Executor`,description:`Thin, steerable executor — follows instructions literally, minimal editorialising, strict scope, terse output; balanced autonomy, no parallel subagents, no self-verification, medium effort for predictable scripted use (neutral-alignment work-style; original English wording).`,effort:`medium`,autonomy:`balanced`,enableParallelSubagents:!1,selfVerification:!1,persona:[`Follow the system and user instructions literally. Do what was asked, the way it was asked, and`,`defer to the given instructions over your own preferences.`,``,`Editorialise as little as possible. Skip unrequested commentary, caveats, and asides — give the`,`result, not a narration of it.`,``,`Stay strictly in scope. Make only the change that was requested and the detail it plainly needs;`,`do not add adjacent refactors, comments, or features that were not asked for.`,``,`Keep output terse. Prefer the shortest response that fully answers, so the result is predictable`,`and easy to consume in a script or pipeline.`].join(`
4
+ `)},d={"ask-first":`default`,balanced:`default`,"act-first":`acceptEdits`},f=[s,c,l,u];function p(e){let t=new Set(f.map(e=>e.id)),n=[],r=[];for(let i of e){if(t.has(i.id)){r.push({id:i.id,reason:`collides with built-in preset`});continue}if(n.some(e=>e.id===i.id)){r.push({id:i.id,reason:`duplicate preset id`});continue}n.push(i)}return{accepted:n,rejected:r}}function m(e){let{id:t,title:n,description:r,...i}=e;return i}function h(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function g(e,t){if(!t)return e;let n={...e,...h(t)};return t.deniedTools!==void 0||e.deniedTools!==void 0?{...n,deniedTools:_(e.deniedTools,t.deniedTools)}:n}function _(e,t){return[...new Set([...e??[],...t??[]])]}function v(e,t,n={}){let r=e.find(e=>e.id===t);if(!r){let n=e.map(e=>e.id).join(`, `);throw Error(`Unknown preset: "${t}". Available presets: ${n}.`)}let i=m(r);return i=g(i,n.cliOverrides),i=g(i,n.explicit),b(i)}function y(e=[]){let t=[...f,...p(e).accepted];return{resolvePreset:(e,n={})=>v(t,e,n),getPreset:e=>t.find(t=>t.id===e),listPresets:()=>t.map(({id:e,title:t,description:n})=>({id:e,title:t,description:n}))}}function b(e){return e.permissionMode===void 0?e.defaultPermissionMode===void 0?e.autonomy===void 0?e:{...e,permissionMode:d[e.autonomy]}:{...e,permissionMode:e.defaultPermissionMode}:e}const x=[`ask-first`,`act-first`,`balanced`],S=[`plan`,`default`,`acceptEdits`,`bypassPermissions`];function C(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function w(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function T(e,t){let n=[[`persona`,e.persona,e=>t.persona=e],[`systemPrompt`,e.systemPrompt,e=>t.systemPrompt=e],[`appendSystemPrompt`,e.appendSystemPrompt,e=>t.appendSystemPrompt=e],[`agentName`,e.agentName,e=>t.agentName=e],[`model`,e.model,e=>t.model=e],[`language`,e.language,e=>t.language=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`string`)return`${e}: expected a string`;r(t)}}function E(e,t){let n=[[`temperature`,e.temperature,e=>t.temperature=e],[`maxOutputTokens`,e.maxOutputTokens,e=>t.maxOutputTokens=e]];for(let[e,t,r]of n)if(t!==void 0){if(typeof t!=`number`||Number.isNaN(t))return`${e}: expected a number`;r(t)}let r=[[`enableParallelSubagents`,e.enableParallelSubagents,e=>t.enableParallelSubagents=e],[`selfVerification`,e.selfVerification,e=>t.selfVerification=e]];for(let[e,t,n]of r)if(t!==void 0){if(typeof t!=`boolean`)return`${e}: expected a boolean`;n(t)}}function D(e,t){if(e.effort!==void 0){if(typeof e.effort!=`string`)return`effort: expected a string`;try{let n=o(e.effort,`effort`);if(n===void 0)return`effort: expected a Core-owned effort selection`;t.effort=n}catch(e){return`effort: ${e instanceof Error?e.message:String(e)}`}}if(e.autonomy!==void 0){if(!x.includes(e.autonomy))return`autonomy: expected one of ${x.join(`, `)}`;t.autonomy=e.autonomy}let n=[[`permissionMode`,e.permissionMode,e=>t.permissionMode=e],[`defaultPermissionMode`,e.defaultPermissionMode,e=>t.defaultPermissionMode=e]];for(let[e,t,r]of n)if(t!==void 0){if(!S.includes(t))return`${e}: expected one of ${S.join(`, `)}`;r(t)}}function O(e,t){let n=[[`allowedTools`,e.allowedTools,e=>t.allowedTools=e],[`deniedTools`,e.deniedTools,e=>t.deniedTools=e],[`enabledCommandModules`,e.enabledCommandModules,e=>t.enabledCommandModules=e],[`disabledCommandModules`,e.disabledCommandModules,e=>t.disabledCommandModules=e]];for(let[e,t,r]of n)if(t!==void 0){if(!w(t))return`${e}: expected an array of strings`;r(t)}}function k(e){if(!C(e))return{ok:!1,error:`preset: expected a non-null object`};let t=[[`id`,e.id],[`title`,e.title],[`description`,e.description]];for(let[e,n]of t)if(typeof n!=`string`||n.length===0)return{ok:!1,error:`${e}: expected a non-empty string`};let n={},r=T(e,n)??E(e,n)??D(e,n)??O(e,n);return r===void 0?{ok:!0,preset:{id:e.id,title:e.title,description:e.description,...n}}:{ok:!1,error:r}}function A(r){if(!e(r))return{presets:[],loaded:[],errors:[]};let i=[],o=[],s=new Map,c=n(r).filter(e=>e.endsWith(`.json`));for(let e of c){let n=a(r,e),c;try{c=JSON.parse(t(n,`utf8`))}catch(t){i.push({file:e,error:t instanceof Error?t.message:String(t)});continue}let l=k(c);if(!l.ok){i.push({file:e,error:l.error});continue}o.push(l.preset),s.set(l.preset.id,e)}let{accepted:l,rejected:u}=p(o);for(let e of u)i.push({file:s.get(e.id)??e.id,error:e.reason});return{presets:l,loaded:l.map(e=>e.id),errors:i}}const j=[{id:`default`,name:`Default`,description:`The ordinary response style.`,instructions:``,keepCodingInstructions:!0,tokenCost:`baseline`,source:`built-in`},{id:`concise`,name:`Concise`,description:`Lead with the result and keep routine responses short.`,instructions:`Lead with the answer and skip routine preamble or tool narration. Keep responses concise while doing the same engineering work. Expand fully when asked for detail. Always keep error reports, security warnings and destructive-action confirmations complete.`,keepCodingInstructions:!0,tokenCost:`low`,source:`built-in`},{id:`proactive`,name:`Proactive`,description:`Take the next reasonable step without pausing on routine choices.`,instructions:`Act on reasonable routine assumptions and take the next useful step. State assumptions when they matter. The active permission mode remains authoritative; this style never grants, changes, or bypasses permission.`,keepCodingInstructions:!0,tokenCost:`medium`,source:`built-in`},{id:`explanatory`,name:`Explanatory`,description:`Teach the reasoning and trade-offs behind the answer.`,instructions:`Explain the reasoning, important trade-offs, and relevant terminology as you work. Keep the explanation connected to the requested outcome and do not omit complete error, security, or destructive-action guidance.`,keepCodingInstructions:!0,tokenCost:`high`,source:`built-in`},{id:`learning`,name:`Learning`,description:`Teach by marking useful gaps for the human to fill.`,instructions:`Teach the requested subject step by step. Mark a small number of useful gaps with [Your turn:] and invite the human to fill them before revealing the explanation. Never turn safety, security, error, or destructive-action guidance into a gap.`,keepCodingInstructions:!0,tokenCost:`high`,source:`built-in`}],M=new Set([`baseline`,`low`,`medium`,`high`,`unspecified`]);function N(e){return e.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/,`$1$2`)}function P(e,t){if(t===`true`)return!0;if(t===`false`)return!1;throw Error(`${e}: expected boolean, received "${t}"`)}function F(e,t){let n=t.split(`
5
+ `);if(n[0]?.trim()!==`---`)throw Error(`frontmatter: expected an opening --- marker`);let r={},i=-1;for(let e=1;e<n.length;e+=1){let t=n[e];if(t.trim()===`---`){i=e;break}if(t.trim()===``)continue;let a=/^([a-z][a-z0-9-]*):\s*(.*)$/.exec(t);if(!a)throw Error(`frontmatter: invalid entry at line ${e+1}`);let o=a[1];if(r[o]!==void 0)throw Error(`frontmatter.${o}: duplicate field`);r[o]=N(a[2].trim())}if(i<0)throw Error(`frontmatter: expected a closing --- marker`);let a=Object.keys(r).filter(e=>![`name`,`description`,`keep-coding-instructions`,`token-cost`].includes(e));if(a.length>0)throw Error(`frontmatter.${a[0]}: unknown field`);return{values:r,instructions:n.slice(i+1).join(`
6
+ `).trim()}}function I(e){let t=r(e,i(e)).trim();if(!/^[a-z0-9][a-z0-9-]*$/i.test(t))throw Error(`id: expected the Markdown filename stem to be a slug, received "${t}"`);return t.toLowerCase()}function L(e,t){if(!e.fileName.endsWith(`.md`))throw Error(`file: expected a .md output-style file`);let n=I(e.fileName),i=F(e.fileName,e.content),a=i.values.name?.trim()||r(e.fileName,`.md`),o=i.values.description?.trim()||`Custom output style: ${a}`,s=i.values[`keep-coding-instructions`]!==void 0&&P(`frontmatter.keep-coding-instructions`,i.values[`keep-coding-instructions`]),c=i.values[`token-cost`]??`unspecified`;if(!M.has(c))throw Error(`frontmatter.token-cost: expected baseline|low|medium|high|unspecified, received "${c}"`);if(i.instructions.length===0)throw Error(`body: expected non-empty style instructions`);return{id:n,name:a,description:o,instructions:i.instructions,keepCodingInstructions:s,tokenCost:c,source:t}}function R(e){return{id:e.id,name:e.name,description:e.description,tokenCost:e.tokenCost,source:e.source}}function z(e){let t=new Map,n=[];for(let e of j)t.set(e.id,e);let r=[...e].sort((e,t)=>e.precedence-t.precedence);for(let e of r){let r=new Set;for(let i of[...e.files].sort((e,t)=>e.fileName.localeCompare(t.fileName))){let a=`${e.displayName}/${i.fileName}`,o;try{o=L(i,e.scope)}catch(e){n.push({file:a,error:e instanceof Error?e.message:String(e)});continue}if(r.has(o.id)){n.push({file:a,error:`duplicate style id "${o.id}" in source`});continue}if(r.add(o.id),t.get(o.id)?.source===`built-in`){n.push({file:a,error:`style id "${o.id}" collides with a built-in`});continue}t.set(o.id,o)}}return{styles:[...t.values()],loaded:[...t.values()].filter(e=>e.source!==`built-in`).map(e=>e.id),errors:n}}function B(e=[]){let t=z(e),n=new Map(t.styles.map(e=>[e.id,e]));return{listOutputStyles:()=>t.styles.map(R),getOutputStyle:e=>n.get(e)}}export{c as autonomousBuilderPreset,j as builtInOutputStyles,B as createOutputStyleRegistry,y as createPresetRegistry,s as defaultPreset,A as loadExternalPresetsFromDir,z as loadOutputStylesFromSources,L as parseOutputStyleFile,p as partitionExternalPresets,k as validateExternalPreset};
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/presets/default.ts","../../src/presets/autonomous-builder.ts","../../src/presets/careful-reviewer.ts","../../src/presets/neutral-executor.ts","../../src/resolve-preset.ts","../../src/preset-validation.ts","../../src/load-external-presets.ts"],"sourcesContent":["import type { IPreset } from '../preset-types.js';\n\n/**\n * The neutral baseline preset. It carries NO option overrides so that resolving it is a\n * pure no-op — applying `default` reproduces the standard agent behaviour exactly (no regression).\n * The default agent identity is owned by `DEFAULT_AGENT_NAME` in `resolve-preset.ts`, not here,\n * so that this preset stays a true identity element under merging.\n */\nexport const defaultPreset: IPreset = {\n id: 'default',\n title: 'Default',\n description: 'Neutral baseline preset — no overrides; reproduces the standard agent behaviour.',\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the autonomous-builder persona.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n */\nconst AUTONOMOUS_BUILDER_PERSONA = [\n 'You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and',\n 'complete the task — act rather than stop to ask. Keep going through the points where a more',\n 'hesitant assistant would pause for confirmation, and only check in when something is genuinely',\n 'ambiguous or risky.',\n '',\n 'Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add',\n 'abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task',\n 'plainly needs, but resist turning a focused change into a sweeping one.',\n '',\n 'After making changes, verify your own work — run the tests, re-read the goal, and confirm the',\n 'result actually matches what was requested before you call it done.',\n '',\n 'Ground your claims in evidence. Before reporting progress, check each claim against an actual',\n 'tool result from this session; if something is not yet verified, say so plainly rather than',\n 'implying it is finished.',\n '',\n 'Be warm and honest without being sycophantic — tell people what is useful, not just what they',\n 'want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get',\n 'something wrong, own it directly, correct it, and move on.',\n '',\n 'Lead with the outcome. Report results plainly instead of narrating each step, keep formatting',\n 'light, and stay concise.',\n].join('\\n');\n\n/**\n * The first opinionated built-in preset: an autonomous, self-verifying builder posture.\n *\n * It both ships a portable persona block AND sets the framework/executor mechanism flags\n * (`effort`, `autonomy`, `enableParallelSubagents`, `selfVerification`) so the style is backed\n * by real, observable behaviour rather than persona text alone. The identifier is generic; the\n * sourcing footnote in `description` is the only place a work-style attribution appears.\n *\n * For long-running tasks the effort dial may be raised to a higher tier; `'high'` is the\n * neutral default carried here.\n */\nexport const autonomousBuilderPreset: IPreset = {\n id: 'autonomous-builder',\n title: 'Autonomous Builder',\n description:\n 'Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel ' +\n 'subagents (proactive autonomous-builder persona; original English wording).',\n effort: 'high',\n autonomy: 'act-first',\n enableParallelSubagents: true,\n selfVerification: true,\n persona: AUTONOMOUS_BUILDER_PERSONA,\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the careful-reviewer persona.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n *\n * The block stays light: a few oriented traits plus a guiding posture, with no stacked emphasis\n * words and no instruction to surface raw reasoning.\n */\nconst CAREFUL_REVIEWER_PERSONA = [\n 'You are a careful, review-oriented assistant. Read and analyse before you change anything —',\n 'understand the surrounding code and context first, then lay out a short plan for the change and',\n 'wait for confirmation before you write or run things that have side effects.',\n '',\n 'When you propose a change, explain why — the reasoning behind it and the trade-offs against the',\n 'alternatives you considered, so the choice can be reviewed rather than taken on trust.',\n '',\n 'Stay conservative in scope. Make the change that was asked for and the detail it plainly needs;',\n 'do not widen the blast radius with unrequested refactors or rewrites.',\n '',\n 'Ground your claims in evidence. Before reporting progress or completion, check each claim against',\n 'an actual tool result from this session; if something is not yet verified, say so plainly rather',\n 'than implying it is done.',\n '',\n 'Be warm and honest without being sycophantic — tell people what is useful, not just what they',\n 'want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get',\n 'something wrong, own it directly, correct it, and move on.',\n].join('\\n');\n\n/**\n * An opinionated built-in preset: a conservative, ask-first reviewing posture.\n *\n * It is the deliberate counterpart to `autonomous-builder` on the autonomy axis. It both ships a\n * portable persona block AND sets the framework/executor mechanism flags so the review style is\n * backed by real, observable behaviour rather than persona text alone:\n *\n * - `autonomy: 'ask-first'` → PRESET-004 maps this onto the ask-on-write permission posture, so\n * writes/exec are prompted rather than auto-accepted.\n * - `selfVerification: true` → the framework/executor verifier loop runs before changes settle.\n * - `enableParallelSubagents: false` → focused analysis, not fan-out.\n * - `effort: 'high'` → deep reading/analysis of code and context before acting.\n *\n * The identifier is generic; no work-style attribution appears in the source.\n */\nexport const carefulReviewerPreset: IPreset = {\n id: 'careful-reviewer',\n title: 'Careful Reviewer',\n description:\n 'Conservative, ask-first reviewing posture — reads and plans before changing, prompts on ' +\n 'write/exec, self-verifies, runs focused (no parallel subagents) at high effort.',\n effort: 'high',\n autonomy: 'ask-first',\n enableParallelSubagents: false,\n selfVerification: true,\n persona: CAREFUL_REVIEWER_PERSONA,\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the neutral-executor persona — a thin, steerable posture.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n *\n * The block is intentionally minimal: follow instructions literally, editorialise little, stay in\n * scope, output tersely. No stacked emphasis words; no instruction to surface raw reasoning.\n */\nconst NEUTRAL_EXECUTOR_PERSONA = [\n 'Follow the system and user instructions literally. Do what was asked, the way it was asked, and',\n 'defer to the given instructions over your own preferences.',\n '',\n 'Editorialise as little as possible. Skip unrequested commentary, caveats, and asides — give the',\n 'result, not a narration of it.',\n '',\n 'Stay strictly in scope. Make only the change that was requested and the detail it plainly needs;',\n 'do not add adjacent refactors, comments, or features that were not asked for.',\n '',\n 'Keep output terse. Prefer the shortest response that fully answers, so the result is predictable',\n 'and easy to consume in a script or pipeline.',\n].join('\\n');\n\n/**\n * A thin, steerable built-in preset: a minimal-opinion executor that follows instructions\n * literally and keeps output predictable for automation/scripting.\n *\n * Unlike `default` (which pins behaviour in no direction), this preset actively pins a terse,\n * literal posture, AND it sets framework/executor mechanism flags so the thinness is observable\n * rather than persona text alone:\n *\n * - `autonomy: 'balanced'` → neither prompts on every write nor acts aggressively (PRESET-004\n * maps it onto the standard permission posture).\n * - `enableParallelSubagents: false` and `selfVerification: false` → minimal machinery, predictable.\n * - `effort: 'medium'` → predictable, reproducible output for scripted use.\n *\n * The identifier is generic; any work-style attribution is confined to `description`.\n */\nexport const neutralExecutorPreset: IPreset = {\n id: 'neutral-executor',\n title: 'Neutral Executor',\n description:\n 'Thin, steerable executor — follows instructions literally, minimal editorialising, strict ' +\n 'scope, terse output; balanced autonomy, no parallel subagents, no self-verification, medium ' +\n 'effort for predictable scripted use (neutral-alignment work-style; original English wording).',\n effort: 'medium',\n autonomy: 'balanced',\n enableParallelSubagents: false,\n selfVerification: false,\n persona: NEUTRAL_EXECUTOR_PERSONA,\n};\n","import { autonomousBuilderPreset } from './presets/autonomous-builder.js';\nimport { carefulReviewerPreset } from './presets/careful-reviewer.js';\nimport { defaultPreset } from './presets/default.js';\nimport { neutralExecutorPreset } from './presets/neutral-executor.js';\n\nimport type {\n IPreset,\n TPresetAutonomy,\n TPresetPermissionMode,\n IResolvedPresetOptions,\n} from './preset-types.js';\n\n/**\n * Map a behavioural {@link TPresetAutonomy} posture onto a concrete permission mode.\n *\n * `act-first` opts into `acceptEdits` (writes are not prompted every time);\n * `ask-first` and `balanced` stay on `default` (the standard ask-on-write posture).\n * Only consulted when the resolved options set `autonomy` but no explicit\n * `permissionMode`/`defaultPermissionMode`.\n */\nconst AUTONOMY_TO_PERMISSION_MODE: Record<TPresetAutonomy, TPresetPermissionMode> = {\n 'ask-first': 'default',\n balanced: 'default',\n 'act-first': 'acceptEdits',\n};\n\n/**\n * Default agent identity. Owned by `agent-preset` (not baked into `defaultPreset`, which must stay\n * a no-op). Consumers apply this when no preset and no explicit override supplies an `agentName`.\n */\nexport const DEFAULT_AGENT_NAME = 'robota-cli';\n\n/** Registry of built-in presets. Built-ins always win on id conflict and cannot be overridden. */\nconst BUILT_IN_PRESETS: readonly IPreset[] = [\n defaultPreset,\n autonomousBuilderPreset,\n carefulReviewerPreset,\n neutralExecutorPreset,\n];\n\n/**\n * Module-level mutable registry of user-authored external presets (PRESET-007).\n * Populated by {@link registerExternalPresets}; the sync readers iterate\n * `[...BUILT_IN_PRESETS, ...externalPresets]` so external presets merge with the built-ins.\n */\nconst externalPresets: IPreset[] = [];\n\n/** The merged preset registry: built-ins first, then registered external presets. */\nfunction allPresets(): readonly IPreset[] {\n return [...BUILT_IN_PRESETS, ...externalPresets];\n}\n\n/** Lightweight `{ id, title, description }` view of a preset for discovery/UX. */\nexport interface IPresetSummary {\n id: string;\n title: string;\n description: string;\n}\n\n/** Outcome of {@link registerExternalPresets}: which ids registered and which were rejected. */\nexport interface IPresetRegistrationResult {\n registered: readonly string[];\n rejected: readonly { id: string; reason: string }[];\n}\n\n/**\n * Register user-authored external presets into the module-level registry.\n *\n * Conflict policy: an external preset whose id matches a BUILT-IN preset is rejected\n * (`'collides with built-in preset'`) — built-ins always win. An external preset whose id\n * matches an already-registered external preset is rejected (`'duplicate preset id'`) — first\n * registration wins. All other presets are appended and counted as registered.\n *\n * @returns the ids that registered and the `{ id, reason }` of each rejection.\n */\nexport function registerExternalPresets(presets: readonly IPreset[]): IPresetRegistrationResult {\n const builtInIds = new Set(BUILT_IN_PRESETS.map((preset) => preset.id));\n const registered: string[] = [];\n const rejected: { id: string; reason: string }[] = [];\n\n for (const preset of presets) {\n if (builtInIds.has(preset.id)) {\n rejected.push({ id: preset.id, reason: 'collides with built-in preset' });\n continue;\n }\n if (externalPresets.some((existing) => existing.id === preset.id)) {\n rejected.push({ id: preset.id, reason: 'duplicate preset id' });\n continue;\n }\n externalPresets.push(preset);\n registered.push(preset.id);\n }\n\n return { registered, rejected };\n}\n\n/**\n * Remove every registered external preset, leaving only the built-ins.\n * Used at startup before a fresh re-load and for test isolation.\n */\nexport function clearExternalPresets(): void {\n externalPresets.length = 0;\n}\n\n/**\n * Override layers for {@link resolvePreset}, in increasing precedence.\n * `cliOverrides` model CLI flags; `explicit` models programmatic/SDK options.\n */\nexport interface IResolvePresetContext {\n cliOverrides?: IResolvedPresetOptions;\n explicit?: IResolvedPresetOptions;\n}\n\n/** Return the `{ id, title, description }` summary of every registered preset. */\nexport function listPresets(): readonly IPresetSummary[] {\n return allPresets().map(({ id, title, description }) => ({ id, title, description }));\n}\n\n/** Look up a registered preset by id, or `undefined` if none matches. */\nexport function getPreset(id: string): IPreset | undefined {\n return allPresets().find((preset) => preset.id === id);\n}\n\n/** Strip the identity triple from a preset, leaving only resolvable option overrides. */\nfunction toPresetOptions(preset: IPreset): IResolvedPresetOptions {\n const { id: _id, title: _title, description: _description, ...options } = preset;\n return options;\n}\n\n/** Keep only the entries of `source` whose value is defined. */\nfunction definedEntries(source: IResolvedPresetOptions): Partial<IResolvedPresetOptions> {\n return Object.fromEntries(Object.entries(source).filter(([, value]) => value !== undefined));\n}\n\n/** Merge `source` onto `target`, skipping `undefined` values so later layers only override set keys. */\nfunction mergeDefined(\n target: IResolvedPresetOptions,\n source: IResolvedPresetOptions | undefined,\n): IResolvedPresetOptions {\n if (!source) {\n return target;\n }\n return { ...target, ...definedEntries(source) };\n}\n\n/**\n * Resolve a preset id into framework option overrides.\n *\n * Precedence LOW → HIGH: preset options < `context.cliOverrides` < `context.explicit`\n * (later layers win; `undefined` values are skipped). For the no-op `'default'` preset the\n * result equals the merged overrides, guaranteeing no regression.\n *\n * @throws Error when `id` does not match a registered preset.\n */\nexport function resolvePreset(\n id: string,\n context: IResolvePresetContext = {},\n): IResolvedPresetOptions {\n const preset = getPreset(id);\n if (!preset) {\n const available = allPresets()\n .map((p) => p.id)\n .join(', ');\n throw new Error(`Unknown preset: \"${id}\". Available presets: ${available}.`);\n }\n\n let resolved = toPresetOptions(preset);\n resolved = mergeDefined(resolved, context.cliOverrides);\n resolved = mergeDefined(resolved, context.explicit);\n return derivePermissionMode(resolved);\n}\n\n/**\n * Fill the framework `permissionMode` seam from the preset's posture fields when it\n * is not already set. Precedence: explicit `permissionMode` (untouched) >\n * `defaultPermissionMode` > `autonomy` mapping. A no-op preset (no posture fields)\n * leaves the object unchanged — keeping `resolvePreset('default')` a no-op.\n */\nfunction derivePermissionMode(resolved: IResolvedPresetOptions): IResolvedPresetOptions {\n if (resolved.permissionMode !== undefined) {\n return resolved;\n }\n if (resolved.defaultPermissionMode !== undefined) {\n return { ...resolved, permissionMode: resolved.defaultPermissionMode };\n }\n if (resolved.autonomy !== undefined) {\n return { ...resolved, permissionMode: AUTONOMY_TO_PERMISSION_MODE[resolved.autonomy] };\n }\n return resolved;\n}\n","import type {\n IPreset,\n TPresetAutonomy,\n TPresetEffort,\n TPresetPermissionMode,\n TPresetTrustLevel,\n IResolvedPresetOptions,\n} from './preset-types.js';\n\n/** Result of {@link validateExternalPreset}: the validated preset, or a single error message. */\nexport type TPresetValidationResult = { ok: true; preset: IPreset } | { ok: false; error: string };\n\n/** Runtime membership list for {@link TPresetEffort}. */\nconst EFFORT_VALUES: readonly TPresetEffort[] = ['low', 'medium', 'high', 'xhigh', 'max'];\n\n/** Runtime membership list for {@link TPresetAutonomy}. */\nconst AUTONOMY_VALUES: readonly TPresetAutonomy[] = ['ask-first', 'act-first', 'balanced'];\n\n/** Runtime membership list for {@link TPresetPermissionMode}. */\nconst PERMISSION_MODE_VALUES: readonly TPresetPermissionMode[] = [\n 'plan',\n 'default',\n 'acceptEdits',\n 'bypassPermissions',\n];\n\n/** Runtime membership list for {@link TPresetTrustLevel}. */\nconst TRUST_LEVEL_VALUES: readonly TPresetTrustLevel[] = ['safe', 'moderate', 'full'];\n\n/** Narrowing guard: `value` is a non-null, non-array object. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Narrowing guard: `value` is an array whose every element is a string. */\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string');\n}\n\n/** Validate the string-typed optional fields onto `options`; return the first error, if any. */\nfunction validateStringFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const fields: readonly [string, unknown, (v: string) => void][] = [\n ['persona', value.persona, (v) => (options.persona = v)],\n ['systemPrompt', value.systemPrompt, (v) => (options.systemPrompt = v)],\n ['appendSystemPrompt', value.appendSystemPrompt, (v) => (options.appendSystemPrompt = v)],\n ['agentName', value.agentName, (v) => (options.agentName = v)],\n ['model', value.model, (v) => (options.model = v)],\n ['language', value.language, (v) => (options.language = v)],\n ];\n for (const [field, raw, assign] of fields) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'string') {\n return `${field}: expected a string`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/** Validate the number- and boolean-typed optional fields onto `options`; return the first error. */\nfunction validateScalarFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const numbers: readonly [string, unknown, (v: number) => void][] = [\n ['temperature', value.temperature, (v) => (options.temperature = v)],\n ['maxOutputTokens', value.maxOutputTokens, (v) => (options.maxOutputTokens = v)],\n ];\n for (const [field, raw, assign] of numbers) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'number' || Number.isNaN(raw)) {\n return `${field}: expected a number`;\n }\n assign(raw);\n }\n\n const booleans: readonly [string, unknown, (v: boolean) => void][] = [\n [\n 'enableParallelSubagents',\n value.enableParallelSubagents,\n (v) => (options.enableParallelSubagents = v),\n ],\n ['selfVerification', value.selfVerification, (v) => (options.selfVerification = v)],\n ];\n for (const [field, raw, assign] of booleans) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'boolean') {\n return `${field}: expected a boolean`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/** Validate the enum-typed optional fields onto `options`; return the first error, if any. */\nfunction validateEnumFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n if (value.effort !== undefined) {\n if (!EFFORT_VALUES.includes(value.effort as TPresetEffort)) {\n return `effort: expected one of ${EFFORT_VALUES.join(', ')}`;\n }\n options.effort = value.effort as TPresetEffort;\n }\n\n if (value.autonomy !== undefined) {\n if (!AUTONOMY_VALUES.includes(value.autonomy as TPresetAutonomy)) {\n return `autonomy: expected one of ${AUTONOMY_VALUES.join(', ')}`;\n }\n options.autonomy = value.autonomy as TPresetAutonomy;\n }\n\n const modes: readonly [string, unknown, (v: TPresetPermissionMode) => void][] = [\n ['permissionMode', value.permissionMode, (v) => (options.permissionMode = v)],\n [\n 'defaultPermissionMode',\n value.defaultPermissionMode,\n (v) => (options.defaultPermissionMode = v),\n ],\n ];\n for (const [field, raw, assign] of modes) {\n if (raw === undefined) {\n continue;\n }\n if (!PERMISSION_MODE_VALUES.includes(raw as TPresetPermissionMode)) {\n return `${field}: expected one of ${PERMISSION_MODE_VALUES.join(', ')}`;\n }\n assign(raw as TPresetPermissionMode);\n }\n\n if (value.defaultTrustLevel !== undefined) {\n if (!TRUST_LEVEL_VALUES.includes(value.defaultTrustLevel as TPresetTrustLevel)) {\n return `defaultTrustLevel: expected one of ${TRUST_LEVEL_VALUES.join(', ')}`;\n }\n options.defaultTrustLevel = value.defaultTrustLevel as TPresetTrustLevel;\n }\n return undefined;\n}\n\n/** Validate the string-array optional fields onto `options`; return the first error, if any. */\nfunction validateArrayFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const arrays: readonly [string, unknown, (v: readonly string[]) => void][] = [\n ['allowedTools', value.allowedTools, (v) => (options.allowedTools = v)],\n ['deniedTools', value.deniedTools, (v) => (options.deniedTools = v)],\n [\n 'enabledCommandModules',\n value.enabledCommandModules,\n (v) => (options.enabledCommandModules = v),\n ],\n [\n 'disabledCommandModules',\n value.disabledCommandModules,\n (v) => (options.disabledCommandModules = v),\n ],\n ];\n for (const [field, raw, assign] of arrays) {\n if (raw === undefined) {\n continue;\n }\n if (!isStringArray(raw)) {\n return `${field}: expected an array of strings`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/**\n * Manually validate an unknown value as an {@link IPreset} (no schema library).\n *\n * Required fields: non-empty `id`, `title`, `description` strings. Every other field is\n * optional and is validated only when present; an unrecognised field is dropped (the built\n * preset carries the recognised fields only, never unknown keys). On the first failed check\n * returns `{ ok: false, error: '<field>: <reason>' }`.\n */\nexport function validateExternalPreset(value: unknown): TPresetValidationResult {\n if (!isPlainObject(value)) {\n return { ok: false, error: 'preset: expected a non-null object' };\n }\n\n const requiredStrings: readonly ['id' | 'title' | 'description', unknown][] = [\n ['id', value.id],\n ['title', value.title],\n ['description', value.description],\n ];\n for (const [field, raw] of requiredStrings) {\n if (typeof raw !== 'string' || raw.length === 0) {\n return { ok: false, error: `${field}: expected a non-empty string` };\n }\n }\n\n // Accumulate recognised optional fields here, then spread onto the identity triple so the\n // built preset never carries unknown keys.\n const options: IResolvedPresetOptions = {};\n const error =\n validateStringFields(value, options) ??\n validateScalarFields(value, options) ??\n validateEnumFields(value, options) ??\n validateArrayFields(value, options);\n if (error !== undefined) {\n return { ok: false, error };\n }\n\n const preset: IPreset = {\n id: value.id as string,\n title: value.title as string,\n description: value.description as string,\n ...options,\n };\n return { ok: true, preset };\n}\n","import { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nimport { validateExternalPreset } from './preset-validation.js';\nimport { registerExternalPresets } from './resolve-preset.js';\n\nimport type { IPreset } from './preset-types.js';\n\n/** Outcome of an external-preset load: which ids loaded and per-file load/validation errors. */\nexport interface IExternalPresetLoadResult {\n loaded: readonly string[];\n errors: readonly { file: string; error: string }[];\n}\n\n/** Conventional external-preset directory: `~/.robota/presets`. */\nexport function defaultExternalPresetDir(): string {\n return join(homedir(), '.robota', 'presets');\n}\n\n/**\n * Load, validate, and register every `*.json` external preset from `dir`.\n *\n * A missing directory yields an empty result (no error). Each file is JSON-parsed and validated;\n * a parse or validation failure is recorded as a per-file error and skipped — the remaining files\n * still load. Validated presets are registered via {@link registerExternalPresets}; registry\n * rejections (built-in id collision or duplicate id) are folded into `errors` against their file.\n */\nexport function loadExternalPresetsFromDir(dir: string): IExternalPresetLoadResult {\n if (!existsSync(dir)) {\n return { loaded: [], errors: [] };\n }\n\n const errors: { file: string; error: string }[] = [];\n const validPresets: IPreset[] = [];\n // Track which file each validated preset id came from so registry rejections map back to a file.\n const fileById = new Map<string, string>();\n\n const jsonFiles = readdirSync(dir).filter((name) => name.endsWith('.json'));\n for (const name of jsonFiles) {\n const filePath = join(dir, name);\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(filePath, 'utf8'));\n } catch (error) {\n // allow-fallback: a malformed file is reported per-file and skipped, not silently swallowed\n errors.push({ file: name, error: error instanceof Error ? error.message : String(error) });\n continue;\n }\n\n const result = validateExternalPreset(parsed);\n if (!result.ok) {\n errors.push({ file: name, error: result.error });\n continue;\n }\n\n validPresets.push(result.preset);\n fileById.set(result.preset.id, name);\n }\n\n const registration = registerExternalPresets(validPresets);\n for (const rejection of registration.rejected) {\n errors.push({ file: fileById.get(rejection.id) ?? rejection.id, error: rejection.reason });\n }\n\n return { loaded: registration.registered, errors };\n}\n\n/**\n * Load external presets from the conventional directory (or `options.dir` when given).\n * Thin wrapper over {@link loadExternalPresetsFromDir}.\n */\nexport function loadExternalPresets(options?: { dir?: string }): IExternalPresetLoadResult {\n const dir = options?.dir ?? defaultExternalPresetDir();\n return loadExternalPresetsFromDir(dir);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/presets/default.ts","../../src/presets/autonomous-builder.ts","../../src/presets/careful-reviewer.ts","../../src/presets/neutral-executor.ts","../../src/resolve-preset.ts","../../src/preset-validation.ts","../../src/load-external-presets.ts","../../src/output-styles.ts","../../src/output-style-registry.ts"],"sourcesContent":["import type { IPreset } from '../preset-types.js';\n\n/**\n * The neutral baseline preset. It carries NO option overrides so that resolving it is a\n * pure no-op — applying `default` reproduces the standard agent behaviour exactly (no regression).\n * The default agent identity is chosen by the product shell, not here,\n * so that this preset stays a true identity element under merging.\n */\nexport const defaultPreset: IPreset = {\n id: 'default',\n title: 'Default',\n description: 'Neutral baseline preset — no overrides; reproduces the standard agent behaviour.',\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the autonomous-builder persona.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n */\nconst AUTONOMOUS_BUILDER_PERSONA = [\n 'You are a proactive, high-autonomy builder. When you have enough to proceed, proceed and',\n 'complete the task — act rather than stop to ask. Keep going through the points where a more',\n 'hesitant assistant would pause for confirmation, and only check in when something is genuinely',\n 'ambiguous or risky.',\n '',\n 'Stay inside the scope of the task. Do the simplest thing that works; do not refactor, add',\n 'abstractions, or expand scope beyond what was asked. Handle the adjacent detail that the task',\n 'plainly needs, but resist turning a focused change into a sweeping one.',\n '',\n 'After making changes, verify your own work — run the tests, re-read the goal, and confirm the',\n 'result actually matches what was requested before you call it done.',\n '',\n 'Ground your claims in evidence. Before reporting progress, check each claim against an actual',\n 'tool result from this session; if something is not yet verified, say so plainly rather than',\n 'implying it is finished.',\n '',\n 'Be warm and honest without being sycophantic — tell people what is useful, not just what they',\n 'want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get',\n 'something wrong, own it directly, correct it, and move on.',\n '',\n 'Lead with the outcome. Report results plainly instead of narrating each step, keep formatting',\n 'light, and stay concise.',\n].join('\\n');\n\n/**\n * The first opinionated built-in preset: an autonomous, self-verifying builder posture.\n *\n * It both ships a portable persona block AND sets the framework/executor mechanism flags\n * (`effort`, `autonomy`, `enableParallelSubagents`, `selfVerification`) so the style is backed\n * by real, observable behaviour rather than persona text alone. The identifier is generic; the\n * sourcing footnote in `description` is the only place a work-style attribution appears.\n *\n * For long-running tasks the effort dial may be raised to a higher tier; `'high'` is the\n * neutral default carried here.\n */\nexport const autonomousBuilderPreset: IPreset = {\n id: 'autonomous-builder',\n title: 'Autonomous Builder',\n description:\n 'Proactive, self-verifying builder posture — high effort, acts first, dispatches parallel ' +\n 'subagents (proactive autonomous-builder persona; original English wording).',\n effort: 'high',\n autonomy: 'act-first',\n enableParallelSubagents: true,\n selfVerification: true,\n persona: AUTONOMOUS_BUILDER_PERSONA,\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the careful-reviewer persona.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n *\n * The block stays light: a few oriented traits plus a guiding posture, with no stacked emphasis\n * words and no instruction to surface raw reasoning.\n */\nconst CAREFUL_REVIEWER_PERSONA = [\n 'You are a careful, review-oriented assistant. Read and analyse before you change anything —',\n 'understand the surrounding code and context first, then lay out a short plan for the change and',\n 'wait for confirmation before you write or run things that have side effects.',\n '',\n 'When you propose a change, explain why — the reasoning behind it and the trade-offs against the',\n 'alternatives you considered, so the choice can be reviewed rather than taken on trust.',\n '',\n 'Stay conservative in scope. Make the change that was asked for and the detail it plainly needs;',\n 'do not widen the blast radius with unrequested refactors or rewrites.',\n '',\n 'Ground your claims in evidence. Before reporting progress or completion, check each claim against',\n 'an actual tool result from this session; if something is not yet verified, say so plainly rather',\n 'than implying it is done.',\n '',\n 'Be warm and honest without being sycophantic — tell people what is useful, not just what they',\n 'want to hear. Stay even-handed and let your conclusions follow from the evidence. When you get',\n 'something wrong, own it directly, correct it, and move on.',\n].join('\\n');\n\n/**\n * An opinionated built-in preset: a conservative, ask-first reviewing posture.\n *\n * It is the deliberate counterpart to `autonomous-builder` on the autonomy axis. It both ships a\n * portable persona block AND sets the framework/executor mechanism flags so the review style is\n * backed by real, observable behaviour rather than persona text alone:\n *\n * - `autonomy: 'ask-first'` → PRESET-004 maps this onto the ask-on-write permission posture, so\n * writes/exec are prompted rather than auto-accepted.\n * - `selfVerification: true` → the framework/executor verifier loop runs before changes settle.\n * - `enableParallelSubagents: false` → focused analysis, not fan-out.\n * - `effort: 'high'` → deep reading/analysis of code and context before acting.\n *\n * The identifier is generic; no work-style attribution appears in the source.\n */\nexport const carefulReviewerPreset: IPreset = {\n id: 'careful-reviewer',\n title: 'Careful Reviewer',\n description:\n 'Conservative, ask-first reviewing posture — reads and plans before changing, prompts on ' +\n 'write/exec, self-verifies, runs focused (no parallel subagents) at high effort.',\n effort: 'high',\n autonomy: 'ask-first',\n enableParallelSubagents: false,\n selfVerification: true,\n persona: CAREFUL_REVIEWER_PERSONA,\n};\n","import type { IPreset } from '../preset-types.js';\n\n/**\n * Portable behavioural principles for the neutral-executor persona — a thin, steerable posture.\n *\n * Authored in our own English wording (paraphrase, not a verbatim copy of any external prompt)\n * and scoped to the PERSONA layer only. It carries no runtime/environment content — working\n * directory, tool schemas, product identity, dates, and permission text remain the framework\n * RUNTIME layer's responsibility (composed after this block by `buildSystemPrompt`).\n *\n * The block is intentionally minimal: follow instructions literally, editorialise little, stay in\n * scope, output tersely. No stacked emphasis words; no instruction to surface raw reasoning.\n */\nconst NEUTRAL_EXECUTOR_PERSONA = [\n 'Follow the system and user instructions literally. Do what was asked, the way it was asked, and',\n 'defer to the given instructions over your own preferences.',\n '',\n 'Editorialise as little as possible. Skip unrequested commentary, caveats, and asides — give the',\n 'result, not a narration of it.',\n '',\n 'Stay strictly in scope. Make only the change that was requested and the detail it plainly needs;',\n 'do not add adjacent refactors, comments, or features that were not asked for.',\n '',\n 'Keep output terse. Prefer the shortest response that fully answers, so the result is predictable',\n 'and easy to consume in a script or pipeline.',\n].join('\\n');\n\n/**\n * A thin, steerable built-in preset: a minimal-opinion executor that follows instructions\n * literally and keeps output predictable for automation/scripting.\n *\n * Unlike `default` (which pins behaviour in no direction), this preset actively pins a terse,\n * literal posture, AND it sets framework/executor mechanism flags so the thinness is observable\n * rather than persona text alone:\n *\n * - `autonomy: 'balanced'` → neither prompts on every write nor acts aggressively (PRESET-004\n * maps it onto the standard permission posture).\n * - `enableParallelSubagents: false` and `selfVerification: false` → minimal machinery, predictable.\n * - `effort: 'medium'` → predictable, reproducible output for scripted use.\n *\n * The identifier is generic; any work-style attribution is confined to `description`.\n */\nexport const neutralExecutorPreset: IPreset = {\n id: 'neutral-executor',\n title: 'Neutral Executor',\n description:\n 'Thin, steerable executor — follows instructions literally, minimal editorialising, strict ' +\n 'scope, terse output; balanced autonomy, no parallel subagents, no self-verification, medium ' +\n 'effort for predictable scripted use (neutral-alignment work-style; original English wording).',\n effort: 'medium',\n autonomy: 'balanced',\n enableParallelSubagents: false,\n selfVerification: false,\n persona: NEUTRAL_EXECUTOR_PERSONA,\n};\n","import { autonomousBuilderPreset } from './presets/autonomous-builder.js';\nimport { carefulReviewerPreset } from './presets/careful-reviewer.js';\nimport { defaultPreset } from './presets/default.js';\nimport { neutralExecutorPreset } from './presets/neutral-executor.js';\n\nimport type {\n IPreset,\n TPresetAutonomy,\n TPresetPermissionMode,\n IResolvedPresetOptions,\n} from './preset-types.js';\n\n/**\n * Map a behavioural {@link TPresetAutonomy} posture onto a concrete permission mode.\n *\n * `act-first` opts into `acceptEdits` (writes are not prompted every time);\n * `ask-first` and `balanced` stay on `default` (the standard ask-on-write posture).\n * Only consulted when the resolved options set `autonomy` but no explicit\n * `permissionMode`/`defaultPermissionMode`.\n */\nconst AUTONOMY_TO_PERMISSION_MODE: Record<TPresetAutonomy, TPresetPermissionMode> = {\n 'ask-first': 'default',\n balanced: 'default',\n 'act-first': 'acceptEdits',\n};\n\n/** Registry of built-in presets. Built-ins always win on id conflict and cannot be overridden. */\nconst BUILT_IN_PRESETS: readonly IPreset[] = [\n defaultPreset,\n autonomousBuilderPreset,\n carefulReviewerPreset,\n neutralExecutorPreset,\n];\n\n/** Lightweight `{ id, title, description }` view of a preset for discovery/UX. */\nexport interface IPresetSummary {\n id: string;\n title: string;\n description: string;\n}\n\n/** Outcome of {@link partitionExternalPresets}: which presets were accepted and which rejected. */\nexport interface IPresetRegistrationResult {\n accepted: readonly IPreset[];\n rejected: readonly { id: string; reason: string }[];\n}\n\n/**\n * Apply the external-preset conflict policy to one list, reading and mutating NOTHING outside it.\n *\n * Conflict policy: an external preset whose id matches a BUILT-IN preset is rejected\n * (`'collides with built-in preset'`) — built-ins always win. An external preset whose id matches an\n * earlier ACCEPTED external preset is rejected (`'duplicate preset id'`) — first one wins.\n *\n * ARCH-009. This is the whole of what the module-global registry used to be, minus the register:\n * the policy was never the process's to hold, only the list it was applied to was. Both callers —\n * {@link createPresetRegistry} and the external-preset loader — now pass their own list, so two\n * products in one process cannot see each other's presets, and a repeated load cannot accumulate.\n */\nexport function partitionExternalPresets(presets: readonly IPreset[]): IPresetRegistrationResult {\n const builtInIds = new Set(BUILT_IN_PRESETS.map((preset) => preset.id));\n const accepted: IPreset[] = [];\n const rejected: { id: string; reason: string }[] = [];\n\n for (const preset of presets) {\n if (builtInIds.has(preset.id)) {\n rejected.push({ id: preset.id, reason: 'collides with built-in preset' });\n continue;\n }\n if (accepted.some((existing) => existing.id === preset.id)) {\n rejected.push({ id: preset.id, reason: 'duplicate preset id' });\n continue;\n }\n accepted.push(preset);\n }\n\n return { accepted, rejected };\n}\n\n/**\n * Override layers for {@link resolvePreset}, in increasing precedence.\n * `cliOverrides` model CLI flags; `explicit` models programmatic/SDK options.\n */\nexport interface IResolvePresetContext {\n cliOverrides?: IResolvedPresetOptions;\n explicit?: IResolvedPresetOptions;\n}\n\n/** Strip the identity triple from a preset, leaving only resolvable option overrides. */\nfunction toPresetOptions(preset: IPreset): IResolvedPresetOptions {\n const { id: _id, title: _title, description: _description, ...options } = preset;\n return options;\n}\n\n/** Keep only the entries of `source` whose value is defined. */\nfunction definedEntries(source: IResolvedPresetOptions): Partial<IResolvedPresetOptions> {\n return Object.fromEntries(Object.entries(source).filter(([, value]) => value !== undefined));\n}\n\n/**\n * Merge `source` onto `target`, skipping `undefined` values so later layers only override set keys.\n *\n * ARCH-040 Group C (issue #1934): the two tool lists combine differently, and the difference is the\n * decision rather than an implementation detail.\n *\n * - **`allowedTools` REPLACES.** An allowlist is a statement of the COMPLETE permitted set, so a\n * later, more specific layer stating one supersedes the earlier answer. Intersecting would let an\n * earlier layer veto a tool the operator just named, and unioning would let it smuggle one in.\n * - **`deniedTools` UNIONS.** A denial is not weakened by a later layer that forgot to repeat it —\n * forgetting is the common case, and the cost of the two mistakes is not symmetric.\n *\n * This lives HERE, in the resolver, because precedence is the resolver's job: a union applied by one\n * of three shells is a rule the other two disagree with, which is the class ARCH-013 exists over.\n */\nfunction mergeDefined(\n target: IResolvedPresetOptions,\n source: IResolvedPresetOptions | undefined,\n): IResolvedPresetOptions {\n if (!source) {\n return target;\n }\n const merged = { ...target, ...definedEntries(source) };\n return source.deniedTools !== undefined || target.deniedTools !== undefined\n ? { ...merged, deniedTools: unionTools(target.deniedTools, source.deniedTools) }\n : merged;\n}\n\n/** Every denial either layer stated, order preserved and duplicates dropped. */\nfunction unionTools(\n earlier: readonly string[] | undefined,\n later: readonly string[] | undefined,\n): string[] {\n return [...new Set([...(earlier ?? []), ...(later ?? [])])];\n}\n\n/**\n * Pure resolve over an explicit preset list — the core every {@link createPresetRegistry} instance\n * resolves through. Reads only its arguments; performs the precedence merge + permission-mode\n * derivation.\n *\n * Precedence LOW → HIGH: preset options < `context.cliOverrides` < `context.explicit` (later layers\n * win; `undefined` values are skipped). For the no-op `'default'` preset the result equals the\n * merged overrides.\n *\n * @throws Error when `id` does not match a preset in `presets`.\n */\nfunction resolvePresetFrom(\n presets: readonly IPreset[],\n id: string,\n context: IResolvePresetContext = {},\n): IResolvedPresetOptions {\n const preset = presets.find((p) => p.id === id);\n if (!preset) {\n const available = presets.map((p) => p.id).join(', ');\n throw new Error(`Unknown preset: \"${id}\". Available presets: ${available}.`);\n }\n\n let resolved = toPresetOptions(preset);\n resolved = mergeDefined(resolved, context.cliOverrides);\n resolved = mergeDefined(resolved, context.explicit);\n return derivePermissionMode(resolved);\n}\n\n/**\n * A per-call, instance-scoped preset registry (ARCH-005 R8) — since ARCH-009 the ONLY one there is.\n *\n * A registry holds its own merged list `[built-ins, ...accepted externals]`, so two products in one\n * process do not share one and repeat construction does not accumulate. The\n * `@robota-sdk/agent-product` assembler builds one per `assembleProduct` call and surfaces it on the\n * command-host context, which is how `/preset` inside a live session reaches THIS product's presets\n * rather than the process's.\n */\nexport interface IPresetRegistry {\n /** Resolve a preset id against this registry's presets. */\n resolvePreset(id: string, context?: IResolvePresetContext): IResolvedPresetOptions;\n /** Look up a preset by id within this registry, or `undefined`. */\n getPreset(id: string): IPreset | undefined;\n /** `{ id, title, description }` summaries of every preset in this registry. */\n listPresets(): readonly IPresetSummary[];\n}\n\n/**\n * Build an instance-scoped {@link IPresetRegistry} over `[built-ins, ...externalPresets]`.\n *\n * The conflict policy is {@link partitionExternalPresets}, applied to the argument list only: built-ins\n * always win, and among the external presets the first one wins. No module-level state is read or\n * mutated — this is a pure factory, and since ARCH-009 there is no module-level state to read.\n *\n * Called with no argument it is the BUILT-INS, which is the registry a host that supplies none gets.\n */\nexport function createPresetRegistry(externalPresets: readonly IPreset[] = []): IPresetRegistry {\n const merged: readonly IPreset[] = [\n ...BUILT_IN_PRESETS,\n ...partitionExternalPresets(externalPresets).accepted,\n ];\n\n return {\n resolvePreset: (id, context = {}) => resolvePresetFrom(merged, id, context),\n getPreset: (id) => merged.find((preset) => preset.id === id),\n listPresets: () => merged.map(({ id, title, description }) => ({ id, title, description })),\n };\n}\n\n/**\n * Fill the framework `permissionMode` seam from the preset's posture fields when it\n * is not already set. Precedence: explicit `permissionMode` (untouched) >\n * `defaultPermissionMode` > `autonomy` mapping. A no-op preset (no posture fields)\n * leaves the object unchanged — keeping `resolvePreset('default')` a no-op.\n */\nfunction derivePermissionMode(resolved: IResolvedPresetOptions): IResolvedPresetOptions {\n if (resolved.permissionMode !== undefined) {\n return resolved;\n }\n if (resolved.defaultPermissionMode !== undefined) {\n return { ...resolved, permissionMode: resolved.defaultPermissionMode };\n }\n if (resolved.autonomy !== undefined) {\n return { ...resolved, permissionMode: AUTONOMY_TO_PERMISSION_MODE[resolved.autonomy] };\n }\n return resolved;\n}\n","import { parseModelEffort } from '@robota-sdk/agent-framework';\n\nimport type {\n IPreset,\n TPresetAutonomy,\n TPresetPermissionMode,\n IResolvedPresetOptions,\n} from './preset-types.js';\n\n/** Result of {@link validateExternalPreset}: the validated preset, or a single error message. */\nexport type TPresetValidationResult = { ok: true; preset: IPreset } | { ok: false; error: string };\n\n/** Runtime membership list for {@link TPresetAutonomy}. */\nconst AUTONOMY_VALUES: readonly TPresetAutonomy[] = ['ask-first', 'act-first', 'balanced'];\n\n/** Runtime membership list for {@link TPresetPermissionMode}. */\nconst PERMISSION_MODE_VALUES: readonly TPresetPermissionMode[] = [\n 'plan',\n 'default',\n 'acceptEdits',\n 'bypassPermissions',\n];\n\n/** Narrowing guard: `value` is a non-null, non-array object. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Narrowing guard: `value` is an array whose every element is a string. */\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string');\n}\n\n/** Validate the string-typed optional fields onto `options`; return the first error, if any. */\nfunction validateStringFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const fields: readonly [string, unknown, (v: string) => void][] = [\n ['persona', value.persona, (v) => (options.persona = v)],\n ['systemPrompt', value.systemPrompt, (v) => (options.systemPrompt = v)],\n ['appendSystemPrompt', value.appendSystemPrompt, (v) => (options.appendSystemPrompt = v)],\n ['agentName', value.agentName, (v) => (options.agentName = v)],\n ['model', value.model, (v) => (options.model = v)],\n ['language', value.language, (v) => (options.language = v)],\n ];\n for (const [field, raw, assign] of fields) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'string') {\n return `${field}: expected a string`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/** Validate the number- and boolean-typed optional fields onto `options`; return the first error. */\nfunction validateScalarFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const numbers: readonly [string, unknown, (v: number) => void][] = [\n ['temperature', value.temperature, (v) => (options.temperature = v)],\n ['maxOutputTokens', value.maxOutputTokens, (v) => (options.maxOutputTokens = v)],\n ];\n for (const [field, raw, assign] of numbers) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'number' || Number.isNaN(raw)) {\n return `${field}: expected a number`;\n }\n assign(raw);\n }\n\n const booleans: readonly [string, unknown, (v: boolean) => void][] = [\n [\n 'enableParallelSubagents',\n value.enableParallelSubagents,\n (v) => (options.enableParallelSubagents = v),\n ],\n ['selfVerification', value.selfVerification, (v) => (options.selfVerification = v)],\n ];\n for (const [field, raw, assign] of booleans) {\n if (raw === undefined) {\n continue;\n }\n if (typeof raw !== 'boolean') {\n return `${field}: expected a boolean`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/** Validate the enum-typed optional fields onto `options`; return the first error, if any. */\nfunction validateEnumFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n if (value.effort !== undefined) {\n if (typeof value.effort !== 'string') {\n return 'effort: expected a string';\n }\n try {\n const effort = parseModelEffort(value.effort, 'effort');\n if (effort === undefined) {\n return 'effort: expected a Core-owned effort selection';\n }\n options.effort = effort;\n } catch (error) {\n return `effort: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n\n if (value.autonomy !== undefined) {\n if (!AUTONOMY_VALUES.includes(value.autonomy as TPresetAutonomy)) {\n return `autonomy: expected one of ${AUTONOMY_VALUES.join(', ')}`;\n }\n options.autonomy = value.autonomy as TPresetAutonomy;\n }\n\n const modes: readonly [string, unknown, (v: TPresetPermissionMode) => void][] = [\n ['permissionMode', value.permissionMode, (v) => (options.permissionMode = v)],\n [\n 'defaultPermissionMode',\n value.defaultPermissionMode,\n (v) => (options.defaultPermissionMode = v),\n ],\n ];\n for (const [field, raw, assign] of modes) {\n if (raw === undefined) {\n continue;\n }\n if (!PERMISSION_MODE_VALUES.includes(raw as TPresetPermissionMode)) {\n return `${field}: expected one of ${PERMISSION_MODE_VALUES.join(', ')}`;\n }\n assign(raw as TPresetPermissionMode);\n }\n\n return undefined;\n}\n\n/** Validate the string-array optional fields onto `options`; return the first error, if any. */\nfunction validateArrayFields(\n value: Record<string, unknown>,\n options: IResolvedPresetOptions,\n): string | undefined {\n const arrays: readonly [string, unknown, (v: readonly string[]) => void][] = [\n ['allowedTools', value.allowedTools, (v) => (options.allowedTools = v)],\n ['deniedTools', value.deniedTools, (v) => (options.deniedTools = v)],\n [\n 'enabledCommandModules',\n value.enabledCommandModules,\n (v) => (options.enabledCommandModules = v),\n ],\n [\n 'disabledCommandModules',\n value.disabledCommandModules,\n (v) => (options.disabledCommandModules = v),\n ],\n ];\n for (const [field, raw, assign] of arrays) {\n if (raw === undefined) {\n continue;\n }\n if (!isStringArray(raw)) {\n return `${field}: expected an array of strings`;\n }\n assign(raw);\n }\n return undefined;\n}\n\n/**\n * Manually validate an unknown value as an {@link IPreset} (no schema library).\n *\n * Required fields: non-empty `id`, `title`, `description` strings. Every other field is\n * optional and is validated only when present; an unrecognised field is dropped (the built\n * preset carries the recognised fields only, never unknown keys). On the first failed check\n * returns `{ ok: false, error: '<field>: <reason>' }`.\n */\nexport function validateExternalPreset(value: unknown): TPresetValidationResult {\n if (!isPlainObject(value)) {\n return { ok: false, error: 'preset: expected a non-null object' };\n }\n\n const requiredStrings: readonly ['id' | 'title' | 'description', unknown][] = [\n ['id', value.id],\n ['title', value.title],\n ['description', value.description],\n ];\n for (const [field, raw] of requiredStrings) {\n if (typeof raw !== 'string' || raw.length === 0) {\n return { ok: false, error: `${field}: expected a non-empty string` };\n }\n }\n\n // Accumulate recognised optional fields here, then spread onto the identity triple so the\n // built preset never carries unknown keys.\n const options: IResolvedPresetOptions = {};\n const error =\n validateStringFields(value, options) ??\n validateScalarFields(value, options) ??\n validateEnumFields(value, options) ??\n validateArrayFields(value, options);\n if (error !== undefined) {\n return { ok: false, error };\n }\n\n const preset: IPreset = {\n id: value.id as string,\n title: value.title as string,\n description: value.description as string,\n ...options,\n };\n return { ok: true, preset };\n}\n","import { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { validateExternalPreset } from './preset-validation.js';\nimport { partitionExternalPresets } from './resolve-preset.js';\n\nimport type { IPreset } from './preset-types.js';\n\n/**\n * Outcome of an external-preset load: the presets themselves, their ids, and per-file errors.\n *\n * ARCH-009 added `presets`. `loaded` used to be the only way out, because the presets went into a\n * module-global registry and the caller read them back by id — which is what made the global\n * load-bearing at startup. The caller now receives the values it loaded and builds its own registry\n * over them, so nothing has to be looked up from process state.\n */\nexport interface IExternalPresetLoadResult {\n presets: readonly IPreset[];\n loaded: readonly string[];\n errors: readonly { file: string; error: string }[];\n}\n\n/**\n * Load and validate every `*.json` external preset from `dir`.\n *\n * A missing directory yields an empty result (no error). Each file is JSON-parsed and validated;\n * a parse or validation failure is recorded as a per-file error and skipped — the remaining files\n * still load. The surviving presets go through {@link partitionExternalPresets}, whose rejections\n * (built-in id collision or duplicate id) are folded into `errors` against their file.\n *\n * Loading REGISTERS NOTHING. The result is a value the caller owns.\n */\nexport function loadExternalPresetsFromDir(dir: string): IExternalPresetLoadResult {\n if (!existsSync(dir)) {\n return { presets: [], loaded: [], errors: [] };\n }\n\n const errors: { file: string; error: string }[] = [];\n const validPresets: IPreset[] = [];\n // Track which file each validated preset id came from so registry rejections map back to a file.\n const fileById = new Map<string, string>();\n\n const jsonFiles = readdirSync(dir).filter((name) => name.endsWith('.json'));\n for (const name of jsonFiles) {\n const filePath = join(dir, name);\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(filePath, 'utf8'));\n } catch (error) {\n // allow-fallback: a malformed file is reported per-file and skipped, not silently swallowed\n errors.push({ file: name, error: error instanceof Error ? error.message : String(error) });\n continue;\n }\n\n const result = validateExternalPreset(parsed);\n if (!result.ok) {\n errors.push({ file: name, error: result.error });\n continue;\n }\n\n validPresets.push(result.preset);\n fileById.set(result.preset.id, name);\n }\n\n const { accepted, rejected } = partitionExternalPresets(validPresets);\n for (const rejection of rejected) {\n errors.push({ file: fileById.get(rejection.id) ?? rejection.id, error: rejection.reason });\n }\n\n return { presets: accepted, loaded: accepted.map((preset) => preset.id), errors };\n}\n","import type { IOutputStyle } from './output-style-types.js';\n\nconst DEFAULT_INSTRUCTIONS = '';\n\nexport const builtInOutputStyles: readonly IOutputStyle[] = [\n {\n id: 'default',\n name: 'Default',\n description: 'The ordinary response style.',\n instructions: DEFAULT_INSTRUCTIONS,\n keepCodingInstructions: true,\n tokenCost: 'baseline',\n source: 'built-in',\n },\n {\n id: 'concise',\n name: 'Concise',\n description: 'Lead with the result and keep routine responses short.',\n instructions:\n 'Lead with the answer and skip routine preamble or tool narration. Keep responses concise while doing the same engineering work. Expand fully when asked for detail. Always keep error reports, security warnings and destructive-action confirmations complete.',\n keepCodingInstructions: true,\n tokenCost: 'low',\n source: 'built-in',\n },\n {\n id: 'proactive',\n name: 'Proactive',\n description: 'Take the next reasonable step without pausing on routine choices.',\n instructions:\n 'Act on reasonable routine assumptions and take the next useful step. State assumptions when they matter. The active permission mode remains authoritative; this style never grants, changes, or bypasses permission.',\n keepCodingInstructions: true,\n tokenCost: 'medium',\n source: 'built-in',\n },\n {\n id: 'explanatory',\n name: 'Explanatory',\n description: 'Teach the reasoning and trade-offs behind the answer.',\n instructions:\n 'Explain the reasoning, important trade-offs, and relevant terminology as you work. Keep the explanation connected to the requested outcome and do not omit complete error, security, or destructive-action guidance.',\n keepCodingInstructions: true,\n tokenCost: 'high',\n source: 'built-in',\n },\n {\n id: 'learning',\n name: 'Learning',\n description: 'Teach by marking useful gaps for the human to fill.',\n instructions:\n 'Teach the requested subject step by step. Mark a small number of useful gaps with [Your turn:] and invite the human to fill them before revealing the explanation. Never turn safety, security, error, or destructive-action guidance into a gap.',\n keepCodingInstructions: true,\n tokenCost: 'high',\n source: 'built-in',\n },\n];\n","import { basename, extname } from 'node:path';\n\nimport { builtInOutputStyles } from './output-styles.js';\n\nimport type {\n IOutputStyle,\n IOutputStyleFile,\n IOutputStyleLoadResult,\n IOutputStyleRegistry,\n IOutputStyleSource,\n IOutputStyleSummary,\n TOutputStyleSource,\n TOutputStyleTokenCost,\n} from './output-style-types.js';\n\nexport { builtInOutputStyles } from './output-styles.js';\n\nconst TOKEN_COSTS = new Set<TOutputStyleTokenCost>([\n 'baseline',\n 'low',\n 'medium',\n 'high',\n 'unspecified',\n]);\n\nfunction stripScalarQuotes(value: string): string {\n return value.replace(/^(?:\"([\\s\\S]*)\"|'([\\s\\S]*)')$/, '$1$2');\n}\n\nfunction parseBoolean(field: string, raw: string): boolean {\n if (raw === 'true') return true;\n if (raw === 'false') return false;\n throw new Error(`${field}: expected boolean, received \"${raw}\"`);\n}\n\nfunction parseFrontmatter(\n fileName: string,\n content: string,\n): { values: Record<string, string>; instructions: string } {\n const lines = content.split('\\n');\n if (lines[0]?.trim() !== '---') {\n throw new Error('frontmatter: expected an opening --- marker');\n }\n const values: Record<string, string> = {};\n let end = -1;\n for (let index = 1; index < lines.length; index += 1) {\n const line = lines[index]!;\n if (line.trim() === '---') {\n end = index;\n break;\n }\n if (line.trim() === '') continue;\n const match = /^([a-z][a-z0-9-]*):\\s*(.*)$/.exec(line);\n if (!match) throw new Error(`frontmatter: invalid entry at line ${index + 1}`);\n const key = match[1]!;\n if (values[key] !== undefined) throw new Error(`frontmatter.${key}: duplicate field`);\n values[key] = stripScalarQuotes(match[2]!.trim());\n }\n if (end < 0) throw new Error('frontmatter: expected a closing --- marker');\n const unknown = Object.keys(values).filter(\n (key) => !['name', 'description', 'keep-coding-instructions', 'token-cost'].includes(key),\n );\n if (unknown.length > 0) {\n throw new Error(`frontmatter.${unknown[0]}: unknown field`);\n }\n return {\n values,\n instructions: lines\n .slice(end + 1)\n .join('\\n')\n .trim(),\n };\n}\n\nfunction fileId(fileName: string): string {\n const id = basename(fileName, extname(fileName)).trim();\n if (!/^[a-z0-9][a-z0-9-]*$/i.test(id)) {\n throw new Error(`id: expected the Markdown filename stem to be a slug, received \"${id}\"`);\n }\n return id.toLowerCase();\n}\n\nexport function parseOutputStyleFile(\n file: IOutputStyleFile,\n source: TOutputStyleSource,\n): IOutputStyle {\n if (!file.fileName.endsWith('.md')) {\n throw new Error('file: expected a .md output-style file');\n }\n const id = fileId(file.fileName);\n const parsed = parseFrontmatter(file.fileName, file.content);\n const name = parsed.values.name?.trim() || basename(file.fileName, '.md');\n const description = parsed.values.description?.trim() || `Custom output style: ${name}`;\n const keepCodingInstructions =\n parsed.values['keep-coding-instructions'] === undefined\n ? false\n : parseBoolean(\n 'frontmatter.keep-coding-instructions',\n parsed.values['keep-coding-instructions'],\n );\n const tokenCost = parsed.values['token-cost'] ?? 'unspecified';\n if (!TOKEN_COSTS.has(tokenCost as TOutputStyleTokenCost)) {\n throw new Error(\n `frontmatter.token-cost: expected baseline|low|medium|high|unspecified, received \"${tokenCost}\"`,\n );\n }\n if (parsed.instructions.length === 0) {\n throw new Error('body: expected non-empty style instructions');\n }\n return {\n id,\n name,\n description,\n instructions: parsed.instructions,\n keepCodingInstructions,\n tokenCost: tokenCost as TOutputStyleTokenCost,\n source,\n };\n}\n\nfunction summarize(style: IOutputStyle): IOutputStyleSummary {\n return {\n id: style.id,\n name: style.name,\n description: style.description,\n tokenCost: style.tokenCost,\n source: style.source,\n };\n}\n\nexport function loadOutputStylesFromSources(\n sources: readonly IOutputStyleSource[],\n): IOutputStyleLoadResult {\n const styles = new Map<string, IOutputStyle>();\n const errors: { file: string; error: string }[] = [];\n for (const style of builtInOutputStyles) styles.set(style.id, style);\n\n const orderedSources = [...sources].sort((a, b) => a.precedence - b.precedence);\n for (const source of orderedSources) {\n const seenInSource = new Set<string>();\n for (const file of [...source.files].sort((a, b) => a.fileName.localeCompare(b.fileName))) {\n const displayFile = `${source.displayName}/${file.fileName}`;\n let style: IOutputStyle;\n try {\n style = parseOutputStyleFile(file, source.scope);\n } catch (error) {\n errors.push({\n file: displayFile,\n error: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n if (seenInSource.has(style.id)) {\n errors.push({ file: displayFile, error: `duplicate style id \"${style.id}\" in source` });\n continue;\n }\n seenInSource.add(style.id);\n if (styles.get(style.id)?.source === 'built-in') {\n errors.push({\n file: displayFile,\n error: `style id \"${style.id}\" collides with a built-in`,\n });\n continue;\n }\n styles.set(style.id, style);\n }\n }\n return {\n styles: [...styles.values()],\n loaded: [...styles.values()]\n .filter((style) => style.source !== 'built-in')\n .map((style) => style.id),\n errors,\n };\n}\n\nexport function createOutputStyleRegistry(\n sources: readonly IOutputStyleSource[] = [],\n): IOutputStyleRegistry {\n const loaded = loadOutputStylesFromSources(sources);\n const byId = new Map(loaded.styles.map((style) => [style.id, style]));\n return {\n listOutputStyles: () => loaded.styles.map(summarize),\n getOutputStyle: (id: string) => byId.get(id),\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,32 @@
1
1
  {
2
2
  "name": "@robota-sdk/agent-preset",
3
- "version": "3.0.0-beta.79",
3
+ "version": "3.0.0-beta.81",
4
4
  "description": "Preset contract and resolver for the Robota SDK (IPreset, resolvePreset, listPresets, built-in presets)",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
7
7
  "types": "dist/node/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./dist/node/index.d.ts",
11
10
  "source": "./src/index.ts",
12
11
  "node": {
13
- "import": "./dist/node/index.js",
14
- "require": "./dist/node/index.cjs"
12
+ "import": {
13
+ "types": "./dist/node/index.d.ts",
14
+ "default": "./dist/node/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/node/index.d.cts",
18
+ "default": "./dist/node/index.cjs"
19
+ }
15
20
  },
16
21
  "default": {
17
- "import": "./dist/node/index.js",
18
- "require": "./dist/node/index.cjs"
22
+ "import": {
23
+ "types": "./dist/node/index.d.ts",
24
+ "default": "./dist/node/index.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/node/index.d.cts",
28
+ "default": "./dist/node/index.cjs"
29
+ }
19
30
  }
20
31
  }
21
32
  },
@@ -31,25 +42,28 @@
31
42
  "dist"
32
43
  ],
33
44
  "dependencies": {
34
- "@robota-sdk/agent-framework": "3.0.0-beta.79"
45
+ "@robota-sdk/agent-framework": "3.0.0-beta.81"
35
46
  },
36
47
  "devDependencies": {
37
48
  "rimraf": "^5.0.10",
38
- "tsdown": "^0.22.2",
39
- "typescript": "^5.9.3",
49
+ "tsdown": "^0.22.14",
50
+ "typescript": "^6.0.3",
40
51
  "vitest": "^3.2.6"
41
52
  },
42
53
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
43
54
  "publishConfig": {
44
55
  "access": "public"
45
56
  },
57
+ "volta": {
58
+ "extends": "../../package.json"
59
+ },
46
60
  "scripts": {
47
- "build": "tsdown",
48
- "build:js": "tsdown --no-dts",
49
- "build:types": "tsdown --dts",
61
+ "build": "rimraf dist && tsdown",
62
+ "build:js": "pnpm run build",
63
+ "build:types": "pnpm run build",
50
64
  "test": "vitest run --passWithNoTests",
51
65
  "test:coverage": "vitest run --coverage --passWithNoTests",
52
- "typecheck": "tsc --noEmit",
66
+ "typecheck": "tsgo --noEmit",
53
67
  "lint": "eslint src/ --ext .ts",
54
68
  "clean": "rimraf dist"
55
69
  }