@roll-agent/core 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/cli/chat/ink/app.js +1 -1
  2. package/dist/cli/chat/ink/commands.js +1 -1
  3. package/dist/cli/chat/ink/display-width.d.ts +1 -0
  4. package/dist/cli/chat/ink/display-width.js +1 -0
  5. package/dist/cli/chat/ink/editor-keymap.d.ts +29 -0
  6. package/dist/cli/chat/ink/editor-keymap.js +1 -0
  7. package/dist/cli/chat/ink/history-item.js +1 -1
  8. package/dist/cli/chat/ink/line-buffer.d.ts +21 -0
  9. package/dist/cli/chat/ink/line-buffer.js +1 -0
  10. package/dist/cli/chat/ink/live-region.js +1 -1
  11. package/dist/cli/chat/ink/markdown.d.ts +0 -1
  12. package/dist/cli/chat/ink/markdown.js +1 -1
  13. package/dist/cli/chat/ink/run-ink-repl.d.ts +1 -1
  14. package/dist/cli/chat/ink/run-ink-repl.js +1 -1
  15. package/dist/cli/chat/ink/state.d.ts +6 -0
  16. package/dist/cli/chat/ink/state.js +1 -1
  17. package/dist/cli/chat/ink/status-line.js +1 -1
  18. package/dist/cli/chat/ink/text-prompt.d.ts +4 -0
  19. package/dist/cli/chat/ink/text-prompt.js +1 -1
  20. package/dist/cli/chat/ink/use-session.d.ts +1 -0
  21. package/dist/cli/chat/ink/use-session.js +1 -1
  22. package/dist/cli/commands/agent-add.js +1 -1
  23. package/dist/cli/commands/agent-env-guidance.d.ts +2 -0
  24. package/dist/cli/commands/agent-env-guidance.js +1 -0
  25. package/dist/cli/commands/agent-install.d.ts +5 -0
  26. package/dist/cli/commands/agent-install.js +1 -1
  27. package/dist/cli/commands/agent-list.d.ts +5 -0
  28. package/dist/cli/commands/agent-list.js +1 -1
  29. package/dist/cli/commands/ask.js +1 -1
  30. package/dist/cli/commands/chat.d.ts +3 -0
  31. package/dist/cli/commands/chat.js +1 -1
  32. package/dist/cli/commands/config-guidance.d.ts +21 -0
  33. package/dist/cli/commands/config-guidance.js +1 -1
  34. package/dist/cli/commands/config-prompts.d.ts +6 -0
  35. package/dist/cli/commands/config-prompts.js +1 -1
  36. package/dist/cli/commands/config-setup.d.ts +6 -1
  37. package/dist/cli/commands/config-setup.js +1 -1
  38. package/dist/cli/commands/config.d.ts +1 -0
  39. package/dist/cli/commands/config.js +1 -1
  40. package/dist/cli/commands/run.js +1 -1
  41. package/dist/cli/commands/setup.d.ts +38 -0
  42. package/dist/cli/commands/setup.js +1 -0
  43. package/dist/cli/commands/skills-install.d.ts +30 -0
  44. package/dist/cli/commands/skills-install.js +1 -0
  45. package/dist/cli/commands/skills.js +1 -1
  46. package/dist/cli/index.js +1 -1
  47. package/dist/cli/utils/catalog-status.d.ts +20 -0
  48. package/dist/cli/utils/catalog-status.js +1 -0
  49. package/dist/cli/utils/chat-renderer.d.ts +1 -0
  50. package/dist/cli/utils/chat-renderer.js +1 -1
  51. package/dist/cli/utils/git-source.d.ts +7 -0
  52. package/dist/cli/utils/git-source.js +1 -0
  53. package/dist/cli/utils/tool-format.d.ts +1 -0
  54. package/dist/cli/utils/tool-format.js +1 -1
  55. package/dist/config/defaults.js +1 -1
  56. package/dist/config/helpers.d.ts +17 -0
  57. package/dist/config/helpers.js +1 -1
  58. package/dist/config/key-codec.js +1 -1
  59. package/dist/config/loader.d.ts +2 -0
  60. package/dist/config/loader.js +1 -1
  61. package/dist/config/migration.d.ts +5 -1
  62. package/dist/config/migration.js +1 -1
  63. package/dist/config/runtime-env.d.ts +30 -30
  64. package/dist/config/schema.d.ts +250 -0
  65. package/dist/config/schema.js +1 -1
  66. package/dist/llm/providers.d.ts +12 -0
  67. package/dist/llm/providers.js +1 -1
  68. package/dist/mcp/client-manager.d.ts +5 -1
  69. package/dist/mcp/client-manager.js +1 -1
  70. package/dist/mcp/sampling-handler.d.ts +14 -2
  71. package/dist/mcp/sampling-handler.js +1 -1
  72. package/dist/registry/catalog-discovery.d.ts +30 -0
  73. package/dist/registry/catalog-discovery.js +1 -0
  74. package/dist/registry/catalog.d.ts +42 -0
  75. package/dist/registry/catalog.js +1 -0
  76. package/dist/registry/discovery.js +1 -1
  77. package/dist/registry/index.d.ts +4 -0
  78. package/dist/registry/index.js +1 -1
  79. package/dist/registry/install.d.ts +69 -0
  80. package/dist/registry/install.js +1 -0
  81. package/dist/skills/documents.js +1 -1
  82. package/dist/skills/install.d.ts +17 -0
  83. package/dist/skills/install.js +1 -0
  84. package/dist/skills/library.d.ts +6 -0
  85. package/dist/skills/library.js +1 -1
  86. package/dist/skills/orchestrators.d.ts +39 -0
  87. package/dist/skills/orchestrators.js +1 -0
  88. package/package.json +3 -2
@@ -7,6 +7,10 @@ declare const CONFIG_MIGRATION_ISSUE_CODES: {
7
7
  readonly unknownRouterKeys: "unknown-router-keys";
8
8
  readonly legacyCamelCaseAgentEnvKey: "legacy-camelcase-agent-env-key";
9
9
  readonly legacyAgentEnvKeyConflict: "legacy-agent-env-key-conflict";
10
+ readonly deprecatedRuntimeBashSection: "deprecated-runtime-bash-section";
11
+ readonly invalidRuntimeBashSection: "invalid-runtime-bash-section";
12
+ readonly invalidRuntimeShellSection: "invalid-runtime-shell-section";
13
+ readonly runtimeShellConflict: "runtime-shell-conflict";
10
14
  };
11
15
  type ConfigMigrationIssueCode = (typeof CONFIG_MIGRATION_ISSUE_CODES)[keyof typeof CONFIG_MIGRATION_ISSUE_CODES];
