Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
762ec3e
task: add ACP runtime permission bridge
raphaeltm Sep 30, 2026
2bc2ae3
feat(web): render ACP permissions in chat
raphaeltm Sep 30, 2026
c517b16
feat(acp): bridge runtime permission requests
raphaeltm Sep 30, 2026
c40fe42
test(acp): cover no-recovery runtime variants
raphaeltm Sep 30, 2026
f247d25
test(acp): preserve permission capability at checkpoints
raphaeltm Sep 30, 2026
0bba2b3
test(acp): accept either permission race winner
raphaeltm Sep 30, 2026
c2c8fd0
fix(web): harden ACP permission state
raphaeltm Sep 30, 2026
79426bf
docs(task): record ACP permission UI evidence
raphaeltm Sep 30, 2026
783a897
fix(acp): enforce permission bridge boundaries
raphaeltm Sep 30, 2026
b3ac376
test(acp): fence duplicate start configuration
raphaeltm Sep 30, 2026
ea3dbad
test(acp): prove permission failures stay closed
raphaeltm Sep 30, 2026
22647cc
docs(task): record ACP bridge delivery
raphaeltm Sep 30, 2026
1abff4b
fix(web): tolerate absent ACP snapshots
raphaeltm Sep 30, 2026
d7439c9
test(acp): advertise permission bridge in vertical fixture
raphaeltm Sep 30, 2026
e687505
fix(web): harden ACP permission interactions
raphaeltm Sep 30, 2026
d3e2b3f
fix(acp): bind permission bridge lifecycle
raphaeltm Sep 30, 2026
88da9a3
docs: record ACP permission review validation
raphaeltm Sep 30, 2026
7e60301
fix(acp): retry settle after create race
raphaeltm Sep 30, 2026
96df904
docs(task): record ACP follow-up validation
raphaeltm Sep 30, 2026
e13a166
fix(web): clear permission statuses from jump control
raphaeltm Sep 30, 2026
9ba27d7
task: integrate ACP permission slices
raphaeltm Sep 30, 2026
bd2dcc1
merge: integrate ACP runtime permission bridge
raphaeltm Sep 30, 2026
3998838
merge: integrate ACP permission chat UI
raphaeltm Sep 30, 2026
b900e76
fix(deploy): forward ACP runtime limits
raphaeltm Sep 30, 2026
5db5eff
test(web): wait for permission jump control
raphaeltm Sep 30, 2026
2f9000a
docs: record ACP integration validation
raphaeltm Sep 30, 2026
70c6c83
fix: close ACP integration review gaps
raphaeltm Sep 30, 2026
89706b1
docs: keep ACP configuration diff focused
raphaeltm Sep 30, 2026
397bfa7
docs: record ACP specialist gates
raphaeltm Sep 30, 2026
b462755
fix(acp): honor runtime path in instant launcher
raphaeltm Sep 30, 2026
0cb2265
fix(acp): require absolute runtime adapter paths
raphaeltm Sep 30, 2026
bb853a0
fix(deploy): preserve worker binding headroom
raphaeltm Sep 30, 2026
aecaf20
docs(task): record ACP staging evidence
raphaeltm Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .claude/skills/env-reference/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ See `apps/api/.env.example` for the full list. Key variables:
- `ACP_ACTIVITY_BINDING_CACHE_TTL_MS` — Short-lived authorized ACP session binding cache used to avoid ProjectData reads during callback storms (default: `30000`)
- `ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES` — Maximum cached ACP activity bindings retained by one Worker isolate (default: `2048`)

