@tencent-ai/agent-harness 0.2.0-beta.5 → 0.2.0-beta.6

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.
@@ -1 +1 @@
1
- {"agents":[{"name":"cli","instructions":"cli-agent-prompt","description":"cli agent","models":["codewise-chat"],"modelTags":["craft"],"commands":["init","compact","statusline","insights"],"tools":["Agent","Read","Write","Edit","Bash","PowerShell","Glob","Grep","EnterPlanMode","ExitPlanMode","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","TaskStop","TaskOutput","Skill","AskUserQuestion","AskUserForStructuredInput","StructuredOutput","ToolSearch","DeferExecuteTool","SendMessage","SendUserMessage","TeamCreate","TeamDelete","NotebookEdit","LSP","EnterWorktree","LeaveWorktree","CronCreate","CronDelete","CronList","DelegateTool","WeChatReply","WeComReply","PushNotification","ReportFindings","ComputerUse","ListMcpResources","ReadMcpResource","WaitForMcpServers","Workflow","Monitor","REPL","A2AGetAgentCard","A2ASendMessage","A2AGetTask","A2ACancelTask"],"tags":["cli","default","model:craft"]},{"name":"general-purpose","instructions":"cli-agent-prompt","description":"general-purpose agent","tools":["Read","Write","Edit","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","TaskStop","TaskOutput","Skill","AskUserQuestion","AskUserForStructuredInput","ToolSearch","DeferExecuteTool","StructuredOutput","SendMessage","SendUserMessage","NotebookEdit","LSP","ComputerUse","ImageGen","ImageEdit","Artifact","ArtifactControl","ListMcpResources","ReadMcpResource","WaitForMcpServers","REPL"],"tags":["cli","general-purpose"]},{"name":"compact","instructions":"compact-agent-prompt","description":"compact agent","tools":["Read"],"commands":["_compact"],"tags":["cli","compact"]},{"name":"contextSummary","instructions":"context-summary-agent-prompt","description":"Context summary agent for conversation compaction and max-token recovery","tools":[],"tags":["cli","contextSummary"]},{"name":"contentAnalyzer","instructions":"content-analyzer-agent-instructions","description":"content analyzer agent","tags":["cli","content-analyzer"],"tools":[]},{"name":"terminalTitleGenerator","instructions":"terminal-title-generator-instructions","description":"Generate terminal window titles from conversation topics.","tags":["cli","terminal-title-generator"],"tools":[]},{"name":"promptSuggestion","instructions":"prompt-suggestion-instructions","description":"Suggest the user's next prompt after a conversation turn.","tags":["cli","prompt-suggestion"],"tools":[]},{"name":"memorySelector","instructions":"memory-selector-instructions","description":"Select relevant memories for the current query.","models":["lite"],"tags":["cli","memory-selector"],"tools":[]},{"name":"summaryGenerator","instructions":"summary-generator-instructions","description":"Generate session summaries from conversation content.","tags":["cli","summary-generator"],"tools":[]},{"name":"securityReviewer","instructions":"security-reviewer-instructions","description":"Review bounded security decisions without tools.","models":["lite"],"tags":["cli","security-reviewer"],"tools":[]},{"name":"autoModeClassifier","instructions":"auto-mode-classifier-instructions","description":"Classify auto mode tool permission risk.","models":["lite"],"tags":["cli","auto-mode-classifier"],"tools":[]},{"name":"promptHookEvaluator","instructions":"prompt-hook-evaluator-instructions","description":"Evaluates prompt hooks using LLM to determine if conditions are met","models":["lite"],"tags":["cli","prompt-hook-evaluator"],"tools":[]},{"name":"insightsAnalyzer","instructions":"base-agent-instructions","description":"Analyzes user usage data facets for the /insights command","tags":["cli","insights-analyzer"],"tools":[]},{"name":"agentInstructions","instructions":"agent-instructions","description":"generating agent instructions","tags":["cli","agent-instructions"],"tools":[]},{"name":"statusline-setup","instructions":"agent-statusline-instructions","description":"Use this agent to configure the user's Codebuddy Code status line setting.","tools":["Read","Write","Edit","ToolSearch","DeferExecuteTool"],"asTool":true,"tags":["cli","sub-agent"]},{"name":"Explore","instructions":"agent-explore-instructions","description":"Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. \"src/components/**/*.tsx\"), search code for keywords (eg. \"API endpoints\"), or answer questions about the codebase (eg. \"how do API endpoints work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"very thorough\" for comprehensive analysis across multiple locations and naming conventions.","models":["lite"],"tools":["Read","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","Skill","SendMessage","SendUserMessage","ToolSearch","DeferExecuteTool"],"asTool":true,"tags":["cli","sub-agent"]},{"name":"Plan","instructions":"agent-plan-instructions","description":"Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a multi-step task before writing code. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs. Read-only: it designs but does not modify files or exit plan mode; the caller reviews the plan and implements it.","tools":["Read","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","Skill","ToolSearch","DeferExecuteTool","TeamCreate","TeamDelete","SendMessage","SendUserMessage"],"asTool":true,"tags":["cli","sub-agent"]}],"models":[{"credits":"x0.01 credits","id":"codewise-chat","name":"Codewise-Chat","vendor":"tencent","maxOutputTokens":8192,"maxInputTokens":128000,"supportsToolCall":true,"supportsImages":false,"disabledMultimodal":true,"maxAllowedSize":56000}],"links":{"officialWebsite":"https://copilot.tencent.com/cli","helpDocument":"https://copilot.tencent.com/docs/cli","issueFeedback":"https://cnb.cool/codebuddy/codebuddy-code/-/issues","issueCreation":"https://cnb.cool/codebuddy/codebuddy-code/-/issues/new","mcpHelpDocument":"https://copilot.tencent.com/docs/cli/mcp","hooksHelpDocument":"https://copilot.tencent.com/docs/cli/hooks","sandboxHelpDocument":"https://copilot.tencent.com/docs/cli/bash-sandboxing","upgradeUrl":""},"productFeatures":{"BillingNotice":false,"ShareLink":true,"Artifact":true,"CodeAdoptionRate":false,"CloudAgentsSmartMerge":true,"CustomModelsJSON":true,"CustomModelIdPrefix":true,"DeferToolLoading":true,"ScheduledTasks":true,"SkipToolCallSupportCheck":true},"commit":"4fab1a63096092a0108ec779786ebf664fd51c4e","date":"2026-09-29T12:29:21.536Z"}
1
+ {"agents":[{"name":"cli","instructions":"cli-agent-prompt","description":"cli agent","models":["codewise-chat"],"modelTags":["craft"],"commands":["init","compact","statusline","insights"],"tools":["Agent","Read","Write","Edit","Bash","PowerShell","Glob","Grep","EnterPlanMode","ExitPlanMode","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","TaskStop","TaskOutput","Skill","AskUserQuestion","AskUserForStructuredInput","StructuredOutput","ToolSearch","DeferExecuteTool","SendMessage","SendUserMessage","TeamCreate","TeamDelete","NotebookEdit","LSP","EnterWorktree","LeaveWorktree","CronCreate","CronDelete","CronList","DelegateTool","WeChatReply","WeComReply","PushNotification","ReportFindings","ComputerUse","ListMcpResources","ReadMcpResource","WaitForMcpServers","Workflow","Monitor","REPL","A2AGetAgentCard","A2ASendMessage","A2AGetTask","A2ACancelTask"],"tags":["cli","default","model:craft"]},{"name":"general-purpose","instructions":"cli-agent-prompt","description":"general-purpose agent","tools":["Read","Write","Edit","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","TaskStop","TaskOutput","Skill","AskUserQuestion","AskUserForStructuredInput","ToolSearch","DeferExecuteTool","StructuredOutput","SendMessage","SendUserMessage","NotebookEdit","LSP","ComputerUse","ImageGen","ImageEdit","Artifact","ArtifactControl","ListMcpResources","ReadMcpResource","WaitForMcpServers","REPL"],"tags":["cli","general-purpose"]},{"name":"compact","instructions":"compact-agent-prompt","description":"compact agent","tools":["Read"],"commands":["_compact"],"tags":["cli","compact"]},{"name":"contextSummary","instructions":"context-summary-agent-prompt","description":"Context summary agent for conversation compaction and max-token recovery","tools":[],"tags":["cli","contextSummary"]},{"name":"contentAnalyzer","instructions":"content-analyzer-agent-instructions","description":"content analyzer agent","tags":["cli","content-analyzer"],"tools":[]},{"name":"terminalTitleGenerator","instructions":"terminal-title-generator-instructions","description":"Generate terminal window titles from conversation topics.","tags":["cli","terminal-title-generator"],"tools":[]},{"name":"promptSuggestion","instructions":"prompt-suggestion-instructions","description":"Suggest the user's next prompt after a conversation turn.","tags":["cli","prompt-suggestion"],"tools":[]},{"name":"memorySelector","instructions":"memory-selector-instructions","description":"Select relevant memories for the current query.","models":["lite"],"tags":["cli","memory-selector"],"tools":[]},{"name":"summaryGenerator","instructions":"summary-generator-instructions","description":"Generate session summaries from conversation content.","tags":["cli","summary-generator"],"tools":[]},{"name":"securityReviewer","instructions":"security-reviewer-instructions","description":"Review bounded security decisions without tools.","models":["lite"],"tags":["cli","security-reviewer"],"tools":[]},{"name":"autoModeClassifier","instructions":"auto-mode-classifier-instructions","description":"Classify auto mode tool permission risk.","models":["lite"],"tags":["cli","auto-mode-classifier"],"tools":[]},{"name":"promptHookEvaluator","instructions":"prompt-hook-evaluator-instructions","description":"Evaluates prompt hooks using LLM to determine if conditions are met","models":["lite"],"tags":["cli","prompt-hook-evaluator"],"tools":[]},{"name":"insightsAnalyzer","instructions":"base-agent-instructions","description":"Analyzes user usage data facets for the /insights command","tags":["cli","insights-analyzer"],"tools":[]},{"name":"agentInstructions","instructions":"agent-instructions","description":"generating agent instructions","tags":["cli","agent-instructions"],"tools":[]},{"name":"statusline-setup","instructions":"agent-statusline-instructions","description":"Use this agent to configure the user's Codebuddy Code status line setting.","tools":["Read","Write","Edit","ToolSearch","DeferExecuteTool"],"asTool":true,"tags":["cli","sub-agent"]},{"name":"Explore","instructions":"agent-explore-instructions","description":"Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. \"src/components/**/*.tsx\"), search code for keywords (eg. \"API endpoints\"), or answer questions about the codebase (eg. \"how do API endpoints work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"very thorough\" for comprehensive analysis across multiple locations and naming conventions.","models":["lite"],"tools":["Read","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","Skill","SendMessage","SendUserMessage","ToolSearch","DeferExecuteTool"],"asTool":true,"tags":["cli","sub-agent"]},{"name":"Plan","instructions":"agent-plan-instructions","description":"Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a multi-step task before writing code. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs. Read-only: it designs but does not modify files or exit plan mode; the caller reviews the plan and implements it.","tools":["Read","Bash","PowerShell","Glob","Grep","TaskCreate","TaskGet","TaskUpdate","TaskList","WebFetch","WebSearch","Skill","ToolSearch","DeferExecuteTool","TeamCreate","TeamDelete","SendMessage","SendUserMessage"],"asTool":true,"tags":["cli","sub-agent"]}],"models":[{"credits":"x0.01 credits","id":"codewise-chat","name":"Codewise-Chat","vendor":"tencent","maxOutputTokens":8192,"maxInputTokens":128000,"supportsToolCall":true,"supportsImages":false,"disabledMultimodal":true,"maxAllowedSize":56000}],"links":{"officialWebsite":"https://copilot.tencent.com/cli","helpDocument":"https://copilot.tencent.com/docs/cli","issueFeedback":"https://cnb.cool/codebuddy/codebuddy-code/-/issues","issueCreation":"https://cnb.cool/codebuddy/codebuddy-code/-/issues/new","mcpHelpDocument":"https://copilot.tencent.com/docs/cli/mcp","hooksHelpDocument":"https://copilot.tencent.com/docs/cli/hooks","sandboxHelpDocument":"https://copilot.tencent.com/docs/cli/bash-sandboxing","upgradeUrl":""},"productFeatures":{"BillingNotice":false,"ShareLink":true,"Artifact":true,"CodeAdoptionRate":false,"CloudAgentsSmartMerge":true,"CustomModelsJSON":true,"CustomModelIdPrefix":true,"DeferToolLoading":true,"ScheduledTasks":true,"SkipToolCallSupportCheck":true},"commit":"007f6802045720488fb36097c2abfbd1355f1f98","date":"2026-09-29T17:44:52.123Z"}
package/docs/client.md CHANGED
@@ -77,6 +77,11 @@ client.on('session/request_permission', (request, context) =>
77
77
  `void | Promise<void>`;各 listener 都会被调用并等待完成,一个 listener 失败不会阻止
78
78
  同一通知的其他 listener。
79
79
 
80
+ 权限弹窗按 `request.options` 展示,并返回用户选择的 `optionId`。普通工具提供
81
+ `kind: 'allow_always'` 时,表示允许该工具在本会话继续使用;未提供时只允许本次操作。
82
+ Defer 工具的 `title` 显示实际目标名称,授权不会覆盖整个 Defer 工具集合。强制审批不会因该授权跳过。
83
+ 通过会话配置进入 Plan 会记录当前权限模式,退出 Plan 后恢复它。
84
+
80
85
  沙箱审批的展示信息位于 `request.subject.toolCall._meta`(先确认 `subject.type === 'tool_call'`),
81
86
  包括 `codebuddy.ai/sandboxIntercept`、`interceptType`、`target`、`operation`、`description`、
82
87
  `sandboxRuleContext` 和 `bulkDeleteInfo` 等 `codebuddy.ai/` 字段。沙箱命令的“本次会话内允许”
@@ -4,7 +4,7 @@ import type { AcpV2ClientCapabilities, AcpV2SetSessionConfigOptionRequest } from
4
4
  import type { WorkspaceSessionModelConfigOption } from '../runtime/product-manager.js';
5
5
  import type { SessionConfigValues } from './config-store.js';
6
6
  export type SessionConfigProjector = (options: QueryOptions, catalog?: WorkspaceSessionModelConfigOption) => SessionConfigOption[];
7
- type ConfigQueryOptions = Pick<QueryOptions, 'model' | 'permissionMode' | 'thinking' | 'effort' | 'contextWindow' | 'agent' | 'multitask' | 'sandboxEnabled'>;
7
+ type ConfigQueryOptions = Pick<QueryOptions, 'model' | 'permissionMode' | 'permissionModeBeforePlan' | 'thinking' | 'effort' | 'contextWindow' | 'agent' | 'multitask' | 'sandboxEnabled'>;
8
8
  export interface SessionConfigDefaults {
9
9
  readonly sandboxEnabled?: boolean;
10
10
  readonly readFailed?: boolean;
@@ -27,16 +27,18 @@ export declare class ServerSessionConfig {
27
27
  get queryOptions(): ConfigQueryOptions;
28
28
  copy(): ServerSessionConfig;
29
29
  replace(config: ServerSessionConfig): void;
30
+ /** Persisted session state, including private Plan restoration metadata; ACP uses snapshot(). */
30
31
  selections(): SessionConfigValues;
31
32
  restore(values: SessionConfigValues): void;
32
33
  snapshot(): SessionConfigOption[];
33
34
  contextSize(modelId?: string): number | undefined;
34
- update(values: Pick<ConfigQueryOptions, 'permissionMode' | 'agent' | 'multitask'>, rememberChanges?: boolean): boolean;
35
+ update(values: Pick<ConfigQueryOptions, 'permissionMode' | 'permissionModeBeforePlan' | 'agent' | 'multitask'>, rememberChanges?: boolean): boolean;
35
36
  lockAgent(): void;
36
37
  initializeBlank(): void;
37
38
  set(params: AcpV2SetSessionConfigOptionRequest): void;
38
39
  private reconcileSelections;
39
40
  private remember;
41
+ private setPermissionMode;
40
42
  private apply;
41
43
  }
42
44
  export {};
@@ -1 +1 @@
1
- var h=Object.defineProperty;var r=(c,e)=>h(c,"name",{value:e,configurable:!0});import{AgentHarnessInvalidParamsError as l}from"../server/errors.js";function d(c){return c?.type==="select"&&Array.isArray(c.options)}r(d,"isSelect");export class ServerSessionConfig{static{r(this,"ServerSessionConfig")}constructor(e,i,n,s,t){this.options=e,this.catalog=i,this.project=n,this.restoreProject=s,this.projectContextSize=t,this.explicitSelections={},this.agentLocked=!1;const o=e.model??i?.currentValue;if(this.modelExplicit=e.model!==void 0,o&&i&&!i.options.some(a=>a.value===o))throw new l("Agent model is outside the admitted Harness catalog");this.values={model:o,permissionMode:e.permissionMode??e.settings?.permissions?.defaultMode??"default",...e.thinking?{thinking:e.thinking}:{},...e.effort!==void 0?{effort:e.effort}:{},...e.contextWindow!==void 0?{contextWindow:e.contextWindow}:{},...e.agent!==void 0?{agent:e.agent}:{},...e.multitask!==void 0?{multitask:e.multitask}:{},...e.sandboxEnabled!==void 0?{sandboxEnabled:e.sandboxEnabled}:{}}}static async create(e,i,n={},s={}){const{createSessionConfigProjector:t,projectSessionContextSize:o}=await import("#agent-harness-components/session-config"),a=s.sandboxEnabled===void 0?{...e}:{...e,settings:{...e.settings,sandbox:{...e.settings?.sandbox,enabled:s.sandboxEnabled}}},u=await t(a,{_meta:{"codebuddy.ai":{mainAgentSupport:!0}}});return new ServerSessionConfig(a,i,await t(a,n),u,o)}refreshDefaults(e){if(e.readFailed)return!1;const i=JSON.stringify(this.snapshot());return this.options.settings={...this.options.settings,sandbox:{...this.options.settings?.sandbox,enabled:e.sandboxEnabled}},i!==JSON.stringify(this.snapshot())}get queryOptions(){return{...this.values}}copy(){const e=new ServerSessionConfig(this.options,this.catalog,this.project,this.restoreProject,this.projectContextSize);return e.replace(this),e}replace(e){for(const i of Object.keys(this.values))delete this.values[i];Object.assign(this.values,structuredClone(e.values)),this.explicitSelections=structuredClone(e.explicitSelections),this.agentLocked=e.agentLocked,this.modelExplicit=e.modelExplicit}selections(){return structuredClone(this.explicitSelections)}restore(e){const i=e.model,n=typeof i=="string"&&this.catalog!==void 0&&!this.catalog.options.some(s=>s.value===i);for(const s of["multitask","sandbox","agent","model","mode","context_window","thought_level"]){if(n&&["model","context_window","thought_level"].includes(s))continue;const t=e[s];if(t!==void 0)try{this.apply(typeof t=="boolean"?{sessionId:"",configId:s,type:"boolean",value:t}:{sessionId:"",configId:s,type:"id",value:t},this.restoreProject),this.remember(s)}catch(o){if(!(o instanceof l))throw o}}}snapshot(){return this.project({...this.options,...this.values},this.catalog)}contextSize(e){return this.projectContextSize({...this.options,...this.values},e)}update(e,i=!1){const n=Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0));if(Object.entries(n).every(([t,o])=>this.values[t]===o))return!1;const s=Object.keys(n).filter(t=>this.values[t]!==n[t]);if(Object.assign(this.values,n),i)for(const t of s)this.remember(t==="permissionMode"?"mode":t);return!0}lockAgent(){this.agentLocked=!0}initializeBlank(){const e=this.snapshot().find(i=>i.configId==="agent");d(e)&&!this.values.agent&&this.apply({sessionId:"",configId:"agent",type:"id",value:e.currentValue},this.project)}set(e){this.apply(e,this.project),this.remember(e.configId)}reconcileSelections(){const e=new Map(this.restoreProject({...this.options,...this.values},this.catalog).map(i=>[i.configId,i.currentValue]));for(const[i,n]of Object.entries(this.explicitSelections))e.get(i)!==n&&delete this.explicitSelections[i]}remember(e){this.reconcileSelections();const i=this.restoreProject({...this.options,...this.values},this.catalog).find(n=>n.configId===e);(typeof i?.currentValue=="string"||typeof i?.currentValue=="boolean")&&(this.explicitSelections[e]=i.currentValue)}apply(e,i){const n=i({...this.options,...this.values},this.catalog).find(t=>t.configId===e.configId);if(!n)throw new l(`Unknown Agent configuration option: ${e.configId}`);if(n.type==="boolean"){if(e.type!=="boolean"||typeof e.value!="boolean")throw new l("Agent boolean configuration requires a boolean value");if(e.configId==="multitask"){this.values.multitask=e.value;return}if(e.configId==="sandbox"){this.values.sandboxEnabled=e.value;return}throw new l(`Unsupported Agent configuration option: ${e.configId}`)}if(e.type!=="id"||typeof e.value!="string")throw new l("Agent select configuration requires an option id");if(!(d(n)?n.options.flatMap(t=>"options"in t?t.options:[t]):[]).some(t=>t.value===e.value))throw new l(`Unknown Agent configuration option: ${e.configId}=${e.value}`);switch(e.configId){case"agent":if(this.agentLocked)throw new l("Main Agent can only change in a blank session");if(e.value==="minimal"&&this.values.multitask)throw new l("Disable Multitask before selecting Minimal");if(this.values.agent=e.value,!this.modelExplicit){const t=this.options.product?.agents?.find(o=>o.name===e.value)?.declaredModel;t&&(!this.catalog||this.catalog.options.some(o=>o.value===t))&&(this.values.model=t)}e.value==="minimal"&&this.values.permissionMode==="plan"&&(this.values.permissionMode="default");return;case"mode":this.values.permissionMode=e.value;return;case"model":{this.modelExplicit=!0,this.values.model=e.value,(this.values.thinking!==void 0||this.values.effort!==void 0)&&(this.values.thinking={type:"adaptive"},this.values.effort=null);const t=this.snapshot().find(o=>o.configId==="context_window");this.values.contextWindow!=null&&(!d(t)||!t.options.some(o=>"value"in o&&o.value===String(this.values.contextWindow)))&&(this.values.contextWindow=null);return}case"thought_level":this.values.thinking={type:e.value==="disabled"?"disabled":"adaptive"},this.values.effort=e.value==="disabled"||e.value==="enabled"?null:e.value;return;case"context_window":this.values.contextWindow=Number(e.value);return;default:throw new l(`Unsupported Agent configuration option: ${e.configId}`)}}}
1
+ var h=Object.defineProperty;var c=(r,e)=>h(r,"name",{value:e,configurable:!0});import{AgentHarnessInvalidParamsError as l}from"../server/errors.js";function d(r){return r?.type==="select"&&Array.isArray(r.options)}c(d,"isSelect");export class ServerSessionConfig{static{c(this,"ServerSessionConfig")}constructor(e,i,s,o,t){this.options=e,this.catalog=i,this.project=s,this.restoreProject=o,this.projectContextSize=t,this.explicitSelections={},this.agentLocked=!1;const n=e.model??i?.currentValue;if(this.modelExplicit=e.model!==void 0,n&&i&&!i.options.some(a=>a.value===n))throw new l("Agent model is outside the admitted Harness catalog");this.values={model:n,permissionMode:e.permissionMode??e.settings?.permissions?.defaultMode??"default",...e.thinking?{thinking:e.thinking}:{},...e.effort!==void 0?{effort:e.effort}:{},...e.contextWindow!==void 0?{contextWindow:e.contextWindow}:{},...e.agent!==void 0?{agent:e.agent}:{},...e.multitask!==void 0?{multitask:e.multitask}:{},...e.sandboxEnabled!==void 0?{sandboxEnabled:e.sandboxEnabled}:{}},this.values.permissionMode==="plan"&&(this.values.permissionModeBeforePlan=e.permissionModeBeforePlan??"default")}static async create(e,i,s={},o={}){const{createSessionConfigProjector:t,projectSessionContextSize:n}=await import("#agent-harness-components/session-config"),a=o.sandboxEnabled===void 0?{...e}:{...e,settings:{...e.settings,sandbox:{...e.settings?.sandbox,enabled:o.sandboxEnabled}}},u=await t(a,{_meta:{"codebuddy.ai":{mainAgentSupport:!0}}});return new ServerSessionConfig(a,i,await t(a,s),u,n)}refreshDefaults(e){if(e.readFailed)return!1;const i=JSON.stringify(this.snapshot());return this.options.settings={...this.options.settings,sandbox:{...this.options.settings?.sandbox,enabled:e.sandboxEnabled}},i!==JSON.stringify(this.snapshot())}get queryOptions(){return{...this.values}}copy(){const e=new ServerSessionConfig(this.options,this.catalog,this.project,this.restoreProject,this.projectContextSize);return e.replace(this),e}replace(e){for(const i of Object.keys(this.values))delete this.values[i];Object.assign(this.values,structuredClone(e.values)),this.explicitSelections=structuredClone(e.explicitSelections),this.agentLocked=e.agentLocked,this.modelExplicit=e.modelExplicit}selections(){return{...structuredClone(this.explicitSelections),...this.explicitSelections.mode==="plan"?{permissionModeBeforePlan:this.values.permissionModeBeforePlan??"default"}:{}}}restore(e){const i=e.model,s=typeof i=="string"&&this.catalog!==void 0&&!this.catalog.options.some(o=>o.value===i);for(const o of["multitask","sandbox","agent","model","mode","context_window","thought_level"]){if(s&&["model","context_window","thought_level"].includes(o))continue;const t=e[o];if(t!==void 0)try{this.apply(typeof t=="boolean"?{sessionId:"",configId:o,type:"boolean",value:t}:{sessionId:"",configId:o,type:"id",value:t},this.restoreProject),this.remember(o)}catch(n){if(!(n instanceof l))throw n}}if(this.values.permissionMode==="plan"&&typeof e.permissionModeBeforePlan=="string"){const o=this.restoreProject({...this.options,...this.values},this.catalog).find(n=>n.configId==="mode"),t=d(o)?o.options.flatMap(n=>"options"in n?n.options:[n]):[];e.permissionModeBeforePlan!=="plan"&&t.some(n=>n.value===e.permissionModeBeforePlan)&&(this.values.permissionModeBeforePlan=e.permissionModeBeforePlan)}}snapshot(){return this.project({...this.options,...this.values},this.catalog)}contextSize(e){return this.projectContextSize({...this.options,...this.values},e)}update(e,i=!1){const s=Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0));if(Object.entries(s).every(([t,n])=>this.values[t]===n))return!1;const o=Object.keys(s).filter(t=>this.values[t]!==s[t]);if(e.permissionMode&&this.setPermissionMode(e.permissionMode),Object.assign(this.values,s),i)for(const t of o)this.remember(t==="permissionMode"?"mode":t);return!0}lockAgent(){this.agentLocked=!0}initializeBlank(){const e=this.snapshot().find(i=>i.configId==="agent");d(e)&&!this.values.agent&&this.apply({sessionId:"",configId:"agent",type:"id",value:e.currentValue},this.project)}set(e){this.apply(e,this.project),this.remember(e.configId)}reconcileSelections(){const e=new Map(this.restoreProject({...this.options,...this.values},this.catalog).map(i=>[i.configId,i.currentValue]));for(const[i,s]of Object.entries(this.explicitSelections))e.get(i)!==s&&delete this.explicitSelections[i]}remember(e){this.reconcileSelections();const i=this.restoreProject({...this.options,...this.values},this.catalog).find(s=>s.configId===e);(typeof i?.currentValue=="string"||typeof i?.currentValue=="boolean")&&(this.explicitSelections[e]=i.currentValue)}setPermissionMode(e){e==="plan"?this.values.permissionMode!=="plan"&&(this.values.permissionModeBeforePlan=this.values.permissionMode??"default"):delete this.values.permissionModeBeforePlan,this.values.permissionMode=e}apply(e,i){const s=i({...this.options,...this.values},this.catalog).find(t=>t.configId===e.configId);if(!s)throw new l(`Unknown Agent configuration option: ${e.configId}`);if(s.type==="boolean"){if(e.type!=="boolean"||typeof e.value!="boolean")throw new l("Agent boolean configuration requires a boolean value");if(e.configId==="multitask"){this.values.multitask=e.value;return}if(e.configId==="sandbox"){this.values.sandboxEnabled=e.value;return}throw new l(`Unsupported Agent configuration option: ${e.configId}`)}if(e.type!=="id"||typeof e.value!="string")throw new l("Agent select configuration requires an option id");if(!(d(s)?s.options.flatMap(t=>"options"in t?t.options:[t]):[]).some(t=>t.value===e.value))throw new l(`Unknown Agent configuration option: ${e.configId}=${e.value}`);switch(e.configId){case"agent":if(this.agentLocked)throw new l("Main Agent can only change in a blank session");if(e.value==="minimal"&&this.values.multitask)throw new l("Disable Multitask before selecting Minimal");if(this.values.agent=e.value,!this.modelExplicit){const t=this.options.product?.agents?.find(n=>n.name===e.value)?.declaredModel;t&&(!this.catalog||this.catalog.options.some(n=>n.value===t))&&(this.values.model=t)}e.value==="minimal"&&this.values.permissionMode==="plan"&&this.setPermissionMode("default");return;case"mode":this.setPermissionMode(e.value);return;case"model":{this.modelExplicit=!0,this.values.model=e.value,(this.values.thinking!==void 0||this.values.effort!==void 0)&&(this.values.thinking={type:"adaptive"},this.values.effort=null);const t=this.snapshot().find(n=>n.configId==="context_window");this.values.contextWindow!=null&&(!d(t)||!t.options.some(n=>"value"in n&&n.value===String(this.values.contextWindow)))&&(this.values.contextWindow=null);return}case"thought_level":this.values.thinking={type:e.value==="disabled"?"disabled":"adaptive"},this.values.effort=e.value==="disabled"||e.value==="enabled"?null:e.value;return;case"context_window":this.values.contextWindow=Number(e.value);return;default:throw new l(`Unsupported Agent configuration option: ${e.configId}`)}}}
@@ -1 +1 @@
1
- var h=Object.defineProperty;var l=(o,t)=>h(o,"name",{value:t,configurable:!0});import{createAskUserQuestionElicitation as A,normalizeAskUserQuestionElicitationAnswers as m}from"#agent-harness-components/question-elicitation";import{FILE_DIRECTORY_APPROVAL_OPTION_ID as q,parseSandboxPermissionMetadata as k}from"#agent-harness-components/sandbox";import{abortable as C}from"../internal/async.js";import{isRecord as y}from"../internal/guards.js";function v(o){if(!Array.isArray(o.questions)||o.questions.length===0)throw new Error("AskUserQuestion requires questions");return{questions:o.questions.map(t=>{if(!y(t)||typeof t.question!="string"||!Array.isArray(t.options))throw new Error("Invalid AskUserQuestion question");return{question:t.question,header:typeof t.header=="string"?t.header:"",multiSelect:t.multiSelect===!0,options:t.options.map(a=>{if(!y(a)||typeof a.label!="string")throw new Error("Invalid AskUserQuestion option");return{label:a.label,description:typeof a.description=="string"?a.description:""}})}})}}l(v,"questionsFrom");export function serverCanUseTool(o,t,a){return async(d,n,e)=>{const i=l(r=>({behavior:"deny",message:r}),"deny");if(e.signal.aborted)return i("Interaction cancelled");const{id:b,meta:p}=t(),c=e.origin?{...e.origin.requestId?{"codebuddy.ai/requestId":e.origin.requestId}:{},...e.origin.rootRequestId?{"codebuddy.ai/rootRequestId":e.origin.rootRequestId}:{},...e.origin.subagent?{"codebuddy.ai/subagent":e.origin.subagent}:{}}:p,g=l(async r=>{await a?.(!0,c);try{return await C(r(),e.signal)}finally{e.signal.aborted||await a?.(!1,c)}},"interact");if(d==="AskUserQuestion"){if(!o.clientCapabilities.elicitation?.form)return i("Client does not support form elicitation");const r=v(n),I=await g(()=>o.callbacks.createElicitation(A(r,b,e.toolUseID,c),{signal:e.signal}));return e.signal.aborted||I.action!=="accept"?{...i("User declined to answer"),interrupt:!0}:{behavior:"allow",updatedInput:{...n,answers:m(r,I.content)}}}const u=e.suggestions?.length?structuredClone(e.suggestions):void 0,f=e.metadata?structuredClone(e.metadata):void 0,{fileApprovalScope:w}=f?.["codebuddy.ai/sandboxIntercept"]===!0?k(f):{},_={sessionId:b,title:e.title??e.displayName??d,...e.description?{description:e.description}:{},subject:{type:"tool_call",toolCall:{toolCallId:e.toolUseID,title:d,rawInput:n,...e.blockedPath?{locations:[{path:e.blockedPath}]}:{},...f?{_meta:{...f,"codebuddy.ai/toolName":d}}:{}}},options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},...u&&!w?[{optionId:"allow_always",name:u.every(r=>r.destination==="session")?"Allow for this session":"Always allow",kind:"allow_always"}]:[],{optionId:"reject_once",name:"Reject",kind:"reject_once"}],_meta:c},s=await g(()=>o.callbacks.requestPermission(_,{signal:e.signal}));return e.signal.aborted||s.outcome.outcome!=="selected"?i("Permission request cancelled"):s.outcome.optionId==="allow_once"?{behavior:"allow",updatedInput:n,decisionClassification:"user_temporary"}:s.outcome.optionId===q&&w?{behavior:"allow",updatedInput:n,decisionClassification:"user_permanent",metadata:{_fileDirectoryApprovalResponderVersion:1}}:s.outcome.optionId==="allow_always"&&w?{behavior:"allow",updatedInput:n,decisionClassification:"user_temporary"}:s.outcome.optionId==="allow_always"&&u?{behavior:"allow",updatedInput:n,updatedPermissions:u,decisionClassification:"user_permanent"}:{...i("Permission denied"),decisionClassification:"user_reject"}}}l(serverCanUseTool,"serverCanUseTool");
1
+ var h=Object.defineProperty;var l=(o,t)=>h(o,"name",{value:t,configurable:!0});import{createAskUserQuestionElicitation as A,normalizeAskUserQuestionElicitationAnswers as m}from"#agent-harness-components/question-elicitation";import{FILE_DIRECTORY_APPROVAL_OPTION_ID as q,parseSandboxPermissionMetadata as k}from"#agent-harness-components/sandbox";import{abortable as C}from"../internal/async.js";import{isRecord as I}from"../internal/guards.js";function v(o){if(!Array.isArray(o.questions)||o.questions.length===0)throw new Error("AskUserQuestion requires questions");return{questions:o.questions.map(t=>{if(!I(t)||typeof t.question!="string"||!Array.isArray(t.options))throw new Error("Invalid AskUserQuestion question");return{question:t.question,header:typeof t.header=="string"?t.header:"",multiSelect:t.multiSelect===!0,options:t.options.map(a=>{if(!I(a)||typeof a.label!="string")throw new Error("Invalid AskUserQuestion option");return{label:a.label,description:typeof a.description=="string"?a.description:""}})}})}}l(v,"questionsFrom");export function serverCanUseTool(o,t,a){return async(d,n,e)=>{const i=l(r=>({behavior:"deny",message:r}),"deny");if(e.signal.aborted)return i("Interaction cancelled");const{id:b,meta:p}=t(),c=e.origin?{...e.origin.requestId?{"codebuddy.ai/requestId":e.origin.requestId}:{},...e.origin.rootRequestId?{"codebuddy.ai/rootRequestId":e.origin.rootRequestId}:{},...e.origin.subagent?{"codebuddy.ai/subagent":e.origin.subagent}:{}}:p,g=l(async r=>{await a?.(!0,c);try{return await C(r(),e.signal)}finally{e.signal.aborted||await a?.(!1,c)}},"interact");if(d==="AskUserQuestion"){if(!o.clientCapabilities.elicitation?.form)return i("Client does not support form elicitation");const r=v(n),y=await g(()=>o.callbacks.createElicitation(A(r,b,e.toolUseID,c),{signal:e.signal}));return e.signal.aborted||y.action!=="accept"?{...i("User declined to answer"),interrupt:!0}:{behavior:"allow",updatedInput:{...n,answers:m(r,y.content)}}}const u=e.suggestions?.length?structuredClone(e.suggestions):void 0,f=e.metadata?structuredClone(e.metadata):void 0,{fileApprovalScope:w}=f?.["codebuddy.ai/sandboxIntercept"]===!0?k(f):{},_={sessionId:b,title:e.title??e.displayName??d,...e.description?{description:e.description}:{},subject:{type:"tool_call",toolCall:{toolCallId:e.toolUseID,title:e.displayName??d,rawInput:n,...e.blockedPath?{locations:[{path:e.blockedPath}]}:{},...f?{_meta:{...f,"codebuddy.ai/toolName":d}}:{}}},options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},...u&&!w?[{optionId:"allow_always",name:u.every(r=>r.destination==="session")?"Allow for this session":"Always allow",kind:"allow_always"}]:[],{optionId:"reject_once",name:"Reject",kind:"reject_once"}],_meta:c},s=await g(()=>o.callbacks.requestPermission(_,{signal:e.signal}));return e.signal.aborted||s.outcome.outcome!=="selected"?i("Permission request cancelled"):s.outcome.optionId==="allow_once"?{behavior:"allow",updatedInput:n,decisionClassification:"user_temporary"}:s.outcome.optionId===q&&w?{behavior:"allow",updatedInput:n,decisionClassification:"user_permanent",metadata:{_fileDirectoryApprovalResponderVersion:1}}:s.outcome.optionId==="allow_always"&&w?{behavior:"allow",updatedInput:n,decisionClassification:"user_temporary"}:s.outcome.optionId==="allow_always"&&u?{behavior:"allow",updatedInput:n,updatedPermissions:u,decisionClassification:"user_permanent"}:{...i("Permission denied"),decisionClassification:"user_reject"}}}l(serverCanUseTool,"serverCanUseTool");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-ai/agent-harness",
3
- "version": "0.2.0-beta.5",
3
+ "version": "0.2.0-beta.6",
4
4
  "description": "Standalone JSON-RPC agent harness backed by CodeBuddy Code",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -225,13 +225,13 @@
