maka-agent 0.2.0-dev.51.20260925 → 0.2.0-dev.53.20260927

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/acp/goal-plan-operations.js +142 -0
  2. package/dist/acp/goal-plan-routes.js +33 -0
  3. package/dist/acp/maka-acp-agent.js +41 -1
  4. package/dist/acp/session-domain-observation.js +185 -0
  5. package/dist/acp/session-event-mapper.js +1 -1
  6. package/dist/acp/session-registry.js +417 -9
  7. package/dist/acp/tool-event-mapper.js +36 -3
  8. package/dist/activation-command.js +11 -3
  9. package/dist/pi-tui-mcp-status.js +73 -5
  10. package/dist/pi-tui-runner.js +1 -1
  11. package/dist/runtime-host-run-command.js +39 -6
  12. package/dist/runtime-host-run-mcp.js +161 -0
  13. package/dist/runtime-host-session-channel.js +4 -0
  14. package/dist/runtime-host-session-driver.js +22 -2
  15. package/dist/tui-copy-catalog.js +6 -0
  16. package/dist/tui-mcp-control.js +11 -2
  17. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  18. package/node_modules/@maka/core/dist/attachments.js +7 -0
  19. package/node_modules/@maka/core/dist/events.js +11 -0
  20. package/node_modules/@maka/core/dist/openai-urls.js +51 -0
  21. package/node_modules/@maka/core/dist/provider-registry.js +11 -2
  22. package/node_modules/@maka/core/dist/relative-time.js +1 -9
  23. package/node_modules/@maka/core/dist/turn-origin.js +6 -0
  24. package/node_modules/@maka/core/package.json +1 -0
  25. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +1 -5
  26. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +90 -32
  27. package/node_modules/@maka/runtime/dist/bots/proxied-fetch.js +5 -4
  28. package/node_modules/@maka/runtime/dist/builtin-tools.js +2 -2
  29. package/node_modules/@maka/runtime/dist/computer-use-tools.js +136 -100
  30. package/node_modules/@maka/runtime/dist/context-budget-helpers.js +4 -0
  31. package/node_modules/@maka/runtime/dist/conversation-copy.js +51 -205
  32. package/node_modules/@maka/runtime/dist/edit-replace.js +7 -7
  33. package/node_modules/@maka/runtime/dist/filesystem-executor.js +7 -22
  34. package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +17 -28
  35. package/node_modules/@maka/runtime/dist/filesystem-worker/protocol.js +7 -4
  36. package/node_modules/@maka/runtime/dist/format-json.js +39 -0
  37. package/node_modules/@maka/runtime/dist/glob-search.js +18 -5
  38. package/node_modules/@maka/runtime/dist/history-compact-checkpoint.js +1 -6
  39. package/node_modules/@maka/runtime/dist/image-file.js +22 -14
  40. package/node_modules/@maka/runtime/dist/model-adapter.js +18 -2
  41. package/node_modules/@maka/runtime/dist/model-factory.js +27 -1
  42. package/node_modules/@maka/runtime/dist/model-fetcher.js +2 -1
  43. package/node_modules/@maka/runtime/dist/model-history.js +201 -3
  44. package/node_modules/@maka/runtime/dist/model-runtime.js +5 -3
  45. package/node_modules/@maka/runtime/dist/network/abortable-connector.js +55 -0
  46. package/node_modules/@maka/runtime/dist/network/proxy-dispatcher.js +72 -37
  47. package/node_modules/@maka/runtime/dist/network/proxy-test.js +1 -1
  48. package/node_modules/@maka/runtime/dist/network/scoped-fetch-transport.js +7 -2
  49. package/node_modules/@maka/runtime/dist/openai-codex-history-compactor.js +1 -3
  50. package/node_modules/@maka/runtime/dist/provider-error-classification.js +36 -8
  51. package/node_modules/@maka/runtime/dist/provider-urls.js +1 -18
  52. package/node_modules/@maka/runtime/dist/recovery-resolver.js +1 -91
  53. package/node_modules/@maka/runtime/dist/runtime-kernel.js +44 -0
  54. package/node_modules/@maka/runtime/dist/scheduled-task-tools.js +27 -2
  55. package/node_modules/@maka/runtime/dist/session-manager.js +54 -58
  56. package/node_modules/@maka/runtime/dist/subscription-model-fetch.js +84 -2
  57. package/node_modules/@maka/runtime/dist/test-connection.js +2 -2
  58. package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +79 -57
  59. package/node_modules/@maka/runtime/dist/workspace-executor.js +5 -6
  60. package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +27 -6
  61. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +4 -1
  62. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +9 -9
  63. package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +9 -1
  64. package/node_modules/@maka/runtime-host/dist/protocol/index.js +14 -1
  65. package/node_modules/@maka/runtime-host/dist/protocol/scheduled-task.js +8 -1
  66. package/node_modules/@maka/runtime-host/dist/protocol/session-catalog-change.js +24 -6
  67. package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +28 -6
  68. package/node_modules/@maka/runtime-host/dist/protocol/turn.js +12 -2
  69. package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +10 -7
  70. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +26 -5
  71. package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +20 -16
  72. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +18 -1
  73. package/node_modules/@maka/runtime-host/dist/server/host-change-feed.js +15 -22
  74. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +2 -0
  75. package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +30 -3
  76. package/node_modules/@maka/runtime-host/dist/server/interactive-turn-coordinator.js +4 -1
  77. package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +4 -2
  78. package/node_modules/@maka/runtime-host/dist/server/operation-dispatcher.js +4 -0
  79. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +7 -6
  80. package/node_modules/@maka/runtime-host/dist/server/safe-boundary-resume-policy.js +27 -0
  81. package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +5 -3
  82. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +23 -5
  83. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +11 -141
  84. package/node_modules/@maka/runtime-host/dist/server/session-revision-graph-references.js +46 -75
  85. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +18 -2
  86. package/node_modules/@maka/runtime-host/dist/server/workhub-result-coordinator.js +33 -3
  87. package/node_modules/@maka/runtime-host/dist/transport/framed-byte-stream-transport.js +39 -5
  88. package/node_modules/@maka/storage/dist/agent-run-store-contract.js +7 -1
  89. package/node_modules/@maka/storage/dist/artifact-store.js +1 -5
  90. package/node_modules/@maka/storage/dist/artifact-stores.js +0 -3
  91. package/node_modules/@maka/storage/dist/atomic-file-write.js +1 -0
  92. package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +107 -57
  93. package/node_modules/@maka/storage/dist/codex-session-adapter.js +227 -19
  94. package/node_modules/@maka/storage/dist/external-session-importer.js +1 -1
  95. package/node_modules/@maka/storage/dist/mcp-config-store.js +22 -3
  96. package/node_modules/@maka/storage/dist/settings-store.js +281 -13
  97. package/package.json +1 -1
