@tencent-ai/agent-harness 0.2.0-beta.2 → 0.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -2
- package/cli/CHANGELOG.md +64 -0
- package/cli/dist-server/shared.cjs +450 -329
- package/cli/dist-server/types/node/acp/acp-protocol.d.ts +8 -0
- package/cli/dist-server/types/node/bash-sandbox/bash-sandbox-protocol.d.ts +3 -0
- package/cli/dist-server/types/node/cli/cli-protocol.d.ts +3 -0
- package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +8 -1
- package/cli/dist-server/types/node/loopback/server-protocol.d.ts +5 -0
- package/cli/dist-server/types/node/sensitive-content/sensitive-content-protocol.d.ts +7 -0
- package/cli/dist-server/types/node/server/boot.d.ts +7 -4
- package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-error-model.d.ts +1 -1
- package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-protocol.d.ts +2 -3
- package/cli/dist-server/types/node/server/formats/acp/index.d.ts +12 -0
- package/cli/dist-server/types/node/server/formats/acp/projection.d.ts +10 -0
- package/cli/dist-server/types/node/server/index.d.ts +1 -1
- package/cli/dist-server/types/node/server/sessions.d.ts +3 -2
- package/cli/dist-server/types/node/server/types.d.ts +59 -7
- package/cli/dist-server/types/node/tools/tool-protocol.d.ts +39 -24
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +31 -2
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-protocol.d.ts +8 -4
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-scope.d.ts +46 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +26 -3
- package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +3 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/model-call-failure.d.ts +9 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/model-step-sequence.d.ts +11 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +43 -9
- package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
- package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +9 -8
- package/cli/dist-server/types/vendor/cbc-core/node/context/compaction-lineage.d.ts +39 -0
- package/cli/dist-server/types/vendor/cbc-core/node/context/context-compact-summarizer.d.ts +2 -0
- package/cli/dist-server/types/vendor/cbc-core/node/context/context-protocol.d.ts +17 -0
- package/cli/dist-server/types/vendor/cbc-core/node/context/index.d.ts +2 -0
- package/cli/dist-server/types/vendor/cbc-core/node/context/mods-bridge.d.ts +115 -0
- package/cli/dist-server/types/vendor/cbc-core/node/context/pre-message-compact-strategy.d.ts +1 -2
- package/cli/dist-server/types/vendor/cbc-core/node/message-queue/followup-queue-protocol.d.ts +3 -2
- package/cli/dist-server/types/vendor/cbc-core/node/message-queue/followup-queue.d.ts +1 -1
- package/cli/dist-server/types/vendor/cbc-core/node/message-queue/steer-input-buffer-protocol.d.ts +4 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/can-use-tool.d.ts +4 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +8 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/model-request-retry-phase.d.ts +16 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +15 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager-host-protocol.d.ts +3 -2
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +37 -3
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +59 -5
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +14 -1
- package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +8 -1
- package/cli/dist-server/types/vendor/cbc-core/node/trace/turn-context.d.ts +28 -1
- package/cli/dist-server/types/vendor/cbc-core/node/utils/command-message-utils.d.ts +20 -0
- package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +4 -4
- package/cli/dist-server/types/vendor/cbc-core/node/utils/input-item-utils.d.ts +9 -1
- package/cli/dist-server/types/vendor/cbc-core/node/utils/token-utils.d.ts +3 -1
- package/cli/dist-server/types/vendor/cbc-shared/node/agent/openai-agents-types.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/checkpoint/checkpoint-types.d.ts +6 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +30 -2
- package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/prompt-codec.d.ts +4 -0
- package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/sandbox-rule-context.d.ts +38 -0
- package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/types.d.ts +15 -1
- package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +3 -3
- package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +6 -0
- package/cli/dist-server/types/workspace/authentication/lib/common/authentication-observation.d.ts +36 -0
- package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +21 -0
- package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +20 -4
- package/cli/dist-server/types/workspace/authentication/lib/common/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-protocol.d.ts +2 -0
- package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-service.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +31 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-protocol.d.ts +8 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-scope.d.ts +46 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +26 -3
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +3 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-call-failure.d.ts +9 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-step-sequence.d.ts +11 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +43 -9
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +9 -8
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/compaction-lineage.d.ts +39 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-compact-summarizer.d.ts +2 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-protocol.d.ts +17 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/index.d.ts +2 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/mods-bridge.d.ts +115 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/context/pre-message-compact-strategy.d.ts +1 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/followup-queue-protocol.d.ts +3 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/followup-queue.d.ts +1 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/steer-input-buffer-protocol.d.ts +4 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/can-use-tool.d.ts +4 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +8 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-request-retry-phase.d.ts +16 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +15 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager-host-protocol.d.ts +3 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +37 -3
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +59 -5
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +14 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +8 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/trace/turn-context.d.ts +28 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/command-message-utils.d.ts +20 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +4 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/input-item-utils.d.ts +9 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/token-utils.d.ts +3 -1
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/agent/openai-agents-types.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/checkpoint/checkpoint-types.d.ts +6 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +30 -2
- package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-service.d.ts +5 -0
- package/cli/dist-server/types/workspace/core/lib/common/protocol.d.ts +8 -1
- package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/product/lib/common/tencent-docs-endpoint.d.ts +37 -0
- package/cli/dist-server/types/workspace/product/lib/common/types/config.d.ts +12 -0
- package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +17 -9
- package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +15 -0
- package/cli/dist-server/types/workspace/prompts/lib/common/product-prompt-provider.d.ts +3 -1
- package/cli/dist-server/types/workspace/prompts/lib/common/prompt-protocol.d.ts +6 -0
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +5 -0
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +4 -1
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/http-policy.d.ts +20 -0
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/rule-config.d.ts +10 -0
- package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +3 -0
- package/cli/dist-server/types/workspace/telemetry/lib/common/event/types/craft.d.ts +43 -3
- package/cli/package.json +1 -1
- package/cli/product.cloudhosted.json +1 -803
- package/cli/product.internal.json +1 -1057
- package/cli/product.ioa.json +1 -1515
- package/cli/product.json +1 -2189
- package/cli/product.selfhosted.json +1 -364
- package/cli/vendor/shim/brokered-bin/7z +675 -0
- package/cli/vendor/shim/brokered-bin/7za +675 -0
- package/cli/vendor/shim/brokered-bin/7zz +675 -0
- package/cli/vendor/shim/brokered-bin/rar +675 -0
- package/cli/vendor/shim/brokered-bin/tar +675 -0
- package/cli/vendor/shim/brokered-bin/zip +187 -0
- package/docs/acp-v2.md +19 -0
- package/docs/client.md +7 -0
- package/docs/in-process.md +26 -2
- package/docs/product.md +4 -0
- package/docs/protocol.md +10 -2
- package/docs/server.md +2 -0
- package/lib/agent/v2.js +1 -1
- package/lib/application/services.js +1 -1
- package/lib/auth/module.d.ts +3 -1
- package/lib/auth/module.js +1 -1
- package/lib/client/client.js +1 -1
- package/lib/client/mcp.d.ts +1 -1
- package/lib/client/mcp.js +1 -1
- package/lib/components/acp-mcp-transport.d.mts +84 -1
- package/lib/components/question-elicitation.d.mts +20 -1
- package/lib/components/sandbox.d.mts +2 -0
- package/lib/components/sandbox.mjs +1 -0
- package/lib/components/{acp/acp-prompt-input.d.ts → session/prompt-input.d.ts} +1 -1
- package/lib/components/session-replay.d.mts +8 -7
- package/lib/components/session-replay.mjs +1 -1
- package/lib/effect-runtime/concurrency.d.mts +2 -4
- package/lib/effect-runtime/concurrency.mjs +1 -1
- package/lib/effect-runtime/mcp-lifecycle.mjs +1 -1
- package/lib/effect-runtime/process-runtime-context.d.ts +5 -1
- package/lib/harness/create-harness.js +1 -1
- package/lib/integration/agent-integration.d.ts +5 -0
- package/lib/protocol/acp-v2-credits.d.ts +10 -0
- package/lib/protocol/acp-v2-credits.js +1 -0
- package/lib/protocol/acp-v2-private-client.d.ts +1 -10
- package/lib/runtime/codebuddy-auth.d.ts +5 -3
- package/lib/runtime/codebuddy-auth.js +1 -1
- package/lib/runtime/private-runtime-role.js +1 -1
- package/lib/session/agent-backend.d.ts +3 -0
- package/lib/session/agent-backend.js +1 -1
- package/lib/session/config-defaults.d.ts +4 -0
- package/lib/session/config-defaults.js +1 -0
- package/lib/session/config-store.d.ts +1 -1
- package/lib/session/config-store.js +1 -1
- package/lib/session/replay.d.ts +3 -3
- package/lib/session/replay.js +1 -1
- package/lib/session/server-config.d.ts +11 -2
- package/lib/session/server-config.js +1 -1
- package/lib/session/server-events.d.ts +10 -8
- package/lib/session/server-events.js +1 -1
- package/lib/session/server-interactions.js +1 -1
- package/lib/session/server-mcp.js +1 -1
- package/lib/subagent/history.js +1 -1
- package/package.json +26 -20
- package/lib/components/acp/acp-client-channel.d.ts +0 -36
- package/lib/components/acp/acp-mcp-transport.d.ts +0 -84
- package/lib/components/acp/acp-question-elicitation.d.ts +0 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
var Ke=Object.defineProperty;var t=(E,H)=>Ke(E,"name",{value:H,configurable:!0});import{homedir as Pe}from"node:os";import*as k from"node:path";import{isDeepStrictEqual as Ve}from"node:util";import{WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI as we}from"@genie/product";import{Context as d,Effect as m,Exit as y,Layer as s,Logger as p,Option as Xe,Scope as h}from"effect";import{createAgentProtocolModule as Qe}from"../agent/router.js";import{createAgentV2Facade as Je}from"../agent/v2.js";import{ManagedAuthLocal as Ze}from"../auth/local.js";import{ManagedAuth as $e}from"../auth/managed.js";import{createAuthProtocolModule as er}from"../auth/module.js";import{Checkpoints as Ae}from"../checkpoint/service.js";import{ConfigFiles as ee}from"../config/files.js";import{createDefaultAgentMcpIntegration as rr}from"../integration/agent-integration.js";import{PluginMcp as _e}from"../integration/plugin-mcp.js";import{UserMcp as be}from"../integration/user-mcp.js";import{requestWithEnvironment as tr}from"../internal/http.js";import{createMcpServerProtocolModule as or}from"../mcp-server/module.js";import{composeAgentHarnessModules as nr}from"../module/compose.js";import{PluginComponents as re}from"../plugin/components.js";import{createProductProtocolModule as ir}from"../product/module.js";import{preflightCodeBuddyCode as ar}from"../runtime/agent-runtime.js";import{buildAgentHarnessClientIdentityEnv as sr,buildAgentHarnessClientIdentityHeaders as cr}from"../runtime/client-identity.js";import{createCodeBuddyAuthRuntime as dr}from"../runtime/codebuddy-auth.js";import{createCodeBuddyProductLifecycle as pr}from"../runtime/codebuddy-product.js";import{DEFAULT_HOST_HEALTH_TIMEOUT_MS as ur,DEFAULT_READY_TIMEOUT_MS as mr}from"../runtime/codebuddy-resource-timeouts.js";import{CodeBuddyProcessContainment as lr}from"../runtime/process-containment.js";import{parseAgentHarnessProductConfig as fr,parseHarnessProductInput as hr}from"../runtime/product-config.js";import{ProductManager as gr}from"../runtime/product-manager.js";import{ProductResolver as ke}from"../runtime/product-resolver.js";import{ProductResolverRequestError as yr}from"../runtime/product-resolver-error.js";import{loadProductSource as Er}from"../runtime/product-source.js";import{HarnessSandboxCenter as Sr}from"../runtime/sandbox-center.js";import{AgentHarnessServer as vr,DEFAULT_LIFECYCLE_HOOK_TIMEOUT_MS as Cr}from"../server/index.js";import{makeServiceRpcs as Pr}from"../server/rpc-services.js";import{AgentBackend as wr,workspaceQueryOptions as Ar}from"../session/agent-backend.js";import{AgentServer as De}from"../session/agent-server.js";import{SessionConfigStore as _r}from"../session/config-store.js";import{SessionFiles as br}from"../session/files.js";import{localFs as Ie}from"../session/local-fs.js";import{SessionReplay as Me}from"../session/replay.js";import{SessionRuntime as kr}from"../session/runtime.js";import{Sessions as Le}from"../session/service.js";import{toExecutorPrivateProxyPolicy as Te}from"../settings/proxy-policy.js";import{createHarnessSettingsRuntime as Dr}from"../settings/runtime.js";import{Settings as Ir}from"../settings/service.js";import{createSubagentProtocolModule as Mr}from"../subagent/module.js";import{createEffectTelemetryMetricAggregator as Lr}from"../telemetry/effect-metric-aggregation.js";import{createTelemetry as Tr}from"../telemetry/runtime.js";import{measureStartup as te,startupProfiler as i}from"../telemetry/startup-profile.js";import{closeInPhases as oe,closeTelemetry as Or,createCloseOnce as _,DEFAULT_TELEMETRY_CLOSE_TIMEOUT_MS as xr}from"./lifecycle.js";export async function createApplicationServices({clientIdentity:E,clientIdentityEnv:H,dependencies:v,packageVersion:Oe,processRuntime:g,productConfig:O,sandboxCenter:xe,tools:ne,strictMcpConfig:Re,mcp:Fe,shutdown:B,telemetryOptions:ie,signal:u}){u?.throwIfAborted();const C=t(e=>m.runPromise(e,{signal:u}),"runStartupEffect"),z=B,ae={name:"@genie/agent-harness",title:"Agent Harness",version:Oe},se=(v.preflightCodeBuddyCode??ar)(),D=new lr,x=new AbortController,l=Tr(ie),W=_(()=>Or(l,g,Math.max(1,Math.min(B.remainingMs(),ie.flushTimeoutMs??xr))));B.registerTelemetryCloser(W);const ce=Lr(e=>l.recordEffectMetrics(e));try{g.addFinalizer(W)}catch(e){throw await W(),e}try{g.setTelemetryObserver({log:t(e=>l.recordEffectLog(e),"log"),metrics:t(e=>ce.record("harness",e),"metrics"),span:t(e=>l.recordEffectSpan(e),"span")})}catch{}const b=t(e=>l.recordLifecycle(e),"recordLifecycle"),R=new Sr(process.env.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(process.env.CODEBUDDY_CONFIG_DIR.trim()):k.join(Pe(),".codebuddy"),xe,process.env.SANDBOX_CENTER_IPC_ADDRESS?.trim()),N=_(()=>R.close());g.addFinalizer(N);let de=!1;const Y=t((e,c,T)=>{de||(de=!0,b({component:"server",error:e,phase:"runtime",process:{pid:process.pid},reason:T,state:c}))},"recordRootFailure");D.signal.addEventListener("abort",()=>{Y(D.signal.reason,"containment_tripped","containment_failed")},{once:!0});const Ue={log(e){try{l.recordEffectLog(e)}catch{}},metrics(e){ce.record("executor",e)},span(e){try{l.recordEffectSpan(e)}catch{}}};let P,n,F,I,a,A,M,w;const L=h.makeUnsafe(),G=_(e=>m.runPromise(h.close(L,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>G(void 0));const j=t(()=>{F&&m.runPromise(m.forkIn(F.prepare,L,{startImmediately:!0})).catch(()=>{})},"prepareRuntime"),pe=h.makeUnsafe(),q=_(async e=>{try{await a?.close(e)}finally{await m.runPromise(h.close(pe,e===void 0?y.void:y.fail(e)))}});g.addFinalizer(()=>q(void 0));const K=h.makeUnsafe(),V=_(e=>m.runPromise(h.close(K,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>V(void 0));const ue=h.makeUnsafe(),X=_(e=>m.runPromise(h.close(ue,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>X(void 0));const me=h.makeUnsafe(),Q=_(async e=>{try{await n?.close(e)}finally{await m.runPromise(h.close(me,e===void 0?y.void:y.fail(e)))}});g.addFinalizer(()=>Q(void 0));try{const e={...process.env},c={...H,...R.environment},T=typeof O=="object"?hr(O):Er(O,{parse:fr});u?.throwIfAborted(),i()?.markStart("harness.product");const He=await C(s.buildWithScope(ke.layer({projection:T.projection,baseConfiguration:O===void 0?void 0:{},packageRoot:se.productRoot??k.dirname(se.packageJsonPath),clientIdentity:{ideName:E.ideName,ideType:E.ideType,ideVersion:E.ideVersion,...E.userAgent===void 0?{}:{userAgent:E.userAgent}},environment:t(()=>({...e,...c}),"environment")}),pe));a=await(v.createProductManager??((r,o)=>gr.create(r,o)))({bootstrap:T.bootstrap,projection:T.projection,resolver:d.get(He,ke)},u),i()?.markEnd("harness.product");const Be=t(()=>{if(!a)throw new Error("Product manager is not ready");return a.getLaunchSnapshot()},"productLaunch");u?.throwIfAborted(),i()?.markStart("harness.config");const ze=await C(s.buildWithScope(ee.layer.pipe(s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),K));i()?.markEnd("harness.config");const fe=d.get(ze,ee);u?.throwIfAborted(),i()?.markStart("harness.settings"),A=await(v.createSettingsRuntime??Dr)({ambientEnvironment:e,config:fe,environment:c,observe:t(r=>l.recordEffectLog({annotations:{component:"harness",operation:"refresh",reason:r.reason,resource:"policy","runtime.role":"harness",status:r.status,...r.policy===void 0?{}:{mode:r.policy.mode,noProxyCount:r.policy.noProxyCount,proxyConfigured:r.policy.proxyConfigured,proxySupport:r.policy.proxySupport,revision:r.policy.revision}},level:r.status==="failed"?"warn":"info",message:"harness.settings.proxy"}),"observe"),processRuntime:g}),i()?.markEnd("harness.settings");const he=_r.layer(k.join(e.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(e.CODEBUDDY_CONFIG_DIR.trim()):k.join(Pe(),".codebuddy"),"harness","sessions"));u?.throwIfAborted(),i()?.markStart("harness.session-runtime");const ge=process.platform==="linux"?e[we]??((await import("#agent-harness-components/session-config")).isLinuxSandboxCLIInstalled()?"1":"0"):void 0,ye=await C(s.buildWithScope(v.sessionRuntimeLayer??wr({checkpoints:!0,headers:cr(E),prepareSandboxCenter:t((r,o)=>R.prepare(r.account?.uid,o),"prepareSandboxCenter"),resolveOptions:t(r=>m.map(Ar(r),o=>({...o,...ne===void 0?{}:{tools:ne}})),"resolveOptions")}).pipe(s.provideMerge(De.layer({product:{},fs:Ie,settingSources:["user","project","local"],env:{...sr(E),CODEBUDDY_API_KEY_DISABLED:"1",CODEBUDDY_REMOTE_CONFIG_DISABLED:"1",CODEBUDDY_INCLUDE_TOPIC_MESSAGE:"true",...ge===void 0?{}:{[we]:ge},...R.environment,CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING:e.CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING??"0"}})),s.provide(he)),L));i()?.markEnd("harness.session-runtime"),F=d.get(ye,kr),u?.throwIfAborted(),i()?.markStart("harness.replay");const We=d.get(await C(s.buildWithScope(Me.layer({},r=>Ie.readFileBuffer(r)).pipe(s.provide(he)),L)),Me);i()?.markEnd("harness.replay"),u?.throwIfAborted(),i()?.markStart("harness.storage");const Ee=await C(s.buildWithScope(s.mergeAll(Le.layer,Ae.layer).pipe(s.provide(br.layer),s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),L));i()?.markEnd("harness.storage");const Ne=d.get(Ee,Le),Ye=d.get(Ee,Ae);I=(v.createMcpIntegration??(r=>rr({containment:r.containment,recordEffectTelemetry:r.recordEffectTelemetry,recordLifecycle:r.recordLifecycle,supervisor:{environment:r.environment,toolsSyncTtlMs:Fe?.toolsSyncTtlMs,proxyPolicy:r.proxyPolicy}})))({containment:D,environment:c,proxyPolicy:Te(A.currentProxyPolicy,c),recordEffectTelemetry:Ue,recordLifecycle:b}),M=A.subscribe(r=>{const o=Te(r,c);I?.configureProxy?.(o).catch(()=>{l.recordEffectLog({annotations:{component:"harness",operation:"update",resource:"policy","runtime.role":"harness",status:"failed"},level:"warn",message:"harness.settings.proxy"})})});const Se=Xe.getOrUndefined(d.getOption(ye,De));u?.throwIfAborted(),i()?.markStart("harness.mcp-services");const J=await C(s.buildWithScope(s.mergeAll(be.layer({environment:t(()=>({...e,...c}),"environment")}),_e.layer).pipe(s.provideMerge(re.layer({environment:t(()=>({...e,...c}),"environment"),product:t(()=>a.getConfiguration(),"product"),writeContext:t(async()=>{await n?.prepareHostExecution(x.signal);const r=t(()=>({environment:{...e,...c},product:structuredClone(a.getConfiguration()),authentication:n?.currentSessionAuthentication()}),"capture");return n?n.runConsistentRead(r):r()},"writeContext"),onConfigChange:Se?async(r,o)=>{const f=o.authentication;Se.notifyConfigChange({source:r.source,filePath:r.file_path,cwd:r.cwd},{product:o.product,environment:o.environment,fetch:t(($,U)=>tr($,U,o.environment),"fetch"),auth:f?{accessToken:f.credential.accessToken,method:f.credential.type,refresh:t(async({signal:$})=>{if(!n||!a)throw new Error("Hook authentication is unavailable");const U=t(()=>{if(!Ve(o.product,a.getConfiguration()))throw new Error("Hook Product changed")},"checkProduct");await n.runConsistentRead(U);const Ce=await n.refreshHostAuthentication(f,$);return await n.runConsistentRead(U),{accessToken:Ce.credential.accessToken,method:Ce.credential.type}},"refresh")}:void 0,account:f?{uid:f.account.id,enterpriseId:f.account.organization?.id}:void 0}).catch(()=>m.runSync(m.logWarning("harness.config-change.failed").pipe(m.provide(p.layer([p.withConsoleError(p.formatLogFmt)])))))}:void 0,reloadUserConfig:t(r=>P?.reloadUserConfig(r)??Promise.resolve(),"reloadUserConfig")})),s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),ue));i()?.markEnd("harness.mcp-services"),u?.throwIfAborted(),i()?.markStart("harness.agent-facade"),P=await(v.createAgentFacade??Je)({userMcp:d.get(J,be),pluginMcp:d.get(J,_e),checkpoints:Ye,sessions:Ne,initialProductGeneration:Be().productGeneration,mcpIntegration:I,strictMcpConfig:Re,onPermanentFailure:t(r=>{Y(r,"fused","recovery_failed"),x.abort(r)},"onPermanentFailure"),prepareSessionRuntime:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.prepareSessionRuntime(r,o.connectionSignal)},"prepareSessionRuntime"),prepareSessionWorkspace:t(async(r,o)=>{if(!n||!a)throw new Error("Product manager is not ready");try{return await a.prepareWorkspace(r,{signal:o})}catch(f){if(!(f instanceof yr&&f.code==="AUTH_REFRESH_REQUIRED"))throw f;return await n.refreshProductAuthentication(o),a.prepareWorkspace(r,{force:!0,signal:o})}},"prepareSessionWorkspace"),releaseSessionWorkspace:t((r,o)=>a?a.releaseWorkspace(r,o):Promise.resolve(),"releaseSessionWorkspace"),refreshAuthentication:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.refreshAuthentication(r,{signal:o?.signal??AbortSignal.abort(new Error("Authentication refresh has no operation signal"))})},"refreshAuthentication"),serverInfo:ae,sessionRuntime:F,sessionReplay:We}),i()?.markEnd("harness.agent-facade");const ve=pr({facade:P,onExecutionProductCommitted:j,product:a});u?.throwIfAborted(),i()?.markStart("harness.auth-service");const Ge=await C(s.buildWithScope(v.managedAuthLayer??Ze({...a.resolveLoginProduct?{resolveLoginProduct:t((r,o)=>a.resolveLoginProduct(r,o),"resolveLoginProduct")}:{},environment:t(()=>({...e,...c}),"environment"),product:t(()=>a.getConfiguration(),"product")}).pipe(s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),me));i()?.markEnd("harness.auth-service"),n=dr({consumer:P,getAuthMethods:t(()=>a.getAuthMethods(),"getAuthMethods"),managedAuth:d.get(Ge,$e),onRuntimePreparing:j,onRuntimePrepared:j,productLifecycle:ve});const S=await er(n);n.bindProtocolBridge(S.bridge);const Z=ir({selectConnectionProductProfile:t((r,o)=>n.selectConnectionProductProfile(r,o),"selectConnectionProductProfile"),provisionProduct:t((r,o)=>S.runAuthMutation(()=>n.provisionProduct(r,o)),"provisionProduct"),readProduct:t((r,o)=>n.readProduct(r,o),"readProduct"),provisionWorkspaceProduct:t((r,o)=>S.runAuthMutation(()=>n.provisionWorkspaceProduct(r,o)),"provisionWorkspaceProduct"),readWorkspaceProduct:t((r,o)=>a.readWorkspaceProduct(r,o),"readWorkspaceProduct")});a.bindPublisher({notifyProductUpdated:t(()=>Z.publisher.notifyProductUpdated(ve.currentProductSnapshot()),"notifyProductUpdated"),notifyWorkspaceProductUpdated:t(r=>Z.publisher.notifyWorkspaceProductUpdated(r),"notifyWorkspaceProductUpdated")});const je=d.empty().pipe(d.add(Ir,A),d.add(ee,fe),d.add(re,d.get(J,re)));u?.throwIfAborted(),i()?.markStart("harness.rpc-services");const qe=await C(m.provide(Pr.pipe(h.provide(K)),je));i()?.markEnd("harness.rpc-services"),w=nr([{name:"private-runtime-lifecycle",capabilities:{},initialize:t(async(r,o)=>{await te("harness.initialize.settings",()=>A?.initialize(o.connectionSignal))},"initialize"),close:t(async r=>{M?.(),M=void 0,await X(r),await A?.close(r),await oe([[()=>G(r),()=>I?.close(r)??Promise.resolve()],[()=>N()],[()=>q(r)]],z,"private runtime shutdown")},"close")},Qe({v2:P}),or({backend:P}),Mr({backend:P}),Z,{name:S.name,capabilities:S.capabilities,initialize:t(async(r,o)=>te("harness.initialize.auth",()=>S.initialize(r,o)),"initialize"),initialized:S.initialized,notificationHandlers:S.notificationHandlers,requestHandlers:S.requestHandlers,close:Q},{...qe,close:V}])}catch(e){throw M?.(),M=void 0,b({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"}),await oe([[()=>V(e)],[()=>Q(e)],[()=>P?.close(e)??Promise.resolve(),()=>G(e)],[()=>I?.close(e)??Promise.resolve()],[()=>X(e)],[()=>A?.close(e)??Promise.resolve()],[()=>N()],[()=>q(e)]],z,"module startup cleanup").catch(()=>{}),e}let le;try{u?.throwIfAborted(),le=(v.createServer??(e=>new vr(e)))({serverInfo:ae,capabilities:w.capabilities,initializeHookTimeoutMs:mr+ur+Cr,initialize:t(async(e,c)=>(i()?.markEnd("harness.wait-initialize"),te("harness.initialize",()=>w.initialize(e,c))),"initialize"),initialized:w.initialized,notificationHandlers:w.notificationHandlers,onContainmentFailure:t(e=>{Y(e,"containment_tripped","containment_failed"),x.abort(e)},"onContainmentFailure"),readinessSignal:D.signal,requestHandlers:w.requestHandlers,telemetryRuntime:l})}catch(e){b({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"});try{await oe([[()=>w.close(e)]],z,"server construction cleanup")}catch(c){b({component:"server",error:c,phase:"cleanup",process:{pid:process.pid},reason:"cleanup_failed",state:"shutdown_failed"})}throw e}return{server:le,modules:w,telemetry:l,containment:D,runtimeShutdown:x,recordLifecycle:b}}t(createApplicationServices,"createApplicationServices");
|
|
1
|
+
var Ve=Object.defineProperty;var t=(E,H)=>Ve(E,"name",{value:H,configurable:!0});import{homedir as we}from"node:os";import*as k from"node:path";import{isDeepStrictEqual as Xe}from"node:util";import{Context as d,Effect as m,Exit as y,Layer as s,Logger as u,Option as Qe,Scope as h}from"effect";import{WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI as Ae}from"#agent-harness-components/sandbox";import{createAgentProtocolModule as Je}from"../agent/router.js";import{createAgentV2Facade as Ze}from"../agent/v2.js";import{ManagedAuthLocal as $e}from"../auth/local.js";import{ManagedAuth as er}from"../auth/managed.js";import{createAuthProtocolModule as rr}from"../auth/module.js";import{Checkpoints as _e}from"../checkpoint/service.js";import{ConfigFiles as re}from"../config/files.js";import{createDefaultAgentMcpIntegration as tr}from"../integration/agent-integration.js";import{PluginMcp as be}from"../integration/plugin-mcp.js";import{UserMcp as ke}from"../integration/user-mcp.js";import{requestWithEnvironment as or}from"../internal/http.js";import{createMcpServerProtocolModule as nr}from"../mcp-server/module.js";import{composeAgentHarnessModules as ir}from"../module/compose.js";import{PluginComponents as te}from"../plugin/components.js";import{createProductProtocolModule as ar}from"../product/module.js";import{preflightCodeBuddyCode as sr}from"../runtime/agent-runtime.js";import{buildAgentHarnessClientIdentityEnv as cr,buildAgentHarnessClientIdentityHeaders as dr}from"../runtime/client-identity.js";import{createCodeBuddyAuthRuntime as ur}from"../runtime/codebuddy-auth.js";import{createCodeBuddyProductLifecycle as pr}from"../runtime/codebuddy-product.js";import{DEFAULT_HOST_HEALTH_TIMEOUT_MS as mr,DEFAULT_READY_TIMEOUT_MS as lr}from"../runtime/codebuddy-resource-timeouts.js";import{CodeBuddyProcessContainment as fr}from"../runtime/process-containment.js";import{parseAgentHarnessProductConfig as hr,parseHarnessProductInput as gr}from"../runtime/product-config.js";import{ProductManager as yr}from"../runtime/product-manager.js";import{ProductResolver as De}from"../runtime/product-resolver.js";import{ProductResolverRequestError as Er}from"../runtime/product-resolver-error.js";import{loadProductSource as Sr}from"../runtime/product-source.js";import{HarnessSandboxCenter as vr}from"../runtime/sandbox-center.js";import{AgentHarnessServer as Cr,DEFAULT_LIFECYCLE_HOOK_TIMEOUT_MS as Pr}from"../server/index.js";import{makeServiceRpcs as wr}from"../server/rpc-services.js";import{AgentBackend as Ar,workspaceQueryOptions as _r}from"../session/agent-backend.js";import{AgentServer as Ie}from"../session/agent-server.js";import{readSessionConfigDefaults as br}from"../session/config-defaults.js";import{SessionConfigStore as kr}from"../session/config-store.js";import{SessionFiles as Dr}from"../session/files.js";import{localFs as Me}from"../session/local-fs.js";import{SessionReplay as Le}from"../session/replay.js";import{SessionRuntime as Ir}from"../session/runtime.js";import{Sessions as Te}from"../session/service.js";import{toExecutorPrivateProxyPolicy as Oe}from"../settings/proxy-policy.js";import{createHarnessSettingsRuntime as Mr}from"../settings/runtime.js";import{Settings as Lr}from"../settings/service.js";import{createSubagentProtocolModule as Tr}from"../subagent/module.js";import{createEffectTelemetryMetricAggregator as Or}from"../telemetry/effect-metric-aggregation.js";import{createTelemetry as Rr}from"../telemetry/runtime.js";import{measureStartup as oe,startupProfiler as i}from"../telemetry/startup-profile.js";import{closeInPhases as ne,closeTelemetry as Fr,createCloseOnce as _,DEFAULT_TELEMETRY_CLOSE_TIMEOUT_MS as xr}from"./lifecycle.js";export async function createApplicationServices({clientIdentity:E,clientIdentityEnv:H,dependencies:v,packageVersion:Re,processRuntime:g,productConfig:O,sandboxCenter:Fe,tools:ie,strictMcpConfig:xe,mcp:Ue,shutdown:B,telemetryOptions:ae,signal:p}){p?.throwIfAborted();const C=t(r=>m.runPromise(r,{signal:p}),"runStartupEffect"),z=B,se={name:"@genie/agent-harness",title:"Agent Harness",version:Re},ce=(v.preflightCodeBuddyCode??sr)(),D=new fr,R=new AbortController,l=Rr(ae),W=_(()=>Fr(l,g,Math.max(1,Math.min(B.remainingMs(),ae.flushTimeoutMs??xr))));B.registerTelemetryCloser(W);const de=Or(r=>l.recordEffectMetrics(r));try{g.addFinalizer(W)}catch(r){throw await W(),r}try{g.setTelemetryObserver({log:t(r=>l.recordEffectLog(r),"log"),metrics:t(r=>de.record("harness",r),"metrics"),span:t(r=>l.recordEffectSpan(r),"span")})}catch{}const b=t(r=>l.recordLifecycle(r),"recordLifecycle"),F=new vr(process.env.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(process.env.CODEBUDDY_CONFIG_DIR.trim()):k.join(we(),".codebuddy"),Fe,process.env.SANDBOX_CENTER_IPC_ADDRESS?.trim()),N=_(()=>F.close());g.addFinalizer(N);let ue=!1;const Y=t((r,c,T)=>{ue||(ue=!0,b({component:"server",error:r,phase:"runtime",process:{pid:process.pid},reason:T,state:c}))},"recordRootFailure");D.signal.addEventListener("abort",()=>{Y(D.signal.reason,"containment_tripped","containment_failed")},{once:!0});const He={log(r){try{l.recordEffectLog(r)}catch{}},metrics(r){de.record("executor",r)},span(r){try{l.recordEffectSpan(r)}catch{}}};let P,n,x,I,a,A,M,w;const L=h.makeUnsafe(),G=_(r=>m.runPromise(h.close(L,r===void 0?y.void:y.fail(r))));g.addFinalizer(()=>G(void 0));const j=t(()=>{x&&m.runPromise(m.forkIn(x.prepare,L,{startImmediately:!0})).catch(()=>{})},"prepareRuntime"),pe=h.makeUnsafe(),q=_(async r=>{try{await a?.close(r)}finally{await m.runPromise(h.close(pe,r===void 0?y.void:y.fail(r)))}});g.addFinalizer(()=>q(void 0));const K=h.makeUnsafe(),V=_(r=>m.runPromise(h.close(K,r===void 0?y.void:y.fail(r))));g.addFinalizer(()=>V(void 0));const me=h.makeUnsafe(),X=_(r=>m.runPromise(h.close(me,r===void 0?y.void:y.fail(r))));g.addFinalizer(()=>X(void 0));const le=h.makeUnsafe(),Q=_(async r=>{try{await n?.close(r)}finally{await m.runPromise(h.close(le,r===void 0?y.void:y.fail(r)))}});g.addFinalizer(()=>Q(void 0));try{const r={...process.env},c={...H,...F.environment},T=typeof O=="object"?gr(O):Sr(O,{parse:hr});p?.throwIfAborted(),i()?.markStart("harness.product");const Be=await C(s.buildWithScope(De.layer({projection:T.projection,baseConfiguration:O===void 0?void 0:{},packageRoot:ce.productRoot??k.dirname(ce.packageJsonPath),clientIdentity:{ideName:E.ideName,ideType:E.ideType,ideVersion:E.ideVersion,...E.userAgent===void 0?{}:{userAgent:E.userAgent}},environment:t(()=>({...r,...c}),"environment")}),pe));a=await(v.createProductManager??((e,o)=>yr.create(e,o)))({bootstrap:T.bootstrap,projection:T.projection,resolver:d.get(Be,De)},p),i()?.markEnd("harness.product");const ze=t(()=>{if(!a)throw new Error("Product manager is not ready");return a.getLaunchSnapshot()},"productLaunch");p?.throwIfAborted(),i()?.markStart("harness.config");const We=await C(s.buildWithScope(re.layer.pipe(s.provide(u.layer([u.withConsoleError(u.formatLogFmt)]))),K));i()?.markEnd("harness.config");const J=d.get(We,re),he=t((e,o)=>br(J,e,o),"sessionConfigDefaults");p?.throwIfAborted(),i()?.markStart("harness.settings"),A=await(v.createSettingsRuntime??Mr)({ambientEnvironment:r,config:J,environment:c,observe:t(e=>l.recordEffectLog({annotations:{component:"harness",operation:"refresh",reason:e.reason,resource:"policy","runtime.role":"harness",status:e.status,...e.policy===void 0?{}:{mode:e.policy.mode,noProxyCount:e.policy.noProxyCount,proxyConfigured:e.policy.proxyConfigured,proxySupport:e.policy.proxySupport,revision:e.policy.revision}},level:e.status==="failed"?"warn":"info",message:"harness.settings.proxy"}),"observe"),processRuntime:g}),i()?.markEnd("harness.settings");const ge=kr.layer(k.join(r.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(r.CODEBUDDY_CONFIG_DIR.trim()):k.join(we(),".codebuddy"),"harness","sessions"));p?.throwIfAborted(),i()?.markStart("harness.session-runtime");const ye=process.platform==="linux"?r[Ae]??((await import("#agent-harness-components/session-config")).isLinuxSandboxCLIInstalled()?"1":"0"):void 0,Ee=await C(s.buildWithScope(v.sessionRuntimeLayer??Ar({checkpoints:!0,headers:dr(E),prepareSandboxCenter:t((e,o)=>F.prepare(e.account?.uid,o),"prepareSandboxCenter"),resolveOptions:t(e=>m.map(_r(e),o=>({...o,...ie===void 0?{}:{tools:ie}})),"resolveOptions"),resolveConfigDefaults:t(e=>m.tryPromise({try:t(()=>he(e.workspace?.canonicalCwd??e.cwd??process.cwd(),e.signal),"try"),catch:t(o=>o,"catch")}),"resolveConfigDefaults")}).pipe(s.provideMerge(Ie.layer({product:{},fs:Me,settingSources:["user","project","local"],env:{...cr(E),CODEBUDDY_API_KEY_DISABLED:"1",CODEBUDDY_REMOTE_CONFIG_DISABLED:"1",CODEBUDDY_INCLUDE_TOPIC_MESSAGE:"true",...ye===void 0?{}:{[Ae]:ye},...F.environment,CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING:r.CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING??"0"}})),s.provide(ge)),L));i()?.markEnd("harness.session-runtime"),x=d.get(Ee,Ir),p?.throwIfAborted(),i()?.markStart("harness.replay");const Ne=d.get(await C(s.buildWithScope(Le.layer({},e=>Me.readFileBuffer(e),he).pipe(s.provide(ge)),L)),Le);i()?.markEnd("harness.replay"),p?.throwIfAborted(),i()?.markStart("harness.storage");const Se=await C(s.buildWithScope(s.mergeAll(Te.layer,_e.layer).pipe(s.provide(Dr.layer),s.provide(u.layer([u.withConsoleError(u.formatLogFmt)]))),L));i()?.markEnd("harness.storage");const Ye=d.get(Se,Te),Ge=d.get(Se,_e);I=(v.createMcpIntegration??(e=>tr({containment:e.containment,recordEffectTelemetry:e.recordEffectTelemetry,recordLifecycle:e.recordLifecycle,supervisor:{environment:e.environment,toolsSyncTtlMs:Ue?.toolsSyncTtlMs,proxyPolicy:e.proxyPolicy}})))({containment:D,environment:c,proxyPolicy:Oe(A.currentProxyPolicy,c),recordEffectTelemetry:He,recordLifecycle:b}),M=A.subscribe(e=>{const o=Oe(e,c);I?.configureProxy?.(o).catch(()=>{l.recordEffectLog({annotations:{component:"harness",operation:"update",resource:"policy","runtime.role":"harness",status:"failed"},level:"warn",message:"harness.settings.proxy"})})});const ve=Qe.getOrUndefined(d.getOption(Ee,Ie));p?.throwIfAborted(),i()?.markStart("harness.mcp-services");const Z=await C(s.buildWithScope(s.mergeAll(ke.layer({environment:t(()=>({...r,...c}),"environment")}),be.layer).pipe(s.provideMerge(te.layer({environment:t(()=>({...r,...c}),"environment"),product:t(()=>a.getConfiguration(),"product"),writeContext:t(async()=>{await n?.prepareHostExecution(R.signal);const e=t(()=>({environment:{...r,...c},product:structuredClone(a.getConfiguration()),authentication:n?.currentSessionAuthentication()}),"capture");return n?n.runConsistentRead(e):e()},"writeContext"),onConfigChange:ve?async(e,o)=>{const f=o.authentication;ve.notifyConfigChange({source:e.source,filePath:e.file_path,cwd:e.cwd},{product:o.product,environment:o.environment,fetch:t((ee,U)=>or(ee,U,o.environment),"fetch"),auth:f?{accessToken:f.credential.accessToken,method:f.credential.type,refresh:t(async({signal:ee})=>{if(!n||!a)throw new Error("Hook authentication is unavailable");const U=t(()=>{if(!Xe(o.product,a.getConfiguration()))throw new Error("Hook Product changed")},"checkProduct");await n.runConsistentRead(U);const Pe=await n.refreshHostAuthentication(f,ee);return await n.runConsistentRead(U),{accessToken:Pe.credential.accessToken,method:Pe.credential.type}},"refresh")}:void 0,account:f?{uid:f.account.id,enterpriseId:f.account.organization?.id}:void 0}).catch(()=>m.runSync(m.logWarning("harness.config-change.failed").pipe(m.provide(u.layer([u.withConsoleError(u.formatLogFmt)])))))}:void 0,reloadUserConfig:t(e=>P?.reloadUserConfig(e)??Promise.resolve(),"reloadUserConfig")})),s.provide(u.layer([u.withConsoleError(u.formatLogFmt)]))),me));i()?.markEnd("harness.mcp-services"),p?.throwIfAborted(),i()?.markStart("harness.agent-facade"),P=await(v.createAgentFacade??Ze)({userMcp:d.get(Z,ke),pluginMcp:d.get(Z,be),checkpoints:Ge,sessions:Ye,initialProductGeneration:ze().productGeneration,mcpIntegration:I,strictMcpConfig:xe,onPermanentFailure:t(e=>{Y(e,"fused","recovery_failed"),R.abort(e)},"onPermanentFailure"),prepareSessionRuntime:t((e,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.prepareSessionRuntime(e,o.connectionSignal)},"prepareSessionRuntime"),prepareSessionWorkspace:t(async(e,o)=>{if(!n||!a)throw new Error("Product manager is not ready");try{return await a.prepareWorkspace(e,{signal:o})}catch(f){if(!(f instanceof Er&&f.code==="AUTH_REFRESH_REQUIRED"))throw f;return await n.refreshProductAuthentication(o),a.prepareWorkspace(e,{force:!0,signal:o})}},"prepareSessionWorkspace"),releaseSessionWorkspace:t((e,o)=>a?a.releaseWorkspace(e,o):Promise.resolve(),"releaseSessionWorkspace"),refreshAuthentication:t((e,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.refreshAuthentication(e,{signal:o?.signal??AbortSignal.abort(new Error("Authentication refresh has no operation signal"))})},"refreshAuthentication"),serverInfo:se,sessionRuntime:x,sessionReplay:Ne}),i()?.markEnd("harness.agent-facade");const Ce=pr({facade:P,onExecutionProductCommitted:j,product:a});p?.throwIfAborted(),i()?.markStart("harness.auth-service");const je=await C(s.buildWithScope(v.managedAuthLayer??$e({...a.resolveLoginProduct?{resolveLoginProduct:t((e,o)=>a.resolveLoginProduct(e,o),"resolveLoginProduct")}:{},environment:t(()=>({...r,...c}),"environment"),product:t(()=>a.getConfiguration(),"product")}).pipe(s.provide(u.layer([u.withConsoleError(u.formatLogFmt)]))),le));i()?.markEnd("harness.auth-service"),n=ur({consumer:P,getAuthMethods:t(()=>a.getAuthMethods(),"getAuthMethods"),managedAuth:d.get(je,er),onRuntimePreparing:j,onRuntimePrepared:j,productLifecycle:Ce});const S=await rr(n);n.bindProtocolBridge(S.bridge);const $=ar({selectConnectionProductProfile:t((e,o)=>n.selectConnectionProductProfile(e,o),"selectConnectionProductProfile"),provisionProduct:t((e,o)=>S.runAuthMutation(()=>n.provisionProduct(e,o),{signal:o.signal}),"provisionProduct"),readProduct:t((e,o)=>n.readProduct(e,o),"readProduct"),provisionWorkspaceProduct:t((e,o)=>S.runAuthMutation(()=>n.provisionWorkspaceProduct(e,o),{signal:o.signal}),"provisionWorkspaceProduct"),readWorkspaceProduct:t((e,o)=>a.readWorkspaceProduct(e,o),"readWorkspaceProduct")});a.bindPublisher({notifyProductUpdated:t(()=>$.publisher.notifyProductUpdated(Ce.currentProductSnapshot()),"notifyProductUpdated"),notifyWorkspaceProductUpdated:t(e=>$.publisher.notifyWorkspaceProductUpdated(e),"notifyWorkspaceProductUpdated")});const qe=d.empty().pipe(d.add(Lr,A),d.add(re,J),d.add(te,d.get(Z,te)));p?.throwIfAborted(),i()?.markStart("harness.rpc-services");const Ke=await C(m.provide(wr.pipe(h.provide(K)),qe));i()?.markEnd("harness.rpc-services"),w=ir([{name:"private-runtime-lifecycle",capabilities:{},initialize:t(async(e,o)=>{await oe("harness.initialize.settings",()=>A?.initialize(o.connectionSignal))},"initialize"),close:t(async e=>{M?.(),M=void 0,await X(e),await A?.close(e),await ne([[()=>G(e),()=>I?.close(e)??Promise.resolve()],[()=>N()],[()=>q(e)]],z,"private runtime shutdown")},"close")},Je({v2:P}),nr({backend:P}),Tr({backend:P}),$,{name:S.name,capabilities:S.capabilities,initialize:t(async(e,o)=>oe("harness.initialize.auth",()=>S.initialize(e,o)),"initialize"),initialized:S.initialized,notificationHandlers:S.notificationHandlers,requestHandlers:S.requestHandlers,close:Q},{...Ke,close:V}])}catch(r){throw M?.(),M=void 0,b({component:"server",error:r,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"}),await ne([[()=>V(r)],[()=>Q(r)],[()=>P?.close(r)??Promise.resolve(),()=>G(r)],[()=>I?.close(r)??Promise.resolve()],[()=>X(r)],[()=>A?.close(r)??Promise.resolve()],[()=>N()],[()=>q(r)]],z,"module startup cleanup").catch(()=>{}),r}let fe;try{p?.throwIfAborted(),fe=(v.createServer??(r=>new Cr(r)))({serverInfo:se,capabilities:w.capabilities,initializeHookTimeoutMs:lr+mr+Pr,initialize:t(async(r,c)=>(i()?.markEnd("harness.wait-initialize"),oe("harness.initialize",()=>w.initialize(r,c))),"initialize"),initialized:w.initialized,notificationHandlers:w.notificationHandlers,onContainmentFailure:t(r=>{Y(r,"containment_tripped","containment_failed"),R.abort(r)},"onContainmentFailure"),readinessSignal:D.signal,requestHandlers:w.requestHandlers,telemetryRuntime:l})}catch(r){b({component:"server",error:r,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"});try{await ne([[()=>w.close(r)]],z,"server construction cleanup")}catch(c){b({component:"server",error:c,phase:"cleanup",process:{pid:process.pid},reason:"cleanup_failed",state:"shutdown_failed"})}throw r}return{server:fe,modules:w,telemetry:l,containment:D,runtimeShutdown:R,recordLifecycle:b}}t(createApplicationServices,"createApplicationServices");
|
package/lib/auth/module.d.ts
CHANGED
|
@@ -119,7 +119,9 @@ export interface AuthProtocolModule extends Omit<AgentHarnessProtocolModule, 'in
|
|
|
119
119
|
* Serializes another process-wide state mutation with Auth ownership.
|
|
120
120
|
* This is an in-process composition seam, never a public protocol method.
|
|
121
121
|
*/
|
|
122
|
-
runAuthMutation<Value>(operation: () => Promise<Value
|
|
122
|
+
runAuthMutation<Value>(operation: () => Promise<Value>, options?: {
|
|
123
|
+
readonly signal?: AbortSignal;
|
|
124
|
+
}): Promise<Value>;
|
|
123
125
|
}
|
|
124
126
|
/**
|
|
125
127
|
* Creates the process-wide authentication module.
|
package/lib/auth/module.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var V=Object.defineProperty;var
|
|
1
|
+
var V=Object.defineProperty;var o=(e,a)=>V(e,"name",{value:a,configurable:!0});import{currentHarnessProcessRuntime as W}from"../effect-runtime/process-runtime-context.js";import{clientManagementCapabilityBranch as Q}from"../module/capabilities.js";import{createUpdatedSubscriberRegistry as F}from"../module/updated-subscribers.js";import{validateParams as _,validateResult as R}from"../module/validation.js";import{ACP_V2_METHODS as K}from"../protocol/acp-v2.js";import{validateAcpV2AuthMethod as X,validateAcpV2CoreSchema as U}from"../protocol/acp-v2-schema.js";import{HARNESS_METHODS as Y}from"../protocol/methods.js";import{accountBinding as q,sameBinding as Z}from"../runtime/external-product-binding.js";import{AGENT_HARNESS_JSON_RPC_ERROR_CODES as S,AgentHarnessInvalidParamsError as N,AgentHarnessJsonRpcError as m}from"../server/errors.js";import{AUTH_STATUS_METHOD as k}from"./rpcs.js";import{accountProvisionParamsSchema as ee,accountProvisionResponseSchema as te,accountReadParamsSchema as ne,accountReadResponseSchema as D,accountRefreshParamsSchema as ae,accountRefreshResponseSchema as oe,accountUpdatedNotificationSchema as ce,authStatusRequestSchema as re,authStatusResponseSchema as ie}from"./schemas.js";const E=-32e3,ue=Object.freeze({account:null,mode:null,state:"unauthenticated"});export const AUTH_PROTOCOL_METHODS=Object.freeze({auth:Object.freeze({status:k}),account:Y.account}),AUTH_PROTOCOL_CAPABILITIES=Object.freeze({agent:Object.freeze({auth:Object.freeze({status:!0})}),account:Object.freeze({mode:"managed"})});function v(e,a){return Z(q(e,null),q(a,null))}o(v,"sameAccountBinding");function L(e,a,c){const g=U(a,c);if(g)throw new N(`Invalid ${e} params: ${g.message}`);return c}o(L,"validateAcpParams");function B(e,a,c){if(U(a,c))throw new m(S.internalError,`Invalid ${e} result`,{boundary:"result",method:e});return c}o(B,"validateAcpBackendResult");function se(e){if(!Array.isArray(e)||!e.every(X))throw new m(S.internalError,"Invalid authentication method catalog",{boundary:"result",method:"initialize"});const a=new Set;for(const c of e){if(a.has(c.methodId))throw new m(S.internalError,"Invalid authentication method catalog",{boundary:"result",method:"initialize"});a.add(c.methodId)}return Object.freeze([...e])}o(se,"validateAuthMethods");function de(e,a){if(e.state==="authenticated"&&e.mode!=="external"||e.state==="unauthenticated"&&e.mode!==null)throw new m(S.internalError,`Invalid ${a} result`,{boundary:"result",method:a})}o(de,"assertExternalSnapshot");function le(e){return Q(e,"account")}o(le,"accountCapability");function he(e){return Object.freeze({agent:Object.freeze({auth:Object.freeze({status:!0})}),account:Object.freeze({mode:e})})}o(he,"selectedCapabilities");function fe(e){return async(a,c)=>{const g=_(AUTH_PROTOCOL_METHODS.account.read,ne,a);return R(AUTH_PROTOCOL_METHODS.account.read,D,await e.readAccount(g,c))}}o(fe,"accountReadHandler");function me(e,a){return async(c,g)=>{const y=_(AUTH_PROTOCOL_METHODS.auth.status,re,c);return await e.prepareAuthStatus?.(y,g),a(async()=>R(AUTH_PROTOCOL_METHODS.auth.status,ie,await e.readAuthStatus(y,g)),{signal:g.signal})}}o(me,"authStatusHandler");export async function createAuthProtocolModule(e,a=W()){const c=K,g=e.accountUpdatePublication==="backend",y=fe(e);let u,P;const T=new WeakSet,C=new WeakMap,z=F();let A=0;const x=a.createSerialGate("Auth ownership mutation"),O=o((r,t={})=>x.run(()=>r(),{...t,uninterruptible:!0}),"runOwnershipMutation"),$=me(e,O),G=o((r,t)=>{u={account:structuredClone(r),context:t};const n=t.connectionSignal,l=o(()=>{if(u?.context.connectionSignal!==n)return;const p=A;u=void 0,O(async()=>{if(A!==p)return;let s,h=!1;try{h=await e.detachExternalAccount(t,n.reason)}catch(d){s=d,h=!0}if(A===p&&h&&(A+=1,g||await H(ue),s!==void 0))throw s}).catch(s=>{t.closeConnection?.(s).catch(()=>{})})},"detach");T.has(t.connectionSignal)||(T.add(t.connectionSignal),t.connectionSignal.addEventListener("abort",l,{once:!0})),n.aborted&&l()},"bindExternalOwner"),M=o(r=>{r.committed||(r.committed=!0,A+=1,G(r.account,r.context))},"commitExternalHandoff"),H=o(async(r,t={})=>{const i=R(AUTH_PROTOCOL_METHODS.account.updated,ce,r);if(i.mode==="external"&&i.state==="authenticated"){const n=P;if(n){const l=v(i.account,n.account),p=u!==void 0&&v(i.account,u.account),s=t.sourceOwner===n.context.connectionSignal,h=t.sourceOwner!==void 0&&t.sourceOwner===u?.context.connectionSignal,d=s&&l,f=h&&p;if(!(t.sourceOwner===void 0?l||p:d||f))throw new m(S.internalError,"Account update changed pending external identity");d&&!f&&M(n)}else if(u&&(!v(i.account,u.account)||t.sourceOwner!==void 0&&t.sourceOwner!==u.context.connectionSignal))throw new m(S.internalError,"Account update changed external identity")}else u=void 0;await z.broadcast(AUTH_PROTOCOL_METHODS.account.updated,i)},"broadcastAccountUpdated"),I=o(async r=>{if(g)return;const t=R(AUTH_PROTOCOL_METHODS.account.read,D,await e.readAccount({},{...r,signal:a.shutdownSignal}));await H(t)},"readAndBroadcastAccount"),J=Object.freeze({notifyAccountUpdated:H,async requestAccountRefresh(r,t){const i=_(AUTH_PROTOCOL_METHODS.account.refresh,ae,r),n=u;if(!n)throw new m(E,"Authentication required");if(n.context.connectionSignal.aborted)throw new m(E,"Authentication required",{reason:"owner_disconnected"});if(n.account.id!==i.accountId||n.context.connectionSignal!==t.expectedOwner)throw new m(E,"Authentication required",{reason:"account_changed"});let l;try{l=await n.context.request(AUTH_PROTOCOL_METHODS.account.refresh,i,t.signal===void 0?void 0:{signal:t.signal})}catch(s){throw n.context.connectionSignal.aborted?new m(E,"Authentication required",{reason:"owner_disconnected"}):s}const p=R(AUTH_PROTOCOL_METHODS.account.refresh,oe,l);if(!v(p.account,n.account))throw new m(E,"Authentication required",{reason:"account_changed"});return p}});return Object.freeze({bridge:J,capabilities:AUTH_PROTOCOL_CAPABILITIES,initialize:o(async(r,t)=>{const i=le(r),n=Object.freeze({mode:i.mode}),l=n.mode==="managed"?se(await e.listAuthMethods(r,t)):Object.freeze([]),p=new Set(l.map(h=>h.methodId));C.set(t.connectionSignal,n),e.selectConnectionAuthProfile?.(n,t),z.register(t);const s=new Map([[AUTH_PROTOCOL_METHODS.auth.status,$],[AUTH_PROTOCOL_METHODS.account.read,y]]);if(n.mode==="managed"&&l.length>0&&(s.set(c.agent.auth.login,async(h,d)=>{const f=L(c.agent.auth.login,"LoginAuthRequest",h);if(!p.has(f.methodId))throw new N(`Authentication method was not advertised: ${f.methodId}`);return O(async()=>{const w=B(c.agent.auth.login,"LoginAuthResponse",await e.login(f,d)??{});return A+=1,u=void 0,await I(d),w},{signal:d.signal})}),s.set(c.agent.auth.logout,async(h,d)=>{const f=L(c.agent.auth.logout,"LogoutAuthRequest",h);return O(async()=>{const w=B(c.agent.auth.logout,"LogoutAuthResponse",await e.logout(f,d)??{});return A+=1,u=void 0,await I(d),w},{signal:d.signal})})),n.mode==="external"){const h=o(async(d,f)=>{const w=_(AUTH_PROTOCOL_METHODS.account.provision,ee,d);return O(async()=>{const j=w.state==="authenticated"?{account:structuredClone(w.account),committed:!1,context:f}:void 0;P=j;try{const b=R(AUTH_PROTOCOL_METHODS.account.provision,te,await e.provisionAccount(w,f));if(de(b,AUTH_PROTOCOL_METHODS.account.provision),w.state!==b.state||w.state==="authenticated"&&b.state==="authenticated"&&!v(w.account,b.account))throw new m(S.internalError,`Invalid ${AUTH_PROTOCOL_METHODS.account.provision} result`,{boundary:"result",method:AUTH_PROTOCOL_METHODS.account.provision});return b.state==="authenticated"?M(j):(A+=1,u=void 0),await I(f),b}finally{P===j&&(P=void 0)}},{signal:f.signal})},"provisionHandler");s.set(AUTH_PROTOCOL_METHODS.account.provision,h)}return{capabilities:he(n.mode),registry:Object.freeze({inboundRequestHandlers:s,outboundNotificationMethods:Object.freeze([AUTH_PROTOCOL_METHODS.account.updated]),outboundRequestMethods:Object.freeze(n.mode==="external"?[AUTH_PROTOCOL_METHODS.account.refresh]:[])}),...l.length>0?{authMethods:l}:{}}},"initialize"),runAuthMutation:O,initialized:o((r,t)=>{z.promote(t);const i=C.get(t.connectionSignal);i&&e.markConnectionInitialized?.(i,t)},"initialized"),name:"auth"})}o(createAuthProtocolModule,"createAuthProtocolModule");
|
package/lib/client/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var h=(f,e)=>C(f,"name",{value:e,configurable:!0});import{client as E,methods as c,PROTOCOL_VERSION as g,RequestError as M}from"@agentclientprotocol/sdk/experimental/v2";import{Effect as b,Stream as S}from"effect";import{isRecord as p}from"../internal/guards.js";import{normalizeAcpV2CreditsForSdk as y,restoreCodeBuddyCreditsFromSdk as v}from"../protocol/acp-v2-credits.js";import{toAcpStream as P}from"../transport/effect.js";import{CLIENT_MCP_METHODS as A,ClientMcp as I,isSessionMcpMethod as z}from"./mcp.js";import{clientMethods as j,notificationDecoders as O,notificationMethods as T,peerRequestDecoders as R,requestDecoders as N,requestMethods as _,reverseMethods as k,sendNotificationMethods as V}from"./rpc.js";import{isInMemoryEndpoint as D,openTransport as L}from"./transport.js";class F{static{h(this,"ClientLifecycle")}constructor(e){this.options=e,this.state="disconnected",this.cleanup=Promise.resolve(),this.handlers=new Map,this.listeners=new Map,this.mcp=new I({request:h((i,o)=>this.requireConnected().request(c.agent.mcp.message,i,{cancellationSignal:o?.signal}),"request"),notify:h(i=>this.requireConnected().notify(c.agent.mcp.message,i),"notify")})}on(e,i){if(this.assertOpen(),A.has(e))throw new TypeError("Client owns MCP handlers; configure mcpServers on the session instead");if(typeof i!="function")throw new TypeError("Client.on requires a function");if(k.has(e))return this.register(e,i);if(T.has(e))return this.subscribe(e,i);throw new TypeError(`${e} is not an incoming Client method`)}register(e,i){if(this.handlers.has(e))throw new Error(`${e} already has a request handler`);return this.handlers.set(e,i),()=>{this.handlers.get(e)===i&&this.handlers.delete(e)}}subscribe(e,i){let o=this.listeners.get(e);return o||this.listeners.set(e,o=new Set),o.add(i),()=>{o.delete(i)}}assertOpen(){if(this.state==="closed"||this.state==="closing")throw new Error("Client is closed")}async publish(e,i){const t=(await Promise.allSettled([...this.listeners.get(e)??[]].map(async n=>{await n(i)}))).filter(n=>n.status==="rejected").map(n=>n.reason);if(t.length>0)throw new AggregateError(t,`Notification listener failed for ${e}`)}handle(e,i,o){const t=this.handlers.get(e);if(t)return t(i,o);if(e===c.client.session.requestPermission)return{outcome:{outcome:"cancelled"}};throw M.methodNotFound(e)}async request(e,i={},o){const t=this.requireConnected(),n=N[e],l=z(e)?this.mcp.prepare(i):void 0;let a;try{const r=l?.params??i,d=await t.request(e,n?n.params(r):r,o);a=n?n.result(d):d}catch(r){throw await l?.rollback(),r}return await l?.commit(a),e===c.agent.session.close&&p(i)&&typeof i.sessionId=="string"&&await this.mcp.closeSession(i.sessionId),a}async notify(e,i){await this.requireConnected().notify(e,i)}requireConnected(){if(this.state!=="connected"||!this.agent)throw new Error("Await client.connect() before making requests");return this.agent}connect(e,i){if(this.state!=="disconnected")return Promise.reject(new Error(`Client is ${this.state}`));if(!p(e))return Promise.reject(new TypeError("connect requires a Server or connection options"));const o=D(e);if(i!==void 0&&!o)return Promise.reject(new TypeError("Separate connection settings require a Server"));const t=o?i??{}:e,n=this.options.capabilities?.elicitation;return(n?.form||n?.url)&&!this.handlers.has(c.client.elicitation.create)?Promise.reject(new Error("Register client.on('elicitation/create', handler) before advertising elicitation capabilities")):t.timeoutMs!==void 0&&(!Number.isFinite(t.timeoutMs)||t.timeoutMs<=0)?Promise.reject(new TypeError("timeoutMs must be positive")):(this.state="connecting",this.initialization=void 0,this.connectAbort=new AbortController,this.connecting=this.open(e,t,this.connectAbort),this.connecting)}async open(e,i,o){const t=setTimeout(()=>o.abort(new Error("Client connect timed out")),i.timeoutMs??3e4),n=i.signal?AbortSignal.any([i.signal,o.signal]):o.signal;let l;try{n.throwIfAborted(),await this.cleanup;const a=await L(e);this.stream=a,n.throwIfAborted();const r=E();r.onConnect(({agent:s})=>{this.agent=s}),r.onRequest(c.client.session.requestPermission,async s=>await this.handle(c.client.session.requestPermission,s.params,s)),r.onRequest(c.client.elicitation.create,async s=>await this.handle(c.client.elicitation.create,s.params,s)),r.onNotification(c.client.session.update,({params:s})=>this.publish(c.client.session.update,v(s))),r.onNotification(c.client.elicitation.complete,({params:s})=>this.publish(c.client.elicitation.complete,s));for(const[s,u]of Object.entries(R))r.onRequest(s,u.params,async m=>u.result(await this.handle(s,m.params,m)));for(const[s,u]of Object.entries(O))r.onNotification(s,u,({params:m})=>this.publish(s,m));r.onRequest(c.client.mcp.connect,s=>this.mcp.connect(s.params,s.signal)),r.onRequest(c.client.mcp.disconnect,s=>this.mcp.disconnect(s.params)),r.onRequest(c.client.mcp.message,s=>this.mcp.message(s.params,s.signal)),r.onNotification(c.client.mcp.message,s=>this.mcp.notify(s.params));const d=r.connect(P(this.adaptInitialize(a)));this.connection=d,this.cleanup=d.closed.then(async()=>{this.connection===d&&(this.connection=void 0,this.agent=void 0,this.state==="connected"&&(this.state="disconnected")),await this.mcp.close(),await b.runPromise(a.close())}),this.cleanup.catch(()=>{});const w=this.agent;if(!w)throw new Error("ACP SDK did not create its client context");const q=w.request(c.agent.initialize,{protocolVersion:g,info:this.options.clientInfo??{name:"agent-harness-client",version:"0.1.0"},capabilities:this.options.capabilities??{}});if(await Promise.race([q,new Promise((s,u)=>{l=h(()=>{d.close(n.reason),u(n.reason)},"onAbort"),n.addEventListener("abort",l,{once:!0}),n.aborted&&l()})]),await w.notify("initialized",{}),n.throwIfAborted(),d.signal.aborted)throw d.signal.reason;this.state="connected"}catch(a){throw this.connection?.close(a),await this.releaseStream(a),this.agent=void 0,this.connection=void 0,this.initialization=void 0,this.state==="connecting"&&(this.state="disconnected"),a}finally{clearTimeout(t),l&&n.removeEventListener("abort",l)}}adaptInitialize(e){let i;const o=h(t=>{if("id"in t&&t.id===i&&"result"in t){const n=t.result;if(!p(n)||n.protocolVersion!==1||!p(n.serverInfo)||!p(n.capabilities))throw new TypeError("Invalid Harness initialize response");return this.initialization=n,{...t,result:{protocolVersion:g,info:n.serverInfo,capabilities:n.capabilities.agent??{},...n.authMethods===void 0?{}:{authMethods:n.authMethods},...n._meta===void 0?{}:{_meta:n._meta}}}}return t},"project");return{...e,incoming:S.map(e.incoming,t=>Array.isArray(t)?y(t.map(o)):y(o(t))),send:h(t=>!Array.isArray(t)&&"method"in t&&"id"in t&&t.method===c.agent.initialize?(i=t.id,e.send({...t,params:{protocolVersion:1,clientInfo:this.options.clientInfo??{name:"agent-harness-client",version:"0.1.0"},capabilities:{agent:this.options.capabilities??{},...this.options.account===void 0?{}:{account:this.options.account},...this.options.product===void 0?{}:{product:this.options.product}}}})):e.send(t),"send")}}async releaseStream(e){this.stream&&await b.runPromise(this.stream.close(e)).catch(()=>{}),await this.cleanup.catch(()=>{}),this.stream=void 0}close(){return this.closing??=(async()=>{this.state="closing",this.connectAbort?.abort(new Error("Client closed")),this.connection?.close(),await this.connecting?.catch(()=>{}),await this.releaseStream(),await this.mcp.close(),this.handlers.clear(),this.listeners.clear(),this.state="closed"})()}}export function createClient(f={}){const e=new F(structuredClone(f));function i(o){const t={};for(const[n,l]of Object.entries(o))if(typeof l!="string"){const a=i(l);Object.keys(a).length>0&&(t[n]=a)}else V.has(l)?t[n]=a=>e.notify(l,a):_.has(l)&&(t[n]=(a,r)=>e.request(l,a,r));return Object.freeze(t)}return h(i,"project"),Object.freeze(Object.defineProperties({...i(j)},{state:{get:h(()=>e.state,"get")},initialization:{get:h(()=>e.initialization,"get")},on:{value:h((o,t)=>e.on(o,t),"value")},connect:{value:h((o,t)=>e.connect(o,t),"value")},close:{value:h(()=>e.close(),"value")}}))}h(createClient,"createClient");
|
package/lib/client/mcp.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare class ClientMcp {
|
|
|
19
19
|
constructor(peer: AgentMcpPeer);
|
|
20
20
|
prepare(params: unknown): {
|
|
21
21
|
params: unknown;
|
|
22
|
-
commit(result: unknown): void
|
|
22
|
+
commit(result: unknown): Promise<void>;
|
|
23
23
|
rollback(): Promise<void>;
|
|
24
24
|
};
|
|
25
25
|
connect(params: ConnectMcpRequest, signal: AbortSignal): Promise<{
|
package/lib/client/mcp.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var M=Object.defineProperty;var a=(d,e)=>M(d,"name",{value:e,configurable:!0});import{randomUUID as u}from"node:crypto";import{methods as w,RequestError as y}from"@agentclientprotocol/sdk/experimental/v2";import{McpPeerTransport as I}from"../integration/mcp-peer-transport.js";import{isRecord as h}from"../internal/guards.js";const g=new WeakSet,P=128,C=128;export class ClientMcp{static{a(this,"ClientMcp")}constructor(e){this.peer=e,this.providers=new Map,this.connections=new Map,this.sessions=new Map,this.generation=0,this.opening=0}prepare(e){const n=[];let r=e;try{h(e)&&Array.isArray(e.mcpServers)&&(r={...e,mcpServers:e.mcpServers.map(t=>{if(!h(t)||!("transport"in t))return t;if(typeof t.name!="string"||!t.name.trim()||"type"in t||"serverId"in t)throw new TypeError("Local MCP requires { name, transport }");const o=t.transport;if(typeof o!="function"&&!v(o))throw new TypeError("MCP transport must implement the MCP SDK Transport interface");if(this.providers.size>=P)throw new RangeError("Too many local MCP providers");const s=u();return this.providers.set(s,{source:o,connections:new Set}),n.push(s),{type:"acp",name:t.name,serverId:s,...t._meta===void 0?{}:{_meta:t._meta}}})})}catch(t){for(const o of n)this.providers.delete(o);throw t}return{params:r,commit:a(async t=>{const o=h(t)&&typeof t.sessionId=="string"?t.sessionId:h(e)&&typeof e.sessionId=="string"?e.sessionId:void 0;if(!o){if(n.length)throw new Error("Session setup returned no sessionId for its MCP providers");return}const s=this.sessions.get(o)??new Set,i=new Set(n);if(h(r)&&Array.isArray(r.mcpServers))for(const c of r.mcpServers)h(c)&&typeof c.serverId=="string"&&this.providers.has(c.serverId)&&i.add(c.serverId);this.sessions.set(o,i),await this.release([...s].filter(c=>!i.has(c)))},"commit"),rollback:a(()=>this.release(n),"rollback")}}async connect(e,n){const r=this.providers.get(e.serverId);if(!r)throw y.invalidParams("Unknown MCP serverId");if(this.connections.size+this.opening>=C)throw new Error("Too many local MCP connections");this.opening++;try{const t=this.generation;n.throwIfAborted();const o=typeof r.source=="function"?await r.source():r.source;if(!v(o))throw new TypeError("MCP transport factory did not return a Transport");if(g.has(o)||o.onmessage||o.onclose||o.onerror)throw new Error("MCP Transport is already owned; return a fresh transport from a factory for each connection");if(g.add(o),n.aborted||t!==this.generation||this.providers.get(e.serverId)!==r)throw await o.close(),n.reason??new Error("MCP provider closed during connection");const s=u(),i=new I(s,this.peer);let c;const l=a(()=>c??=Promise.resolve().then(async()=>{this.connections.delete(s),r.connections.delete(s),i.closeFromScope(new Error("MCP connection closed")),await o.close()}),"close"),p=a(()=>{l().catch(()=>{})},"fail");i.onmessage=f=>{o.send(f).catch(p)},o.onmessage=f=>{i.send(f).catch(p)},i.onclose=o.onclose=p,i.onerror=o.onerror=p,this.connections.set(s,{provider:r,bridge:i,transport:o,close:l}),r.connections.add(s);const m=a(()=>{p()},"abort");n.addEventListener("abort",m,{once:!0});try{if(await i.start(),await o.start(),n.throwIfAborted(),c)throw new Error("MCP Transport closed during startup");return{connectionId:s}}catch(f){throw await l(),f}finally{n.removeEventListener("abort",m)}}finally{this.opening--}}message(e,n){return this.require(e.connectionId).bridge.receiveRequest(e.method,e.params,n)}notify(e){this.require(e.connectionId).bridge.receiveNotification(e.method,e.params)}async disconnect(e){return await this.connections.get(e.connectionId)?.close(),{}}async closeSession(e){const n=this.sessions.get(e)??[];this.sessions.delete(e),await this.release(n)}async close(){this.generation++,this.sessions.clear(),await this.release([...this.providers.keys()])}async release(e){const n=[];for(const r of e){const t=this.providers.get(r);this.providers.delete(r);for(const o of t?.connections??[]){const s=this.connections.get(o);s&&n.push(s)}}await Promise.all(n.map(r=>r.close()))}require(e){const n=this.connections.get(e);if(!n)throw y.invalidParams("Unknown MCP connectionId");return n}}function v(d){return h(d)&&["start","send","close"].every(e=>typeof d[e]=="function")}a(v,"isTransport");export const CLIENT_MCP_METHODS=new Set(Object.values(w.client.mcp)),sessionMcpMethods=[w.agent.session.new,w.agent.session.resume,w.agent.session.fork];export function isSessionMcpMethod(d){return sessionMcpMethods.some(e=>e===d)}a(isSessionMcpMethod,"isSessionMcpMethod");
|
|
@@ -1 +1,84 @@
|
|
|
1
|
-
|
|
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 +1,20 @@
|
|
|
1
|
-
|
|
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>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { FILE_DIRECTORY_APPROVAL_OPTION_ID, parseSandboxPermissionMetadata } from '../../cli/dist-server/types/workspace/agent-client-protocol/lib/common/index.js';
|
|
2
|
+
export { WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI } from '../../cli/dist-server/types/workspace/product/lib/common/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import o from"#agent-harness-runtime";const a=o["component-sandbox"]();export const{FILE_DIRECTORY_APPROVAL_OPTION_ID,parseSandboxPermissionMetadata,WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI}=a;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PromptRequest as V2PromptRequest } from '@agentclientprotocol/sdk/experimental/v2';
|
|
2
|
+
import type { PromptRequest } from '../../../cli/dist-server/types/node/server/formats/acp/acp-protocol.js';
|
|
2
3
|
import type { AgentInputItem } from '../../../cli/dist-server/types/vendor/cbc-shared/node/index.js';
|
|
3
|
-
import type { PromptRequest } from './acp-protocol.js';
|
|
4
4
|
/** Persist SDK content once. Resource bytes are projected for the model only at its boundary. */
|
|
5
5
|
export declare function acpPromptInput(input: PromptRequest | V2PromptRequest): AgentInputItem[];
|
|
6
6
|
export { projectPromptFilesForModel } from '../../../cli/dist-server/types/node/utils/embedded-resource.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { codeBuddyErrorFromRequestError } from '../../cli/dist-server/types/node/server/formats/acp/acp-error-model.js';
|
|
1
2
|
import type { AgentInputItem } from '../../cli/dist-server/types/vendor/cbc-shared/node/index.js';
|
|
2
|
-
import type {
|
|
3
|
+
import type { SessionReplayProjector, SessionUsage, SessionUsageHistory } from '../session/replay.js';
|
|
3
4
|
import type { AgentHarnessRewindSessionRequest } from '../session/turn.js';
|
|
4
|
-
|
|
5
|
-
export { acpPromptInput } from './
|
|
5
|
+
export { AcpSessionFormatter } from '../../cli/dist-server/types/node/server/formats/acp/index.js';
|
|
6
|
+
export { acpPromptInput } from './session/prompt-input.js';
|
|
6
7
|
/** Interpret ACP turn cursors outside the Agent's native storage API. */
|
|
7
8
|
export declare function selectRewindMessage(snapshot: Parameters<SessionReplayProjector>[0], boundary: AgentHarnessRewindSessionRequest['_meta']): string | null;
|
|
8
9
|
export declare function createToolInputParser(): (delta: string) => Record<string, unknown>;
|
|
@@ -13,12 +14,12 @@ export declare function projectAgentError(message: string, info?: {
|
|
|
13
14
|
code?: string | number;
|
|
14
15
|
details?: string;
|
|
15
16
|
} | null): ReturnType<typeof codeBuddyErrorFromRequestError>;
|
|
17
|
+
export declare function projectAgentFailure(error: unknown): ReturnType<typeof projectAgentError>;
|
|
16
18
|
/** The durable assistant error carries its original HTTP/category fields. */
|
|
17
19
|
export declare function projectAgentItemError(item: AgentInputItem): ReturnType<typeof projectAgentError> | undefined;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export declare const projectAgentEvent: AgentEventProjector;
|
|
20
|
+
export { projectAgentItem, projectAgentEvent } from '../../cli/dist-server/types/node/server/formats/acp/projection.js';
|
|
21
|
+
/** Per-model-request measurements, shared by live delivery and durable replay. */
|
|
22
|
+
export declare function readItemUsageMeta(item: AgentInputItem, origin?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
22
23
|
/** Storage-only ACP projection: no Cell container or execution services. */
|
|
23
24
|
export declare const projectSessionReplay: SessionReplayProjector;
|
|
24
25
|
/** Per-transcript billing stages and context; tree edges come from live lifecycle or SessionStore. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"#agent-harness-runtime";const t=e["component-session-replay"]();export const{selectRewindMessage,createToolInputParser,projectAgentError,projectAgentItemError,createSessionUsage,acpPromptInput,projectAgentItem,projectAgentEvent,projectSessionReplay}=t;
|
|
1
|
+
import e from"#agent-harness-runtime";const t=e["component-session-replay"]();export const{selectRewindMessage,createToolInputParser,projectAgentError,projectAgentFailure,projectAgentItemError,readItemUsageMeta,createSessionUsage,AcpSessionFormatter,acpPromptInput,projectAgentItem,projectAgentEvent,projectSessionReplay}=t;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
import type { HarnessProcessRuntime } from './process-runtime.mjs';
|
|
3
|
-
import type { HarnessPolicyDeadlineHandle, HarnessPolicyDeadlineOptions } from './process-runtime-context.js';
|
|
3
|
+
import type { HarnessPolicyDeadlineHandle, HarnessPolicyDeadlineOptions, HarnessSerialGateRunOptions } from './process-runtime-context.js';
|
|
4
4
|
declare const HarnessConcurrencyClosedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
5
|
readonly _tag: "HarnessConcurrencyClosedError";
|
|
6
6
|
} & Readonly<A>;
|
|
@@ -47,9 +47,7 @@ export declare class HarnessSerialGate {
|
|
|
47
47
|
private readonly semaphore;
|
|
48
48
|
private readonly state;
|
|
49
49
|
constructor(component: string, processRuntime: HarnessProcessRuntime);
|
|
50
|
-
run<Value>(operation: (signal: AbortSignal) => Promise<Value>, options?:
|
|
51
|
-
readonly signal?: AbortSignal;
|
|
52
|
-
}): Promise<Value>;
|
|
50
|
+
run<Value>(operation: (signal: AbortSignal) => Promise<Value>, options?: HarnessSerialGateRunOptions): Promise<Value>;
|
|
53
51
|
close(reason: unknown): Promise<void>;
|
|
54
52
|
private closeInternal;
|
|
55
53
|
/** @internal Root-Scope finalizer used by the process runtime. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var U=Object.defineProperty;var l=(n,t)=>U(n,"name",{value:t,configurable:!0});import{Clock as C,Data as y,Deferred as d,Effect as a,Semaphore as v,SynchronizedRef as c}from"effect";export class HarnessConcurrencyClosedError extends y.TaggedError("HarnessConcurrencyClosedError"){static{l(this,"HarnessConcurrencyClosedError")}constructor(t,e){super({component:t,message:`${t} is closed`,reason:e}),this.code="HARNESS_CONCURRENCY_CLOSED"}}export class HarnessOperationTimeoutError extends y.TaggedError("HarnessOperationTimeoutError"){static{l(this,"HarnessOperationTimeoutError")}constructor(t,e){super({message:`${t} timed out after ${e}ms`,operation:t,timeoutMs:e}),this.code="HARNESS_OPERATION_TIMEOUT"}}export class HarnessConcurrencyOperationError extends y.TaggedError("HarnessConcurrencyOperationError"){static{l(this,"HarnessConcurrencyOperationError")}constructor(t,e){super({cause:e,component:t,message:`${t} operation failed`}),this.code="HARNESS_CONCURRENCY_OPERATION_FAILED"}}export class HarnessSerialGate{static{l(this,"HarnessSerialGate")}constructor(t,e){this.component=t,this.processRuntime=e,this.semaphore=v.makeUnsafe(1),this.state=c.makeUnsafe({closed:!1,drained:d.makeUnsafe(),pending:0})}async run(t,e={}){const r=await this.processRuntime.runEffect(c.modify(this.state,o=>o.closed?[{accepted:!1,error:new HarnessConcurrencyClosedError(this.component,o.closedReason)},o]:[{accepted:!0},{...o,pending:o.pending+1}]));if(!r.accepted)throw r.error;const i=b(this.semaphore.withPermit(E(this.component,t)).pipe(a.ensuring(c.update(this.state,o=>{const s=o.pending-1;return s===0&&o.closed&&d.doneUnsafe(o.drained,a.void),{...o,pending:s}}))),this.component);try{return await this.processRuntime.runEffect(i,e)}catch(o){throw e.signal?.aborted?h(e.signal,`${this.component} operation aborted`):R(o)}}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>{if(r.closed)return[r.drained,r];const i={...r,closed:!0,closedReason:t};return i.pending===0&&d.doneUnsafe(i.drained,a.void),[i.drained,i]}));await this.processRuntime.runEffect(d.await(e))}closeEffect(t){return c.modify(this.state,e=>{if(e.closed)return[e.drained,e];const r={...e,closed:!0,closedReason:t};return r.pending===0&&d.doneUnsafe(r.drained,a.void),[r.drained,r]}).pipe(a.flatMap(d.await))}}export class HarnessStateCell{static{l(this,"HarnessStateCell")}constructor(t,e){this.processRuntime=t,this.state=c.makeUnsafe(e)}get current(){return c.getUnsafe(this.state)}set(t){return this.processRuntime.runEffect(c.set(this.state,t))}update(t){return this.processRuntime.runEffect(c.update(this.state,t))}}export class HarnessKeyedSerialGate{static{l(this,"HarnessKeyedSerialGate")}constructor(t,e){this.component=t,this.processRuntime=e,this.state=c.makeUnsafe({closed:!1,entries:new Map})}async run(t,e,r={}){const i=await this.processRuntime.runEffect(c.modify(this.state,s=>{if(s.closed)return[{entry:void 0,error:new HarnessConcurrencyClosedError(this.component,s.closedReason)},s];const u=s.entries.get(t),f=u===void 0?{drained:d.makeUnsafe(),pending:1,semaphore:v.makeUnsafe(1)}:{...u,pending:u.pending+1},m=new Map(s.entries);return m.set(t,f),[{entry:f},{...s,entries:m}]}));if(i.entry===void 0)throw i.error;const o=b(i.entry.semaphore.withPermit(E(this.component,e)).pipe(a.ensuring(c.update(this.state,s=>{const u=s.entries.get(t);if(u===void 0)return s;const f=new Map(s.entries);return u.pending===1?(d.doneUnsafe(u.drained,a.void),f.delete(t)):f.set(t,{...u,pending:u.pending-1}),{...s,entries:f}}))),this.component);try{return await this.processRuntime.runEffect(o,r)}catch(s){throw r.signal?.aborted?h(r.signal,`${this.component} operation aborted`):R(s)}}async waitForIdle(t,e={}){const r=c.getUnsafe(this.state).entries.get(t)?.drained;if(r!==void 0)try{await this.processRuntime.runEffect(d.await(r),e)}catch(i){throw e.signal?.aborted?h(e.signal,`${this.component} wait aborted`):i}}has(t){return c.getUnsafe(this.state).entries.has(t)}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>[[...r.entries.values()],{...r,closed:!0,closedReason:r.closed?r.closedReason:t}]));await Promise.allSettled(e.map(r=>this.processRuntime.runEffect(d.await(r.drained))))}closeEffect(t){return c.modify(this.state,e=>[[...e.entries.values()],{...e,closed:!0,closedReason:e.closed?e.closedReason:t}]).pipe(a.flatMap(e=>a.forEach(e,r=>d.await(r.drained),{concurrency:"unbounded",discard:!0})),a.andThen(c.update(this.state,e=>({...e,entries:new Map}))))}}export class HarnessSingleFlight{static{l(this,"HarnessSingleFlight")}constructor(t,e){this.component=t,this.processRuntime=e,this.state=c.makeUnsafe({closed:!1,flights:new Map})}async run(t,e,r={}){const i=await this.processRuntime.runEffect(c.modify(this.state,o=>{if(o.closed)return[{entry:void 0,error:new HarnessConcurrencyClosedError(this.component,o.closedReason),owner:!1},o];const s=o.flights.get(t);if(s!==void 0)return[{entry:s,owner:!1},o];const u={completed:d.makeUnsafe(),controller:new AbortController,result:d.makeUnsafe()},f=new Map(o.flights);return f.set(t,u),[{entry:u,owner:!0},{...o,flights:f}]}));if(i.entry===void 0)throw i.error;i.owner&&this.runOwner(t,i.entry,e,r.timeoutMs);try{return await this.processRuntime.runEffect(d.await(i.entry.result),{signal:r.signal})}catch(o){throw r.signal?.aborted?h(r.signal,r.abortMessage??`${this.component} wait aborted`):R(o)}}abortAll(t){const e=c.getUnsafe(this.state);for(const r of e.flights.values())r.controller.abort(t)}has(t){return c.getUnsafe(this.state).flights.has(t)}get activeCount(){return c.getUnsafe(this.state).flights.size}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>r.closed?[[...r.flights.values()],r]:[[...r.flights.values()],{...r,closed:!0,closedReason:t}]));for(const r of e)r.controller.abort(t);await Promise.allSettled(e.map(r=>this.processRuntime.runEffect(d.await(r.completed))))}closeEffect(t){return c.modify(this.state,e=>e.closed?[[...e.flights.values()],e]:[[...e.flights.values()],{...e,closed:!0,closedReason:t}]).pipe(a.tap(e=>a.sync(()=>{for(const r of e)r.controller.abort(t)})),a.flatMap(e=>a.forEach(e,r=>d.await(r.completed),{concurrency:"unbounded",discard:!0})),a.andThen(c.update(this.state,e=>({...e,flights:new Map}))))}async runOwner(t,e,r,i){let o=E(this.component,r);i!==void 0&&(o=withOperationTimeout(o,this.component,i)),o=b(o,this.component);try{const s=await this.processRuntime.runEffect(o,{signal:e.controller.signal});d.doneUnsafe(e.result,a.succeed(s))}catch(s){const u=e.controller.signal.aborted?new HarnessConcurrencyOperationError(this.component,h(e.controller.signal,`${this.component} owner aborted`)):s;d.doneUnsafe(e.result,u instanceof HarnessConcurrencyOperationError||u instanceof HarnessOperationTimeoutError?a.fail(u):a.die(u))}finally{await this.processRuntime.runEffect(c.update(this.state,s=>{if(s.flights.get(t)!==e)return s;const u=new Map(s.flights);return u.delete(t),{...s,flights:u}})).catch(()=>{}),d.doneUnsafe(e.completed,a.void)}}}export function policyDelay(n){return a.sleep(n)}l(policyDelay,"policyDelay");export function policyBackoff(n,t,e){return policyDelay(N(n,t,e))}l(policyBackoff,"policyBackoff");export function policyNow(){return C.currentTimeMillis}l(policyNow,"policyNow");export function withOperationTimeout(n,t,e){return n.pipe(a.timeout(e),a.catchTag("TimeoutError",()=>a.fail(new HarnessOperationTimeoutError(t,e))))}l(withOperationTimeout,"withOperationTimeout");export async function runPolicyDelay(n,t,e,r){try{await n.runEffect(policyDelay(t),{signal:e})}catch(i){throw e.aborted?h(e,r):i}}l(runPolicyDelay,"runPolicyDelay");export async function runPolicyBackoff(n,t,e,r,i,o){try{await n.runEffect(policyBackoff(t,e,r),{signal:i})}catch(s){throw i.aborted?h(i,o):s}}l(runPolicyBackoff,"runPolicyBackoff");export function createPolicyDeadline(n,t,e={}){if(!Number.isSafeInteger(t)||t<=0)throw new RangeError("Policy deadline must be a positive integer");const r=new AbortController,i=new AbortController,o=e.signals??[],s=AbortSignal.any([...o,r.signal]),u=[];let f=!1;const m=l(()=>{for(const[p,w]of u)p.removeEventListener("abort",w);u.length=0},"cleanup"),g=l(()=>{f||(f=!0,m(),i.abort(new Error("Policy deadline completed")))},"close");for(const p of o){if(p.aborted){g();break}const w=g;if(u.push([p,w]),p.addEventListener("abort",w,{once:!0}),p.aborted){g();break}}return f||n.runEffect(policyDelay(t),{signal:i.signal}).then(()=>{f||(f=!0,m(),r.abort(e.timeoutReason??new HarnessOperationTimeoutError("policy deadline",t)))}).catch(p=>{f||i.signal.aborted||(f=!0,m(),r.abort(p))}),Object.freeze({close:g,signal:s})}l(createPolicyDeadline,"createPolicyDeadline");function N(n,t,e){if(!Number.isSafeInteger(n)||n<=0||!Number.isSafeInteger(t)||t<=0||!Number.isSafeInteger(e)||e<=0)throw new RangeError("Policy backoff values must be positive integers");return Math.min(e,n*2**(t-1))}l(N,"policyBackoffDuration");function h(n,t){return n.reason??new Error(t)}l(h,"abortReason");function E(n,t){return a.tryPromise({catch:l(e=>new HarnessConcurrencyOperationError(n,e),"catch"),try:t})}l(E,"tryConcurrencyOperation");function R(n){return n instanceof HarnessConcurrencyOperationError?n.cause:n}l(R,"unwrapConcurrencyOperationError");function b(n,t){const e=P(t);if(e===void 0)return n;const r={component:e.component,operation:e.operation};return n.pipe(a.tap(()=>a.logInfo(e.eventName).pipe(a.annotateLogs({...r,outcome:"success"}))),a.tapError(()=>a.logWarning(e.eventName).pipe(a.annotateLogs({...r,outcome:"error"}))),a.withSpan(e.eventName,{attributes:r}))}l(b,"observeConcurrencyEffect");function P(n){switch(n){case"Auth ownership mutation":case"Authentication mutation":return{component:"auth",eventName:"harness.auth.mutation",operation:"update"};case"Authentication refresh":return{component:"auth",eventName:"harness.auth.refresh",operation:"refresh"};case"Product mutation":return{component:"product",eventName:"harness.product.mutation",operation:"update"};case"Workspace Product cleanup":return{component:"product",eventName:"harness.product.mutation",operation:"release"};case"Workspace Product resolution":return{component:"product",eventName:"harness.product.resolve",operation:"resolve"};default:return}}l(P,"concurrencyTelemetrySpec");
|
|
1
|
+
var U=Object.defineProperty;var l=(o,t)=>U(o,"name",{value:t,configurable:!0});import{Clock as C,Data as y,Deferred as d,Effect as s,Semaphore as v,SynchronizedRef as c}from"effect";export class HarnessConcurrencyClosedError extends y.TaggedError("HarnessConcurrencyClosedError"){static{l(this,"HarnessConcurrencyClosedError")}constructor(t,e){super({component:t,message:`${t} is closed`,reason:e}),this.code="HARNESS_CONCURRENCY_CLOSED"}}export class HarnessOperationTimeoutError extends y.TaggedError("HarnessOperationTimeoutError"){static{l(this,"HarnessOperationTimeoutError")}constructor(t,e){super({message:`${t} timed out after ${e}ms`,operation:t,timeoutMs:e}),this.code="HARNESS_OPERATION_TIMEOUT"}}export class HarnessConcurrencyOperationError extends y.TaggedError("HarnessConcurrencyOperationError"){static{l(this,"HarnessConcurrencyOperationError")}constructor(t,e){super({cause:e,component:t,message:`${t} operation failed`}),this.code="HARNESS_CONCURRENCY_OPERATION_FAILED"}}export class HarnessSerialGate{static{l(this,"HarnessSerialGate")}constructor(t,e){this.component=t,this.processRuntime=e,this.semaphore=v.makeUnsafe(1),this.state=c.makeUnsafe({closed:!1,drained:d.makeUnsafe(),pending:0})}async run(t,e={}){const r=c.modify(this.state,n=>n.closed?[{accepted:!1,error:new HarnessConcurrencyClosedError(this.component,n.closedReason)},n]:[{accepted:!0},{...n,pending:n.pending+1}]).pipe(s.flatMap(n=>n.accepted?s.void:s.fail(n.error))),i=E(this.component,t),u=b(s.acquireUseRelease(r,()=>this.semaphore.withPermit(e.uninterruptible?s.uninterruptible(i):i),()=>c.update(this.state,n=>{const a=n.pending-1;return a===0&&n.closed&&d.doneUnsafe(n.drained,s.void),{...n,pending:a}})),this.component);try{return await this.processRuntime.runEffect(u,{signal:e.signal})}catch(n){throw e.signal?.aborted?h(e.signal,`${this.component} operation aborted`):R(n)}}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>{if(r.closed)return[r.drained,r];const i={...r,closed:!0,closedReason:t};return i.pending===0&&d.doneUnsafe(i.drained,s.void),[i.drained,i]}));await this.processRuntime.runEffect(d.await(e))}closeEffect(t){return c.modify(this.state,e=>{if(e.closed)return[e.drained,e];const r={...e,closed:!0,closedReason:t};return r.pending===0&&d.doneUnsafe(r.drained,s.void),[r.drained,r]}).pipe(s.flatMap(d.await))}}export class HarnessStateCell{static{l(this,"HarnessStateCell")}constructor(t,e){this.processRuntime=t,this.state=c.makeUnsafe(e)}get current(){return c.getUnsafe(this.state)}set(t){return this.processRuntime.runEffect(c.set(this.state,t))}update(t){return this.processRuntime.runEffect(c.update(this.state,t))}}export class HarnessKeyedSerialGate{static{l(this,"HarnessKeyedSerialGate")}constructor(t,e){this.component=t,this.processRuntime=e,this.state=c.makeUnsafe({closed:!1,entries:new Map})}async run(t,e,r={}){const i=await this.processRuntime.runEffect(c.modify(this.state,n=>{if(n.closed)return[{entry:void 0,error:new HarnessConcurrencyClosedError(this.component,n.closedReason)},n];const a=n.entries.get(t),f=a===void 0?{drained:d.makeUnsafe(),pending:1,semaphore:v.makeUnsafe(1)}:{...a,pending:a.pending+1},m=new Map(n.entries);return m.set(t,f),[{entry:f},{...n,entries:m}]}));if(i.entry===void 0)throw i.error;const u=b(i.entry.semaphore.withPermit(E(this.component,e)).pipe(s.ensuring(c.update(this.state,n=>{const a=n.entries.get(t);if(a===void 0)return n;const f=new Map(n.entries);return a.pending===1?(d.doneUnsafe(a.drained,s.void),f.delete(t)):f.set(t,{...a,pending:a.pending-1}),{...n,entries:f}}))),this.component);try{return await this.processRuntime.runEffect(u,r)}catch(n){throw r.signal?.aborted?h(r.signal,`${this.component} operation aborted`):R(n)}}async waitForIdle(t,e={}){const r=c.getUnsafe(this.state).entries.get(t)?.drained;if(r!==void 0)try{await this.processRuntime.runEffect(d.await(r),e)}catch(i){throw e.signal?.aborted?h(e.signal,`${this.component} wait aborted`):i}}has(t){return c.getUnsafe(this.state).entries.has(t)}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>[[...r.entries.values()],{...r,closed:!0,closedReason:r.closed?r.closedReason:t}]));await Promise.allSettled(e.map(r=>this.processRuntime.runEffect(d.await(r.drained))))}closeEffect(t){return c.modify(this.state,e=>[[...e.entries.values()],{...e,closed:!0,closedReason:e.closed?e.closedReason:t}]).pipe(s.flatMap(e=>s.forEach(e,r=>d.await(r.drained),{concurrency:"unbounded",discard:!0})),s.andThen(c.update(this.state,e=>({...e,entries:new Map}))))}}export class HarnessSingleFlight{static{l(this,"HarnessSingleFlight")}constructor(t,e){this.component=t,this.processRuntime=e,this.state=c.makeUnsafe({closed:!1,flights:new Map})}async run(t,e,r={}){const i=await this.processRuntime.runEffect(c.modify(this.state,u=>{if(u.closed)return[{entry:void 0,error:new HarnessConcurrencyClosedError(this.component,u.closedReason),owner:!1},u];const n=u.flights.get(t);if(n!==void 0)return[{entry:n,owner:!1},u];const a={completed:d.makeUnsafe(),controller:new AbortController,result:d.makeUnsafe()},f=new Map(u.flights);return f.set(t,a),[{entry:a,owner:!0},{...u,flights:f}]}));if(i.entry===void 0)throw i.error;i.owner&&this.runOwner(t,i.entry,e,r.timeoutMs);try{return await this.processRuntime.runEffect(d.await(i.entry.result),{signal:r.signal})}catch(u){throw r.signal?.aborted?h(r.signal,r.abortMessage??`${this.component} wait aborted`):R(u)}}abortAll(t){const e=c.getUnsafe(this.state);for(const r of e.flights.values())r.controller.abort(t)}has(t){return c.getUnsafe(this.state).flights.has(t)}get activeCount(){return c.getUnsafe(this.state).flights.size}close(t){return this.closePromise??=this.closeInternal(t),this.closePromise}async closeInternal(t){const e=await this.processRuntime.runEffect(c.modify(this.state,r=>r.closed?[[...r.flights.values()],r]:[[...r.flights.values()],{...r,closed:!0,closedReason:t}]));for(const r of e)r.controller.abort(t);await Promise.allSettled(e.map(r=>this.processRuntime.runEffect(d.await(r.completed))))}closeEffect(t){return c.modify(this.state,e=>e.closed?[[...e.flights.values()],e]:[[...e.flights.values()],{...e,closed:!0,closedReason:t}]).pipe(s.tap(e=>s.sync(()=>{for(const r of e)r.controller.abort(t)})),s.flatMap(e=>s.forEach(e,r=>d.await(r.completed),{concurrency:"unbounded",discard:!0})),s.andThen(c.update(this.state,e=>({...e,flights:new Map}))))}async runOwner(t,e,r,i){let u=E(this.component,r);i!==void 0&&(u=withOperationTimeout(u,this.component,i)),u=b(u,this.component);try{const n=await this.processRuntime.runEffect(u,{signal:e.controller.signal});d.doneUnsafe(e.result,s.succeed(n))}catch(n){const a=e.controller.signal.aborted?new HarnessConcurrencyOperationError(this.component,h(e.controller.signal,`${this.component} owner aborted`)):n;d.doneUnsafe(e.result,a instanceof HarnessConcurrencyOperationError||a instanceof HarnessOperationTimeoutError?s.fail(a):s.die(a))}finally{await this.processRuntime.runEffect(c.update(this.state,n=>{if(n.flights.get(t)!==e)return n;const a=new Map(n.flights);return a.delete(t),{...n,flights:a}})).catch(()=>{}),d.doneUnsafe(e.completed,s.void)}}}export function policyDelay(o){return s.sleep(o)}l(policyDelay,"policyDelay");export function policyBackoff(o,t,e){return policyDelay(N(o,t,e))}l(policyBackoff,"policyBackoff");export function policyNow(){return C.currentTimeMillis}l(policyNow,"policyNow");export function withOperationTimeout(o,t,e){return o.pipe(s.timeout(e),s.catchTag("TimeoutError",()=>s.fail(new HarnessOperationTimeoutError(t,e))))}l(withOperationTimeout,"withOperationTimeout");export async function runPolicyDelay(o,t,e,r){try{await o.runEffect(policyDelay(t),{signal:e})}catch(i){throw e.aborted?h(e,r):i}}l(runPolicyDelay,"runPolicyDelay");export async function runPolicyBackoff(o,t,e,r,i,u){try{await o.runEffect(policyBackoff(t,e,r),{signal:i})}catch(n){throw i.aborted?h(i,u):n}}l(runPolicyBackoff,"runPolicyBackoff");export function createPolicyDeadline(o,t,e={}){if(!Number.isSafeInteger(t)||t<=0)throw new RangeError("Policy deadline must be a positive integer");const r=new AbortController,i=new AbortController,u=e.signals??[],n=AbortSignal.any([...u,r.signal]),a=[];let f=!1;const m=l(()=>{for(const[p,w]of a)p.removeEventListener("abort",w);a.length=0},"cleanup"),g=l(()=>{f||(f=!0,m(),i.abort(new Error("Policy deadline completed")))},"close");for(const p of u){if(p.aborted){g();break}const w=g;if(a.push([p,w]),p.addEventListener("abort",w,{once:!0}),p.aborted){g();break}}return f||o.runEffect(policyDelay(t),{signal:i.signal}).then(()=>{f||(f=!0,m(),r.abort(e.timeoutReason??new HarnessOperationTimeoutError("policy deadline",t)))}).catch(p=>{f||i.signal.aborted||(f=!0,m(),r.abort(p))}),Object.freeze({close:g,signal:n})}l(createPolicyDeadline,"createPolicyDeadline");function N(o,t,e){if(!Number.isSafeInteger(o)||o<=0||!Number.isSafeInteger(t)||t<=0||!Number.isSafeInteger(e)||e<=0)throw new RangeError("Policy backoff values must be positive integers");return Math.min(e,o*2**(t-1))}l(N,"policyBackoffDuration");function h(o,t){return o.reason??new Error(t)}l(h,"abortReason");function E(o,t){return s.tryPromise({catch:l(e=>new HarnessConcurrencyOperationError(o,e),"catch"),try:t})}l(E,"tryConcurrencyOperation");function R(o){return o instanceof HarnessConcurrencyOperationError?o.cause:o}l(R,"unwrapConcurrencyOperationError");function b(o,t){const e=P(t);if(e===void 0)return o;const r={component:e.component,operation:e.operation};return o.pipe(s.tap(()=>s.logInfo(e.eventName).pipe(s.annotateLogs({...r,outcome:"success"}))),s.tapError(()=>s.logWarning(e.eventName).pipe(s.annotateLogs({...r,outcome:"error"}))),s.withSpan(e.eventName,{attributes:r}))}l(b,"observeConcurrencyEffect");function P(o){switch(o){case"Auth ownership mutation":case"Authentication mutation":return{component:"auth",eventName:"harness.auth.mutation",operation:"update"};case"Authentication refresh":return{component:"auth",eventName:"harness.auth.refresh",operation:"refresh"};case"Product mutation":return{component:"product",eventName:"harness.product.mutation",operation:"update"};case"Workspace Product cleanup":return{component:"product",eventName:"harness.product.mutation",operation:"release"};case"Workspace Product resolution":return{component:"product",eventName:"harness.product.resolve",operation:"resolve"};default:return}}l(P,"concurrencyTelemetrySpec");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var N=Object.defineProperty;var r=(e,t)=>N(e,"name",{value:t,configurable:!0});import{Effect as c,Exit as b,MutableList as
|
|
1
|
+
var N=Object.defineProperty;var r=(e,t)=>N(e,"name",{value:t,configurable:!0});import{Effect as c,Exit as b,MutableList as R,PubSub as w,Queue as S,Scope as y,Semaphore as U,SubscriptionRef as B,SynchronizedRef as E}from"effect";class k extends Error{static{r(this,"McpPromiseError")}constructor(t,s){super(`MCP Promise rejected during ${t}`),this.operation=t,this.cause=s,this._tag="McpPromiseError",this.name=this._tag}}function x(e,t){return c.tryPromise({catch:r(s=>new k(e,s),"catch"),try:t})}r(x,"tryMcpPromise");function q(e){return e.catch(t=>{throw t instanceof k?t.cause:t})}r(q,"preserveMcpPromiseError");function $(e){return e}r($,"runtimeOf");function C(e){return e.forkScopeUnsafe()}r(C,"forkProcessScope");export async function createMcpSubscriptionState(e,t){const s=e,i=await s.runEffect(B.make(t));return{close:r(()=>s.runEffect(w.shutdown(i.pubsub)),"close"),get:r(()=>s.runEffect(B.get(i)),"get"),getUnsafe:r(()=>B.getUnsafe(i),"getUnsafe"),modify:r(f=>s.runEffect(B.modify(i,f)),"modify")}}r(createMcpSubscriptionState,"createMcpSubscriptionState");export function createMcpKeyedSerialExecutor(e){const t=e,s=E.makeUnsafe(new Map),i=r(n=>t.runEffect(E.modify(s,a=>{const o=a.get(n);if(o){const p={...o,users:o.users+1};return[p,new Map(a).set(n,p)]}const u={semaphore:U.makeUnsafe(1),users:1};return[u,new Map(a).set(n,u)]})),"gateFor"),f=r((n,a)=>t.runEffect(E.update(s,o=>{const u=o.get(n);if(u?.semaphore!==a.semaphore)return o;const p=new Map(o);return u.users<=1?p.delete(n):p.set(n,{...u,users:u.users-1}),p})),"releaseGate"),l=r(n=>t.runEffect(n.semaphore.withPermit(c.void)),"waitForGate");return{get activeKeyCount(){return E.getUnsafe(s).size},run:r(async(n,a,o)=>{const u=await i(n);try{return await q(t.runEffect(G(u.semaphore.withPermit(x("registry.reconcile",o)),a)))}finally{await f(n,u)}},"run"),waitForIdle:r(async()=>{const n=await t.runEffect(E.get(s));await Promise.all([...n.values()].map(l))},"waitForIdle"),waitForKey:r(async n=>{const a=(await t.runEffect(E.get(s))).get(n);a&&await l(a)},"waitForKey")}}r(createMcpKeyedSerialExecutor,"createMcpKeyedSerialExecutor");export async function openMcpEffectScope(e,t={}){const s=e,i=C(e),f=new Map;let l=!1,n;return{acquire:r(async o=>{if(l)throw new Error("MCP Effect scope is closed");const u=Symbol("mcp-scope-acquire"),p=new AbortController,g=(async()=>{const m=await s.runEffect(y.fork(i,"sequential"),{signal:p.signal}),d=o.acquire(p.signal),v=t.interruptPendingAcquires===!1?d:F(d,p.signal,o.release);let z;try{z=await q(s.runEffect(y.provide(c.acquireRelease(x("attachment.acquire",()=>v),h=>x("attachment.release",()=>o.release(h)).pipe(c.orDie)),m),{signal:p.signal}))}catch(h){throw await s.runEffect(y.close(m,b.fail(h))).catch(()=>{}),h}let P;const M=r(()=>(P??=q(s.runEffect(y.close(m,b.void))),P),"release");if(l)throw await M(),new Error("MCP Effect scope is closed");return{release:M,value:z}})();f.set(u,{controller:p,promise:g});try{return await g}finally{f.delete(u)}},"acquire"),close:r(()=>{if(n)return n;l=!0;const o=new Error("MCP Effect scope is closed");if(t.interruptPendingAcquires!==!1)for(const u of f.values())u.controller.abort(o);return n=(async()=>{await Promise.allSettled([...f.values()].map(u=>u.promise)),await q(s.runEffect(y.close(i,b.void)))})(),n},"close")}}r(openMcpEffectScope,"openMcpEffectScope");function F(e,t,s){return new Promise((i,f)=>{let l=!1;const n=r(()=>{l||(l=!0,f(t.reason??new Error("MCP scoped acquisition aborted")))},"abort");t.aborted?n():t.addEventListener("abort",n,{once:!0}),e.then(a=>{if(t.removeEventListener("abort",n),l){s(a).catch(()=>{});return}l=!0,i(a)},a=>{t.removeEventListener("abort",n),!l&&(l=!0,f(a))})})}r(F,"interruptibleAcquisition");function G(e,t){const s="harness.executor.runtime",i={component:"executor",operation:t,resource:"registration"};return e.pipe(c.tap(()=>c.logInfo(s).pipe(c.annotateLogs({...i,outcome:"success"}))),c.tapError(()=>c.logWarning(s).pipe(c.annotateLogs({...i,outcome:"error"}))),c.withSpan(s,{attributes:i}))}r(G,"observeExecutorRegistrationEffect");export async function openMcpLivePubSub(e){if(!Number.isSafeInteger(e.capacity)||e.capacity<=0)throw new RangeError("MCP live PubSub capacity must be a positive safe integer");I(e.maxBufferedBytes,"MCP live PubSub");const t=e.processRuntime,s=C(e.processRuntime),i=await t.runEffect(w.sliding({capacity:e.capacity,replay:0})),f=U.makeUnsafe(1),l=[];let n=0,a=!1,o;const u=r(()=>{i.pubsub.slide();const m=l.shift();n-=m?.size??0},"removeOldest"),p=r(()=>{const m=w.sizeUnsafe(i);for(;l.length>m;){const d=l.shift();n-=d?.size??0}n<0&&(n=0)},"reconcile"),g=r(()=>{l.length=0,n=0},"clearBudget");return{capacity:e.capacity,buffered:r(()=>w.sizeUnsafe(i),"buffered"),bufferedBytes:r(()=>(p(),n),"bufferedBytes"),close:r(()=>o||(a=!0,o=t.runEffect(w.shutdown(i).pipe(c.andThen(y.close(s,b.void)),c.ensuring(c.sync(g)))),o),"close"),publish:r(m=>{if(a)return Promise.resolve(!1);const d={message:m,size:L(e.sizeOf,m,"MCP live PubSub")};return d.size>e.maxBufferedBytes?Promise.resolve(!1):t.runEffect(f.withPermit(c.gen(function*(){if(a)return!1;for(p();l.length>=e.capacity||n+d.size>e.maxBufferedBytes;)u();l.push(d),n+=d.size;const v=yield*w.publish(i,d);return p(),v})))},"publish"),subscribe:r(async m=>{if(a)throw new Error("MCP live PubSub is closed");const d=await t.runEffect(y.fork(s,"sequential")),v=await t.runEffect(y.provide(w.subscribe(i),d)),z=c.gen(function*(){for(;;){const h=yield*w.take(v);yield*c.sync(p),yield*x("registry.consume",A=>m(h.message,A)).pipe(c.catchCause(()=>c.void))}});await t.runEffect(c.forkIn(z,d));let P;const M=r(()=>(P??=t.runEffect(y.close(d,b.void).pipe(c.ensuring(c.sync(p)))),P),"release");if(a)throw await M(),new Error("MCP live PubSub is closed");return{release:M}},"subscribe")}}r(openMcpLivePubSub,"openMcpLivePubSub");export async function openMcpLiveQueue(e){if(!Number.isSafeInteger(e.capacity)||e.capacity<=0)throw new RangeError("MCP live queue capacity must be a positive safe integer");I(e.maxBufferedBytes,"MCP live queue");const t=e.processRuntime,s=C(e.processRuntime),i=await t.runEffect(S.sliding(e.capacity));let f=0;const l=c.gen(function*(){for(;;){const o=yield*S.take(i);yield*c.sync(()=>{f=Math.max(0,f-o.size)}),yield*x("queue.consume",u=>e.consume(o.message,u)).pipe(c.catchCause(()=>c.void))}});await t.runEffect(c.forkIn(l,s));let n=!1,a;return{capacity:e.capacity,buffered:r(()=>S.sizeUnsafe(i),"buffered"),bufferedBytes:r(()=>f,"bufferedBytes"),close:r(()=>a||(n=!0,a=t.runEffect(S.shutdown(i).pipe(c.andThen(y.close(s,b.void)),c.ensuring(c.sync(()=>{f=0})))),a),"close"),offer:r(o=>{if(n)return!1;const u={message:o,size:L(e.sizeOf,o,"MCP live queue")};if(u.size>e.maxBufferedBytes)return!1;for(;i.messages.length>=e.capacity||f+u.size>e.maxBufferedBytes;){const g=R.take(i.messages);if(g===R.Empty)break;f=Math.max(0,f-g.size)}const p=S.offerUnsafe(i,u);return p&&(f+=u.size),p},"offer")}}r(openMcpLiveQueue,"openMcpLiveQueue");function I(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new RangeError(`${t} maxBufferedBytes must be a positive safe integer`)}r(I,"assertByteBudget");function L(e,t,s){const i=e(t);if(!Number.isSafeInteger(i)||i<0)throw new RangeError(`${s} message size must be a non-negative safe integer`);return i}r(L,"sizeMessage");
|
|
@@ -2,9 +2,13 @@ declare const harnessProcessRuntimeHandleBrand: unique symbol;
|
|
|
2
2
|
export interface HarnessConcurrencyRunOptions {
|
|
3
3
|
readonly signal?: AbortSignal;
|
|
4
4
|
}
|
|
5
|
+
export interface HarnessSerialGateRunOptions extends HarnessConcurrencyRunOptions {
|
|
6
|
+
/** Cancel queued admission, but join a started operation before releasing its permit. */
|
|
7
|
+
readonly uninterruptible?: boolean;
|
|
8
|
+
}
|
|
5
9
|
export interface HarnessSerialGateHandle {
|
|
6
10
|
close(reason: unknown): Promise<void>;
|
|
7
|
-
run<Value>(operation: (signal: AbortSignal) => Promise<Value>, options?:
|
|
11
|
+
run<Value>(operation: (signal: AbortSignal) => Promise<Value>, options?: HarnessSerialGateRunOptions): Promise<Value>;
|
|
8
12
|
}
|
|
9
13
|
export interface HarnessKeyedSerialGateHandle<Key> {
|
|
10
14
|
close(reason: unknown): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var r=(e,n)=>l(e,"name",{value:n,configurable:!0});import{isAbsolute as b}from"node:path";const o=Symbol.for("codebuddy.ai/agent-harness/application-owner");export async function createHarness(e={}){if(e.signal?.throwIfAborted(),e.configDir!==void 0&&!b(e.configDir))throw new TypeError("Harness configDir must be an absolute path");if(typeof e.sandboxCenter=="object"&&!e.sandboxCenter.address?.trim())throw new TypeError("sandboxCenter.address must be a non-empty IPC address");const n=globalThis;if(n[o]!==void 0)throw new Error("This process already owns a Harness. Reuse it for additional Clients and Sessions, or await its close() before creating another.");const d={};n[o]=d;const i=process.env.CODEBUDDY_CONFIG_DIR;e.configDir!==void 0&&(process.env.CODEBUDDY_CONFIG_DIR=e.configDir);const f=r(()=>{n[o]===d&&(delete n[o],e.configDir!==void 0&&process.env.CODEBUDDY_CONFIG_DIR===e.configDir&&(i===void 0?delete process.env.CODEBUDDY_CONFIG_DIR:process.env.CODEBUDDY_CONFIG_DIR=i))},"release");try{const t={...e,host:e.host===void 0?void 0:{...e.host},productConfig:typeof e.productConfig=="object"?structuredClone(e.productConfig):e.productConfig,sandboxCenter:typeof e.sandboxCenter=="object"?{...e.sandboxCenter}:e.sandboxCenter},{startHarness:u}=await import("./runtime.js"),s=await u(t),c=s.closed.then(f);c.catch(()=>{});const D=r(()=>(s.close().catch(()=>{}),c),"close");return{get ready(){return s.ready},connect:r((a,C)=>s.connect(a,C),"connect"),connectInMemory:r(a=>s.connectInMemory(a),"connectInMemory"),closed:c,close:D,[Symbol.asyncDispose]:D}}catch(t){throw f(),t}}r(createHarness,"createHarness");
|
|
@@ -49,6 +49,11 @@ export interface AgentMcpAttachment {
|
|
|
49
49
|
message(params: AcpV2MessageMcpRequest, options: AgentMcpMessageOptions): Promise<unknown>;
|
|
50
50
|
notify(params: AcpV2MessageMcpNotification, options: AgentMcpNotificationOptions): void;
|
|
51
51
|
callTool(logicalName: string, toolName: string, args: unknown, signal?: AbortSignal): Promise<ExecutorMcpCallResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Irreversibly disable this attachment's access, then release resources.
|
|
54
|
+
* A cleanup rejection must not restore access. This releases session
|
|
55
|
+
* capabilities; it does not revoke the user's upstream OAuth/API token.
|
|
56
|
+
*/
|
|
52
57
|
revoke(): Promise<void>;
|
|
53
58
|
subscribeServerStatus(listener: (status: SessionMcpServerStatus) => void): () => void;
|
|
54
59
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnyWireMessage, UpdateSessionNotification } from '@agentclientprotocol/sdk/experimental/v2';
|
|
2
|
+
/**
|
|
3
|
+
* Keep CodeBuddy's Credit unit intact across the official SDK's
|
|
4
|
+
* lenient v2 parser. The SDK accepts only three uppercase currency characters
|
|
5
|
+
* and otherwise silently drops `cost`, so the transport substitutes a
|
|
6
|
+
* valid placeholder plus a reserved marker before the SDK sees the message.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeAcpV2CreditsForSdk(message: AnyWireMessage): AnyWireMessage;
|
|
9
|
+
/** Restore the product Credit unit and remove the private transport marker. */
|
|
10
|
+
export declare function restoreCodeBuddyCreditsFromSdk(notification: UpdateSessionNotification): UpdateSessionNotification;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var d=(t,r)=>s(t,"name",{value:r,configurable:!0});import{isRecord as n}from"../internal/guards.js";const a="_codebuddy.ai/privateCreditCurrency",i="XCR";function p(t){if(!n(t))return{changed:!1,value:t};const r=n(t._meta)?t._meta:void 0,e=r?{...r}:void 0,o=e!==void 0&&Object.hasOwn(e,a);if(e&&delete e[a],t.currency!=="credits")return o?{changed:!0,value:{...t,...e&&Object.keys(e).length>0?{_meta:e}:{_meta:void 0}}}:{changed:!1,value:t};if(typeof t.amount!="number"||!Number.isFinite(t.amount)||t.amount<0)throw new Error("ACP peer emitted an invalid Credits cost amount");return{changed:!0,value:{...t,currency:i,_meta:{...e??{},[a]:"credits"}}}}d(p,"normalizedCostForSdk");function u(t){if(!("method"in t)||t.method!=="session/update"||!n(t.params)||!n(t.params.update)||t.params.update.sessionUpdate!=="usage_update")return t;const r=p(t.params.update.cost);return r.changed?{...t,params:{...t.params,update:{...t.params.update,cost:r.value}}}:t}d(u,"normalizeCreditsNotificationForSdk");export function normalizeAcpV2CreditsForSdk(t){return Array.isArray(t)?t.map(r=>u(r)):u(t)}d(normalizeAcpV2CreditsForSdk,"normalizeAcpV2CreditsForSdk");export function restoreCodeBuddyCreditsFromSdk(t){const r=t.update,e=r.cost;if(r.sessionUpdate!=="usage_update"||!n(e))return t;const o=n(e._meta)?e._meta:void 0;if(e.currency!==i||o?.[a]!=="credits")return t;const c={...o};return delete c[a],{...t,update:{...r,cost:{...e,currency:"credits",...Object.keys(c).length>0?{_meta:c}:{_meta:void 0}}}}}d(restoreCodeBuddyCreditsFromSdk,"restoreCodeBuddyCreditsFromSdk");
|