@tencent-ai/agent-harness 0.2.0-beta.2 → 0.2.0-beta.3

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 (149) hide show
  1. package/CHANGELOG.md +26 -2
  2. package/cli/CHANGELOG.md +64 -0
  3. package/cli/dist-server/shared.cjs +379 -315
  4. package/cli/dist-server/types/node/bash-sandbox/bash-sandbox-protocol.d.ts +3 -0
  5. package/cli/dist-server/types/node/cli/cli-protocol.d.ts +3 -0
  6. package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +8 -1
  7. package/cli/dist-server/types/node/sensitive-content/sensitive-content-protocol.d.ts +7 -0
  8. package/cli/dist-server/types/node/server/boot.d.ts +7 -4
  9. package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-error-model.d.ts +1 -1
  10. package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-protocol.d.ts +2 -3
  11. package/cli/dist-server/types/node/server/formats/acp/index.d.ts +12 -0
  12. package/cli/dist-server/types/node/server/formats/acp/projection.d.ts +10 -0
  13. package/cli/dist-server/types/node/server/index.d.ts +1 -1
  14. package/cli/dist-server/types/node/server/sessions.d.ts +3 -2
  15. package/cli/dist-server/types/node/server/types.d.ts +59 -7
  16. package/cli/dist-server/types/node/tools/tool-protocol.d.ts +16 -2
  17. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +31 -2
  18. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-protocol.d.ts +8 -4
  19. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-scope.d.ts +46 -0
  20. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +26 -3
  21. package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +3 -0
  22. package/cli/dist-server/types/vendor/cbc-core/node/agent/model-call-failure.d.ts +9 -0
  23. package/cli/dist-server/types/vendor/cbc-core/node/agent/model-step-sequence.d.ts +11 -0
  24. package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +25 -9
  25. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  26. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +9 -8
  27. package/cli/dist-server/types/vendor/cbc-core/node/context/compaction-lineage.d.ts +39 -0
  28. package/cli/dist-server/types/vendor/cbc-core/node/context/context-compact-summarizer.d.ts +2 -0
  29. package/cli/dist-server/types/vendor/cbc-core/node/context/context-protocol.d.ts +17 -0
  30. package/cli/dist-server/types/vendor/cbc-core/node/context/index.d.ts +1 -0
  31. package/cli/dist-server/types/vendor/cbc-core/node/context/pre-message-compact-strategy.d.ts +1 -2
  32. package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +1 -0
  33. package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +8 -0
  34. package/cli/dist-server/types/vendor/cbc-core/node/session/model-request-retry-phase.d.ts +16 -0
  35. package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +15 -0
  36. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager-host-protocol.d.ts +3 -2
  37. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +7 -3
  38. package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +47 -5
  39. package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +14 -1
  40. package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +8 -1
  41. package/cli/dist-server/types/vendor/cbc-core/node/trace/turn-context.d.ts +28 -1
  42. package/cli/dist-server/types/vendor/cbc-core/node/utils/command-message-utils.d.ts +20 -0
  43. package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +4 -4
  44. package/cli/dist-server/types/vendor/cbc-core/node/utils/input-item-utils.d.ts +8 -0
  45. package/cli/dist-server/types/vendor/cbc-core/node/utils/token-utils.d.ts +3 -1
  46. package/cli/dist-server/types/vendor/cbc-shared/node/agent/openai-agents-types.d.ts +1 -0
  47. package/cli/dist-server/types/vendor/cbc-shared/node/checkpoint/checkpoint-types.d.ts +6 -0
  48. package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +30 -2
  49. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/index.d.ts +1 -0
  50. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/sandbox-rule-context.d.ts +38 -0
  51. package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +3 -3
  52. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +6 -0
  53. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-observation.d.ts +36 -0
  54. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +21 -0
  55. package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +20 -4
  56. package/cli/dist-server/types/workspace/authentication/lib/common/index.d.ts +1 -0
  57. package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-protocol.d.ts +2 -0
  58. package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-service.d.ts +1 -0
  59. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +31 -2
  60. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-protocol.d.ts +8 -4
  61. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-scope.d.ts +46 -0
  62. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +26 -3
  63. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +3 -0
  64. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-call-failure.d.ts +9 -0
  65. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-step-sequence.d.ts +11 -0
  66. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +25 -9
  67. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  68. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +9 -8
  69. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/compaction-lineage.d.ts +39 -0
  70. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-compact-summarizer.d.ts +2 -0
  71. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-protocol.d.ts +17 -0
  72. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/index.d.ts +1 -0
  73. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/pre-message-compact-strategy.d.ts +1 -2
  74. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +1 -0
  75. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +8 -0
  76. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-request-retry-phase.d.ts +16 -0
  77. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +15 -0
  78. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager-host-protocol.d.ts +3 -2
  79. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +7 -3
  80. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +47 -5
  81. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +14 -1
  82. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +8 -1
  83. package/cli/dist-server/types/workspace/cbc-core/lib/node/trace/turn-context.d.ts +28 -1
  84. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/command-message-utils.d.ts +20 -0
  85. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +4 -4
  86. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/input-item-utils.d.ts +8 -0
  87. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/token-utils.d.ts +3 -1
  88. package/cli/dist-server/types/workspace/cbc-shared/lib/node/agent/openai-agents-types.d.ts +1 -0
  89. package/cli/dist-server/types/workspace/cbc-shared/lib/node/checkpoint/checkpoint-types.d.ts +6 -0
  90. package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +30 -2
  91. package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-service.d.ts +5 -0
  92. package/cli/dist-server/types/workspace/core/lib/common/protocol.d.ts +8 -1
  93. package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
  94. package/cli/dist-server/types/workspace/product/lib/common/tencent-docs-endpoint.d.ts +37 -0
  95. package/cli/dist-server/types/workspace/product/lib/common/types/config.d.ts +12 -0
  96. package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +1 -9
  97. package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +15 -0
  98. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +5 -0
  99. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +4 -1
  100. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/http-policy.d.ts +20 -0
  101. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/rule-config.d.ts +10 -0
  102. package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +3 -0
  103. package/cli/dist-server/types/workspace/telemetry/lib/common/event/types/craft.d.ts +43 -3
  104. package/cli/package.json +1 -1
  105. package/cli/product.cloudhosted.json +4 -4
  106. package/cli/product.internal.json +11 -7
  107. package/cli/product.ioa.json +32 -24
  108. package/cli/product.json +45 -17
  109. package/cli/product.selfhosted.json +2 -2
  110. package/cli/vendor/shim/brokered-bin/7z +675 -0
  111. package/cli/vendor/shim/brokered-bin/7za +675 -0
  112. package/cli/vendor/shim/brokered-bin/7zz +675 -0
  113. package/cli/vendor/shim/brokered-bin/rar +675 -0
  114. package/cli/vendor/shim/brokered-bin/tar +675 -0
  115. package/cli/vendor/shim/brokered-bin/zip +187 -0
  116. package/docs/in-process.md +26 -2
  117. package/docs/protocol.md +7 -1
  118. package/docs/server.md +2 -0
  119. package/lib/agent/v2.js +1 -1
  120. package/lib/application/services.js +1 -1
  121. package/lib/client/client.js +1 -1
  122. package/lib/client/mcp.d.ts +1 -1
  123. package/lib/client/mcp.js +1 -1
  124. package/lib/components/acp-mcp-transport.d.mts +84 -1
  125. package/lib/components/question-elicitation.d.mts +20 -1
  126. package/lib/components/{acp/acp-prompt-input.d.ts → session/prompt-input.d.ts} +1 -1
  127. package/lib/components/session-replay.d.mts +6 -7
  128. package/lib/components/session-replay.mjs +1 -1
  129. package/lib/effect-runtime/mcp-lifecycle.mjs +1 -1
  130. package/lib/harness/create-harness.js +1 -1
  131. package/lib/integration/agent-integration.d.ts +5 -0
  132. package/lib/runtime/private-runtime-role.js +1 -1
  133. package/lib/session/agent-backend.d.ts +3 -0
  134. package/lib/session/agent-backend.js +1 -1
  135. package/lib/session/config-defaults.d.ts +4 -0
  136. package/lib/session/config-defaults.js +1 -0
  137. package/lib/session/config-store.d.ts +1 -1
  138. package/lib/session/config-store.js +1 -1
  139. package/lib/session/replay.d.ts +2 -2
  140. package/lib/session/replay.js +1 -1
  141. package/lib/session/server-config.d.ts +11 -2
  142. package/lib/session/server-config.js +1 -1
  143. package/lib/session/server-events.d.ts +10 -8
  144. package/lib/session/server-events.js +1 -1
  145. package/lib/session/server-mcp.js +1 -1
  146. package/package.json +20 -19
  147. package/lib/components/acp/acp-client-channel.d.ts +0 -36
  148. package/lib/components/acp/acp-mcp-transport.d.ts +0 -84
  149. package/lib/components/acp/acp-question-elicitation.d.ts +0 -20