@@ -0,0 +1,142 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { RequestError } from '@agentclientprotocol/sdk';
20
+ import { RuntimeHostOperationError, RuntimeHostRequestInterruptedError, } from '@maka/runtime-host/client';
21
+ export class AcpGoalPlanOperations {
22
+ #port;
23
+ constructor(port) {
24
+ this.#port = port;
25
+ }
26
+ goalQuery(input, context) {
27
+ return this.#run('goal.query', input, context, !!context.notifyGoalStatus);
28
+ }
29
+ goalArm(input, context) {
30
+ return this.#run('goal.arm', input, context, true);
31
+ }
32
+ goalControl(input, context) {
33
+ return this.#run('goal.control', input, context, true);
34
+ }
35
+ planQuery(input, context) {
36
+ return this.#run('plan.query', input, context, !!context.notifyPlanChanged);
37
+ }
38
+ planControl(input, context) {
39
+ return this.#run('plan.control', input, context, true);
40
+ }
41
+ async planTurnStart(input, context) {
42
+ const prepared = await this.#port.prepare(input.sessionId, context, input.turnId, true);
43
+ let dispatched = false;
44
+ const onAbort = () => prepared.cancelObservation?.();
45
+ context.signal.addEventListener('abort', onAbort, { once: true });
46
+ if (context.signal.aborted)
47
+ onAbort();
48
+ try {
49
+ context.signal.throwIfAborted();
50
+ this.#port.assertCurrent(input.sessionId);
51
+ const observation = prepared.observation;
52
+ if (!observation && !prepared.observedReplay)
53
+ throw new Error('Plan Turn observer was not installed');
54
+ observation?.markDispatched();
55
+ dispatched = true;
56
+ const result = await prepared.connection.request('plan.turn.start', input);
57
+ observation?.settleStartRequest(result.turn);
58
+ prepared.commit();
59
+ return result;
60
+ }
61
+ catch (error) {
62
+ if (dispatched && isDispatchedUnknown(error)) {
63
+ prepared.observation?.failStartRequest(error);
64
+ prepared.reconcileAdmission?.();
65
+ prepared.commit();
66
+ throw RequestError.internalError({
67
+ source: 'runtime_host',
68
+ operation: 'plan.turn.start',
69
+ code: 'outcome_unknown',
70
+ dispatch: 'dispatched',
71
+ sessionId: input.sessionId,
72
+ turnId: input.turnId,
73
+ ...(input.kind === 'approve_proposal'
74
+ ? { proposalId: input.proposalId }
75
+ : { executionId: input.executionId }),
76
+ }, 'Plan Turn start outcome is unknown; query the Plan and exact Turn before retrying');
77
+ }
78
+ if (dispatched && isPersistenceUnknown(error)) {
79
+ prepared.observation?.failStartRequest(error);
80
+ prepared.reconcileAdmission?.();
81
+ prepared.commit();
82
+ throw this.#port.mapError(error, 'plan.turn.start', {
83
+ sessionId: input.sessionId,
84
+ turnId: input.turnId,
85
+ });
86
+ }
87
+ prepared.rollback(error);
88
+ if (error instanceof RequestError)
89
+ throw error;
90
+ throw this.#port.mapError(error, 'plan.turn.start', {
91
+ sessionId: input.sessionId,
92
+ turnId: input.turnId,
93
+ });
94
+ }
95
+ finally {
96
+ context.signal.removeEventListener('abort', onAbort);
97
+ }
98
+ }
99
+ async #run(operation, input, context, observe) {
100
+ const prepared = await this.#port.prepare(input.sessionId, context, undefined, observe);
101
+ let dispatched = false;
102
+ try {
103
+ context.signal.throwIfAborted();
104
+ this.#port.assertCurrent(input.sessionId);
105
+ dispatched = true;
106
+ // The Host protocol validates both request and response against the operation spec.
107
+ const result = await prepared.connection.request(operation, input);
108
+ prepared.commit();
109
+ return result;
110
+ }
111
+ catch (error) {
112
+ if (dispatched && isDispatchedUnknown(error)) {
113
+ prepared.commit();
114
+ throw RequestError.internalError({
115
+ source: 'runtime_host',
116
+ operation,
117
+ code: 'outcome_unknown',
118
+ dispatch: 'dispatched',
119
+ sessionId: input.sessionId,
120
+ ...('goalId' in input ? { goalId: input.goalId } : {}),
121
+ ...('operationId' in input ? { operationId: input.operationId } : {}),
122
+ ...('proposalId' in input ? { proposalId: input.proposalId } : {}),
123
+ ...('executionId' in input ? { executionId: input.executionId } : {}),
124
+ }, 'Runtime Host operation outcome is unknown; query authoritative state before retrying');
125
+ }
126
+ if (dispatched && isPersistenceUnknown(error)) {
127
+ prepared.commit();
128
+ throw this.#port.mapError(error, operation, { sessionId: input.sessionId });
129
+ }
130
+ prepared.rollback(error);
131
+ if (error instanceof RequestError)
132
+ throw error;
133
+ throw this.#port.mapError(error, operation, { sessionId: input.sessionId });
134
+ }
135
+ }
136
+ }
137
+ function isDispatchedUnknown(error) {
138
+ return error instanceof RuntimeHostRequestInterruptedError && error.dispatch === 'dispatched';
139
+ }
140
+ function isPersistenceUnknown(error) {
141
+ return error instanceof RuntimeHostOperationError && error.code === 'persistence_failed';
142
+ }
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { RequestError } from '@agentclientprotocol/sdk';
20
+ import { HOST_OPERATION_SPECS } from '@maka/runtime-host/protocol';
21
+ /** Keep ACP extension parsing identical to the Host's current wire contract. */
22
+ export function goalPlanRouteInput(operation) {
23
+ return {
24
+ parse(value) {
25
+ try {
26
+ return HOST_OPERATION_SPECS[operation].decodeInput(value);
27
+ }
28
+ catch {
29
+ throw RequestError.invalidParams({ reason: 'invalid_goal_plan_input', operation }, `Invalid ${operation} request`);
30
+ }
31
+ },
32
+ };
33
+ }
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import { agent, methods, RequestError, } from '@agentclientprotocol/sdk';
20
20
  import { HOST_OPERATION_SPECS } from '@maka/runtime-host/protocol';