225
225
  "@tencent-ai/sandbox-cli-linux-x64": "5.8.0-beta.7",
226
226
  "@tencent-ai/sandbox-cli-win32-x64": "5.8.0-beta.7",
227
227
  "esbuild": "^0.25.12",
228
- "@tencent-ai/agent-harness-darwin-arm64": "0.2.0-beta.5",
229
- "@tencent-ai/agent-harness-darwin-x64": "0.2.0-beta.5",
230
- "@tencent-ai/agent-harness-linux-arm64": "0.2.0-beta.5",
231
- "@tencent-ai/agent-harness-linux-arm64-musl": "0.2.0-beta.5",
232
- "@tencent-ai/agent-harness-linux-x64": "0.2.0-beta.5",
233
- "@tencent-ai/agent-harness-linux-x64-musl": "0.2.0-beta.5",
234
- "@tencent-ai/agent-harness-win32-x64": "0.2.0-beta.5"
228
+ "@tencent-ai/agent-harness-darwin-arm64": "0.2.0-beta.6",
229
+ "@tencent-ai/agent-harness-darwin-x64": "0.2.0-beta.6",
230
+ "@tencent-ai/agent-harness-linux-arm64": "0.2.0-beta.6",
231
+ "@tencent-ai/agent-harness-linux-arm64-musl": "0.2.0-beta.6",
232
+ "@tencent-ai/agent-harness-linux-x64": "0.2.0-beta.6",
233
+ "@tencent-ai/agent-harness-linux-x64-musl": "0.2.0-beta.6",
234
+ "@tencent-ai/agent-harness-win32-x64": "0.2.0-beta.6"
235
235
  },
236
236
  "devDependencies": {
237
237
  "@anthropic-ai/sandbox-runtime": "0.0.17",