@@ -5,6 +5,10 @@ import type { WorkspaceSessionModelConfigOption } from '../runtime/product-manag
5
5
  import type { SessionConfigValues } from './config-store.js';
6
6
  export type SessionConfigProjector = (options: QueryOptions, catalog?: WorkspaceSessionModelConfigOption) => SessionConfigOption[];
7
7
  type ConfigQueryOptions = Pick<QueryOptions, 'model' | 'permissionMode' | 'thinking' | 'effort' | 'contextWindow' | 'agent' | 'multitask' | 'sandboxEnabled'>;
8
+ export interface SessionConfigDefaults {
9
+ readonly sandboxEnabled?: boolean;
10
+ readonly readFailed?: boolean;
11
+ }
8
12
  /** Session selections are validated against the same projection sent to clients. */
9
13
  export declare class ServerSessionConfig {
10
14
  private readonly options;
@@ -13,10 +17,13 @@ export declare class ServerSessionConfig {
13
17
  private readonly restoreProject;
14
18
  private readonly projectContextSize;
15
19
  private readonly values;
20
+ /** Explicit Host choices and subsequent Agent configuration transitions survive resume. */
21
+ private explicitSelections;
16
22
  private agentLocked;
17
23
  private modelExplicit;
18
24
  private constructor();
19
- static create(options: QueryOptions, catalog?: WorkspaceSessionModelConfigOption, capabilities?: AcpV2ClientCapabilities): Promise<ServerSessionConfig>;
25
+ static create(options: QueryOptions, catalog?: WorkspaceSessionModelConfigOption, capabilities?: AcpV2ClientCapabilities, defaults?: SessionConfigDefaults): Promise<ServerSessionConfig>;
26
+ refreshDefaults(defaults: SessionConfigDefaults): boolean;
20
27
  get queryOptions(): ConfigQueryOptions;
21
28
  copy(): ServerSessionConfig;
22
29
  replace(config: ServerSessionConfig): void;
@@ -24,10 +31,12 @@ export declare class ServerSessionConfig {
24
31
  restore(values: SessionConfigValues): void;
25
32
  snapshot(): SessionConfigOption[];
26
33
  contextSize(modelId?: string): number | undefined;
27
- update(values: Pick<ConfigQueryOptions, 'permissionMode' | 'agent' | 'multitask'>): boolean;
34
+ update(values: Pick<ConfigQueryOptions, 'permissionMode' | 'agent' | 'multitask'>, rememberChanges?: boolean): boolean;
28
35
  lockAgent(): void;
29
36
  initializeBlank(): void;
30
37
  set(params: AcpV2SetSessionConfigOptionRequest): void;
38
+ private reconcileSelections;
39
+ private remember;
31
40
  private apply;
32
41
  }
33
42
  export {};
@@ -1 +1 @@
1
- var r=Object.defineProperty;var u=(a,e)=>r(a,"name",{value:e,configurable:!0});import{AgentHarnessInvalidParamsError as l}from"../server/errors.js";function d(a){return a?.type==="select"&&Array.isArray(a.options)}u(d,"isSelect");export class ServerSessionConfig{static{u(this,"ServerSessionConfig")}constructor(e,t,o,s,n){this.options=e,this.catalog=t,this.project=o,this.restoreProject=s,this.projectContextSize=n,this.agentLocked=!1;const i=e.model??t?.currentValue;if(this.modelExplicit=e.model!==void 0,i&&t&&!t.options.some(c=>c.value===i))throw new l("Agent model is outside the admitted Harness catalog");this.values={model:i,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,t,o={}){const{createSessionConfigProjector:s,projectSessionContextSize:n}=await import("#agent-harness-components/session-config"),i=await s(e,{_meta:{"codebuddy.ai":{mainAgentSupport:!0}}});return new ServerSessionConfig(e,t,await s(e,o),i,n)}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 t of Object.keys(this.values))delete this.values[t];Object.assign(this.values,structuredClone(e.values)),this.agentLocked=e.agentLocked,this.modelExplicit=e.modelExplicit}selections(){const e={};for(const t of this.restoreProject({...this.options,...this.values},this.catalog))(typeof t.currentValue=="string"||typeof t.currentValue=="boolean")&&(e[t.configId]=t.currentValue);return e}restore(e){const t=e.model,o=typeof t=="string"&&this.catalog!==void 0&&!this.catalog.options.some(s=>s.value===t);for(const s of["multitask","sandbox","agent","model","mode","context_window","thought_level"]){if(o&&["model","context_window","thought_level"].includes(s))continue;const n=e[s];if(n!==void 0)try{this.apply(typeof n=="boolean"?{sessionId:"",configId:s,type:"boolean",value:n}:{sessionId:"",configId:s,type:"id",value:n},this.restoreProject)}catch(i){if(!(i instanceof l))throw i}}}snapshot(){return this.project({...this.options,...this.values},this.catalog)}contextSize(e){return this.projectContextSize({...this.options,...this.values},e)}update(e){const t=Object.fromEntries(Object.entries(e).filter(([,o])=>o!==void 0));return Object.entries(t).every(([o,s])=>this.values[o]===s)?!1:(Object.assign(this.values,t),!0)}lockAgent(){this.agentLocked=!0}initializeBlank(){const e=this.snapshot().find(t=>t.configId==="agent");d(e)&&!this.values.agent&&this.set({sessionId:"",configId:"agent",type:"id",value:e.currentValue})}set(e){this.apply(e,this.project)}apply(e,t){const o=t({...this.options,...this.values},this.catalog).find(n=>n.configId===e.configId);if(!o)throw new l(`Unknown Agent configuration option: ${e.configId}`);if(o.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(o)?o.options.flatMap(n=>"options"in n?n.options:[n]):[]).some(n=>n.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 n=this.options.product?.agents?.find(i=>i.name===e.value)?.declaredModel;n&&(!this.catalog||this.catalog.options.some(i=>i.value===n))&&(this.values.model=n)}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 n=this.snapshot().find(i=>i.configId==="context_window");this.values.contextWindow!=null&&(!d(n)||!n.options.some(i=>"value"in i&&i.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 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,13 +1,13 @@
1
- import type { QueryResult, SessionEvent } from '#agent-harness-codebuddy/server';
1
+ import type { AgentEvent, FormattedSessionEvent, QueryResult } from '#agent-harness-codebuddy/server';
2
2
  import type { AcpV2SetSessionConfigOptionResponse, AcpV2UpdateSessionNotification } from '../protocol/acp-v2.js';
3
3
  import { type SessionUsageHistory } from './replay.js';
4
4
  import type { ServerSessionConfig } from './server-config.js';
5
- /** Agent stream-json → ACP. No ACP implementation is loaded into the Agent kernel. */
5
+ /** Host policy and delivery for Server-projected ACP; no stream-json conversion. */
6
6
  export declare class ServerSessionEvents {
7
7
  private readonly sessionId;
8
8
  private readonly deliver;
9
9
  private readonly config?;
10
- private readonly persistConfiguration?;
10
+ private readonly persistConfig?;
11
11
  private requestId?;
12
12
  private delivery;
13
13
  private completion?;
@@ -15,12 +15,10 @@ export declare class ServerSessionEvents {
15
15
  private accounting?;
16
16
  private foregroundError?;
17
17
  private resultError?;
18
- private readonly compactions;
19
- constructor(sessionId: string, deliver: (update: AcpV2UpdateSessionNotification) => Promise<void>, config?: ServerSessionConfig | undefined, persistConfiguration?: ((candidate: ServerSessionConfig) => Promise<void>) | undefined);
18
+ constructor(sessionId: string, deliver: (update: AcpV2UpdateSessionNotification) => Promise<void>, config?: ServerSessionConfig | undefined, persistConfig?: ((config: ServerSessionConfig) => Promise<void>) | undefined);
20
19
  get meta(): Record<string, string>;
20
+ private configurationObserved;
21
21
  private readonly interactions;
22
- private readonly toolStreams;
23
- private readonly toolParsers;
24
22
  private readonly pendingTools;
25
23
  interaction(waiting: boolean, meta: Record<string, unknown>): Promise<void>;
26
24
  begin(requestId: string): Promise<void>;
@@ -33,6 +31,10 @@ export declare class ServerSessionEvents {
33
31
  private send;
34
32
  private finishTools;
35
33
  private usage;
36
- accept(frame: SessionEvent): Promise<void>;
34
+ /** Catalog reads are host operations outside the Agent subscription. */
35
+ catalog(data: Extract<AgentEvent['event'], {
36
+ type: 'catalog';
37
+ }>['data']): Promise<void>;
38
+ accept(frame: FormattedSessionEvent<'acp-v2'>): Promise<void>;
37
39
  private completeToolInvocation;
38
40
  }
@@ -1 +1 @@
1
- var y=Object.defineProperty;var g=(I,t)=>y(I,"name",{value:t,configurable:!0});import{isRecord as l}from"../internal/guards.js";import{AGENT_HARNESS_ERROR_META_KEY as f,AGENT_HARNESS_ERROR_UPDATE as _,agentHarnessErrorSchema as b}from"../protocol/error.js";import{replayCodecs as c}from"./replay.js";export class ServerSessionEvents{static{g(this,"ServerSessionEvents")}constructor(t,o,n,a){this.sessionId=t,this.deliver=o,this.config=n,this.persistConfiguration=a,this.delivery=Promise.resolve(),this.compactions=new Set,this.interactions=new Map,this.toolStreams=new Map,this.toolParsers=new Map,this.pendingTools=new Map}get meta(){return this.requestId?{"codebuddy.ai/requestId":this.requestId,"codebuddy.ai/rootRequestId":this.requestId}:{}}async interaction(t,o){const n=o["codebuddy.ai/requestId"];if(typeof n!="string")return;const a=Math.max(0,(this.interactions.get(n)??0)+(t?1:-1));a?this.interactions.set(n,a):this.interactions.delete(n),(!t&&a===0||t&&a===1)&&(o["codebuddy.ai/subagent"]||this.requestId===n)&&await this.send({sessionUpdate:"state_update",state:t?"requires_action":"running"},o)}async begin(t){const o=Promise.withResolvers();o.promise.catch(()=>{}),this.completion={runId:t,outcome:o},this.requestId||await this.start(t)}async start(t){this.requestId!==t&&(this.requestId=t,this.foregroundError=void 0,this.resultError=void 0,await this.send({sessionUpdate:"state_update",state:"running"},this.meta))}waitForCompletion(t){return this.completion?.runId!==t?Promise.reject(new Error("No matching foreground run")):this.completion.outcome.promise}fail(t){this.completion?.outcome.reject(t)}async end(t){const o=t.stopReason==="error"?this.foregroundError??(this.resultError?.runId===t.runId?this.resultError.error:void 0)??(await c()).projectAgentError(t.errorMessage??"Agent execution failed"):void 0;o&&!this.foregroundError&&await this.send({sessionUpdate:_,error:o,willRetry:!1},this.meta),await this.finishTools(n=>!n["codebuddy.ai/subagent"]&&n["codebuddy.ai/requestId"]===t.runId,t.stopReason==="aborted"?"Tool execution cancelled":"Tool did not complete"),await this.send({sessionUpdate:"state_update",state:"idle",stopReason:t.stopReason==="aborted"?"cancelled":t.stopReason==="error"?_:"end_turn",...t.usage?{usage:t.usage}:{}},{...this.meta,...o?{[f]:o}:{}}),this.requestId=void 0,this.interactions.delete(t.runId),this.completion?.runId===t.runId&&this.completion.outcome.resolve(t)}async restoreUsage(t,o){this.accounting=(await c()).createSessionUsage(this.sessionId,t,o),this.lastContextTokens=this.accounting.context?.used??(t.length===0?0:void 0)}async configuration(t){await this.send({sessionUpdate:"config_option_update",configOptions:t}),this.lastContextTokens!==void 0&&await this.usage(this.lastContextTokens)}send(t,o={}){const n={sessionId:this.sessionId,update:{...t,_meta:{...o,...l(t._meta)?t._meta:{}}}};return t.sessionUpdate===_&&t.willRetry===!1&&this.requestId!==void 0&&n.update._meta["codebuddy.ai/requestId"]===this.requestId&&!n.update._meta["codebuddy.ai/subagent"]&&(this.foregroundError=b.parse(t.error)),t.sessionUpdate==="tool_call_update"&&typeof t.toolCallId=="string"&&(t.status==="completed"||t.status==="failed"||t.status==="cancelled"?(this.pendingTools.delete(t.toolCallId),this.toolParsers.delete(t.toolCallId)):(t.status==="pending"||t.status==="in_progress")&&this.pendingTools.set(t.toolCallId,n.update._meta)),this.delivery=this.delivery.then(()=>this.deliver(n)),this.delivery}async finishTools(t,o){for(const[n,a]of this.pendingTools)t(a)&&await this.send({sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",content:[{type:"content",content:{type:"text",text:o}}]},a);for(const[n,a]of this.toolStreams){for(const[r,u]of a)this.pendingTools.has(u)||a.delete(r);a.size===0&&this.toolStreams.delete(n)}}async usage(t,o,n={}){const a=this.config?.contextSize(o),r=n["codebuddy.ai/subagent"],u=l(r)&&typeof r.sessionId=="string"?r.sessionId:this.sessionId,p=this.accounting?.snapshot(u).cost;a!==void 0&&await this.send({sessionUpdate:"usage_update",used:t,size:a,...p?{cost:p}:{}},n)}async accept(t){if("session_id"in t&&t.session_id!==this.sessionId)return;if(t.type==="run_started"){await this.start(t.runId);return}if(t.type==="run_completed"){if(!this.requestId&&this.completion?.runId===t.runId&&(this.requestId=t.runId,this.foregroundError=void 0,this.resultError=void 0),t.session_id===this.sessionId&&t.runId===this.requestId){const{type:e,session_id:i,_meta:s,...d}=t;await this.end(d)}return}if(t.type==="ai-title"||t.type==="topic"){t.session_id===this.sessionId&&await this.send({sessionUpdate:"session_info_update",title:t.type==="ai-title"?t.aiTitle:t.topic});return}if("parent_tool_use_id"in t&&t.parent_tool_use_id&&!t.origin?.subagent)return;const o={...t.origin===void 0?this.meta:{},...t._meta,...t.origin?.requestId?{"codebuddy.ai/requestId":t.origin.requestId}:{},...t.origin?.rootRequestId?{"codebuddy.ai/rootRequestId":t.origin.rootRequestId}:{},...t.origin?.subagent?{"codebuddy.ai/subagent":t.origin.subagent}:{}},n=g(e=>this.send(e,o),"send"),a=g(e=>e.sessionUpdate==="_codebuddy.ai/compaction"&&typeof e.compactionId=="string"&&this.compactions.has(e.compactionId)?Promise.resolve():n(e),"sendItem"),r=t.item??(t.type==="agent_event"&&t.event.type==="input"?t.event.data:void 0);if(r){this.accounting??=(await c()).createSessionUsage(this.sessionId);const e=o["codebuddy.ai/subagent"],i=l(e)&&typeof e.sessionId=="string"?e.sessionId:this.sessionId;this.accounting.accept(r,i);const s=t.origin?.requestId??t._meta?.["codebuddy.ai/requestId"]??r.providerData?.conversationRequestId;if(i===this.sessionId&&typeof s=="string"&&s===this.requestId){const d=(await c()).projectAgentItemError(r);d&&(this.resultError={runId:s,error:d})}}if(t.type==="result"){const e=t.origin?.requestId??t._meta?.["codebuddy.ai/requestId"];if(t.is_error&&"errors"in t&&typeof e=="string"&&e===this.requestId&&!t.origin?.subagent&&!t._meta?.["codebuddy.ai/subagent"]){const i=t.errors_info?.findIndex(s=>s!=null)??-1;this.resultError={runId:e,error:(await c()).projectAgentError(t.errors[i<0?0:i]??"Agent execution failed",i<0?void 0:t.errors_info?.[i])}}return}if(t.type==="agent_event"){if(t.event.type==="compaction"&&t.event.data.status==="in_progress"&&this.compactions.add(t.event.data.compactionId),t.event.type==="subagent_status"&&(this.accounting??=(await c()).createSessionUsage(this.sessionId),this.accounting.child(t.event.data.sessionId,t.event.data.parentSessionId,t.event.data.parentToolCallId)),t.event.type==="subagent_status"&&t.event.data.status!=="running"){const e=t.event.data.sessionId;this.interactions.delete(t.event.data.conversationRequestId),await this.finishTools(i=>l(i["codebuddy.ai/subagent"])&&i["codebuddy.ai/subagent"].sessionId===e,"Subagent tool did not complete")}if(t.event.type==="configuration"){const e=t.origin?.subagent?void 0:this.config?.copy();e?.update(t.event.data)&&(await this.persistConfiguration?.(e),this.config.replace(e),await n({sessionUpdate:"config_option_update",configOptions:e.snapshot()}))}else if(t.event.type==="usage")t.origin?.subagent||(this.lastContextTokens=t.event.data.contextTokens),await this.usage(t.event.data.contextTokens,t.event.data.modelId,o),t.origin?.subagent&&this.lastContextTokens!==void 0&&await this.usage(this.lastContextTokens);else{const{projectAgentEvent:e}=await c();for(const i of await e(t))await(t.event.type==="input"?a(i.update):n(i.update));t.event.type==="input"&&this.completeToolInvocation(t.event.data)}t.event.type==="compaction"&&t.event.data.status!=="in_progress"&&this.compactions.delete(t.event.data.compactionId);return}if(t.item){const{projectAgentItem:e}=await c();for(const i of await e(this.sessionId,t.item))await a(i.update);this.completeToolInvocation(t.item);return}const u=t._meta?.["codebuddy.ai/messageId"],p=typeof u=="string"&&u.length>0?u:void 0;if(t.type==="stream_event"){const e=t.event,i=JSON.stringify([o["codebuddy.ai/requestId"],t.origin?.subagent?.sessionId]);if(e.type==="message_start"&&this.toolStreams.set(i,new Map),e.type==="content_block_start"&&e.content_block.type==="tool_use"){const s=e.content_block;let d=this.toolStreams.get(i);d||this.toolStreams.set(i,d=new Map),d.set(e.index,s.id);const{createToolInputParser:h}=await c();this.toolParsers.set(s.id,h()),await n({sessionUpdate:"tool_call_update",toolCallId:s.id,name:s.name,title:s.name,status:"pending"})}if(e.type==="content_block_delta"&&e.delta.type==="input_json_delta"){const s=this.toolStreams.get(i)?.get(e.index),d=s?this.toolParsers.get(s):void 0;if(s&&d){const h=e.delta.partial_json;await n({sessionUpdate:"tool_call_update",toolCallId:s,rawInput:d(h),content:[{type:"content",content:{type:"text",text:h}}]})}}if(e.type==="message_stop"&&this.toolStreams.delete(i),e.type==="content_block_delta"&&p){const s=e.delta;if(s.type==="text_delta"||s.type==="thinking_delta"){const d=s.type==="thinking_delta",h=d?s.thinking:s.text;await n({sessionUpdate:d?"agent_thought_chunk":"agent_message_chunk",messageId:p,content:{type:"text",text:h}})}}return}if(t.type==="assistant"){const e=p??t.uuid,i=[],s=[];for(const d of t.message.content)d.type==="text"||d.type==="thinking"?(d.type==="thinking"?s:i).push({type:"text",text:d.type==="thinking"?d.thinking:d.text}):d.type==="tool_use"&&await n({sessionUpdate:"tool_call_update",toolCallId:d.id,name:d.name,title:d.name,status:"in_progress",rawInput:d.input});s.length&&await n({sessionUpdate:"agent_thought",messageId:e,content:s}),(i.length||t.message.content.length===0)&&await n({sessionUpdate:"agent_message",messageId:e,content:i});return}if(t.type==="user"){const e=t.message.content,i=Array.isArray(e)?e.filter(s=>l(s)&&s.type==="tool_result"):[];for(const s of i)l(s)&&s.type==="tool_result"&&typeof s.tool_use_id=="string"&&await n({sessionUpdate:"tool_call_update",toolCallId:s.tool_use_id,status:s.is_error?"failed":"completed",rawOutput:s.content})}}completeToolInvocation(t){l(t)&&t.type==="function_call_result"&&t.status==="completed"&&typeof t.callId=="string"&&(this.pendingTools.delete(t.callId),this.toolParsers.delete(t.callId))}}
1
+ var g=Object.defineProperty;var u=(l,t)=>g(l,"name",{value:t,configurable:!0});import{isRecord as r}from"../internal/guards.js";import{AGENT_HARNESS_ERROR_META_KEY as p,AGENT_HARNESS_ERROR_UPDATE as h,agentHarnessErrorSchema as I}from"../protocol/error.js";import{replayCodecs as a}from"./replay.js";export class ServerSessionEvents{static{u(this,"ServerSessionEvents")}constructor(t,e,s,n){this.sessionId=t,this.deliver=e,this.config=s,this.persistConfig=n,this.delivery=Promise.resolve(),this.configurationObserved=!1,this.interactions=new Map,this.pendingTools=new Map}get meta(){return this.requestId?{"codebuddy.ai/requestId":this.requestId,"codebuddy.ai/rootRequestId":this.requestId}:{}}async interaction(t,e){const s=e["codebuddy.ai/requestId"];if(typeof s!="string")return;const n=Math.max(0,(this.interactions.get(s)??0)+(t?1:-1));n?this.interactions.set(s,n):this.interactions.delete(s),(!t&&n===0||t&&n===1)&&(e["codebuddy.ai/subagent"]||this.requestId===s)&&await this.send({sessionUpdate:"state_update",state:t?"requires_action":"running"},e)}async begin(t){const e=Promise.withResolvers();e.promise.catch(()=>{}),this.completion={runId:t,outcome:e},this.requestId||await this.start(t)}async start(t){this.requestId!==t&&(this.requestId=t,this.foregroundError=void 0,this.resultError=void 0,await this.send({sessionUpdate:"state_update",state:"running"},this.meta))}waitForCompletion(t){return this.completion?.runId!==t?Promise.reject(new Error("No matching foreground run")):this.completion.outcome.promise}fail(t){this.completion?.outcome.reject(t)}async end(t){const e=t.stopReason==="error"?this.foregroundError??(this.resultError?.runId===t.runId?this.resultError.error:void 0)??(await a()).projectAgentError(t.errorMessage??"Agent execution failed"):void 0;e&&!this.foregroundError&&await this.send({sessionUpdate:h,error:e,willRetry:!1},this.meta),await this.finishTools(s=>!s["codebuddy.ai/subagent"]&&s["codebuddy.ai/requestId"]===t.runId,t.stopReason==="aborted"?"Tool execution cancelled":"Tool did not complete"),await this.send({sessionUpdate:"state_update",state:"idle",stopReason:t.stopReason==="aborted"?"cancelled":t.stopReason==="error"?h:"end_turn",...t.usage?{usage:t.usage}:{}},{...this.meta,...e?{[p]:e}:{}}),this.requestId=void 0,this.interactions.delete(t.runId),this.completion?.runId===t.runId&&this.completion.outcome.resolve(t)}async restoreUsage(t,e){this.accounting=(await a()).createSessionUsage(this.sessionId,t,e),this.lastContextTokens=this.accounting.context?.used??(t.length===0?0:void 0)}async configuration(t){await this.send({sessionUpdate:"config_option_update",configOptions:t}),this.lastContextTokens!==void 0&&await this.usage(this.lastContextTokens)}send(t,e={}){const s={sessionId:this.sessionId,update:{...t,_meta:{...e,...r(t._meta)?t._meta:{}}}};return t.sessionUpdate===h&&t.willRetry===!1&&this.requestId!==void 0&&s.update._meta["codebuddy.ai/requestId"]===this.requestId&&!s.update._meta["codebuddy.ai/subagent"]&&(this.foregroundError=I.parse(t.error)),t.sessionUpdate==="tool_call_update"&&typeof t.toolCallId=="string"&&(t.status==="completed"||t.status==="failed"||t.status==="cancelled"?this.pendingTools.delete(t.toolCallId):(t.status==="pending"||t.status==="in_progress")&&this.pendingTools.set(t.toolCallId,s.update._meta)),this.delivery=this.delivery.then(()=>this.deliver(s)),this.delivery}async finishTools(t,e){for(const[s,n]of this.pendingTools)t(n)&&await this.send({sessionUpdate:"tool_call_update",toolCallId:s,status:"failed",content:[{type:"content",content:{type:"text",text:e}}]},n)}async usage(t,e,s={}){const n=this.config?.contextSize(e),i=s["codebuddy.ai/subagent"],o=r(i)&&typeof i.sessionId=="string"?i.sessionId:this.sessionId,d=this.accounting?.snapshot(o).cost;n!==void 0&&await this.send({sessionUpdate:"usage_update",used:t,size:n,...d?{cost:d}:{}},s)}async catalog(t){const e=await a();for(const s of await e.projectAgentEvent({type:"agent_event",session_id:this.sessionId,event:{type:"catalog",data:t}}))await this.accept({type:"acp_update",notification:s})}async accept(t){if("session_id"in t&&t.session_id!==this.sessionId)return;if(t.type==="run_started"){await this.start(t.runId);return}if(t.type==="run_completed"){if(!this.requestId&&this.completion?.runId===t.runId&&(this.requestId=t.runId,this.foregroundError=void 0,this.resultError=void 0),t.session_id===this.sessionId&&t.runId===this.requestId){const{type:i,session_id:o,_meta:d,...c}=t;await this.end(c)}return}const e={...t.origin===void 0?this.meta:{},...t._meta,...t.origin?.requestId?{"codebuddy.ai/requestId":t.origin.requestId}:{},...t.origin?.rootRequestId?{"codebuddy.ai/rootRequestId":t.origin.rootRequestId}:{},...t.origin?.subagent?{"codebuddy.ai/subagent":t.origin.subagent}:{}},s=u(i=>this.send(i,e),"send"),n=t.item??(t.type==="agent_event"&&t.event.type==="input"?t.event.data:void 0);if(n){this.accounting??=(await a()).createSessionUsage(this.sessionId);const i=e["codebuddy.ai/subagent"],o=r(i)&&typeof i.sessionId=="string"?i.sessionId:this.sessionId;this.accounting.accept(n,o);const d=t.origin?.requestId??t._meta?.["codebuddy.ai/requestId"]??n.providerData?.conversationRequestId;if(o===this.sessionId&&typeof d=="string"&&d===this.requestId){const c=(await a()).projectAgentItemError(n);c&&(this.resultError={runId:d,error:c})}}if(t.type==="acp_update"){t.notification.sessionId===this.sessionId&&await s(t.notification.update);return}if(t.type==="agent_event"){if(t.event.type==="subagent_status"&&(this.accounting??=(await a()).createSessionUsage(this.sessionId),this.accounting.child(t.event.data.sessionId,t.event.data.parentSessionId,t.event.data.parentToolCallId)),t.event.type==="subagent_status"&&t.event.data.status!=="running"){const i=t.event.data.sessionId;this.interactions.delete(t.event.data.conversationRequestId),await this.finishTools(o=>r(o["codebuddy.ai/subagent"])&&o["codebuddy.ai/subagent"].sessionId===i,"Subagent tool did not complete")}if(t.event.type==="error"){const i=t.origin?.requestId;i&&i===this.requestId&&!t.origin?.subagent&&this.resultError?.runId!==i&&(this.resultError={runId:i,error:(await a()).projectAgentFailure(t.event.data)})}else if(t.event.type==="configuration"){const i=t.origin?.subagent?void 0:this.config?.copy(),o=JSON.stringify(this.config?.selections()),d=i?.update(t.event.data,this.configurationObserved);i&&(this.configurationObserved=!0),i&&d&&(this.config.replace(i),JSON.stringify(i.selections())!==o&&await this.persistConfig?.(i),await s({sessionUpdate:"config_option_update",configOptions:i.snapshot()}))}else t.event.type==="usage"?(t.origin?.subagent||(this.lastContextTokens=t.event.data.contextTokens),await this.usage(t.event.data.contextTokens,t.event.data.modelId,e),t.origin?.subagent&&this.lastContextTokens!==void 0&&await this.usage(this.lastContextTokens)):t.event.type==="input"&&this.completeToolInvocation(t.event.data)}}completeToolInvocation(t){r(t)&&t.type==="function_call_result"&&t.status==="completed"&&typeof t.callId=="string"&&this.pendingTools.delete(t.callId)}}
@@ -1 +1 @@
1
- var h=Object.defineProperty;var r=(b,i)=>h(b,"name",{value:i,configurable:!0});import{Schema as t}from"effect";import{McpPeerTransport as f}from"../integration/mcp-peer-transport.js";import{abortable as y}from"../internal/async.js";import{AgentHarnessInvalidParamsError as p}from"../server/errors.js";const u=t.decodeUnknownSync(t.Struct({description:t.optionalKey(t.String),alwaysLoad:t.optionalKey(t.Boolean),defer_loading:t.optionalKey(t.Boolean),repl_expose:t.optionalKey(t.Boolean),transparent_proxy:t.optionalKey(t.Boolean),builtin_tools:t.optionalKey(t.Array(t.String)),tools:t.optionalKey(t.Record(t.String,t.Struct({defer_loading:t.optionalKey(t.Boolean),server_name:t.optionalKey(t.String),bare_name:t.optionalKey(t.Boolean),prompt_cache_stability:t.optionalKey(t.Literals(["stable","volatile"])),tool_control_id:t.optionalKey(t.String),tool_control_compatibility_ids:t.optionalKey(t.Array(t.String))})))}),{reportInput:!1});export class ServerSessionMcp{static{r(this,"ServerSessionMcp")}constructor(i,s){this.callbacks=i,this.currentSignal=s,this.lifetime=new AbortController,this.transports=new Set}configure(i,s){if(i.length===0)return s;if(!this.callbacks.mcpConnect||!this.callbacks.mcpDisconnect||!this.callbacks.mcpMessage||!this.callbacks.mcpNotification)throw new p("Session MCP requires Harness connection callbacks");const a={...s};for(const n of i){if(n.type!=="acp"||typeof n.serverId!="string"||typeof n.name!="string")throw new p("Harness must materialize MCP servers before binding the Agent session");if(Object.hasOwn(a,n.name))throw new p(`Duplicate MCP server: ${n.name}`);const c=n.serverId;let o;try{o=u(n._meta??{})}catch{throw new p(`Invalid MCP metadata: ${n.name}`)}const d={...o,builtin_tools:o.builtin_tools?[...o.builtin_tools]:void 0,tools:o.tools?Object.fromEntries(Object.entries(o.tools).map(([m,e])=>[m,{...e,tool_control_compatibility_ids:e.tool_control_compatibility_ids?[...e.tool_control_compatibility_ids]:void 0}])):void 0,type:"transport",transport:r(()=>this.connect(c),"transport")};Object.defineProperty(a,n.name,{enumerable:!0,configurable:!0,writable:!0,value:d})}return a}close(){return this.closing??=(async()=>{this.lifetime.abort(),await Promise.allSettled([...this.transports].map(i=>i.close())),await this.callbacks.mcpPeerClosed?.()})()}async connect(i){const s=[this.lifetime.signal,this.currentSignal()].filter(e=>!!e),a=AbortSignal.any(s);a.throwIfAborted();const n=this.callbacks.mcpConnect({serverId:i},{request:r((e,l)=>o.receiveRequest(e.method,e.params,l?.signal),"request"),notify:r(async e=>o.receiveNotification(e.method,e.params),"notify")},{signal:a});let c;try{c=await y(n,a)}catch(e){throw a.aborted&&n.then(l=>this.callbacks.mcpDisconnect({connectionId:l.connectionId})).catch(()=>{}),e}const o=new f(c.connectionId,{request:r((e,l)=>this.callbacks.mcpMessage(e,l),"request"),notify:r(e=>this.callbacks.mcpNotification(e),"notify")}),d=o.close.bind(o);let m;return o.close=()=>m??=(async()=>{this.transports.delete(o),await d(),await this.callbacks.mcpDisconnect({connectionId:c.connectionId})})(),this.transports.add(o),a.aborted&&(await o.close(),a.throwIfAborted()),o}}
1
+ var h=Object.defineProperty;var r=(b,i)=>h(b,"name",{value:i,configurable:!0});import{Schema as t}from"effect";import{McpPeerTransport as f}from"../integration/mcp-peer-transport.js";import{abortable as y}from"../internal/async.js";import{AgentHarnessInvalidParamsError as p}from"../server/errors.js";const u=t.decodeUnknownSync(t.Struct({description:t.optionalKey(t.String),alwaysLoad:t.optionalKey(t.Boolean),defer_loading:t.optionalKey(t.Boolean),repl_expose:t.optionalKey(t.Boolean),transparent_proxy:t.optionalKey(t.Boolean),builtin_tools:t.optionalKey(t.Array(t.String)),tools:t.optionalKey(t.Record(t.String,t.Struct({defer_loading:t.optionalKey(t.Boolean),server_name:t.optionalKey(t.String),bare_name:t.optionalKey(t.Boolean),prompt_cache_stability:t.optionalKey(t.Literals(["stable","volatile"])),tool_control_id:t.optionalKey(t.String),tool_control_compatibility_ids:t.optionalKey(t.Array(t.String))})))}),{reportInput:!1});export class ServerSessionMcp{static{r(this,"ServerSessionMcp")}constructor(i,s){this.callbacks=i,this.currentSignal=s,this.lifetime=new AbortController,this.transports=new Set}configure(i,s){if(i.length===0)return{...s};if(!this.callbacks.mcpConnect||!this.callbacks.mcpDisconnect||!this.callbacks.mcpMessage||!this.callbacks.mcpNotification)throw new p("Session MCP requires Harness connection callbacks");const a={...s};for(const n of i){if(n.type!=="acp"||typeof n.serverId!="string"||typeof n.name!="string")throw new p("Harness must materialize MCP servers before binding the Agent session");if(Object.hasOwn(a,n.name))throw new p(`Duplicate MCP server: ${n.name}`);const c=n.serverId;let o;try{o=u(n._meta??{})}catch{throw new p(`Invalid MCP metadata: ${n.name}`)}const d={...o,builtin_tools:o.builtin_tools?[...o.builtin_tools]:void 0,tools:o.tools?Object.fromEntries(Object.entries(o.tools).map(([m,e])=>[m,{...e,tool_control_compatibility_ids:e.tool_control_compatibility_ids?[...e.tool_control_compatibility_ids]:void 0}])):void 0,type:"transport",transport:r(()=>this.connect(c),"transport")};Object.defineProperty(a,n.name,{enumerable:!0,configurable:!0,writable:!0,value:d})}return a}close(){return this.closing??=(async()=>{this.lifetime.abort(),await Promise.allSettled([...this.transports].map(i=>i.close())),await this.callbacks.mcpPeerClosed?.()})()}async connect(i){const s=[this.lifetime.signal,this.currentSignal()].filter(e=>!!e),a=AbortSignal.any(s);a.throwIfAborted();const n=this.callbacks.mcpConnect({serverId:i},{request:r((e,l)=>o.receiveRequest(e.method,e.params,l?.signal),"request"),notify:r(async e=>o.receiveNotification(e.method,e.params),"notify")},{signal:a});let c;try{c=await y(n,a)}catch(e){throw a.aborted&&n.then(l=>this.callbacks.mcpDisconnect({connectionId:l.connectionId})).catch(()=>{}),e}const o=new f(c.connectionId,{request:r((e,l)=>this.callbacks.mcpMessage(e,l),"request"),notify:r(e=>this.callbacks.mcpNotification(e),"notify")}),d=o.close.bind(o);let m;return o.close=()=>m??=(async()=>{this.transports.delete(o),await d(),await this.callbacks.mcpDisconnect({connectionId:c.connectionId})})(),this.transports.add(o),a.aborted&&(await o.close(),a.throwIfAborted()),o}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-ai/agent-harness",
3
- "version": "0.2.0-beta.2",
3
+ "version": "0.2.0-beta.3",
4
4
  "description": "Standalone JSON-RPC agent harness backed by CodeBuddy Code",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -197,6 +197,7 @@
197
197
  },
198
198
  "dependencies": {
199
199
  "@agentclientprotocol/sdk": "1.4.0",
200
+ "@agentclientprotocol/sdk-server": "npm:@agentclientprotocol/sdk@1.4.0",
200
201
  "@effect/platform-node": "4.0.0-rc.115",
201
202
  "@modelcontextprotocol/sdk": "1.29.0",
202
203
  "ajv": "^8.20.0",
@@ -214,18 +215,18 @@
214
215
  "@lydell/node-pty-linux-x64": "1.2.0-beta.14",
215
216
  "@lydell/node-pty-win32-arm64": "1.2.0-beta.14",
216
217
  "@lydell/node-pty-win32-x64": "1.2.0-beta.14",
217
- "@tencent-ai/sandbox-cli-darwin-arm64": "5.8.0-beta.3",
218
- "@tencent-ai/sandbox-cli-darwin-x64": "5.8.0-beta.3",
219
- "@tencent-ai/sandbox-cli-linux-arm64": "5.8.0-beta.3",
220
- "@tencent-ai/sandbox-cli-linux-x64": "5.8.0-beta.3",
221
- "@tencent-ai/sandbox-cli-win32-x64": "5.8.0-beta.3",
222
- "@tencent-ai/agent-harness-darwin-arm64": "0.2.0-beta.2",
223
- "@tencent-ai/agent-harness-darwin-x64": "0.2.0-beta.2",
224
- "@tencent-ai/agent-harness-linux-arm64": "0.2.0-beta.2",
225
- "@tencent-ai/agent-harness-linux-arm64-musl": "0.2.0-beta.2",
226
- "@tencent-ai/agent-harness-linux-x64": "0.2.0-beta.2",
227
- "@tencent-ai/agent-harness-linux-x64-musl": "0.2.0-beta.2",
228
- "@tencent-ai/agent-harness-win32-x64": "0.2.0-beta.2"
218
+ "@tencent-ai/sandbox-cli-darwin-arm64": "5.8.0-beta.7",
219
+ "@tencent-ai/sandbox-cli-darwin-x64": "5.8.0-beta.7",
220
+ "@tencent-ai/sandbox-cli-linux-arm64": "5.8.0-beta.7",
221
+ "@tencent-ai/sandbox-cli-linux-x64": "5.8.0-beta.7",
222
+ "@tencent-ai/sandbox-cli-win32-x64": "5.8.0-beta.7",
223
+ "@tencent-ai/agent-harness-darwin-arm64": "0.2.0-beta.3",
224
+ "@tencent-ai/agent-harness-darwin-x64": "0.2.0-beta.3",
225
+ "@tencent-ai/agent-harness-linux-arm64": "0.2.0-beta.3",
226
+ "@tencent-ai/agent-harness-linux-arm64-musl": "0.2.0-beta.3",
227
+ "@tencent-ai/agent-harness-linux-x64": "0.2.0-beta.3",
228
+ "@tencent-ai/agent-harness-linux-x64-musl": "0.2.0-beta.3",
229
+ "@tencent-ai/agent-harness-win32-x64": "0.2.0-beta.3"
229
230
  },
230
231
  "devDependencies": {
231
232
  "@anthropic-ai/sandbox-runtime": "0.0.17",
@@ -253,11 +254,11 @@
253
254
  "@oven/bun-linux-x64-musl": "1.4.2",
254
255
  "@oven/bun-windows-x64": "1.4.2",
255
256
  "@rspack/core": "^1.7.6",
256
- "@tencent-ai/sandbox-cli-darwin-arm64": "5.8.0-beta.3",
257
- "@tencent-ai/sandbox-cli-darwin-x64": "5.8.0-beta.3",
258
- "@tencent-ai/sandbox-cli-linux-arm64": "5.8.0-beta.3",
259
- "@tencent-ai/sandbox-cli-linux-x64": "5.8.0-beta.3",
260
- "@tencent-ai/sandbox-cli-win32-x64": "5.8.0-beta.3",
257
+ "@tencent-ai/sandbox-cli-darwin-arm64": "5.8.0-beta.7",
258
+ "@tencent-ai/sandbox-cli-darwin-x64": "5.8.0-beta.7",
259
+ "@tencent-ai/sandbox-cli-linux-arm64": "5.8.0-beta.7",
260
+ "@tencent-ai/sandbox-cli-linux-x64": "5.8.0-beta.7",
261
+ "@tencent-ai/sandbox-cli-win32-x64": "5.8.0-beta.7",
261
262
  "@types/node": "22",
262
263
  "@types/sinon": "^10.0.15",
263
264
  "@types/which": "^3.0.4",
@@ -411,7 +412,7 @@
411
412
  "build": "pnpm --workspace-root exec nx run @genie/agent-harness:build --skipSync",
412
413
  "build:lib": "pnpm --workspace-root exec nx run @genie/agent-harness:build:lib --skipSync",
413
414
  "build:components": "node scripts/build-components.mjs",
414
- "compile:run": "pnpm run build:components && tsc --build executor/tsconfig.json --force && tsc --build tsconfig.lib.json --force",
415
+ "compile:run": "pnpm run build:components && tsc --build executor/tsconfig.json && tsc --build tsconfig.lib.json",
415
416
  "build:lib:run": "pnpm run clean && pnpm run compile:run && pnpm --dir executor run build:capsule && node scripts/write-product-schema.mjs && node scripts/prune-library.mjs && node scripts/minify-library.mjs",
416
417
  "build:run": "pnpm run build:lib:run && pnpm run sync:codebuddy:runtime",
417
418
  "build:sfe": "node scripts/build-sfe.mjs",
@@ -1,36 +0,0 @@
1
- import { type AgentContext, type CompleteElicitationNotification, type CreateElicitationRequest, type CreateElicitationResponse, type CreateTerminalRequest, type KillTerminalResponse, type ReadTextFileRequest, type ReadTextFileResponse, type ReleaseTerminalResponse, type RequestPermissionRequest, type RequestPermissionResponse, type SendRequestOptions, type SessionNotification, type TerminalOutputResponse, type WaitForTerminalExitResponse, type WriteTextFileRequest, type WriteTextFileResponse } from '@agentclientprotocol/sdk';
2
- /**
3
- * Agent CLI 业务实际依赖的终端句柄。
4
- *
5
- * 不直接暴露 SDK `TerminalHandle` class,避免业务代码依赖其私有连接实现;
6
- * compatibility transport 与 AgentContext adapter 返回的句柄都满足此接口。
7
- */
8
- export interface AcpTerminalHandle {
9
- readonly id: string;
10
- currentOutput(): Promise<TerminalOutputResponse>;
11
- waitForExit(): Promise<WaitForTerminalExitResponse>;
12
- kill(): Promise<KillTerminalResponse>;
13
- release(): Promise<ReleaseTerminalResponse | void>;
14
- }
15
- /**
16
- * Agent 到 ACP client 的连接级调用通道。
17
- *
18
- * 该 facade 只描述 Agent CLI 的出站调用面,不绑定 SDK 的连接生命周期实现。
19
- * compatibility 与 official runtime 都通过 {@link createAcpClientChannel}
20
- * 从 connection-scoped `AgentContext` 构造同一调用面。
21
- */
22
- export interface AcpClientChannel {
23
- sessionUpdate(params: SessionNotification): Promise<void>;
24
- requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse>;
25
- readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse>;
26
- writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse>;
27
- createTerminal(params: CreateTerminalRequest): Promise<AcpTerminalHandle>;
28
- createElicitation(params: CreateElicitationRequest): Promise<CreateElicitationResponse>;
29
- completeElicitation(params: CompleteElicitationNotification): Promise<void>;
30
- request<Response = unknown, Params = unknown>(method: string, params?: Params, options?: SendRequestOptions): Promise<Response>;
31
- notify<Params = unknown>(method: string, params?: Params): Promise<void>;
32
- }
33
- /**
34
- * 将 SDK handler 收到的 AgentContext 适配成 Agent CLI 连接级调用通道。
35
- */
36
- export declare function createAcpClientChannel(context: AgentContext): AcpClientChannel;
@@ -1,84 +0,0 @@
1
- import { type AgentContext, type JsonRpcId as AcpJsonRpcId, type MessageMcpNotification, type MessageMcpRequest } from '@agentclientprotocol/sdk/experimental/v2';
2
- import type { Transport, TransportSendOptions } from '@modelcontextprotocol/sdk/shared/transport.js';
3
- import { type JSONRPCMessage, type RequestId } from '@modelcontextprotocol/sdk/types.js';
4
- type McpClientContext = Pick<AgentContext, 'request' | 'notify'>;
5
- type AcpMcpParams = Record<string, unknown> | null | undefined;
6
- export interface AcpMcpPeerRegistration {
7
- readonly peer: AcpMcpPeer;
8
- dispose(reason?: unknown): Promise<void>;
9
- }
10
- export interface AcpMcpTransportOptions {
11
- readonly routeId: string;
12
- readonly serverId: string;
13
- /** Cancels acquisition without transferring ownership of an established connection. */
14
- readonly signal?: AbortSignal;
15
- }
16
- /**
17
- * Registers the client side of one live ACP v2 connection.
18
- *
19
- * Session MCP configuration crosses the Agent CLI's internal HTTP boundary, so
20
- * it carries only the opaque route id and resolves the live `AgentContext`
21
- * here. A route is exact and cannot be replaced while it is active.
22
- */
23
- export declare function registerAcpMcpPeer(routeId: string, client: McpClientContext, signal: AbortSignal): AcpMcpPeerRegistration;
24
- export declare function requireAcpMcpPeer(routeId: string): AcpMcpPeer;
25
- /**
26
- * Connection-scoped MCP-over-ACP dispatcher. One peer may own many physical
27
- * MCP connections, each selected by the provider-generated `connectionId`.
28
- */
29
- export declare class AcpMcpPeer {
30
- private readonly client;
31
- private readonly rootSignal;
32
- private readonly transports;
33
- private isClosed;
34
- constructor(client: McpClientContext, rootSignal: AbortSignal);
35
- get closed(): boolean;
36
- connect(serverId: string, signal: AbortSignal): Promise<string>;
37
- attach(connectionId: string, transport: AcpMcpTransport): void;
38
- request(transport: AcpMcpTransport, connectionId: string, method: string, params: AcpMcpParams, signal: AbortSignal): Promise<unknown>;
39
- notify(transport: AcpMcpTransport, connectionId: string, method: string, params: AcpMcpParams): Promise<void>;
40
- disconnect(transport: AcpMcpTransport, connectionId: string): Promise<void>;
41
- disconnectUnattached(connectionId: string): Promise<void>;
42
- receiveRequest(params: MessageMcpRequest, requestId: AcpJsonRpcId, signal: AbortSignal): Promise<unknown>;
43
- receiveNotification(params: MessageMcpNotification): void;
44
- closeFromRoot(reason?: unknown): Promise<void>;
45
- private requireTransport;
46
- private assertAttached;
47
- private assertOpen;
48
- }
49
- /**
50
- * MCP SDK transport backed by the standard ACP v2 MCP methods.
51
- *
52
- * ACP intentionally omits the inner JSON-RPC envelope. The outer request id is
53
- * the id observed by the MCP provider, while this transport restores the local
54
- * MCP SDK's id when it delivers the response back to the SDK.
55
- */
56
- export declare class AcpMcpTransport implements Transport {
57
- private readonly options;
58
- private state;
59
- private peer?;
60
- private connectionIdValue?;
61
- private startController?;
62
- private closePromise?;
63
- private closeNotified;
64
- private readonly outbound;
65
- private readonly inbound;
66
- onclose?: () => void;
67
- onerror?: (error: Error) => void;
68
- onmessage?: <T extends JSONRPCMessage>(message: T) => void;
69
- constructor(options: AcpMcpTransportOptions);
70
- get sessionId(): string | undefined;
71
- start(): Promise<void>;
72
- send(message: JSONRPCMessage, _options?: TransportSendOptions): Promise<void>;
73
- close(): Promise<void>;
74
- closeFromPeer(reason?: unknown): Promise<void>;
75
- receiveRequest(requestId: RequestId, method: string, params: AcpMcpParams, signal: AbortSignal): Promise<unknown>;
76
- receiveNotification(method: string, params: AcpMcpParams): void;
77
- private sendRequest;
78
- private sendNotification;
79
- private settleInbound;
80
- private finishClose;
81
- private deliver;
82
- private notifyClose;
83
- }
84
- export {};
@@ -1,20 +0,0 @@
1
- import type { CreateElicitationRequest, ElicitationSchema } from '@agentclientprotocol/sdk';
2
- export interface AskUserQuestionInput {
3
- questions: Array<{
4
- question: string;
5
- header: string;
6
- options: Array<{
7
- label: string;
8
- description: string;
9
- }>;
10
- multiSelect?: boolean;
11
- }>;
12
- metadata?: {
13
- source?: string;
14
- };
15
- }
16
- export declare function createAskUserQuestionElicitation(input: AskUserQuestionInput, sessionId: string, toolCallId: string, meta?: Record<string, unknown>): CreateElicitationRequest & {
17
- mode: 'form';
18
- requestedSchema: ElicitationSchema;
19
- };
20
- export declare function normalizeAskUserQuestionElicitationAnswers(input: AskUserQuestionInput, content: unknown): Record<string, string>;