21
+ import { goalPlanRouteInput } from './goal-plan-routes.js';
21
22
  export function createMakaAcpAgent(options) {
22
23
  let clientCapabilities = {};
23
24
  return agent({ name: 'maka' })
@@ -28,6 +29,7 @@ export function createMakaAcpAgent(options) {
28
29
  agentCapabilities: {
29
30
  loadSession: true,
30
31
  sessionCapabilities: { list: {}, resume: {}, close: {} },
32
+ _meta: { '_maka/goalPlan': { version: 1 } },
31
33
  },
32
34
  authMethods: [],
33
35
  agentInfo: { name: 'maka', title: 'Maka', version: options.version },
@@ -44,6 +46,12 @@ export function createMakaAcpAgent(options) {
44
46
  throw RequestError.invalidParams({ reason: 'invalid_resume_query' }, 'Invalid Turn resume request');
45
47
  }
46
48
  }, ({ params, signal, client }) => options.sessionRegistry.resumeTurn(params, sessionContext(client, signal, clientCapabilities, true)))
49
+ .onRequest('_maka/goal/query', goalPlanRouteInput('goal.query'), ({ params, signal, client }) => options.sessionRegistry.goalQuery(params, sessionContext(client, signal, clientCapabilities, true)))
50
+ .onRequest('_maka/goal/arm', goalPlanRouteInput('goal.arm'), ({ params, signal, client }) => options.sessionRegistry.goalArm(params, sessionContext(client, signal, clientCapabilities, true)))
51
+ .onRequest('_maka/goal/control', goalPlanRouteInput('goal.control'), ({ params, signal, client }) => options.sessionRegistry.goalControl(params, sessionContext(client, signal, clientCapabilities, true)))
52
+ .onRequest('_maka/plan/query', goalPlanRouteInput('plan.query'), ({ params, signal, client }) => options.sessionRegistry.planQuery(params, sessionContext(client, signal, clientCapabilities, true)))
53
+ .onRequest('_maka/plan/control', goalPlanRouteInput('plan.control'), ({ params, signal, client }) => options.sessionRegistry.planControl(params, sessionContext(client, signal, clientCapabilities, true)))
54
+ .onRequest('_maka/plan/turn/start', goalPlanRouteInput('plan.turn.start'), ({ params, signal, client }) => options.sessionRegistry.planTurnStart(params, sessionContext(client, signal, clientCapabilities, true)))
47
55
  .onRequest('_maka/session/copy-source/query', {
48
56
  parse: (value) => {
49
57
  try {
@@ -88,7 +96,33 @@ export function createMakaAcpAgent(options) {
88
96
  .onRequest(methods.agent.session.setConfigOption, ({ params }) => options.sessionRegistry.setConfigOption(params))
89
97
  .onRequest(methods.agent.session.prompt, ({ params, signal, client }) => options.sessionRegistry.prompt(params, sessionContext(client, signal, clientCapabilities)))
90
98
  .onNotification(methods.agent.session.cancel, ({ params }) => options.sessionRegistry.cancel(params))
91
- .onRequest(methods.agent.session.close, ({ params }) => options.sessionRegistry.close(params));
99
+ .onRequest(methods.agent.session.close, ({ params }) => options.sessionRegistry.close(params))
100
+ .onRequest('_maka/artifact/query', extensionParams('artifact.query', HOST_OPERATION_SPECS['artifact.query'].decodeInput), ({ params }) => options.sessionRegistry.artifactQuery(params))
101
+ .onRequest('_maka/artifact/ingest', extensionParams('artifact.ingest', HOST_OPERATION_SPECS['artifact.ingest'].decodeInput), ({ params }) => options.sessionRegistry.artifactIngest(params))
102
+ .onRequest('_maka/artifact/delete', extensionParams('artifact.delete', HOST_OPERATION_SPECS['artifact.delete'].decodeInput), ({ params }) => options.sessionRegistry.artifactDelete(params))
103
+ .onRequest('_maka/memory/query', extensionParams('memory.query', HOST_OPERATION_SPECS['memory.query'].decodeInput), ({ params }) => options.sessionRegistry.memoryQuery(params))
104
+ .onRequest('_maka/memory/mutate', extensionParams('memory.mutate', HOST_OPERATION_SPECS['memory.mutate'].decodeInput), ({ params }) => options.sessionRegistry.memoryMutate(params));
105
+ }
106
+ function extensionParams(operation, decode) {
107
+ return (params) => {
108
+ try {
109
+ if (params && typeof params === 'object' && !Array.isArray(params) && '_meta' in params) {
110
+ const record = params;
111
+ const meta = record._meta;
112
+ if (meta !== undefined &&
113
+ meta !== null &&
114
+ (typeof meta !== 'object' || Array.isArray(meta))) {
115
+ throw new Error('Invalid ACP request metadata');
116
+ }
117
+ const { _meta: _ignored, ...domainParams } = record;
118
+ return decode(domainParams);
119
+ }
120
+ return decode(params);
121
+ }
122
+ catch {
123
+ throw RequestError.invalidParams({ source: 'adapter', operation, code: 'invalid_request' }, `Invalid ${operation} request`);
124
+ }
125
+ };
92
126
  }
93
127
  function sessionContext(client, signal, capabilities, turnStatus = false) {
94
128
  return {
@@ -104,5 +138,11 @@ function sessionContext(client, signal, capabilities, turnStatus = false) {
104
138
  notifyTurnStatus: (status) => client.notify('_maka/turn/status', status),
105
139
  }
106
140
  : {}),
141
+ ...(capabilities._meta?.['_maka/goalPlanStatus'] === true
142
+ ? {
143
+ notifyGoalStatus: (status) => client.notify('_maka/goal/status', status),
144
+ notifyPlanChanged: (status) => client.notify('_maka/plan/changed', status),
145
+ }
146
+ : {}),
107
147
  };
108
148
  }
@@ -0,0 +1,185 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ /** Latest authoritative domain state for one retained Session attachment. */
20
+ export class AcpSessionDomainObservation {
21
+ #sessionId;
22
+ #queryPlan;
23
+ #goalNotify;
24
+ #planNotify;
25
+ #disposed = false;
26
+ #epoch = 0;
27
+ #goal = null;
28
+ #goalKnown = false;
29
+ #goalDelivered;
30
+ #planDelivered;
31
+ #planSeen;
32
+ #planDirty = false;
33
+ #planRefresh;
34
+ #planRetryCount = 0;
35
+ #planRetryTimer;
36
+ #goalDelivery;
37
+ #planDelivery;
38
+ #pendingGoal;
39
+ #pendingPlan;
40
+ constructor(options) {
41
+ this.#sessionId = options.sessionId;
42
+ this.#queryPlan = options.queryPlan;
43
+ this.#goalNotify = options.goalNotify;
44
+ this.#planNotify = options.planNotify;
45
+ }
46
+ initialize(goal) {
47
+ this.goalChanged(goal);
48
+ this.planChanged();
49
+ }
50
+ goalChanged(goal) {
51
+ if (this.#disposed)
52
+ return;
53
+ if (this.#goalKnown &&
54
+ goal?.goalId === this.#goal?.goalId &&
55
+ (goal?.revision ?? -1) < (this.#goal?.revision ?? -1))
56
+ return;
57
+ this.#goalKnown = true;
58
+ this.#goal = goal;
59
+ // Even a return to the last delivered value must replace an older pending
60
+ // snapshot: an in-flight notification may still change what the client sees.
61
+ this.#pendingGoal = { sessionId: this.#sessionId, goal };
62
+ this.#sendGoal();
63
+ }
64
+ planChanged() {
65
+ if (this.#disposed)
66
+ return;
67
+ if (!this.#planNotify())
68
+ return;
69
+ if (this.#planRetryTimer) {
70
+ clearTimeout(this.#planRetryTimer);
71
+ this.#planRetryTimer = undefined;
72
+ }
73
+ this.#planRetryCount = 0;
74
+ this.#planDirty = true;
75
+ this.#kickPlan();
76
+ }
77
+ #kickPlan() {
78
+ if (!this.#planRefresh) {
79
+ this.#planRefresh = this.#refreshPlan().finally(() => {
80
+ this.#planRefresh = undefined;
81
+ if (this.#planDirty && !this.#disposed && !this.#planRetryTimer && this.#planRetryCount < 4)
82
+ this.#kickPlan();
83
+ });
84
+ }
85
+ }
86
+ canonicalReplacement(goal) {
87
+ this.#epoch += 1;
88
+ this.#goalDelivered = undefined;
89
+ this.#planDelivered = undefined;
90
+ this.#planSeen = undefined;
91
+ this.#goalKnown = false;
92
+ this.initialize(goal);
93
+ }
94
+ dispose() {
95
+ this.#disposed = true;
96
+ this.#epoch += 1;
97
+ this.#pendingGoal = undefined;
98
+ this.#pendingPlan = undefined;
99
+ this.#planDirty = false;
100
+ if (this.#planRetryTimer)
101
+ clearTimeout(this.#planRetryTimer);
102
+ this.#planRetryTimer = undefined;
103
+ }
104
+ async #refreshPlan() {
105
+ // A frame received during a read is folded into one follow-up read.
106
+ while (this.#planDirty && !this.#disposed) {
107
+ this.#planDirty = false;
108
+ const epoch = this.#epoch;
109
+ try {
110
+ const result = await this.#queryPlan();
111
+ if (this.#disposed || epoch !== this.#epoch || result.kind !== 'page')
112
+ continue;
113
+ this.#planRetryCount = 0;
114
+ if (this.#planSeen !== undefined && result.storeVersion < this.#planSeen)
115
+ continue;
116
+ this.#planSeen = result.storeVersion;
117
+ const status = {
118
+ sessionId: this.#sessionId,
119
+ storeVersion: result.storeVersion,
120
+ latestProposalId: result.latestProposalId,
121
+ activeExecutionId: result.activeExecutionId,
122
+ };
123
+ if (result.storeVersion !== this.#planDelivered) {
124
+ this.#pendingPlan = status;
125
+ this.#sendPlan();
126
+ }
127
+ }
128
+ catch (error) {
129
+ console.error('[acp] Plan status refresh failed:', error);
130
+ this.#planDirty = true;
131
+ this.#planRetryCount += 1;
132
+ if (this.#planRetryCount <= 3 && !this.#disposed) {
133
+ this.#planRetryTimer = setTimeout(() => {
134
+ this.#planRetryTimer = undefined;
135
+ this.#kickPlan();
136
+ }, 25 * 2 ** (this.#planRetryCount - 1));
137
+ }
138
+ break;
139
+ }
140
+ }
141
+ }
142
+ #sendGoal() {
143
+ if (this.#goalDelivery || !this.#pendingGoal || this.#disposed)
144
+ return;
145
+ const notify = this.#goalNotify();
146
+ if (!notify)
147
+ return;
148
+ const status = this.#pendingGoal;
149
+ const epoch = this.#epoch;
150
+ this.#pendingGoal = undefined;
151
+ const key = JSON.stringify(status);
152
+ if (key === this.#goalDelivered)
153
+ return;
154
+ this.#goalDelivery = notify(status)
155
+ .then(() => {
156
+ if (!this.#disposed && epoch === this.#epoch)
157
+ this.#goalDelivered = key;
158
+ })
159
+ .catch((error) => console.error('[acp] Goal status delivery failed:', error))
160
+ .finally(() => {
161
+ this.#goalDelivery = undefined;
162
+ this.#sendGoal();
163
+ });
164
+ }
165
+ #sendPlan() {
166
+ if (this.#planDelivery || !this.#pendingPlan || this.#disposed)
167
+ return;
168
+ const notify = this.#planNotify();
169
+ if (!notify)
170
+ return;
171
+ const status = this.#pendingPlan;
172
+ const epoch = this.#epoch;
173
+ this.#pendingPlan = undefined;
174
+ this.#planDelivery = notify(status)
175
+ .then(() => {
176
+ if (!this.#disposed && epoch === this.#epoch)
177
+ this.#planDelivered = status.storeVersion;
178
+ })
179
+ .catch((error) => console.error('[acp] Plan status delivery failed:', error))
180
+ .finally(() => {
181
+ this.#planDelivery = undefined;
182
+ this.#sendPlan();
183
+ });
184
+ }
185
+ }
@@ -35,7 +35,7 @@ export class AcpSessionEventMapper {
35
35
  this.#sessionId = options.sessionId;
36
36
  this.#notify = options.notify;
37
37
  this.#signal = options.signal;
38
- this.#tools = new AcpToolEventMapper((update) => this.#deliver({ sessionId: this.#sessionId, update }));
38
+ this.#tools = new AcpToolEventMapper((update) => this.#deliver({ sessionId: this.#sessionId, update }), this.#sessionId);
39
39
  }
40
40
  accept(event) {
41
41
  return this.#enqueue(async () => {