- `ACP_INTERACTIONS_ENABLED` — Dormant durable ACP interaction foundation kill switch. Slice A defaults this to `false`; later slices must intentionally enable producers/consumers (default: `false`)
- `ACP_INTERACTIONS_ENABLED` — Durable ACP interaction creation kill switch. Runtime and UI consumers are wired, while creation remains disabled by default pending rollout (default: `false`)
- `ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS` / `ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS` / `ACP_INTERACTION_DEADLINE_MARGIN_MS` — Runtime permission deadlines for task and conversation sessions and the margin before an enclosing prompt deadline (defaults: `1800000` / `7200000` / `60000`)
- `ACP_INTERACTION_MAX_DEADLINE_MS` — Absolute deadline ceiling for runtime-created requests (default: `14400000`)
- `ACP_INTERACTION_MAX_PENDING_PER_SESSION` — Maximum pending durable ACP interactions per chat (default: `8`)
- `ACP_INTERACTION_REQUEST_MAX_BYTES`, `ACP_INTERACTION_OPTIONS_MAX_COUNT`, `ACP_INTERACTION_OPTION_NAME_MAX_CHARS`, `ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES`, `ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES`, `ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM` — Request/detail and schema bounds for encrypted ACP interaction payloads (defaults: `32768`, `16`, `200`, `16384`, `20`, `50`)
- `ACP_INTERACTION_REQUEST_MAX_BYTES`, `ACP_INTERACTION_OPTIONS_MAX_COUNT`, `ACP_INTERACTION_OPTION_ID_MAX_CHARS`, `ACP_INTERACTION_OPTION_NAME_MAX_CHARS`, `ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES`, `ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES`, `ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM` — Request/detail and schema bounds for encrypted ACP interaction payloads (defaults: `32768`, `16`, `128`, `200`, `16384`, `20`, `50`)
- `ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT` / `ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES` — Per-SessionHost idempotency receipt bound and maximum create/settle response body read by the runtime (defaults: `256` / `65536`)
- `ACP_INTERACTION_ANSWER_MAX_BYTES` / `ACP_INTERACTION_ANSWER_STRING_MAX_BYTES` — Answer decision and individual answer string bounds before encrypted storage (defaults: `16384` / `4096`)
- `ACP_INTERACTION_RETRY_DELAYS_MS` / `ACP_INTERACTION_RETRY_STEADY_MS` / `ACP_INTERACTION_DELIVERY_WINDOW_MS` — Durable answer outbox retry sequence, steady retry delay, and max post-answer retry window (defaults: `1000,5000,30000,120000,300000`, `300000`, `900000`)
- `ACP_INTERACTION_SENSITIVE_PURGE_MS`, `ACP_INTERACTION_SUMMARY_RETENTION_MS`, `ACP_INTERACTION_SUMMARY_LAST_SETTLED`, `ACP_INTERACTION_SNAPSHOT_LAST_SETTLED` — Sensitive encrypted payload purge, settled summary retention, and bounded snapshot controls (defaults: `3600000`, `2592000000`, `100`, `20`)
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/deploy-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,17 @@ jobs:
ACP_ACTIVITY_BINDING_CACHE_TTL_MS: ${{ vars.ACP_ACTIVITY_BINDING_CACHE_TTL_MS }}
ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES: ${{ vars.ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES }}
ACP_INTERACTIONS_ENABLED: ${{ vars.ACP_INTERACTIONS_ENABLED }}
ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS: ${{ vars.ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS }}
ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS: ${{ vars.ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS }}
ACP_INTERACTION_MAX_DEADLINE_MS: ${{ vars.ACP_INTERACTION_MAX_DEADLINE_MS }}
ACP_INTERACTION_DEADLINE_MARGIN_MS: ${{ vars.ACP_INTERACTION_DEADLINE_MARGIN_MS }}
ACP_INTERACTION_MAX_PENDING_PER_SESSION: ${{ vars.ACP_INTERACTION_MAX_PENDING_PER_SESSION }}
ACP_INTERACTION_REQUEST_MAX_BYTES: ${{ vars.ACP_INTERACTION_REQUEST_MAX_BYTES }}
ACP_INTERACTION_OPTIONS_MAX_COUNT: ${{ vars.ACP_INTERACTION_OPTIONS_MAX_COUNT }}
ACP_INTERACTION_OPTION_ID_MAX_CHARS: ${{ vars.ACP_INTERACTION_OPTION_ID_MAX_CHARS }}
ACP_INTERACTION_OPTION_NAME_MAX_CHARS: ${{ vars.ACP_INTERACTION_OPTION_NAME_MAX_CHARS }}
ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT: ${{ vars.ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT }}
ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES: ${{ vars.ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM }}
Expand Down Expand Up @@ -977,6 +983,9 @@ jobs:
VITE_WORKSPACE_PORTS_CIRCUIT_RESET_MS: ${{ vars.VITE_WORKSPACE_PORTS_CIRCUIT_RESET_MS || '300000' }}
VITE_PROJECT_PREFETCH_DELAY_MS: ${{ vars.VITE_PROJECT_PREFETCH_DELAY_MS || '120' }}
VITE_BACKGROUND_FETCH_DELAY_MS: ${{ vars.VITE_BACKGROUND_FETCH_DELAY_MS || '150' }}
VITE_ACP_PERMISSION_POLL_MS: ${{ vars.VITE_ACP_PERMISSION_POLL_MS || '2000' }}
VITE_ACP_PERMISSION_RECOVERY_POLL_MS: ${{ vars.VITE_ACP_PERMISSION_RECOVERY_POLL_MS || '30000' }}
VITE_ACP_PERMISSION_QUERY_RETRY_COUNT: ${{ vars.VITE_ACP_PERMISSION_QUERY_RETRY_COUNT || '3' }}