12
16
  export interface ConfigMigrationIssue {
@@ -29,7 +33,7 @@ export type ApplyKnownConfigMigrationsResult = {
29
33
  readonly changed: false;
30
34
  readonly issues: readonly ConfigMigrationIssue[];
31
35
  };
32
- export type ConfigMigrationScope = "llm" | "ask" | "agents";
36
+ export type ConfigMigrationScope = "llm" | "ask" | "agents" | "runtime";
33
37
  export declare function detectKnownConfigMigrations(document: Record<string, unknown>, options?: {
34
38
  readonly scope?: ConfigMigrationScope;
35
39
  }): ConfigMigrationReport;
@@ -1 +1 @@
1
- import{camelToKebab as e}from"./key-codec.js";const t={deprecatedRouterSection:"deprecated-router-section",invalidAskSection:"invalid-ask-section",invalidRouterSection:"invalid-router-section",routerAskConflict:"router-ask-conflict",duplicateEquivalentKeys:"duplicate-equivalent-keys",unknownRouterKeys:"unknown-router-keys",legacyCamelCaseAgentEnvKey:"legacy-camelcase-agent-env-key",legacyAgentEnvKeyConflict:"legacy-agent-env-key-conflict"},s={llmModel:{routerKeys:["llm-model","llmModel"],askKeys:["llm-model","llmModel"],targetAskKey:"llm-model"},confirmThreshold:{routerKeys:["confirm-threshold","confirmThreshold"],askKeys:["confirm-threshold","confirmThreshold"],targetAskKey:"confirm-threshold"}},n=[...s.llmModel.routerKeys,...s.confirmThreshold.routerKeys,"mode"],o=new Set([t.invalidAskSection,t.invalidRouterSection,t.routerAskConflict,t.unknownRouterKeys,t.legacyAgentEnvKeyConflict]);function r(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function u(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function i(e,t){return{code:e,message:t}}function c(e,t){return t.filter(t=>u(e,t))}function a(e,s,n){const o=c(s,n);if(0===o.length)return{ok:!0,key:void 0,value:void 0};const[r]=o,u=r?s[r]:void 0;return o.some(e=>s[e]!==u)?{ok:!1,issue:i(t.duplicateEquivalentKeys,`\`${e}\` 同时包含等价键 ${o.join(", ")} 且值不一致,请手动处理。`)}:{ok:!0,key:r,value:u}}function l(e){if(!u(e,"router"))return{matches:!1,canAutoMigrate:!1,issues:[]};const c=[i(t.deprecatedRouterSection,"`router` 配置段已废弃,请改用 `ask`。"),i(t.deprecatedRouterSection,"将 `router.llm-model` 迁移为 `ask.llm-model`。"),i(t.deprecatedRouterSection,"将 `router.confirm-threshold` 迁移为 `ask.confirm-threshold`。"),i(t.deprecatedRouterSection,"删除 `router.mode`;命令本身已决定策略(`run` / `ask` / `chat`)。")],l=e.router;if(!r(l))return c.push(i(t.invalidRouterSection,"`router` 配置段不是对象,无法自动迁移,请手动修复。")),{matches:!0,canAutoMigrate:!1,issues:c};const d=Object.keys(l).filter(e=>!n.includes(e));d.length>0&&c.push(i(t.unknownRouterKeys,`\`router\` 包含无法自动迁移的未知键:${d.join(", ")}。`));const g=e.ask;if(void 0===g||r(g)||c.push(i(t.invalidAskSection,"`ask` 配置段不是对象,无法自动迁移,请手动修复。")),r(g))for(const e of Object.keys(s)){const n=s[e],o=a("router",l,n.routerKeys),r=a("ask",g,n.askKeys);o.ok?r.ok?o.key&&r.key&&r.value!==o.value&&c.push(i(t.routerAskConflict,`\`router.${n.targetAskKey}\` 与 \`ask.${n.targetAskKey}\` 同时存在且值冲突,请手动处理。`)):c.push(r.issue):c.push(o.issue)}return{matches:!0,canAutoMigrate:!c.some(e=>o.has(e.code)),issues:c}}function d(e){const t=l(e);if(!t.matches)return{ok:!0,changed:!1,document:structuredClone(e),issues:[],summary:[]};if(!t.canAutoMigrate)return{ok:!1,changed:!1,issues:t.issues};const n=structuredClone(e),o=n.router;if(!r(o))return{ok:!1,changed:!1,issues:t.issues};const i=n.ask,c=r(i)?i:{};let d=!1;const g=[];for(const e of Object.keys(s)){const t=s[e],n=a("router",o,t.routerKeys);if(!n.ok)return{ok:!1,changed:!1,issues:[n.issue]};if(!n.key)continue;const r=a("ask",c,t.askKeys);if(!r.ok)return{ok:!1,changed:!1,issues:[r.issue]};r.key?g.push(`移除已废弃的 \`router.${t.targetAskKey}\``):(c[t.targetAskKey]=n.value,d=!0,g.push(`将 \`router.${t.targetAskKey}\` 迁移到 \`ask.${t.targetAskKey}\``));for(const e of t.routerKeys)u(o,e)&&delete o[e]}return u(o,"mode")&&(delete o.mode,g.push("删除已废弃的 `router.mode`")),d&&(n.ask=c),0===Object.keys(o).length&&(delete n.router,g.push("删除空的 `router` 配置段")),{ok:!0,changed:g.length>0,document:n,issues:t.issues,summary:g}}const g=/^[a-z0-9]+(-[a-z0-9]+)*$/;function f(e){return!g.test(e)}function k(t){const s=e(t).toLowerCase();return g.test(s)?s:void 0}function y(e){const s=e.agents;if(!r(s))return{matches:!1,canAutoMigrate:!1,issues:[]};const n=s.env;if(!r(n))return{matches:!1,canAutoMigrate:!1,issues:[]};const o=Object.keys(n).filter(f);if(0===o.length)return{matches:!1,canAutoMigrate:!1,issues:[]};const c=[];let a=!1;for(const e of o){const s=k(e);void 0!==s?u(n,s)?(a=!0,c.push(i(t.legacyAgentEnvKeyConflict,`\`agents.env\` 下同时存在 \`${e}\` 与 \`${s}\`,无法自动合并,请手动处理。`))):c.push(i(t.legacyCamelCaseAgentEnvKey,`\`agents.env.${e}\` 应使用 kebab-case(\`${s}\`)。`)):(a=!0,c.push(i(t.legacyAgentEnvKeyConflict,`\`agents.env.${e}\` 命名不符合 kebab-case 规范,无法自动迁移,请手动重命名。`)))}return{matches:!0,canAutoMigrate:!a,issues:c}}function h(e){const t=y(e);if(!t.matches)return{ok:!0,changed:!1,document:structuredClone(e),issues:[],summary:[]};if(!t.canAutoMigrate)return{ok:!1,changed:!1,issues:t.issues};const s=structuredClone(e),n=s.agents;if(!r(n))return{ok:!1,changed:!1,issues:t.issues};const o=n.env;if(!r(o))return{ok:!1,changed:!1,issues:t.issues};const u=[];for(const e of Object.keys(o).filter(f)){const t=k(e);void 0!==t&&(o[t]=o[e],delete o[e],u.push(`将 \`agents.env.${e}\` 重命名为 \`agents.env.${t}\``))}return{ok:!0,changed:u.length>0,document:s,issues:t.issues,summary:u}}const m=[{id:"router-to-ask",scopes:new Set(["ask"]),inspect:l,apply:d},{id:"legacy-agent-env-keys",scopes:new Set(["agents"]),inspect:y,apply:h}];export function detectKnownConfigMigrations(e,t={}){const{scope:s}=t,n=(void 0!==s?m.filter(e=>e.scopes.has(s)):m).map(t=>t.inspect(e)).filter(e=>e.matches);return 0===n.length?{needsMigration:!1,canAutoMigrate:!1,issues:[]}:{needsMigration:!0,canAutoMigrate:n.every(e=>e.canAutoMigrate),issues:n.flatMap(e=>e.issues)}}export function applyKnownConfigMigrations(e){let t=structuredClone(e);const s=[],n=[];let o=!1;for(const e of m){const r=e.apply(t);if(!r.ok)return{ok:!1,changed:!1,issues:r.issues};t=r.document,r.changed&&(o=!0,s.push(...r.summary)),n.push(...r.issues)}return{ok:!0,changed:o,document:t,summary:s,issues:n}}export function formatConfigMigrationError(e,t){const s=[`Config validation failed (${e}):`];for(const e of t.issues)s.push(` - ${e.message}`);return t.canAutoMigrate?s.push(" - 可运行 `roll config migrate` 自动迁移当前配置。"):t.needsMigration&&s.push(" - 检测到配置迁移冲突,请手动处理后再重试。"),s.join("\n")}
1
+ import{camelToKebab as e,CONFIG_KEY_CODEC as t,kebabToCamel as s}from"./key-codec.js";const n={deprecatedRouterSection:"deprecated-router-section",invalidAskSection:"invalid-ask-section",invalidRouterSection:"invalid-router-section",routerAskConflict:"router-ask-conflict",duplicateEquivalentKeys:"duplicate-equivalent-keys",unknownRouterKeys:"unknown-router-keys",legacyCamelCaseAgentEnvKey:"legacy-camelcase-agent-env-key",legacyAgentEnvKeyConflict:"legacy-agent-env-key-conflict",deprecatedRuntimeBashSection:"deprecated-runtime-bash-section",invalidRuntimeBashSection:"invalid-runtime-bash-section",invalidRuntimeShellSection:"invalid-runtime-shell-section",runtimeShellConflict:"runtime-shell-conflict"},o={llmModel:{routerKeys:["llm-model","llmModel"],askKeys:["llm-model","llmModel"],targetAskKey:"llm-model"},confirmThreshold:{routerKeys:["confirm-threshold","confirmThreshold"],askKeys:["confirm-threshold","confirmThreshold"],targetAskKey:"confirm-threshold"}},r=[...o.llmModel.routerKeys,...o.confirmThreshold.routerKeys,"mode"],i=new Set([n.invalidAskSection,n.invalidRouterSection,n.routerAskConflict,n.unknownRouterKeys,n.legacyAgentEnvKeyConflict,n.invalidRuntimeBashSection,n.invalidRuntimeShellSection,n.runtimeShellConflict]);function u(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function c(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function a(e,t){return{code:e,message:t}}function l(e,t){if(Object.is(e,t))return!0;if(!u(e)||!u(t))return!1;const s=Object.keys(e).sort(),n=Object.keys(t).sort();return s.length===n.length&&s.every((s,o)=>s===n[o]&&l(e[s],t[s]))}function d(){if("object"!==t.kind)throw new Error("runtime shell key codec is unavailable");const e=t.fields.runtime;if("object"!==e?.kind)throw new Error("runtime shell key codec is unavailable");const s=e.fields.shell;if("object"!==s?.kind)throw new Error("runtime shell key codec is unavailable");return s}function h(e,t,n){if(!u(e)||"leaf"===t.kind)return{ok:!0,value:e};const o={};for(const[r,i]of Object.entries(e)){const e="object"===t.kind?s(r):r,u="object"===t.kind?t.fields[e]:t.value,a=void 0===u?{ok:!0,value:i}:h(i,u,[...n,e]);if(!a.ok)return a;if(c(o,e)){if(!l(o[e],a.value))return{ok:!1,conflictPath:[...n,e].join(".")}}else o[e]=a.value}return{ok:!0,value:o}}function f(e,t){const s=h(e,d(),[t]);return s.ok?u(s.value)?{ok:!0,value:s.value}:{ok:!0,value:e}:s}function m(e,t){if(!u(e)||"leaf"===t.kind)return e;const n={},o=new Set;for(const[r,i]of Object.entries(e)){const e="object"===t.kind?s(r):r;if(o.has(e))continue;o.add(e);const u="object"===t.kind?t.fields[e]:t.value;n[r]=void 0===u?i:m(i,u)}return n}function k(e,t){return t.filter(t=>c(e,t))}function g(e,t,s){const o=k(t,s);if(0===o.length)return{ok:!0,key:void 0,value:void 0};const[r]=o,i=r?t[r]:void 0;return o.some(e=>t[e]!==i)?{ok:!1,issue:a(n.duplicateEquivalentKeys,`\`${e}\` 同时包含等价键 ${o.join(", ")} 且值不一致,请手动处理。`)}:{ok:!0,key:r,value:i}}function y(e){if(!c(e,"router"))return{matches:!1,canAutoMigrate:!1,issues:[]};const t=[a(n.deprecatedRouterSection,"`router` 配置段已废弃,请改用 `ask`。"),a(n.deprecatedRouterSection,"将 `router.llm-model` 迁移为 `ask.llm-model`。"),a(n.deprecatedRouterSection,"将 `router.confirm-threshold` 迁移为 `ask.confirm-threshold`。"),a(n.deprecatedRouterSection,"删除 `router.mode`;命令本身已决定策略(`run` / `ask` / `chat`)。")],s=e.router;if(!u(s))return t.push(a(n.invalidRouterSection,"`router` 配置段不是对象,无法自动迁移,请手动修复。")),{matches:!0,canAutoMigrate:!1,issues:t};const l=Object.keys(s).filter(e=>!r.includes(e));l.length>0&&t.push(a(n.unknownRouterKeys,`\`router\` 包含无法自动迁移的未知键:${l.join(", ")}。`));const d=e.ask;if(void 0===d||u(d)||t.push(a(n.invalidAskSection,"`ask` 配置段不是对象,无法自动迁移,请手动修复。")),u(d))for(const e of Object.keys(o)){const r=o[e],i=g("router",s,r.routerKeys),u=g("ask",d,r.askKeys);i.ok?u.ok?i.key&&u.key&&u.value!==i.value&&t.push(a(n.routerAskConflict,`\`router.${r.targetAskKey}\` 与 \`ask.${r.targetAskKey}\` 同时存在且值冲突,请手动处理。`)):t.push(u.issue):t.push(i.issue)}return{matches:!0,canAutoMigrate:!t.some(e=>i.has(e.code)),issues:t}}function v(e){const t=y(e);if(!t.matches)return{ok:!0,changed:!1,document:structuredClone(e),issues:[],summary:[]};if(!t.canAutoMigrate)return{ok:!1,changed:!1,issues:t.issues};const s=structuredClone(e),n=s.router;if(!u(n))return{ok:!1,changed:!1,issues:t.issues};const r=s.ask,i=u(r)?r:{};let a=!1;const l=[];for(const e of Object.keys(o)){const t=o[e],s=g("router",n,t.routerKeys);if(!s.ok)return{ok:!1,changed:!1,issues:[s.issue]};if(!s.key)continue;const r=g("ask",i,t.askKeys);if(!r.ok)return{ok:!1,changed:!1,issues:[r.issue]};r.key?l.push(`移除已废弃的 \`router.${t.targetAskKey}\``):(i[t.targetAskKey]=s.value,a=!0,l.push(`将 \`router.${t.targetAskKey}\` 迁移到 \`ask.${t.targetAskKey}\``));for(const e of t.routerKeys)c(n,e)&&delete n[e]}return c(n,"mode")&&(delete n.mode,l.push("删除已废弃的 `router.mode`")),a&&(s.ask=i),0===Object.keys(n).length&&(delete s.router,l.push("删除空的 `router` 配置段")),{ok:!0,changed:l.length>0,document:s,issues:t.issues,summary:l}}const p=/^[a-z0-9]+(-[a-z0-9]+)*$/;function b(e){return!p.test(e)}function A(t){const s=e(t).toLowerCase();return p.test(s)?s:void 0}function K(e){const t=e.agents;if(!u(t))return{matches:!1,canAutoMigrate:!1,issues:[]};const s=t.env;if(!u(s))return{matches:!1,canAutoMigrate:!1,issues:[]};const o=Object.keys(s).filter(b);if(0===o.length)return{matches:!1,canAutoMigrate:!1,issues:[]};const r=[];let i=!1;for(const e of o){const t=A(e);void 0!==t?c(s,t)?(i=!0,r.push(a(n.legacyAgentEnvKeyConflict,`\`agents.env\` 下同时存在 \`${e}\` 与 \`${t}\`,无法自动合并,请手动处理。`))):r.push(a(n.legacyCamelCaseAgentEnvKey,`\`agents.env.${e}\` 应使用 kebab-case(\`${t}\`)。`)):(i=!0,r.push(a(n.legacyAgentEnvKeyConflict,`\`agents.env.${e}\` 命名不符合 kebab-case 规范,无法自动迁移,请手动重命名。`)))}return{matches:!0,canAutoMigrate:!i,issues:r}}function S(e){const t=K(e);if(!t.matches)return{ok:!0,changed:!1,document:structuredClone(e),issues:[],summary:[]};if(!t.canAutoMigrate)return{ok:!1,changed:!1,issues:t.issues};const s=structuredClone(e),n=s.agents;if(!u(n))return{ok:!1,changed:!1,issues:t.issues};const o=n.env;if(!u(o))return{ok:!1,changed:!1,issues:t.issues};const r=[];for(const e of Object.keys(o).filter(b)){const t=A(e);void 0!==t&&(o[t]=o[e],delete o[e],r.push(`将 \`agents.env.${e}\` 重命名为 \`agents.env.${t}\``))}return{ok:!0,changed:r.length>0,document:s,issues:t.issues,summary:r}}function M(e){const t=e.runtime;if(!u(t))return{matches:!1,canAutoMigrate:!1,issues:[]};if(!c(t,"bash"))return{matches:!1,canAutoMigrate:!1,issues:[]};const s=[a(n.deprecatedRuntimeBashSection,"`runtime.bash` 配置段已废弃,请改用 `runtime.shell`。")],o=t.bash;u(o)||s.push(a(n.invalidRuntimeBashSection,"`runtime.bash` 配置段不是对象,无法自动迁移,请手动修复。"));const r=t.shell;void 0===r||u(r)||s.push(a(n.invalidRuntimeShellSection,"`runtime.shell` 配置段不是对象,无法自动迁移,请手动修复。"));const d=u(o)?f(o,"runtime.bash"):void 0,h=u(r)?f(r,"runtime.shell"):void 0;for(const e of[d,h])void 0===e||e.ok||s.push(a(n.runtimeShellConflict,`\`${e.conflictPath}\` 同时包含等价键且值冲突,请手动处理。`));!0!==d?.ok||!0!==h?.ok||l(d.value,h.value)||s.push(a(n.runtimeShellConflict,"`runtime.bash` 与 `runtime.shell` 同时存在且值冲突,请手动处理。"));return{matches:!0,canAutoMigrate:!s.some(e=>i.has(e.code)),issues:s}}function C(e){const t=M(e);if(!t.matches)return{ok:!0,changed:!1,document:structuredClone(e),issues:[],summary:[]};if(!t.canAutoMigrate)return{ok:!1,changed:!1,issues:t.issues};const s=structuredClone(e),n=s.runtime;if(!u(n))return{ok:!1,changed:!1,issues:t.issues};const o=n.bash;if(!u(o))return{ok:!1,changed:!1,issues:t.issues};const r=[];return c(n,"shell")?r.push("删除已废弃的 `runtime.bash`"):(n.shell=m(o,d()),r.push("将 `runtime.bash` 迁移为 `runtime.shell`")),delete n.bash,{ok:!0,changed:!0,document:s,issues:t.issues,summary:r}}const j=[{id:"router-to-ask",scopes:new Set(["ask"]),inspect:y,apply:v},{id:"legacy-agent-env-keys",scopes:new Set(["agents"]),inspect:K,apply:S},{id:"runtime-bash-to-shell",scopes:new Set(["runtime"]),inspect:M,apply:C}];export function detectKnownConfigMigrations(e,t={}){const{scope:s}=t,n=(void 0!==s?j.filter(e=>e.scopes.has(s)):j).map(t=>t.inspect(e)).filter(e=>e.matches);return 0===n.length?{needsMigration:!1,canAutoMigrate:!1,issues:[]}:{needsMigration:!0,canAutoMigrate:n.every(e=>e.canAutoMigrate),issues:n.flatMap(e=>e.issues)}}export function applyKnownConfigMigrations(e){let t=structuredClone(e);const s=[],n=[];let o=!1;for(const e of j){const r=e.apply(t);if(!r.ok)return{ok:!1,changed:!1,issues:r.issues};t=r.document,r.changed&&(o=!0,s.push(...r.summary)),n.push(...r.issues)}return{ok:!0,changed:o,document:t,summary:s,issues:n}}export function formatConfigMigrationError(e,t){const s=[`Config validation failed (${e}):`];for(const e of t.issues)s.push(` - ${e.message}`);return t.canAutoMigrate?s.push(" - 可运行 `roll config migrate` 自动迁移当前配置。"):t.needsMigration&&s.push(" - 检测到配置迁移冲突,请手动处理后再重试。"),s.join("\n")}
@@ -107,17 +107,17 @@ export declare const BrowserInstanceStatusDiagnosticSchema: z.ZodObject<{
107
107
  }, "strip", z.ZodTypeAny, {
108
108
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
109
109
  id: string;
110
+ profile: {
111
+ exists: boolean;
112
+ writable: boolean;
113
+ userDataDir?: string | undefined;
114
+ };
110
115
  cdp: {
111
116
  endpoint: string;
112
117
  versionReachable: boolean;
113
118
  listReachable: boolean;
114
119
  port?: number | undefined;
115
120
  };
116
- profile: {
117
- exists: boolean;
118
- writable: boolean;
119
- userDataDir?: string | undefined;
120
- };
121
121
  tracking: {
122
122
  source: "instance" | "missing" | "default-env";
123
123
  agentIdFingerprint?: string | undefined;
@@ -126,17 +126,17 @@ export declare const BrowserInstanceStatusDiagnosticSchema: z.ZodObject<{
126
126
  }, {
127
127
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
128
128
  id: string;
129
+ profile: {
130
+ exists: boolean;
131
+ writable: boolean;
132
+ userDataDir?: string | undefined;
133
+ };
129
134
  cdp: {
130
135
  endpoint: string;
131
136
  versionReachable: boolean;
132
137
  listReachable: boolean;
133
138
  port?: number | undefined;
134
139
  };
135
- profile: {
136
- exists: boolean;
137
- writable: boolean;
138
- userDataDir?: string | undefined;
139
- };
140
140
  tracking: {
141
141
  source: "instance" | "missing" | "default-env";
142
142
  agentIdFingerprint?: string | undefined;
@@ -251,17 +251,17 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
251
251
  }, "strip", z.ZodTypeAny, {
252
252
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
253
253
  id: string;
254
+ profile: {
255
+ exists: boolean;
256
+ writable: boolean;
257
+ userDataDir?: string | undefined;
258
+ };
254
259
  cdp: {
255
260
  endpoint: string;
256
261
  versionReachable: boolean;
257
262
  listReachable: boolean;
258
263
  port?: number | undefined;
259
264
  };
260
- profile: {
261
- exists: boolean;
262
- writable: boolean;
263
- userDataDir?: string | undefined;
264
- };
265
265
  tracking: {
266
266
  source: "instance" | "missing" | "default-env";
267
267
  agentIdFingerprint?: string | undefined;
@@ -270,17 +270,17 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
270
270
  }, {
271
271
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
272
272
  id: string;
273
+ profile: {
274
+ exists: boolean;
275
+ writable: boolean;
276
+ userDataDir?: string | undefined;
277
+ };
273
278
  cdp: {
274
279
  endpoint: string;
275
280
  versionReachable: boolean;
276
281
  listReachable: boolean;
277
282
  port?: number | undefined;
278
283
  };
279
- profile: {
280
- exists: boolean;
281
- writable: boolean;
282
- userDataDir?: string | undefined;
283
- };
284
284
  tracking: {
285
285
  source: "instance" | "missing" | "default-env";
286
286
  agentIdFingerprint?: string | undefined;
@@ -295,17 +295,17 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
295
295
  instances?: {
296
296
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
297
297
  id: string;
298
+ profile: {
299
+ exists: boolean;
300
+ writable: boolean;
301
+ userDataDir?: string | undefined;
302
+ };
298
303
  cdp: {
299
304
  endpoint: string;
300
305
  versionReachable: boolean;
301
306
  listReachable: boolean;
302
307
  port?: number | undefined;
303
308
  };
304
- profile: {
305
- exists: boolean;
306
- writable: boolean;
307
- userDataDir?: string | undefined;
308
- };
309
309
  tracking: {
310
310
  source: "instance" | "missing" | "default-env";
311
311
  agentIdFingerprint?: string | undefined;
@@ -339,17 +339,17 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
339
339
  instances?: {
340
340
  mode: "managed-cdp" | "remote-cdp" | "existing-session";
341
341
  id: string;
342
+ profile: {
343
+ exists: boolean;
344
+ writable: boolean;
345
+ userDataDir?: string | undefined;
346
+ };
342
347
  cdp: {
343
348
  endpoint: string;
344
349
  versionReachable: boolean;
345
350
  listReachable: boolean;
346
351
  port?: number | undefined;
347
352
  };
348
- profile: {
349
- exists: boolean;
350
- writable: boolean;
351
- userDataDir?: string | undefined;
352
- };
353
353
  tracking: {
354
354
  source: "instance" | "missing" | "default-env";
355
355
  agentIdFingerprint?: string | undefined;
@@ -93,6 +93,72 @@ export declare const runtimeCompactionConfigSchema: z.ZodObject<{
93
93
  keepRecentTokens?: number | undefined;
94
94
  }>;
95
95
  export declare const runtimeThinkingLevels: readonly ["off", "low", "medium", "high"];
96
+ export declare const runtimeShellSessionConfigSchema: z.ZodObject<{
97
+ enabled: z.ZodDefault<z.ZodBoolean>;
98
+ maxSessions: z.ZodDefault<z.ZodNumber>;
99
+ defaultYieldMs: z.ZodDefault<z.ZodNumber>;
100
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
101
+ }, "strip", z.ZodTypeAny, {
102
+ maxOutputTokens: number;
103
+ enabled: boolean;
104
+ maxSessions: number;
105
+ defaultYieldMs: number;
106
+ }, {
107
+ maxOutputTokens?: number | undefined;
108
+ enabled?: boolean | undefined;
109
+ maxSessions?: number | undefined;
110
+ defaultYieldMs?: number | undefined;
111
+ }>;
112
+ export declare const runtimeShellConfigSchema: z.ZodObject<{
113
+ enabled: z.ZodDefault<z.ZodBoolean>;
114
+ autoApproveSafe: z.ZodDefault<z.ZodBoolean>;
115
+ defaultTimeoutMs: z.ZodDefault<z.ZodNumber>;
116
+ maxTimeoutMs: z.ZodDefault<z.ZodNumber>;
117
+ maxCaptureBytes: z.ZodDefault<z.ZodNumber>;
118
+ maxModelOutputChars: z.ZodDefault<z.ZodNumber>;
119
+ session: z.ZodDefault<z.ZodObject<{
120
+ enabled: z.ZodDefault<z.ZodBoolean>;
121
+ maxSessions: z.ZodDefault<z.ZodNumber>;
122
+ defaultYieldMs: z.ZodDefault<z.ZodNumber>;
123
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
124
+ }, "strip", z.ZodTypeAny, {
125
+ maxOutputTokens: number;
126
+ enabled: boolean;
127
+ maxSessions: number;
128
+ defaultYieldMs: number;
129
+ }, {
130
+ maxOutputTokens?: number | undefined;
131
+ enabled?: boolean | undefined;
132
+ maxSessions?: number | undefined;
133
+ defaultYieldMs?: number | undefined;
134
+ }>>;
135
+ }, "strip", z.ZodTypeAny, {
136
+ enabled: boolean;
137
+ autoApproveSafe: boolean;
138
+ defaultTimeoutMs: number;
139
+ maxTimeoutMs: number;
140
+ maxCaptureBytes: number;
141
+ maxModelOutputChars: number;
142
+ session: {
143
+ maxOutputTokens: number;
144
+ enabled: boolean;
145
+ maxSessions: number;
146
+ defaultYieldMs: number;
147
+ };
148
+ }, {
149
+ enabled?: boolean | undefined;
150
+ autoApproveSafe?: boolean | undefined;
151
+ defaultTimeoutMs?: number | undefined;
152
+ maxTimeoutMs?: number | undefined;
153
+ maxCaptureBytes?: number | undefined;
154
+ maxModelOutputChars?: number | undefined;
155
+ session?: {
156
+ maxOutputTokens?: number | undefined;
157
+ enabled?: boolean | undefined;
158
+ maxSessions?: number | undefined;
159
+ defaultYieldMs?: number | undefined;
160
+ } | undefined;
161
+ }>;
96
162
  export declare const runtimeConfigSchema: z.ZodObject<{
97
163
  provider: z.ZodOptional<z.ZodString>;
98
164
  model: z.ZodOptional<z.ZodString>;
@@ -130,7 +196,71 @@ export declare const runtimeConfigSchema: z.ZodObject<{
130
196
  keepRecentTurns?: number | undefined;
131
197
  keepRecentTokens?: number | undefined;
132
198
  }>>;
199
+ shell: z.ZodDefault<z.ZodObject<{
200
+ enabled: z.ZodDefault<z.ZodBoolean>;
201
+ autoApproveSafe: z.ZodDefault<z.ZodBoolean>;
202
+ defaultTimeoutMs: z.ZodDefault<z.ZodNumber>;
203
+ maxTimeoutMs: z.ZodDefault<z.ZodNumber>;
204
+ maxCaptureBytes: z.ZodDefault<z.ZodNumber>;
205
+ maxModelOutputChars: z.ZodDefault<z.ZodNumber>;
206
+ session: z.ZodDefault<z.ZodObject<{
207
+ enabled: z.ZodDefault<z.ZodBoolean>;
208
+ maxSessions: z.ZodDefault<z.ZodNumber>;
209
+ defaultYieldMs: z.ZodDefault<z.ZodNumber>;
210
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
211
+ }, "strip", z.ZodTypeAny, {
212
+ maxOutputTokens: number;
213
+ enabled: boolean;
214
+ maxSessions: number;
215
+ defaultYieldMs: number;
216
+ }, {
217
+ maxOutputTokens?: number | undefined;
218
+ enabled?: boolean | undefined;
219
+ maxSessions?: number | undefined;
220
+ defaultYieldMs?: number | undefined;
221
+ }>>;
222
+ }, "strip", z.ZodTypeAny, {
223
+ enabled: boolean;
224
+ autoApproveSafe: boolean;
225
+ defaultTimeoutMs: number;
226
+ maxTimeoutMs: number;
227
+ maxCaptureBytes: number;
228
+ maxModelOutputChars: number;
229
+ session: {
230
+ maxOutputTokens: number;
231
+ enabled: boolean;
232
+ maxSessions: number;
233
+ defaultYieldMs: number;
234
+ };
235
+ }, {
236
+ enabled?: boolean | undefined;
237
+ autoApproveSafe?: boolean | undefined;
238
+ defaultTimeoutMs?: number | undefined;
239
+ maxTimeoutMs?: number | undefined;
240
+ maxCaptureBytes?: number | undefined;
241
+ maxModelOutputChars?: number | undefined;
242
+ session?: {
243
+ maxOutputTokens?: number | undefined;
244
+ enabled?: boolean | undefined;
245
+ maxSessions?: number | undefined;
246
+ defaultYieldMs?: number | undefined;
247
+ } | undefined;
248
+ }>>;
133
249
  }, "strip", z.ZodTypeAny, {
250
+ shell: {
251
+ enabled: boolean;
252
+ autoApproveSafe: boolean;
253
+ defaultTimeoutMs: number;
254
+ maxTimeoutMs: number;
255
+ maxCaptureBytes: number;
256
+ maxModelOutputChars: number;
257
+ session: {
258
+ maxOutputTokens: number;
259
+ enabled: boolean;
260
+ maxSessions: number;
261
+ defaultYieldMs: number;
262
+ };
263
+ };
134
264
  maxSteps: number;
135
265
  turnTimeoutMs: number;
136
266
  threadsDir: string;
@@ -150,6 +280,20 @@ export declare const runtimeConfigSchema: z.ZodObject<{
150
280
  provider?: string | undefined;
151
281
  contextWindow?: number | undefined;
152
282
  }, {
283
+ shell?: {
284
+ enabled?: boolean | undefined;
285
+ autoApproveSafe?: boolean | undefined;
286
+ defaultTimeoutMs?: number | undefined;
287
+ maxTimeoutMs?: number | undefined;
288
+ maxCaptureBytes?: number | undefined;
289
+ maxModelOutputChars?: number | undefined;
290
+ session?: {
291
+ maxOutputTokens?: number | undefined;
292
+ enabled?: boolean | undefined;
293
+ maxSessions?: number | undefined;
294
+ defaultYieldMs?: number | undefined;
295
+ } | undefined;
296
+ } | undefined;
153
297
  model?: string | undefined;
154
298
  provider?: string | undefined;
155
299
  maxSteps?: number | undefined;
@@ -621,7 +765,71 @@ export declare const rollConfigSchema: z.ZodObject<{
621
765
  keepRecentTurns?: number | undefined;
622
766
  keepRecentTokens?: number | undefined;
623
767
  }>>;
768
+ shell: z.ZodDefault<z.ZodObject<{
769
+ enabled: z.ZodDefault<z.ZodBoolean>;
770
+ autoApproveSafe: z.ZodDefault<z.ZodBoolean>;
771
+ defaultTimeoutMs: z.ZodDefault<z.ZodNumber>;
772
+ maxTimeoutMs: z.ZodDefault<z.ZodNumber>;
773
+ maxCaptureBytes: z.ZodDefault<z.ZodNumber>;
774
+ maxModelOutputChars: z.ZodDefault<z.ZodNumber>;
775
+ session: z.ZodDefault<z.ZodObject<{
776
+ enabled: z.ZodDefault<z.ZodBoolean>;
777
+ maxSessions: z.ZodDefault<z.ZodNumber>;
778
+ defaultYieldMs: z.ZodDefault<z.ZodNumber>;
779
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
780
+ }, "strip", z.ZodTypeAny, {
781
+ maxOutputTokens: number;
782
+ enabled: boolean;
783
+ maxSessions: number;
784
+ defaultYieldMs: number;
785
+ }, {
786
+ maxOutputTokens?: number | undefined;
787
+ enabled?: boolean | undefined;
788
+ maxSessions?: number | undefined;
789
+ defaultYieldMs?: number | undefined;
790
+ }>>;
791
+ }, "strip", z.ZodTypeAny, {
792
+ enabled: boolean;
793
+ autoApproveSafe: boolean;
794
+ defaultTimeoutMs: number;
795
+ maxTimeoutMs: number;
796
+ maxCaptureBytes: number;
797
+ maxModelOutputChars: number;
798
+ session: {
799
+ maxOutputTokens: number;
800
+ enabled: boolean;
801
+ maxSessions: number;
802
+ defaultYieldMs: number;
803
+ };
804
+ }, {
805
+ enabled?: boolean | undefined;
806
+ autoApproveSafe?: boolean | undefined;
807
+ defaultTimeoutMs?: number | undefined;
808
+ maxTimeoutMs?: number | undefined;
809
+ maxCaptureBytes?: number | undefined;
810
+ maxModelOutputChars?: number | undefined;
811
+ session?: {
812
+ maxOutputTokens?: number | undefined;
813
+ enabled?: boolean | undefined;
814
+ maxSessions?: number | undefined;
815
+ defaultYieldMs?: number | undefined;
816
+ } | undefined;
817
+ }>>;
624
818
  }, "strip", z.ZodTypeAny, {
819
+ shell: {
820
+ enabled: boolean;
821
+ autoApproveSafe: boolean;
822
+ defaultTimeoutMs: number;
823
+ maxTimeoutMs: number;
824
+ maxCaptureBytes: number;
825
+ maxModelOutputChars: number;
826
+ session: {
827
+ maxOutputTokens: number;
828
+ enabled: boolean;
829
+ maxSessions: number;
830
+ defaultYieldMs: number;
831
+ };
832
+ };
625
833
  maxSteps: number;
626
834
  turnTimeoutMs: number;
627
835
  threadsDir: string;
@@ -641,6 +849,20 @@ export declare const rollConfigSchema: z.ZodObject<{
641
849
  provider?: string | undefined;
642
850
  contextWindow?: number | undefined;
643
851
  }, {
852
+ shell?: {
853
+ enabled?: boolean | undefined;
854
+ autoApproveSafe?: boolean | undefined;
855
+ defaultTimeoutMs?: number | undefined;
856
+ maxTimeoutMs?: number | undefined;
857
+ maxCaptureBytes?: number | undefined;
858
+ maxModelOutputChars?: number | undefined;
859
+ session?: {
860
+ maxOutputTokens?: number | undefined;
861
+ enabled?: boolean | undefined;
862
+ maxSessions?: number | undefined;
863
+ defaultYieldMs?: number | undefined;
864
+ } | undefined;
865
+ } | undefined;
644
866
  model?: string | undefined;
645
867
  provider?: string | undefined;
646
868
  maxSteps?: number | undefined;
@@ -962,6 +1184,20 @@ export declare const rollConfigSchema: z.ZodObject<{
962
1184
  }>;
963
1185
  };
964
1186
  runtime: {
1187
+ shell: {
1188
+ enabled: boolean;
1189
+ autoApproveSafe: boolean;
1190
+ defaultTimeoutMs: number;
1191
+ maxTimeoutMs: number;
1192
+ maxCaptureBytes: number;
1193
+ maxModelOutputChars: number;
1194
+ session: {
1195
+ maxOutputTokens: number;
1196
+ enabled: boolean;
1197
+ maxSessions: number;
1198
+ defaultYieldMs: number;
1199
+ };
1200
+ };
965
1201
  maxSteps: number;
966
1202
  turnTimeoutMs: number;
967
1203
  threadsDir: string;
@@ -1037,6 +1273,20 @@ export declare const rollConfigSchema: z.ZodObject<{
1037
1273
  }> | undefined;
1038
1274
  } | undefined;
1039
1275
  runtime?: {
1276
+ shell?: {
1277
+ enabled?: boolean | undefined;
1278
+ autoApproveSafe?: boolean | undefined;
1279
+ defaultTimeoutMs?: number | undefined;
1280
+ maxTimeoutMs?: number | undefined;
1281
+ maxCaptureBytes?: number | undefined;
1282
+ maxModelOutputChars?: number | undefined;
1283
+ session?: {
1284
+ maxOutputTokens?: number | undefined;
1285
+ enabled?: boolean | undefined;
1286
+ maxSessions?: number | undefined;
1287
+ defaultYieldMs?: number | undefined;
1288
+ } | undefined;
1289
+ } | undefined;
1040
1290
  model?: string | undefined;
1041
1291
  provider?: string | undefined;
1042
1292
  maxSteps?: number | undefined;
@@ -1 +1 @@
1
- import{z as e}from"zod";const t=["zhipin","yupao"],o=["managed-cdp","remote-cdp","existing-session"],n=["chrome","chromium","msedge"],i=["guarded","auto","deny"],r=["auto","confirm","deny"],a=["summarize","truncate"],s=e.string().trim().regex(/^#[\da-fA-F]{6}$/,"profileColor must be a hex RGB color such as #2563EB").transform(e=>e.toUpperCase());export const browserWindowBoundsSchema=e.object({x:e.number().int().optional(),y:e.number().int().optional(),width:e.number().int().positive().optional(),height:e.number().int().positive().optional()});export const providerConfigSchema=e.object({apiKey:e.string(),baseUrl:e.string().optional()});export const llmConfigSchema=e.object({defaultProvider:e.string(),defaultModel:e.string(),providers:e.record(e.string(),providerConfigSchema)});export const askConfigSchema=e.object({llmModel:e.string().optional(),confirmThreshold:e.number().optional()});export const runtimeApprovalConfigSchema=e.object({default:e.enum(i).default("guarded"),overrides:e.record(e.string(),e.enum(r)).default({})});export const runtimeCompactionConfigSchema=e.object({enabled:e.boolean().default(!0),strategy:e.enum(a).default("summarize"),threshold:e.number().min(.1).max(.95).default(.75),keepRecentTurns:e.number().int().min(1).default(4),keepRecentTokens:e.number().int().min(1).default(32e3)});export const runtimeThinkingLevels=["off","low","medium","high"];export const runtimeConfigSchema=e.object({provider:e.string().optional(),model:e.string().optional(),maxSteps:e.number().int().min(1).default(80),turnTimeoutMs:e.number().int().min(1e4).default(3e5),threadsDir:e.string().default("~/.roll-agent/threads"),contextWindow:e.number().int().min(1).optional(),thinkingLevel:e.enum(runtimeThinkingLevels).default("medium"),approval:runtimeApprovalConfigSchema.default({}),compaction:runtimeCompactionConfigSchema.default({})});export const skillsConfigSchema=e.object({dirs:e.array(e.string().trim().min(1)).default([])});export const agentsConfigSchema=e.object({dataDir:e.string(),env:e.record(e.string(),e.record(e.string(),e.string())).optional()});export const installConfigSchema=e.object({registry:e.string().trim().url().optional(),fetchRetries:e.number().int().min(0).max(10).default(3),preferOffline:e.boolean().default(!1),networkTimeoutMs:e.number().int().min(1e4).default(12e4)});export const browserInstanceConfigSchema=e.object({platform:e.enum(t).optional(),mode:e.enum(o).default("managed-cdp"),headless:e.boolean().optional(),cdpUrl:e.string().optional(),cdpHost:e.string().default("127.0.0.1"),cdpPort:e.number().int().min(1).max(65535).optional(),channel:e.enum(n).default("chrome"),executablePath:e.string().optional(),userDataDir:e.string().trim().min(1),sessionsDir:e.string().trim().min(1).optional(),args:e.array(e.string()).optional(),profileName:e.string().trim().min(1).optional(),profileColor:s.optional(),windowBounds:browserWindowBoundsSchema.optional(),trackingAgentId:e.string().trim().min(1).optional()}).superRefine((t,o)=>{"managed-cdp"===t.mode&&void 0===t.cdpPort&&o.addIssue({code:e.ZodIssueCode.custom,path:["cdpPort"],message:"managed-cdp browser instance requires cdpPort"}),"remote-cdp"!==t.mode&&"existing-session"!==t.mode||void 0!==t.cdpUrl||o.addIssue({code:e.ZodIssueCode.custom,path:["cdpUrl"],message:`${t.mode} browser instance requires cdpUrl`})});export const browserConfigSchema=e.object({defaultInstance:e.string().trim().min(1).optional(),instances:e.record(e.string(),browserInstanceConfigSchema).default({})}).superRefine((t,o)=>{const n=Object.entries(t.instances);void 0!==t.defaultInstance&&void 0===t.instances[t.defaultInstance]&&o.addIssue({code:e.ZodIssueCode.custom,path:["defaultInstance"],message:`defaultInstance "${t.defaultInstance}" is not declared in browser.instances`});const i=new Map,r=new Map;for(const[t,a]of n){if(void 0!==a.cdpPort){const n=i.get(a.cdpPort);void 0!==n?o.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"cdpPort"],message:`cdpPort ${String(a.cdpPort)} is already used by browser instance "${n}"`}):i.set(a.cdpPort,t)}const n=r.get(a.userDataDir);void 0!==n?o.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"userDataDir"],message:`userDataDir is already used by browser instance "${n}"`}):r.set(a.userDataDir,t)}});export const rollConfigSchema=e.object({llm:llmConfigSchema,ask:askConfigSchema,runtime:runtimeConfigSchema.default({}),skills:skillsConfigSchema.default({}),agents:agentsConfigSchema,install:installConfigSchema.default({}),browser:browserConfigSchema.default({})});
1
+ import{z as e}from"zod";const t=["zhipin","yupao"],n=["managed-cdp","remote-cdp","existing-session"],o=["chrome","chromium","msedge"],i=["guarded","auto","deny"],a=["auto","confirm","deny"],r=["summarize","truncate"],s=e.string().trim().regex(/^#[\da-fA-F]{6}$/,"profileColor must be a hex RGB color such as #2563EB").transform(e=>e.toUpperCase());export const browserWindowBoundsSchema=e.object({x:e.number().int().optional(),y:e.number().int().optional(),width:e.number().int().positive().optional(),height:e.number().int().positive().optional()});export const providerConfigSchema=e.object({apiKey:e.string(),baseUrl:e.string().optional()});export const llmConfigSchema=e.object({defaultProvider:e.string(),defaultModel:e.string(),providers:e.record(e.string(),providerConfigSchema)});export const askConfigSchema=e.object({llmModel:e.string().optional(),confirmThreshold:e.number().optional()});export const runtimeApprovalConfigSchema=e.object({default:e.enum(i).default("guarded"),overrides:e.record(e.string(),e.enum(a)).default({})});export const runtimeCompactionConfigSchema=e.object({enabled:e.boolean().default(!0),strategy:e.enum(r).default("summarize"),threshold:e.number().min(.1).max(.95).default(.75),keepRecentTurns:e.number().int().min(1).default(4),keepRecentTokens:e.number().int().min(1).default(32e3)});export const runtimeThinkingLevels=["off","low","medium","high"];export const runtimeShellSessionConfigSchema=e.object({enabled:e.boolean().default(!1),maxSessions:e.number().int().min(1).max(64).default(8),defaultYieldMs:e.number().int().min(250).max(3e4).default(1e4),maxOutputTokens:e.number().int().min(256).default(1e4)});export const runtimeShellConfigSchema=e.object({enabled:e.boolean().default(!1),autoApproveSafe:e.boolean().default(!0),defaultTimeoutMs:e.number().int().min(1e3).max(6e5).default(1e4),maxTimeoutMs:e.number().int().min(1e3).max(6e5).default(6e5),maxCaptureBytes:e.number().int().min(16384).default(1048576),maxModelOutputChars:e.number().int().min(1e3).default(16e3),session:runtimeShellSessionConfigSchema.default({})});export const runtimeConfigSchema=e.object({provider:e.string().optional(),model:e.string().optional(),maxSteps:e.number().int().min(1).default(80),turnTimeoutMs:e.number().int().min(1e4).default(3e5),threadsDir:e.string().default("~/.roll-agent/threads"),contextWindow:e.number().int().min(1).optional(),thinkingLevel:e.enum(runtimeThinkingLevels).default("medium"),approval:runtimeApprovalConfigSchema.default({}),compaction:runtimeCompactionConfigSchema.default({}),shell:runtimeShellConfigSchema.default({})});export const skillsConfigSchema=e.object({dirs:e.array(e.string().trim().min(1)).default([])});export const agentsConfigSchema=e.object({dataDir:e.string(),env:e.record(e.string(),e.record(e.string(),e.string())).optional()});export const installConfigSchema=e.object({registry:e.string().trim().url().optional(),fetchRetries:e.number().int().min(0).max(10).default(3),preferOffline:e.boolean().default(!1),networkTimeoutMs:e.number().int().min(1e4).default(12e4)});export const browserInstanceConfigSchema=e.object({platform:e.enum(t).optional(),mode:e.enum(n).default("managed-cdp"),headless:e.boolean().optional(),cdpUrl:e.string().optional(),cdpHost:e.string().default("127.0.0.1"),cdpPort:e.number().int().min(1).max(65535).optional(),channel:e.enum(o).default("chrome"),executablePath:e.string().optional(),userDataDir:e.string().trim().min(1),sessionsDir:e.string().trim().min(1).optional(),args:e.array(e.string()).optional(),profileName:e.string().trim().min(1).optional(),profileColor:s.optional(),windowBounds:browserWindowBoundsSchema.optional(),trackingAgentId:e.string().trim().min(1).optional()}).superRefine((t,n)=>{"managed-cdp"===t.mode&&void 0===t.cdpPort&&n.addIssue({code:e.ZodIssueCode.custom,path:["cdpPort"],message:"managed-cdp browser instance requires cdpPort"}),"remote-cdp"!==t.mode&&"existing-session"!==t.mode||void 0!==t.cdpUrl||n.addIssue({code:e.ZodIssueCode.custom,path:["cdpUrl"],message:`${t.mode} browser instance requires cdpUrl`})});export const browserConfigSchema=e.object({defaultInstance:e.string().trim().min(1).optional(),instances:e.record(e.string(),browserInstanceConfigSchema).default({})}).superRefine((t,n)=>{const o=Object.entries(t.instances);void 0!==t.defaultInstance&&void 0===t.instances[t.defaultInstance]&&n.addIssue({code:e.ZodIssueCode.custom,path:["defaultInstance"],message:`defaultInstance "${t.defaultInstance}" is not declared in browser.instances`});const i=new Map,a=new Map;for(const[t,r]of o){if(void 0!==r.cdpPort){const o=i.get(r.cdpPort);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"cdpPort"],message:`cdpPort ${String(r.cdpPort)} is already used by browser instance "${o}"`}):i.set(r.cdpPort,t)}const o=a.get(r.userDataDir);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"userDataDir"],message:`userDataDir is already used by browser instance "${o}"`}):a.set(r.userDataDir,t)}});export const rollConfigSchema=e.object({llm:llmConfigSchema,ask:askConfigSchema,runtime:runtimeConfigSchema.default({}),skills:skillsConfigSchema.default({}),agents:agentsConfigSchema,install:installConfigSchema.default({}),browser:browserConfigSchema.default({})});
@@ -15,10 +15,22 @@ export interface ResolvedLLMCall {
15
15
  readonly model: LanguageModelV4;
16
16
  readonly providerOptions?: SharedV4ProviderOptions;
17
17
  }
18
+ /**
19
+ * 把 resolveLLMCall(..., "sampling", ...) 的结果转换成
20
+ * McpClientManager.connect() 需要的 samplingModel/samplingProviderOptions 字段。
21
+ * 统一入口,避免每个调用方(ask/run/chat)各自拼一份、漏传 providerOptions。
22
+ */
23
+ export declare function toSamplingConnectOptions(call: ResolvedLLMCall | undefined): {
24
+ readonly samplingModel?: LanguageModelV4;
25
+ readonly samplingProviderOptions?: SharedV4ProviderOptions;
26
+ };
18
27
  /**
19
28
  * 按 provider + 调用目的解析 generateText 的完整调用上下文。
20
29
  *
21
30
  * structured-output 场景下,对 qwen provider 自动注入 enableThinking: false,
22
31
  * 因为阿里云 thinking mode 不支持 structured output。
32
+ *
33
+ * chat 与 sampling 场景下都是纯文本 generateText 调用,复用同一套
34
+ * thinkingProviderOptions 映射注入 reasoning/thinking effort。
23
35
  */
24
36
  export declare function resolveLLMCall(providerName: string, modelName: string, apiKey: string, purpose: LLMCallPurpose, baseURL?: string, thinkingLevel?: ThinkingLevel): ResolvedLLMCall;
@@ -1 +1 @@
1
- import{createAlibaba as e}from"@ai-sdk/alibaba";import{createAnthropic as i}from"@ai-sdk/anthropic";import{createOpenAI as n}from"@ai-sdk/openai";import{createDeepSeek as o}from"@ai-sdk/deepseek";import{runtimeThinkingLevels as t}from"../config/schema.js";const a={low:2048,medium:8192,high:16384},r=["gpt-5.1","gpt-5.2","gpt-5.3","gpt-5.4"];function p(e){return r.some(i=>e.startsWith(i))}function s(e){const i=/^claude-[a-z]+-(\d+)(?:-(\d+))?(?:\b|-)/.exec(e),n=i?.[1];if(!n)return!1;const o=Number(n),t=i?.[2],a=void 0!==t&&t.length<=2?Number(t):0;return o>4||4===o&&a>=6}export function thinkingProviderOptions(e,i,n){return"openai"===e?"off"===n?p(i)?{openai:{reasoningEffort:"none"}}:void 0:{openai:{reasoningEffort:n}}:"anthropic"===e?"off"===n?{anthropic:{thinking:{type:"disabled"}}}:s(i)?{anthropic:{thinking:{type:"adaptive"},effort:n}}:{anthropic:{thinking:{type:"enabled",budgetTokens:a[n]}}}:"qwen"===e?"off"===n?{alibaba:{enableThinking:!1}}:{alibaba:{enableThinking:!0,thinkingBudget:a[n]}}:"deepseek"===e?{deepseek:{thinking:{type:"off"===n?"disabled":"enabled"}}}:void 0}const d="https://dashscope.aliyuncs.com/compatible-mode/v1",c={anthropic:(e,{apiKey:n,baseURL:o})=>i({apiKey:n,...o?{baseURL:o}:{}})(e),openai:(e,{apiKey:i,baseURL:o})=>n({apiKey:i,...o?{baseURL:o}:{}})(e),deepseek:(e,{apiKey:i,baseURL:n})=>o({apiKey:i,...n?{baseURL:n}:{}})(e),qwen:(i,{apiKey:n,baseURL:o})=>e({apiKey:n,baseURL:o??d})(i)};export function createProviderModel(e,i,n,o){const t=c[e];if(!t){const i=Object.keys(c).join(", ");throw new Error(`Unknown LLM provider "${e}". Supported: ${i}`)}return t(i,{apiKey:n,baseURL:o})}export function resolveLLMCall(e,i,n,o,t,a="medium"){const r=createProviderModel(e,i,n,t);if("structured-output"===o&&"qwen"===e)return{model:r,providerOptions:{alibaba:{enableThinking:!1}}};if("chat"===o){const n=thinkingProviderOptions(e,i,a);return n?{model:r,providerOptions:n}:{model:r}}return{model:r}}
1
+ import{createAlibaba as e}from"@ai-sdk/alibaba";import{createAnthropic as i}from"@ai-sdk/anthropic";import{createOpenAI as n}from"@ai-sdk/openai";import{createDeepSeek as o}from"@ai-sdk/deepseek";import{runtimeThinkingLevels as t}from"../config/schema.js";const r={low:2048,medium:8192,high:16384},a=["gpt-5.1","gpt-5.2","gpt-5.3","gpt-5.4"];function p(e){return a.some(i=>e.startsWith(i))}function s(e){const i=/^claude-[a-z]+-(\d+)(?:-(\d+))?(?:\b|-)/.exec(e),n=i?.[1];if(!n)return!1;const o=Number(n),t=i?.[2],r=void 0!==t&&t.length<=2?Number(t):0;return o>4||4===o&&r>=6}export function thinkingProviderOptions(e,i,n){return"openai"===e?"off"===n?p(i)?{openai:{reasoningEffort:"none"}}:void 0:{openai:{reasoningEffort:n}}:"anthropic"===e?"off"===n?{anthropic:{thinking:{type:"disabled"}}}:s(i)?{anthropic:{thinking:{type:"adaptive"},effort:n}}:{anthropic:{thinking:{type:"enabled",budgetTokens:r[n]}}}:"qwen"===e?"off"===n?{alibaba:{enableThinking:!1}}:{alibaba:{enableThinking:!0,thinkingBudget:r[n]}}:"deepseek"===e?{deepseek:{thinking:{type:"off"===n?"disabled":"enabled"}}}:void 0}const d="https://dashscope.aliyuncs.com/compatible-mode/v1",c={anthropic:(e,{apiKey:n,baseURL:o})=>i({apiKey:n,...o?{baseURL:o}:{}})(e),openai:(e,{apiKey:i,baseURL:o})=>n({apiKey:i,...o?{baseURL:o}:{}})(e),deepseek:(e,{apiKey:i,baseURL:n})=>o({apiKey:i,...n?{baseURL:n}:{}})(e),qwen:(i,{apiKey:n,baseURL:o})=>e({apiKey:n,baseURL:o??d})(i)};export function createProviderModel(e,i,n,o){const t=c[e];if(!t){const i=Object.keys(c).join(", ");throw new Error(`Unknown LLM provider "${e}". Supported: ${i}`)}return t(i,{apiKey:n,baseURL:o})}export function toSamplingConnectOptions(e){return e?{samplingModel:e.model,...e.providerOptions?{samplingProviderOptions:e.providerOptions}:{}}:{}}export function resolveLLMCall(e,i,n,o,t,r="medium"){const a=createProviderModel(e,i,n,t);if("structured-output"===o&&"qwen"===e)return{model:a,providerOptions:{alibaba:{enableThinking:!1}}};if("chat"===o||"sampling"===o){const n=thinkingProviderOptions(e,i,r);return n?{model:a,providerOptions:n}:{model:a}}return{model:a}}
@@ -1,11 +1,13 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import type { LanguageModelV4 } from "@ai-sdk/provider";
2
+ import type { LanguageModelV4, SharedV4ProviderOptions } from "@ai-sdk/provider";
3
3
  import type { AgentTransport } from "../types/agent.ts";
4
4
  export interface ConnectOptions {
5
5
  /** 连接超时(毫秒),默认 30s */
6
6
  readonly timeoutMs?: number;
7
7
  /** 为子 Agent 提供的 LLM model(启用 Sampling 支持) */
8
8
  readonly samplingModel?: LanguageModelV4;
9
+ /** Sampling 调用的 provider 级参数(如 reasoning/thinking effort) */
10
+ readonly samplingProviderOptions?: SharedV4ProviderOptions;
9
11
  /** 注入到 stdio 子进程的环境变量(与 process.env 合并) */
10
12
  readonly env?: Readonly<Record<string, string>>;
11
13
  }
@@ -28,6 +30,8 @@ export declare class McpClientManager {
28
30
  * @param cwd 仅 stdio 模式使用,作为子进程工作目录
29
31
  */
30
32
  connect(agentName: string, transport: AgentTransport, cwd: string, options?: ConnectOptions): Promise<Client>;
33
+ /** 更新全部已连接 Agent 后续 Sampling 请求使用的 provider 参数。 */
34
+ setSamplingProviderOptions(providerOptions: SharedV4ProviderOptions | undefined): void;
31
35
  /** 断开指定 Agent 的连接 */
32
36
  disconnect(agentName: string): Promise<void>;
33
37
  /** 断开所有连接 */
@@ -1 +1 @@
1
- import{Client as n}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as t}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as e}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{registerSamplingHandler as o}from"./sampling-handler.js";const s=3e4,i="--disable-warning=ExperimentalWarning";export function buildStdioChildEnv(n){const t=n?{...process.env,...n}:{};return{...t,NODE_OPTIONS:r(t.NODE_OPTIONS,i),ROLL_AGENT_LOG_LEVEL:t.ROLL_AGENT_LOG_LEVEL??"warn",PYTHONUTF8:t.PYTHONUTF8??"1",PYTHONIOENCODING:t.PYTHONIOENCODING??"utf-8"}}function r(n,t){const e=n?.trim();if(!e)return t;const o=e.split(/\s+/);return o.includes("--no-warnings")||o.includes(t)?e:`${e} ${t}`}export function shouldSuppressStdioChildStderrLine(n){const t=n.trim();return t.includes("ExperimentalWarning:")||t.startsWith("(Use `node --trace-warnings")||/\[INFO\s*\]\s*\[[^\]]+\]\s*MCP Server running on stdio$/.test(t)}function c(n,e,o){const s=new t({command:n.command,args:[...n.args??[]],cwd:e,env:buildStdioChildEnv(o),stderr:"pipe"});return l(s),s}function l(n){const t=n.stderr;if(!t)return;let e="";const o=n=>{shouldSuppressStdioChildStderrLine(n)||process.stderr.write(`${n}\n`)};t.on("data",n=>{e+=n.toString();const t=e.split(/\r?\n/);e=t.pop()??"";for(const n of t)o(n)}),t.on("end",()=>{e.length>0&&(o(e),e="")})}export class McpClientManager{connections=new Map;async connect(t,i,r,l={}){const a=this.connections.get(t);if(a)return a.client;const d=l.timeoutMs??s,p=l.samplingModel?{sampling:{}}:{},m=new n({name:`roll-client-${t}`,version:"0.0.1"},{capabilities:p});l.samplingModel&&o(m,l.samplingModel);const u="streamable-http"===i.type?new e(new URL(i.endpoint)):c(i,r,l.env),h=m.connect(u);let O;const g=new Promise((n,e)=>{O=setTimeout(()=>e(new Error(`Connection to "${t}" timed out after ${d}ms`)),d)});try{await Promise.race([h,g])}catch(n){throw await m.close().catch(()=>{}),n}finally{clearTimeout(O)}return this.connections.set(t,{client:m,transportType:i.type}),m}async disconnect(n){const t=this.connections.get(n);t&&(await t.client.close(),this.connections.delete(n))}async disconnectAll(){const n=[...this.connections.keys()];await Promise.all(n.map(n=>this.disconnect(n)))}isConnected(n){return this.connections.has(n)}}
1
+ import{Client as n}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as t}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as e}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{registerSamplingHandler as o}from"./sampling-handler.js";const s=3e4,i="--disable-warning=ExperimentalWarning";export function buildStdioChildEnv(n){const t={...process.env,...n??{}};return{...t,NODE_OPTIONS:r(t.NODE_OPTIONS,i),ROLL_AGENT_LOG_LEVEL:t.ROLL_AGENT_LOG_LEVEL??"warn",PYTHONUTF8:t.PYTHONUTF8??"1",PYTHONIOENCODING:t.PYTHONIOENCODING??"utf-8"}}function r(n,t){const e=n?.trim();if(!e)return t;const o=e.split(/\s+/);return o.includes("--no-warnings")||o.includes(t)?e:`${e} ${t}`}export function shouldSuppressStdioChildStderrLine(n){const t=n.trim();return t.includes("ExperimentalWarning:")||t.startsWith("(Use `node --trace-warnings")||/\[INFO\s*\]\s*\[[^\]]+\]\s*MCP Server running on stdio$/.test(t)}function c(n,e,o){const s=new t({command:n.command,args:[...n.args??[]],cwd:e,env:buildStdioChildEnv(o),stderr:"pipe"});return l(s),s}function l(n){const t=n.stderr;if(!t)return;let e="";const o=n=>{shouldSuppressStdioChildStderrLine(n)||process.stderr.write(`${n}\n`)};t.on("data",n=>{e+=n.toString();const t=e.split(/\r?\n/);e=t.pop()??"";for(const n of t)o(n)}),t.on("end",()=>{e.length>0&&(o(e),e="")})}export class McpClientManager{connections=new Map;async connect(t,i,r,l={}){const a=this.connections.get(t);if(a)return a.client;const d=l.timeoutMs??s,p=l.samplingModel?{sampling:{}}:{},m=new n({name:`roll-client-${t}`,version:"0.0.1"},{capabilities:p}),u=l.samplingModel?o(m,l.samplingModel,l.samplingProviderOptions):void 0,g="streamable-http"===i.type?new e(new URL(i.endpoint)):c(i,r,l.env),h=m.connect(g);let O;const f=new Promise((n,e)=>{O=setTimeout(()=>e(new Error(`Connection to "${t}" timed out after ${d}ms`)),d)});try{await Promise.race([h,f])}catch(n){throw await m.close().catch(()=>{}),n}finally{clearTimeout(O)}return this.connections.set(t,{client:m,transportType:i.type,...u?{samplingController:u}:{}}),m}setSamplingProviderOptions(n){for(const t of this.connections.values())t.samplingController?.setProviderOptions(n)}async disconnect(n){const t=this.connections.get(n);t&&(await t.client.close(),this.connections.delete(n))}async disconnectAll(){const n=[...this.connections.keys()];await Promise.all(n.map(n=>this.disconnect(n)))}isConnected(n){return this.connections.has(n)}}
@@ -1,5 +1,17 @@
1
1
  import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import type { LanguageModelV4 } from "@ai-sdk/provider";
2
+ import type { ModelMessage } from "ai";
3
+ import type { LanguageModelV4, SharedV4ProviderOptions } from "@ai-sdk/provider";
4
+ export interface SamplingHandlerController {
5
+ /** 更新后续 Sampling 请求使用的 provider 参数;不影响已经发出的请求。 */
6
+ setProviderOptions(providerOptions: SharedV4ProviderOptions | undefined): void;
7
+ }
8
+ /** 组装传给 AI SDK generateText() 的调用参数(供单测复用,不依赖真实网络请求) */
9
+ export declare function buildSamplingGenerateTextParams(model: LanguageModelV4, messages: ModelMessage[], maxTokens: number, providerOptions?: SharedV4ProviderOptions): {
10
+ providerOptions?: SharedV4ProviderOptions;
11
+ maxOutputTokens?: number;
12
+ model: LanguageModelV4;
13
+ messages: ModelMessage[];
14
+ };
3
15
  /**
4
16
  * 在 MCP Client 上注册 Sampling Handler。
5
17
  *
@@ -8,4 +20,4 @@ import type { LanguageModelV4 } from "@ai-sdk/provider";
8
20
  *
9
21
  * @see https://spec.modelcontextprotocol.io/specification/client/sampling/
10
22
  */
11
- export declare function registerSamplingHandler(client: Client, model: LanguageModelV4): void;
23
+ export declare function registerSamplingHandler(client: Client, model: LanguageModelV4, providerOptions?: SharedV4ProviderOptions): SamplingHandlerController;
@@ -1 +1 @@
1
- import{CreateMessageRequestSchema as t}from"@modelcontextprotocol/sdk/types.js";import{generateText as e}from"ai";export function registerSamplingHandler(o,s){o.setRequestHandler(t,async t=>{const o=n(t.params.messages),r=t.params.maxTokens;let a;try{a=await e({model:s,messages:o,...r>0?{maxOutputTokens:r}:{}})}catch(t){throw new Error("Sampling handler: LLM generation failed",{cause:t})}return{role:"assistant",content:{type:"text",text:a.text},model:a.response.modelId,..."length"===a.finishReason?{stopReason:"maxTokens"}:{stopReason:"endTurn"}}})}function n(t){return t.map(t=>{const e=o(t.content);return"assistant"===t.role?{role:"assistant",content:[{type:"text",text:e}]}:{role:"user",content:[{type:"text",text:e}]}})}function o(t){if("string"==typeof t)return t;if("object"==typeof t&&null!==t&&"type"in t){const e=t;if("text"===e.type&&"string"==typeof e.text)return e.text}return JSON.stringify(t)}
1
+ import{CreateMessageRequestSchema as t}from"@modelcontextprotocol/sdk/types.js";import{generateText as e}from"ai";export function buildSamplingGenerateTextParams(t,e,n,r){return{model:t,messages:e,...n>0?{maxOutputTokens:n}:{},...r?{providerOptions:r}:{}}}export function registerSamplingHandler(r,o,s){let a=s;return r.setRequestHandler(t,async t=>{const r=n(t.params.messages),s=t.params.maxTokens;let i;try{i=await e(buildSamplingGenerateTextParams(o,r,s,a))}catch(t){throw new Error("Sampling handler: LLM generation failed",{cause:t})}return{role:"assistant",content:{type:"text",text:i.text},model:i.response.modelId,..."length"===i.finishReason?{stopReason:"maxTokens"}:{stopReason:"endTurn"}}}),{setProviderOptions(t){a=t}}}function n(t){return t.map(t=>{const e=r(t.content);return"assistant"===t.role?{role:"assistant",content:[{type:"text",text:e}]}:{role:"user",content:[{type:"text",text:e}]}})}function r(t){if("string"==typeof t)return t;if("object"==typeof t&&null!==t&&"type"in t){const e=t;if("text"===e.type&&"string"==typeof e.text)return e.text}return JSON.stringify(t)}