# Bake the deployment-built vm-agent before Wrangler builds the raw container.
- name: Setup Go for Container Runtime
Expand Down Expand Up @@ -1207,11 +1216,17 @@ jobs:
ACP_ACTIVITY_BINDING_CACHE_TTL_MS: ${{ vars.ACP_ACTIVITY_BINDING_CACHE_TTL_MS }}
ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES: ${{ vars.ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES }}
ACP_INTERACTIONS_ENABLED: ${{ vars.ACP_INTERACTIONS_ENABLED }}
ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS: ${{ vars.ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS }}
ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS: ${{ vars.ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS }}
ACP_INTERACTION_MAX_DEADLINE_MS: ${{ vars.ACP_INTERACTION_MAX_DEADLINE_MS }}
ACP_INTERACTION_DEADLINE_MARGIN_MS: ${{ vars.ACP_INTERACTION_DEADLINE_MARGIN_MS }}
ACP_INTERACTION_MAX_PENDING_PER_SESSION: ${{ vars.ACP_INTERACTION_MAX_PENDING_PER_SESSION }}
ACP_INTERACTION_REQUEST_MAX_BYTES: ${{ vars.ACP_INTERACTION_REQUEST_MAX_BYTES }}
ACP_INTERACTION_OPTIONS_MAX_COUNT: ${{ vars.ACP_INTERACTION_OPTIONS_MAX_COUNT }}
ACP_INTERACTION_OPTION_ID_MAX_CHARS: ${{ vars.ACP_INTERACTION_OPTION_ID_MAX_CHARS }}
ACP_INTERACTION_OPTION_NAME_MAX_CHARS: ${{ vars.ACP_INTERACTION_OPTION_NAME_MAX_CHARS }}
ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT: ${{ vars.ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT }}
ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES: ${{ vars.ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES }}
ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM: ${{ vars.ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM }}
Expand Down
8 changes: 7 additions & 1 deletion apps/api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -797,13 +797,19 @@ INFOMANIAK_IP_POLL_INTERVAL_MS=3000
# ACP_ACTIVITY_COALESCE_MAX_PENDING=512 # Max pending coalesced activity reports per Worker isolate
# ACP_ACTIVITY_BINDING_CACHE_TTL_MS=30000 # Short-lived authorized ACP session binding cache
# ACP_ACTIVITY_BINDING_CACHE_MAX_ENTRIES=2048 # Max cached ACP activity bindings per Worker isolate
# Dormant durable ACP interaction foundation. Slice A keeps this disabled; later slices wire runtime/UI producers and consumers.
# Durable ACP runtime and UI are wired; creation remains disabled by default pending rollout.
# ACP_INTERACTIONS_ENABLED=false # Fail-closed feature flag for durable ACP interaction creation
# ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS=1800000 # Runtime permission deadline for task sessions (30m)
# ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS=7200000 # Runtime permission deadline for conversation sessions (2h)
# ACP_INTERACTION_MAX_DEADLINE_MS=14400000 # Absolute max request deadline (4h)
# ACP_INTERACTION_DEADLINE_MARGIN_MS=60000 # Margin before an enclosing prompt deadline
# ACP_INTERACTION_MAX_PENDING_PER_SESSION=8 # Pending durable interactions allowed per chat
# ACP_INTERACTION_REQUEST_MAX_BYTES=32768 # Encrypted request detail cap
# ACP_INTERACTION_OPTIONS_MAX_COUNT=16 # Permission option count cap
# ACP_INTERACTION_OPTION_ID_MAX_CHARS=128 # Permission option identifier cap
# ACP_INTERACTION_OPTION_NAME_MAX_CHARS=200 # Permission option display cap
# ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT=256 # In-memory idempotency receipts retained per SessionHost
# ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES=65536 # Max runtime create/settle response body read
# ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES=16384 # Encrypted form schema cap
# ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES=20 # Form schema property cap
# ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM=50 # Form enum option cap
Expand Down
23 changes: 23 additions & 0 deletions apps/api/src/durable-objects/vm-agent-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,29 @@ export class VmAgentContainer extends Container<Env> {
return this.proxyHttpAuthorized(request, port);
}

/** Forward only to an already-running runtime; never wake or start recovery. */
async proxyHttpNoWake(request: Request, port?: number): Promise<Response> {
const status = await this.ctx.storage.get<LifecycleStatus>('lifecycleStatus');
if (status !== 'running') {
return recoveryResponse('RUNTIME_STOPPED', RUNTIME_STOPPED_MESSAGE, 410);
}
const container = this.ctx.container;
if (!container?.running) {
return recoveryResponse('RUNTIME_STOPPED', RUNTIME_STOPPED_MESSAGE, 410);
}
try {
// Container.containerFetch() is intentionally forbidden here: the pinned
// SDK starts compute when either the real runtime is stopped or its own
// persisted health state is stale. The direct port primitive never starts
// a container; if stop/crash wins after the running check, fetch rejects.
const tcpPort = container.getTcpPort(port ?? this.defaultPort);
const containerUrl = request.url.replace('https:', 'http:');
return await tcpPort.fetch(containerUrl, request);
} catch {
return interruptedRequestResponse(request);
}
}

private async proxyHttpAuthorized(
request: Request,
port?: number,
Expand Down
6 changes: 6 additions & 0 deletions apps/api/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,11 +846,17 @@ export interface Env extends WebhookTriggerEnv, TaskRecoveryEnv {
PROJECT_EVENT_WAKE_MAX_PER_SUBSCRIPTION?: string;
PROJECT_EVENT_SOURCE_OUTBOX_SWEEP_WALL_MS?: string;
ACP_INTERACTIONS_ENABLED?: string;
ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS?: string;
ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS?: string;
ACP_INTERACTION_MAX_DEADLINE_MS?: string;
ACP_INTERACTION_DEADLINE_MARGIN_MS?: string;
ACP_INTERACTION_MAX_PENDING_PER_SESSION?: string;
ACP_INTERACTION_REQUEST_MAX_BYTES?: string;
ACP_INTERACTION_OPTIONS_MAX_COUNT?: string;
ACP_INTERACTION_OPTION_ID_MAX_CHARS?: string;
ACP_INTERACTION_OPTION_NAME_MAX_CHARS?: string;
ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT?: string;
ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM?: string;
Expand Down
19 changes: 15 additions & 4 deletions apps/api/src/routes/projects/acp-interaction-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,21 @@ async function verifyWorkspaceCallback(c: {
};
}

async function assertAgentSessionCurrent(env: Env, workspaceId: string, agentSessionId: string) {
async function assertAgentSessionExists(
env: Env,
workspaceId: string,
agentSessionId: string,
requireRunning: boolean
) {
const row = await env.DATABASE.prepare(
`SELECT id, status FROM agent_sessions WHERE id = ? AND workspace_id = ? LIMIT 1`
)
.bind(agentSessionId, workspaceId)
.first<{ id: string; status: string }>();
if (!row) throw errors.notFound('Agent session');
if (row.status !== 'running') throw errors.conflict(`Agent session is ${row.status}`);
if (requireRunning && row.status !== 'running') {
throw errors.conflict(`Agent session is ${row.status}`);
}
}

function settleStatusCode(status: string): 200 | 404 | 409 {
Expand All @@ -90,7 +97,7 @@ acpInteractionCallbackRoute.post(
async (c) => {
const identity = await verifyWorkspaceCallback(c);
const body = c.req.valid('json');
await assertAgentSessionCurrent(c.env, identity.workspaceId, body.agentSessionId);
await assertAgentSessionExists(c.env, identity.workspaceId, body.agentSessionId, true);
const result = await createInteraction(c.env, {
...body,
projectId: identity.projectId,
Expand Down Expand Up @@ -122,7 +129,11 @@ acpInteractionCallbackRoute.post(
if (body.interactionId !== c.req.param('interactionId')) {
throw errors.badRequest('interactionId route/body mismatch');
}
await assertAgentSessionCurrent(c.env, identity.workspaceId, body.agentSessionId);
// A terminal session may race the runtime's final settle callback. The
// InteractionStore still fences settlement by agentSessionId, generation,
// and runtimeIdentity, so accepting the existing row cannot settle another
// runtime's interaction.
await assertAgentSessionExists(c.env, identity.workspaceId, body.agentSessionId, false);
const result = await settleInteraction(c.env, {
...body,
projectId: identity.projectId,
Expand Down
42 changes: 42 additions & 0 deletions apps/api/src/services/acp-interaction-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
DEFAULT_ACP_INTERACTION_ALARM_WALL_TIME_MS,
DEFAULT_ACP_INTERACTION_ANSWER_MAX_BYTES,
DEFAULT_ACP_INTERACTION_ANSWER_STRING_MAX_BYTES,
DEFAULT_ACP_INTERACTION_DEADLINE_MARGIN_MS,
DEFAULT_ACP_INTERACTION_DELIVERY_BATCH_SIZE,
DEFAULT_ACP_INTERACTION_DELIVERY_WINDOW_MS,
DEFAULT_ACP_INTERACTION_EXPIRY_BATCH_SIZE,
Expand All @@ -11,12 +12,17 @@ import {
DEFAULT_ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES,
DEFAULT_ACP_INTERACTION_MAX_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_MAX_PENDING_PER_SESSION,
DEFAULT_ACP_INTERACTION_OPTION_ID_MAX_CHARS,
DEFAULT_ACP_INTERACTION_OPTION_NAME_MAX_CHARS,
DEFAULT_ACP_INTERACTION_OPTIONS_MAX_COUNT,
DEFAULT_ACP_INTERACTION_OUTBOX_BATCH_SIZE,
DEFAULT_ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_REQUEST_MAX_BYTES,
DEFAULT_ACP_INTERACTION_RETRY_DELAYS_MS,
DEFAULT_ACP_INTERACTION_RETRY_STEADY_MS,
DEFAULT_ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT,
DEFAULT_ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES,
DEFAULT_ACP_INTERACTION_SENSITIVE_PURGE_MS,
DEFAULT_ACP_INTERACTION_SNAPSHOT_LAST_SETTLED,
DEFAULT_ACP_INTERACTION_SUMMARY_LAST_SETTLED,
Expand All @@ -26,11 +32,17 @@ import {

export interface AcpInteractionConfigEnv {
ACP_INTERACTIONS_ENABLED?: string;
ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS?: string;
ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS?: string;
ACP_INTERACTION_MAX_DEADLINE_MS?: string;
ACP_INTERACTION_DEADLINE_MARGIN_MS?: string;
ACP_INTERACTION_MAX_PENDING_PER_SESSION?: string;
ACP_INTERACTION_REQUEST_MAX_BYTES?: string;
ACP_INTERACTION_OPTIONS_MAX_COUNT?: string;
ACP_INTERACTION_OPTION_ID_MAX_CHARS?: string;
ACP_INTERACTION_OPTION_NAME_MAX_CHARS?: string;
ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT?: string;
ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_PROPERTIES?: string;
ACP_INTERACTION_FORM_SCHEMA_MAX_ENUM?: string;
Expand All @@ -52,11 +64,17 @@ export interface AcpInteractionConfigEnv {

export interface AcpInteractionConfig {
enabled: boolean;
permissionTaskDeadlineMs: number;
permissionConversationDeadlineMs: number;
maxDeadlineMs: number;
deadlineMarginMs: number;
maxPendingPerSession: number;
requestMaxBytes: number;
optionsMaxCount: number;
optionIdMaxChars: number;
optionNameMaxChars: number;
runtimeReceiptLimit: number;
runtimeResponseMaxBytes: number;
formSchemaMaxBytes: number;
formSchemaMaxProperties: number;
formSchemaMaxEnum: number;
Expand Down Expand Up @@ -99,10 +117,22 @@ function positiveIntList(value: string | undefined, fallback: readonly number[])
export function getAcpInteractionConfig(env: AcpInteractionConfigEnv): AcpInteractionConfig {
return {
enabled: envFlag(env.ACP_INTERACTIONS_ENABLED, DEFAULT_ACP_INTERACTIONS_ENABLED),
permissionTaskDeadlineMs: positiveInt(
env.ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_PERMISSION_TASK_DEADLINE_MS
),
permissionConversationDeadlineMs: positiveInt(
env.ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_PERMISSION_CONVERSATION_DEADLINE_MS
),
maxDeadlineMs: positiveInt(
env.ACP_INTERACTION_MAX_DEADLINE_MS,
DEFAULT_ACP_INTERACTION_MAX_DEADLINE_MS
),
deadlineMarginMs: positiveInt(
env.ACP_INTERACTION_DEADLINE_MARGIN_MS,
DEFAULT_ACP_INTERACTION_DEADLINE_MARGIN_MS
),
maxPendingPerSession: positiveInt(
env.ACP_INTERACTION_MAX_PENDING_PER_SESSION,
DEFAULT_ACP_INTERACTION_MAX_PENDING_PER_SESSION
Expand All @@ -115,10 +145,22 @@ export function getAcpInteractionConfig(env: AcpInteractionConfigEnv): AcpIntera
env.ACP_INTERACTION_OPTIONS_MAX_COUNT,
DEFAULT_ACP_INTERACTION_OPTIONS_MAX_COUNT
),
optionIdMaxChars: positiveInt(
env.ACP_INTERACTION_OPTION_ID_MAX_CHARS,
DEFAULT_ACP_INTERACTION_OPTION_ID_MAX_CHARS
),
optionNameMaxChars: positiveInt(
env.ACP_INTERACTION_OPTION_NAME_MAX_CHARS,
DEFAULT_ACP_INTERACTION_OPTION_NAME_MAX_CHARS
),
runtimeReceiptLimit: positiveInt(
env.ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT,
DEFAULT_ACP_INTERACTION_RUNTIME_RECEIPT_LIMIT
),
runtimeResponseMaxBytes: positiveInt(
env.ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES,
DEFAULT_ACP_INTERACTION_RUNTIME_RESPONSE_MAX_BYTES
),
formSchemaMaxBytes: positiveInt(
env.ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES,
DEFAULT_ACP_INTERACTION_FORM_SCHEMA_MAX_BYTES
Expand Down
Loading
Loading