maka-agent 0.2.0-dev.67.20261002 → 0.2.0-dev.69.20261004
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/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-catalog.js +132 -0
- package/node_modules/@maka/acp-executor-plugin/dist/index.js +251 -113
- package/node_modules/@maka/acp-executor-plugin/dist/plugin.mjs +431 -108
- package/node_modules/@maka/core/dist/executor-catalog.js +25 -3
- package/node_modules/@maka/core/dist/recall.js +13 -14
- package/node_modules/@maka/runtime/dist/admission-limiter.js +3 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +0 -3
- package/node_modules/@maka/runtime/dist/model-history.js +4 -14
- package/node_modules/@maka/runtime/dist/plugin-data-services.js +7 -0
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +19 -3
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +23 -4
- package/node_modules/@maka/runtime/dist/session-manager.js +1 -0
- package/node_modules/@maka/runtime/package.json +1 -0
- package/node_modules/@maka/runtime-host/dist/antigravity-program.js +49 -0
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +3 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +8 -2
- package/node_modules/@maka/runtime-host/dist/server/acp/antigravity.js +5 -19
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +14 -3
- package/node_modules/@maka/runtime-host/dist/server/external-agent-setup-coordinator.js +3 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-data-runtime.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-scratch-directory.js +55 -0
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +40 -6
- package/node_modules/@maka/runtime-host/package.json +1 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +10 -0
- package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +74 -5
- package/package.json +1 -1
|
@@ -7,9 +7,199 @@ var __export = (target, all) => {
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { constants as constants2, createReadStream } from "node:fs";
|
|
10
|
-
import { access,
|
|
10
|
+
import { access, mkdir, mkdtemp, realpath as realpath2, rm, stat as stat2 } from "node:fs/promises";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
// ../runtime/dist/admission-limiter.js
|
|
14
|
+
var AdmissionLimiter = class {
|
|
15
|
+
capacity;
|
|
16
|
+
active = 0;
|
|
17
|
+
waiters = [];
|
|
18
|
+
closedError;
|
|
19
|
+
constructor(capacity) {
|
|
20
|
+
this.capacity = capacity;
|
|
21
|
+
if (!Number.isSafeInteger(capacity) || capacity < 1) {
|
|
22
|
+
throw new Error("Admission capacity must be a positive safe integer");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
get activeCount() {
|
|
26
|
+
return this.active;
|
|
27
|
+
}
|
|
28
|
+
get waitingCount() {
|
|
29
|
+
return this.waiters.length;
|
|
30
|
+
}
|
|
31
|
+
acquire(signal) {
|
|
32
|
+
if (this.closedError)
|
|
33
|
+
return Promise.reject(this.closedError);
|
|
34
|
+
if (signal.aborted)
|
|
35
|
+
return Promise.reject(abortReason(signal));
|
|
36
|
+
if (this.active < this.capacity && this.waiters.length === 0) {
|
|
37
|
+
this.active += 1;
|
|
38
|
+
return Promise.resolve(this.createPermit());
|
|
39
|
+
}
|
|
40
|
+
return new Promise((resolve3, reject) => {
|
|
41
|
+
const waiter = {
|
|
42
|
+
signal,
|
|
43
|
+
resolve: resolve3,
|
|
44
|
+
reject,
|
|
45
|
+
onAbort: () => {
|
|
46
|
+
const index = this.waiters.indexOf(waiter);
|
|
47
|
+
if (index < 0)
|
|
48
|
+
return;
|
|
49
|
+
this.waiters.splice(index, 1);
|
|
50
|
+
signal.removeEventListener("abort", waiter.onAbort);
|
|
51
|
+
reject(abortReason(signal));
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
this.waiters.push(waiter);
|
|
55
|
+
signal.addEventListener("abort", waiter.onAbort, { once: true });
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
close(error62) {
|
|
59
|
+
if (this.closedError)
|
|
60
|
+
return;
|
|
61
|
+
this.closedError = error62;
|
|
62
|
+
for (const waiter of this.waiters.splice(0)) {
|
|
63
|
+
waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
64
|
+
waiter.reject(error62);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
createPermit() {
|
|
68
|
+
let released = false;
|
|
69
|
+
return {
|
|
70
|
+
release: () => {
|
|
71
|
+
if (released)
|
|
72
|
+
return;
|
|
73
|
+
released = true;
|
|
74
|
+
this.active -= 1;
|
|
75
|
+
this.grantWaiting();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
grantWaiting() {
|
|
80
|
+
if (this.closedError)
|
|
81
|
+
return;
|
|
82
|
+
while (this.active < this.capacity && this.waiters.length > 0) {
|
|
83
|
+
const waiter = this.waiters.shift();
|
|
84
|
+
waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
85
|
+
if (waiter.signal.aborted) {
|
|
86
|
+
waiter.reject(abortReason(waiter.signal));
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
this.active += 1;
|
|
90
|
+
waiter.resolve(this.createPermit());
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
function abortReason(signal) {
|
|
95
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Child agent run cancelled while waiting for runtime capacity");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/acp-catalog.ts
|
|
99
|
+
var CATALOG_TTL_MS = 6e4;
|
|
100
|
+
var PROBE_TIMEOUT_MS = 3e4;
|
|
101
|
+
var AcpCatalog = class {
|
|
102
|
+
constructor(admission, probe, unavailable) {
|
|
103
|
+
this.admission = admission;
|
|
104
|
+
this.probe = probe;
|
|
105
|
+
this.unavailable = unavailable;
|
|
106
|
+
}
|
|
107
|
+
admission;
|
|
108
|
+
probe;
|
|
109
|
+
unavailable;
|
|
110
|
+
#cached;
|
|
111
|
+
#pending;
|
|
112
|
+
#tail;
|
|
113
|
+
#operations = /* @__PURE__ */ new Set();
|
|
114
|
+
#revision = 0;
|
|
115
|
+
#disposed = false;
|
|
116
|
+
async get(signal, refresh = false) {
|
|
117
|
+
signal.throwIfAborted();
|
|
118
|
+
if (this.#disposed) return this.unavailable();
|
|
119
|
+
if (refresh) this.invalidate();
|
|
120
|
+
while (true) {
|
|
121
|
+
signal.throwIfAborted();
|
|
122
|
+
if (this.#disposed) return this.unavailable();
|
|
123
|
+
const cached2 = this.#cached;
|
|
124
|
+
if (cached2 && cached2.expires > Date.now()) return cached2.entry;
|
|
125
|
+
const pending = this.#ensureProbe();
|
|
126
|
+
const result = await waitForSignal(pending.promise, signal);
|
|
127
|
+
signal.throwIfAborted();
|
|
128
|
+
if (this.#disposed) return this.unavailable();
|
|
129
|
+
if (pending.revision !== this.#revision) continue;
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
#ensureProbe() {
|
|
134
|
+
if (!this.#pending) {
|
|
135
|
+
const revision = this.#revision;
|
|
136
|
+
const controller = new AbortController();
|
|
137
|
+
const startup = AbortSignal.any([controller.signal, AbortSignal.timeout(PROBE_TIMEOUT_MS)]);
|
|
138
|
+
const previous = this.#tail;
|
|
139
|
+
const run = async () => {
|
|
140
|
+
try {
|
|
141
|
+
await previous;
|
|
142
|
+
startup.throwIfAborted();
|
|
143
|
+
const permit = await this.admission.acquire(startup);
|
|
144
|
+
let entry;
|
|
145
|
+
try {
|
|
146
|
+
startup.throwIfAborted();
|
|
147
|
+
entry = await this.probe(startup);
|
|
148
|
+
} finally {
|
|
149
|
+
permit.release();
|
|
150
|
+
}
|
|
151
|
+
if (startup.aborted || revision !== this.#revision || this.#disposed)
|
|
152
|
+
return this.unavailable();
|
|
153
|
+
if (entry.readiness === "ready")
|
|
154
|
+
this.#cached = { entry, expires: Date.now() + CATALOG_TTL_MS };
|
|
155
|
+
return entry;
|
|
156
|
+
} catch {
|
|
157
|
+
return this.unavailable();
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const promise2 = run().finally(() => {
|
|
161
|
+
this.#operations.delete(promise2);
|
|
162
|
+
if (this.#pending?.promise === promise2) this.#pending = void 0;
|
|
163
|
+
if (this.#tail === promise2) this.#tail = void 0;
|
|
164
|
+
});
|
|
165
|
+
this.#pending = { revision, controller, promise: promise2 };
|
|
166
|
+
this.#tail = promise2;
|
|
167
|
+
this.#operations.add(promise2);
|
|
168
|
+
}
|
|
169
|
+
return this.#pending;
|
|
170
|
+
}
|
|
171
|
+
invalidate() {
|
|
172
|
+
this.#revision++;
|
|
173
|
+
this.#cached = void 0;
|
|
174
|
+
this.#pending?.controller.abort(new Error("ACP catalog invalidated"));
|
|
175
|
+
this.#pending = void 0;
|
|
176
|
+
}
|
|
177
|
+
async dispose() {
|
|
178
|
+
this.#disposed = true;
|
|
179
|
+
this.invalidate();
|
|
180
|
+
await Promise.allSettled(this.#operations);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
async function waitForSignal(promise2, signal) {
|
|
184
|
+
signal.throwIfAborted();
|
|
185
|
+
return await new Promise((resolve3, reject) => {
|
|
186
|
+
const aborted2 = () => reject(signal.reason);
|
|
187
|
+
signal.addEventListener("abort", aborted2, { once: true });
|
|
188
|
+
void promise2.then(
|
|
189
|
+
(value) => {
|
|
190
|
+
signal.removeEventListener("abort", aborted2);
|
|
191
|
+
resolve3(value);
|
|
192
|
+
},
|
|
193
|
+
(error62) => {
|
|
194
|
+
signal.removeEventListener("abort", aborted2);
|
|
195
|
+
reject(error62);
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/index.ts
|
|
202
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join, resolve as resolve2 } from "node:path";
|
|
13
203
|
|
|
14
204
|
// ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15
205
|
var AGENT_METHODS = {
|
|
@@ -23412,6 +23602,28 @@ var legacyClientNotificationMethods = /* @__PURE__ */ new Set([
|
|
|
23412
23602
|
CLIENT_METHODS.elicitation_complete
|
|
23413
23603
|
]);
|
|
23414
23604
|
|
|
23605
|
+
// ../runtime/dist/plugin-runtime.js
|
|
23606
|
+
var MakaPluginRuntimeError = class extends Error {
|
|
23607
|
+
code;
|
|
23608
|
+
name = "MakaPluginRuntimeError";
|
|
23609
|
+
constructor(code, message, options) {
|
|
23610
|
+
super(message, options);
|
|
23611
|
+
this.code = code;
|
|
23612
|
+
}
|
|
23613
|
+
};
|
|
23614
|
+
function pluginIdentity(ctx) {
|
|
23615
|
+
const metadata = ctx.maka;
|
|
23616
|
+
if (!metadata) {
|
|
23617
|
+
throw new MakaPluginRuntimeError("activation_failed", "Contribution registration requires a composition entry Context");
|
|
23618
|
+
}
|
|
23619
|
+
return Object.freeze({
|
|
23620
|
+
entryId: metadata.entryId,
|
|
23621
|
+
scopeId: metadata.rootId,
|
|
23622
|
+
extensionId: metadata.packageId,
|
|
23623
|
+
generation: metadata.generation
|
|
23624
|
+
});
|
|
23625
|
+
}
|
|
23626
|
+
|
|
23415
23627
|
// src/acp-errors.ts
|
|
23416
23628
|
var AcpRuntimeError = class extends Error {
|
|
23417
23629
|
constructor(message, code) {
|
|
@@ -23889,7 +24101,8 @@ var AcpExecutor = class {
|
|
|
23889
24101
|
#sessions = /* @__PURE__ */ new Map();
|
|
23890
24102
|
#disposed = false;
|
|
23891
24103
|
#catalog;
|
|
23892
|
-
#
|
|
24104
|
+
#withCatalogDirectory;
|
|
24105
|
+
#temporaryDirectory;
|
|
23893
24106
|
constructor(adapter, config2, options = {}) {
|
|
23894
24107
|
this.#adapter = validateAdapter(adapter);
|
|
23895
24108
|
this.id = adapter.id;
|
|
@@ -23897,79 +24110,107 @@ var AcpExecutor = class {
|
|
|
23897
24110
|
this.#configured = validateConfiguredAgent(adapter.configure(config2));
|
|
23898
24111
|
this.#createConnection = options.createConnection ?? createAcpConnection;
|
|
23899
24112
|
this.#state = options.state;
|
|
24113
|
+
this.#withCatalogDirectory = options.withCatalogDirectory ?? (async (signal, use) => {
|
|
24114
|
+
signal.throwIfAborted();
|
|
24115
|
+
this.#temporaryDirectory ??= mkdtemp(join(tmpdir(), "maka-acp-catalog-"));
|
|
24116
|
+
const directory = await this.#temporaryDirectory;
|
|
24117
|
+
await mkdir(directory, { recursive: true, mode: 448 });
|
|
24118
|
+
try {
|
|
24119
|
+
return await use(await realpath2(directory));
|
|
24120
|
+
} finally {
|
|
24121
|
+
await rm(directory, { recursive: true, force: true });
|
|
24122
|
+
}
|
|
24123
|
+
});
|
|
24124
|
+
this.#catalog = new AcpCatalog(
|
|
24125
|
+
options.catalogAdmission ?? new AdmissionLimiter(1),
|
|
24126
|
+
(signal) => this.#probeCatalog(signal),
|
|
24127
|
+
() => this.#catalogEntry("unavailable")
|
|
24128
|
+
);
|
|
23900
24129
|
}
|
|
23901
24130
|
async discover(input2) {
|
|
23902
|
-
|
|
23903
|
-
|
|
23904
|
-
|
|
23905
|
-
|
|
23906
|
-
|
|
23907
|
-
|
|
24131
|
+
return await this.#catalog.get(input2.signal, input2.refresh);
|
|
24132
|
+
}
|
|
24133
|
+
async #probeCatalog(signal) {
|
|
24134
|
+
return await this.#withCatalogDirectory(
|
|
24135
|
+
signal,
|
|
24136
|
+
(directory) => this.#readCatalog(directory, signal)
|
|
24137
|
+
);
|
|
24138
|
+
}
|
|
24139
|
+
async #readCatalog(directory, signal) {
|
|
24140
|
+
let session;
|
|
24141
|
+
try {
|
|
24142
|
+
signal.throwIfAborted();
|
|
24143
|
+
session = {
|
|
23908
24144
|
conversationKey: "catalog-probe",
|
|
23909
|
-
cwd,
|
|
24145
|
+
cwd: await realpath2(directory),
|
|
23910
24146
|
configOptions: [],
|
|
23911
24147
|
lost: false
|
|
23912
24148
|
};
|
|
23913
|
-
|
|
23914
|
-
|
|
23915
|
-
|
|
23916
|
-
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
|
|
23921
|
-
|
|
23922
|
-
|
|
23923
|
-
|
|
23924
|
-
|
|
23925
|
-
}
|
|
23926
|
-
};
|
|
23927
|
-
this.#discovery = probe().finally(() => {
|
|
23928
|
-
this.#discovery = void 0;
|
|
23929
|
-
});
|
|
23930
|
-
return this.#discovery;
|
|
24149
|
+
await this.#initialize(session, signal, true);
|
|
24150
|
+
return this.#catalogEntry("ready", session.configOptions);
|
|
24151
|
+
} catch (error62) {
|
|
24152
|
+
return this.#catalogEntry(
|
|
24153
|
+
isAuthenticationFailure(error62) ? "authentication_required" : "unavailable"
|
|
24154
|
+
);
|
|
24155
|
+
} finally {
|
|
24156
|
+
if (session) await (session.loss ?? this.#disposeSession(session));
|
|
24157
|
+
}
|
|
24158
|
+
}
|
|
24159
|
+
invalidateCatalog() {
|
|
24160
|
+
this.#catalog.invalidate();
|
|
23931
24161
|
}
|
|
23932
24162
|
async inspectConversation(input2) {
|
|
23933
24163
|
const session = this.#sessions.get(input2.conversationKey);
|
|
23934
24164
|
if (this.#disposed) return this.#catalogEntry("unavailable");
|
|
23935
24165
|
if (session && session.cwd !== resolve2(input2.cwd))
|
|
23936
|
-
return this.#catalogEntry("history_only", [], input2.configuration
|
|
24166
|
+
return this.#catalogEntry("history_only", [], input2.configuration);
|
|
23937
24167
|
if (session?.restoring)
|
|
23938
|
-
return this.#catalogEntry("restoring", session.configOptions, input2.configuration
|
|
24168
|
+
return this.#catalogEntry("restoring", session.configOptions, input2.configuration);
|
|
23939
24169
|
if (session?.restoreFailed)
|
|
23940
|
-
return this.#catalogEntry(
|
|
23941
|
-
"restore_failed",
|
|
23942
|
-
session.configOptions,
|
|
23943
|
-
input2.configuration?.model
|
|
23944
|
-
);
|
|
24170
|
+
return this.#catalogEntry("restore_failed", session.configOptions, input2.configuration);
|
|
23945
24171
|
if (session?.historyGap)
|
|
23946
|
-
return this.#catalogEntry("history_gap", session.configOptions, input2.configuration
|
|
24172
|
+
return this.#catalogEntry("history_gap", session.configOptions, input2.configuration);
|
|
23947
24173
|
if (session && !session.lost)
|
|
23948
|
-
return this.#catalogEntry("ready", session.configOptions, input2.configuration
|
|
24174
|
+
return this.#catalogEntry("ready", session.configOptions, input2.configuration);
|
|
23949
24175
|
if (session?.lost && !session.record)
|
|
23950
|
-
return this.#catalogEntry("history_only", session.configOptions, input2.configuration
|
|
24176
|
+
return this.#catalogEntry("history_only", session.configOptions, input2.configuration);
|
|
23951
24177
|
const stored = this.#state?.read ? decodeContinuity(await this.#state.read(input2.conversationKey)) : await this.#state?.has(input2.conversationKey, input2.cwd) ? "legacy" : void 0;
|
|
23952
|
-
if (!stored) return this.#catalogEntry("ready", [], input2.configuration
|
|
24178
|
+
if (!stored) return this.#catalogEntry("ready", [], input2.configuration);
|
|
23953
24179
|
if (stored === "invalid" || stored === "legacy" || stored.cwd !== resolve2(input2.cwd))
|
|
23954
|
-
return this.#catalogEntry("history_only", [], input2.configuration
|
|
24180
|
+
return this.#catalogEntry("history_only", [], input2.configuration);
|
|
23955
24181
|
if (stored.phase === "reserved")
|
|
23956
|
-
return this.#catalogEntry("history_only", [], input2.configuration
|
|
24182
|
+
return this.#catalogEntry("history_only", [], input2.configuration);
|
|
23957
24183
|
return this.#catalogEntry(
|
|
23958
24184
|
stored.phase === "prompt_pending" || stored.phase === "history_gap" ? "history_gap" : "restorable",
|
|
23959
24185
|
[],
|
|
23960
|
-
|
|
24186
|
+
{
|
|
24187
|
+
model: input2.configuration?.model ?? stored.confirmedModel,
|
|
24188
|
+
mode: input2.configuration?.mode ?? stored.confirmedMode
|
|
24189
|
+
}
|
|
23961
24190
|
);
|
|
23962
24191
|
}
|
|
23963
24192
|
async configureConversation(input2, signal) {
|
|
23964
|
-
if (!input2.configuration?.model
|
|
24193
|
+
if (!input2.configuration?.model && !input2.configuration?.mode)
|
|
24194
|
+
throw new Error("ACP configuration change is unavailable");
|
|
23965
24195
|
const session = await this.#session(input2);
|
|
23966
|
-
if (session.active || session.configuring
|
|
24196
|
+
if (session.active || session.configuring || session.restoring || session.awaitingAck)
|
|
24197
|
+
throw new Error("ACP configuration change is unavailable while the Session is busy");
|
|
23967
24198
|
session.configuring = true;
|
|
23968
24199
|
const wasConnected = !!session.connection;
|
|
23969
24200
|
try {
|
|
23970
|
-
await this.#ensureInitialized(session, signal);
|
|
23971
|
-
await this.#applyInitialConfig(
|
|
24201
|
+
await this.#ensureInitialized(session, signal, true);
|
|
24202
|
+
await this.#applyInitialConfig(
|
|
24203
|
+
session,
|
|
24204
|
+
!wasConnected && !session.restoredFromState ? { ...this.#configured.launch.initialConfig, ...input2.configuration } : input2.configuration,
|
|
24205
|
+
signal,
|
|
24206
|
+
true
|
|
24207
|
+
);
|
|
24208
|
+
return {
|
|
24209
|
+
...currentAcpModel(session.configOptions) ? { model: currentAcpModel(session.configOptions) } : {},
|
|
24210
|
+
...acpOption(session.configOptions, "mode")?.currentValue ? { mode: acpOption(session.configOptions, "mode").currentValue } : {}
|
|
24211
|
+
};
|
|
23972
24212
|
} catch (error62) {
|
|
24213
|
+
if (isAuthenticationFailure(error62)) this.invalidateCatalog();
|
|
23973
24214
|
if (!wasConnected || session.lost) {
|
|
23974
24215
|
await this.#lose(session);
|
|
23975
24216
|
if (session.record?.sessionId && !session.historyGap) session.restoreFailed = true;
|
|
@@ -23986,16 +24227,24 @@ var AcpExecutor = class {
|
|
|
23986
24227
|
const model = options.find(
|
|
23987
24228
|
(option) => option.type === "select" && (option.category === "model" || option.id === "model")
|
|
23988
24229
|
);
|
|
23989
|
-
const models = model?.type === "select" ? model.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).map((entry) => ({ id: entry.value, name: entry.name })) :
|
|
24230
|
+
const models = model?.type === "select" ? model.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).map((entry) => ({ id: entry.value, name: entry.name })) : selected?.model ? [{ id: selected.model, name: selected.model }] : [];
|
|
24231
|
+
const mode = options.find(
|
|
24232
|
+
(option) => option.type === "select" && (option.category === "mode" || option.id === "mode")
|
|
24233
|
+
);
|
|
24234
|
+
const modes = mode?.type === "select" ? mode.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).map((entry) => ({ id: entry.value, name: entry.name })) : selected?.mode ? [{ id: selected.mode, name: selected.mode }] : [];
|
|
23990
24235
|
return {
|
|
23991
24236
|
id: this.id,
|
|
23992
24237
|
displayName: this.displayName,
|
|
23993
24238
|
readiness,
|
|
23994
24239
|
...model?.type === "select" ? this.#adapter.describeModels?.(models) ?? { models } : {
|
|
23995
|
-
models
|
|
23996
|
-
|
|
24240
|
+
models
|
|
24241
|
+
},
|
|
24242
|
+
...model?.type === "select" ? { currentModel: model.currentValue } : selected?.model ? { currentModel: selected.model } : {},
|
|
24243
|
+
...mode?.type === "select" ? { modes, currentMode: mode.currentValue, supportsModeChange: true } : {
|
|
24244
|
+
modes,
|
|
24245
|
+
...selected?.mode ? { currentMode: selected.mode } : {},
|
|
24246
|
+
supportsModeChange: false
|
|
23997
24247
|
},
|
|
23998
|
-
...model?.type === "select" ? { currentModel: model.currentValue } : selected ? { currentModel: selected } : {},
|
|
23999
24248
|
supportsAttachments: false,
|
|
24000
24249
|
supportsModelChange: model?.type === "select"
|
|
24001
24250
|
};
|
|
@@ -24011,7 +24260,7 @@ var AcpExecutor = class {
|
|
|
24011
24260
|
if (request.configuration?.model && request.model && request.model !== this.id && request.configuration.model !== request.model)
|
|
24012
24261
|
return failure2("Conflicting executor models", "acp_config_invalid");
|
|
24013
24262
|
const model = request.configuration?.model ?? (request.model === this.id ? void 0 : request.model);
|
|
24014
|
-
if (model) request = { ...request, configuration: { model } };
|
|
24263
|
+
if (model) request = { ...request, configuration: { ...request.configuration, model } };
|
|
24015
24264
|
let session;
|
|
24016
24265
|
try {
|
|
24017
24266
|
session = await this.#session(request);
|
|
@@ -24025,12 +24274,8 @@ var AcpExecutor = class {
|
|
|
24025
24274
|
try {
|
|
24026
24275
|
await this.#ensureInitialized(session, context.signal);
|
|
24027
24276
|
context.signal.throwIfAborted();
|
|
24028
|
-
if (request.configuration?.model)
|
|
24029
|
-
await this.#applyInitialConfig(
|
|
24030
|
-
session,
|
|
24031
|
-
{ model: request.configuration.model },
|
|
24032
|
-
context.signal
|
|
24033
|
-
);
|
|
24277
|
+
if (request.configuration?.model || request.configuration?.mode)
|
|
24278
|
+
await this.#applyInitialConfig(session, request.configuration, context.signal);
|
|
24034
24279
|
await this.#beginPrompt(session, request.turnId);
|
|
24035
24280
|
const prompt = session.connection.agent.request(methods.agent.session.prompt, {
|
|
24036
24281
|
sessionId: session.acpSessionId,
|
|
@@ -24053,6 +24298,7 @@ var AcpExecutor = class {
|
|
|
24053
24298
|
}
|
|
24054
24299
|
return { status: "completed", text: active.text };
|
|
24055
24300
|
} catch (error62) {
|
|
24301
|
+
if (isAuthenticationFailure(error62)) this.invalidateCatalog();
|
|
24056
24302
|
if (errorCode(error62) === "acp_history_gap") session.historyGap = true;
|
|
24057
24303
|
await this.#lose(session);
|
|
24058
24304
|
if (session.record?.sessionId && !session.historyGap) session.restoreFailed = true;
|
|
@@ -24076,6 +24322,7 @@ var AcpExecutor = class {
|
|
|
24076
24322
|
async dispose() {
|
|
24077
24323
|
if (this.#disposed) return;
|
|
24078
24324
|
this.#disposed = true;
|
|
24325
|
+
await this.#catalog.dispose();
|
|
24079
24326
|
const sessions = [...this.#sessions.values()];
|
|
24080
24327
|
this.#sessions.clear();
|
|
24081
24328
|
const settlements = await Promise.allSettled(
|
|
@@ -24114,9 +24361,9 @@ var AcpExecutor = class {
|
|
|
24114
24361
|
this.#sessions.set(request.conversationKey, created);
|
|
24115
24362
|
return created;
|
|
24116
24363
|
}
|
|
24117
|
-
async #ensureInitialized(session, signal) {
|
|
24364
|
+
async #ensureInitialized(session, signal, deferSelectedConfig = false) {
|
|
24118
24365
|
if (session.initialization) return await session.initialization;
|
|
24119
|
-
const initialization = this.#initialize(session, signal);
|
|
24366
|
+
const initialization = this.#initialize(session, signal, false, deferSelectedConfig);
|
|
24120
24367
|
session.initialization = initialization;
|
|
24121
24368
|
try {
|
|
24122
24369
|
await initialization;
|
|
@@ -24127,7 +24374,7 @@ var AcpExecutor = class {
|
|
|
24127
24374
|
throw error62;
|
|
24128
24375
|
}
|
|
24129
24376
|
}
|
|
24130
|
-
async #initialize(session, signal, probe = false) {
|
|
24377
|
+
async #initialize(session, signal, probe = false, deferSelectedConfig = false) {
|
|
24131
24378
|
const timeout = AbortSignal.timeout(INITIALIZE_TIMEOUT_MS);
|
|
24132
24379
|
const startupSignal = AbortSignal.any([signal, timeout]);
|
|
24133
24380
|
startupSignal.throwIfAborted();
|
|
@@ -24148,6 +24395,7 @@ var AcpExecutor = class {
|
|
|
24148
24395
|
"External Session history cannot be aligned with saved conversation events",
|
|
24149
24396
|
"acp_history_gap"
|
|
24150
24397
|
);
|
|
24398
|
+
session.restoredFromState = !!stored;
|
|
24151
24399
|
if (stored) {
|
|
24152
24400
|
session.record = stored;
|
|
24153
24401
|
session.acpSessionId = stored.sessionId;
|
|
@@ -24204,7 +24452,27 @@ var AcpExecutor = class {
|
|
|
24204
24452
|
]);
|
|
24205
24453
|
session.configOptions = restored.configOptions ?? [];
|
|
24206
24454
|
const restoredModel = currentAcpModel(session.configOptions);
|
|
24207
|
-
|
|
24455
|
+
const restoredMode = acpOption(session.configOptions, "mode")?.currentValue;
|
|
24456
|
+
if (stored.confirmedModel && restoredModel !== stored.confirmedModel || stored.confirmedMode && restoredMode !== stored.confirmedMode) {
|
|
24457
|
+
const confirmed = await this.#applyInitialConfig(
|
|
24458
|
+
session,
|
|
24459
|
+
{
|
|
24460
|
+
...stored.confirmedModel ? { model: stored.confirmedModel } : {},
|
|
24461
|
+
...stored.confirmedMode ? { mode: stored.confirmedMode } : {}
|
|
24462
|
+
},
|
|
24463
|
+
startupSignal,
|
|
24464
|
+
false,
|
|
24465
|
+
// Only an explicit model-only configuration can recover a removed
|
|
24466
|
+
// saved mode. Ordinary execution still requires the exact saved pair.
|
|
24467
|
+
deferSelectedConfig && !!session.configuration?.model && !session.configuration.mode
|
|
24468
|
+
);
|
|
24469
|
+
if (confirmed.model && currentAcpModel(session.configOptions) !== confirmed.model || confirmed.mode && acpOption(session.configOptions, "mode")?.currentValue !== confirmed.mode)
|
|
24470
|
+
throw new AcpRuntimeError(
|
|
24471
|
+
"Restored Agent configuration differs from the saved task",
|
|
24472
|
+
"acp_config_unconfirmed"
|
|
24473
|
+
);
|
|
24474
|
+
}
|
|
24475
|
+
await this.#persistConfirmedConfig(session);
|
|
24208
24476
|
session.restoring = false;
|
|
24209
24477
|
if (pending) {
|
|
24210
24478
|
session.historyGap = true;
|
|
@@ -24261,13 +24529,12 @@ var AcpExecutor = class {
|
|
|
24261
24529
|
};
|
|
24262
24530
|
await this.#state?.write?.(session.conversationKey, established);
|
|
24263
24531
|
session.record = established;
|
|
24264
|
-
|
|
24265
|
-
if (createdModel) await this.#persistConfirmedModel(session, createdModel);
|
|
24532
|
+
await this.#persistConfirmedConfig(session);
|
|
24266
24533
|
}
|
|
24267
|
-
if (!probe) {
|
|
24534
|
+
if (!probe && !deferSelectedConfig) {
|
|
24268
24535
|
await this.#applyInitialConfig(
|
|
24269
24536
|
session,
|
|
24270
|
-
session.configuration?.model ? {
|
|
24537
|
+
session.configuration?.model || session.configuration?.mode ? { ...launch.initialConfig, ...session.configuration } : launch.initialConfig ?? {},
|
|
24271
24538
|
startupSignal
|
|
24272
24539
|
);
|
|
24273
24540
|
}
|
|
@@ -24321,71 +24588,104 @@ var AcpExecutor = class {
|
|
|
24321
24588
|
await this.#lose(session);
|
|
24322
24589
|
}
|
|
24323
24590
|
}
|
|
24324
|
-
async #applyInitialConfig(session, values, signal, restoreOnFailure = false) {
|
|
24325
|
-
|
|
24326
|
-
|
|
24327
|
-
|
|
24328
|
-
|
|
24329
|
-
|
|
24591
|
+
async #applyInitialConfig(session, values, signal, restoreOnFailure = false, omitUnavailableMode = false) {
|
|
24592
|
+
let target = Object.entries(values).filter(
|
|
24593
|
+
(entry) => entry[1] !== void 0
|
|
24594
|
+
);
|
|
24595
|
+
const before = session.configOptions;
|
|
24596
|
+
const selectedModel = target.find(([key]) => key === "model")?.[1];
|
|
24597
|
+
const changingModel = selectedModel !== void 0 && acpOption(before, "model")?.currentValue !== selectedModel;
|
|
24598
|
+
const validate2 = (options, key, value) => {
|
|
24599
|
+
const option = acpOption(options, key);
|
|
24600
|
+
if (!option)
|
|
24330
24601
|
throw new AcpRuntimeError(
|
|
24331
24602
|
`ACP configuration is unavailable: ${key}`,
|
|
24332
24603
|
"acp_config_unavailable"
|
|
24333
24604
|
);
|
|
24334
|
-
const
|
|
24605
|
+
const candidates = option.options.flatMap(
|
|
24335
24606
|
(entry) => "options" in entry ? entry.options : [entry]
|
|
24336
24607
|
);
|
|
24337
|
-
if (!
|
|
24608
|
+
if (!candidates.some((entry) => entry.value === value))
|
|
24338
24609
|
throw new AcpRuntimeError(
|
|
24339
24610
|
`ACP configuration value is unavailable: ${key}`,
|
|
24340
24611
|
"acp_config_invalid"
|
|
24341
24612
|
);
|
|
24342
|
-
|
|
24343
|
-
|
|
24344
|
-
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
|
|
24613
|
+
};
|
|
24614
|
+
for (const [key, value] of target) {
|
|
24615
|
+
if (omitUnavailableMode && key === "mode") continue;
|
|
24616
|
+
if (!changingModel || key === "model") validate2(before, key, value);
|
|
24617
|
+
}
|
|
24618
|
+
const ordered = [
|
|
24619
|
+
...target.filter(([key]) => key === "model"),
|
|
24620
|
+
...target.filter(([key]) => key !== "model")
|
|
24621
|
+
];
|
|
24622
|
+
let mutationAttempted = false;
|
|
24623
|
+
try {
|
|
24624
|
+
for (const [key, value] of ordered) {
|
|
24625
|
+
const option = acpOption(session.configOptions, key);
|
|
24626
|
+
if (omitUnavailableMode && key === "mode" && !option?.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).some((entry) => entry.value === value)) {
|
|
24627
|
+
target = target.filter(([candidate]) => candidate !== "mode");
|
|
24628
|
+
continue;
|
|
24629
|
+
}
|
|
24630
|
+
validate2(session.configOptions, key, value);
|
|
24631
|
+
if (!option) throw new Error("Validated ACP option disappeared");
|
|
24632
|
+
if (option.currentValue === value) continue;
|
|
24633
|
+
signal.throwIfAborted();
|
|
24634
|
+
mutationAttempted = true;
|
|
24348
24635
|
const updated = await session.connection.agent.request(
|
|
24349
24636
|
methods.agent.session.setConfigOption,
|
|
24350
24637
|
{ sessionId: session.acpSessionId, configId: option.id, value },
|
|
24351
24638
|
{ cancellationSignal: signal }
|
|
24352
24639
|
);
|
|
24353
|
-
|
|
24354
|
-
if (
|
|
24640
|
+
session.configOptions = updated.configOptions;
|
|
24641
|
+
if (acpOption(updated.configOptions, key)?.currentValue !== value)
|
|
24355
24642
|
throw new AcpRuntimeError(
|
|
24356
24643
|
"Agent did not confirm the selected configuration",
|
|
24357
24644
|
"acp_config_unconfirmed"
|
|
24358
24645
|
);
|
|
24359
|
-
|
|
24360
|
-
|
|
24361
|
-
|
|
24362
|
-
|
|
24363
|
-
|
|
24364
|
-
|
|
24646
|
+
}
|
|
24647
|
+
if (target.some(([key, value]) => acpOption(session.configOptions, key)?.currentValue !== value))
|
|
24648
|
+
throw new AcpRuntimeError(
|
|
24649
|
+
"Agent changed another selected configuration",
|
|
24650
|
+
"acp_config_unconfirmed"
|
|
24651
|
+
);
|
|
24652
|
+
await this.#persistConfirmedConfig(session);
|
|
24653
|
+
return Object.fromEntries(target);
|
|
24654
|
+
} catch (error62) {
|
|
24655
|
+
let restored = false;
|
|
24656
|
+
if (restoreOnFailure && !session.lost && !signal.aborted) {
|
|
24657
|
+
try {
|
|
24658
|
+
for (const key of ["model", "mode"]) {
|
|
24659
|
+
const original = acpOption(before, key);
|
|
24660
|
+
const current = acpOption(session.configOptions, key);
|
|
24661
|
+
if (!original || !current || !mutationAttempted && current.currentValue === original.currentValue)
|
|
24662
|
+
continue;
|
|
24365
24663
|
const rollback = await session.connection.agent.request(
|
|
24366
24664
|
methods.agent.session.setConfigOption,
|
|
24367
|
-
{
|
|
24665
|
+
{
|
|
24666
|
+
sessionId: session.acpSessionId,
|
|
24667
|
+
configId: current.id,
|
|
24668
|
+
value: original.currentValue
|
|
24669
|
+
},
|
|
24368
24670
|
{ cancellationSignal: AbortSignal.timeout(5e3) }
|
|
24369
24671
|
);
|
|
24370
|
-
|
|
24371
|
-
(candidate) => candidate.id === option.id
|
|
24372
|
-
);
|
|
24373
|
-
if (confirmed?.type === "select" && confirmed.currentValue === option.currentValue && !session.lost) {
|
|
24374
|
-
session.configOptions = rollback.configOptions;
|
|
24375
|
-
if (key === "model") await this.#persistConfirmedModel(session, option.currentValue);
|
|
24376
|
-
restored = true;
|
|
24377
|
-
}
|
|
24378
|
-
} catch {
|
|
24672
|
+
session.configOptions = rollback.configOptions;
|
|
24379
24673
|
}
|
|
24674
|
+
restored = ["model", "mode"].every((key) => {
|
|
24675
|
+
const original = acpOption(before, key);
|
|
24676
|
+
return !original || acpOption(session.configOptions, key)?.currentValue === original.currentValue;
|
|
24677
|
+
});
|
|
24678
|
+
} catch {
|
|
24380
24679
|
}
|
|
24381
|
-
if (!restored) await this.#lose(session);
|
|
24382
|
-
throw error62;
|
|
24383
24680
|
}
|
|
24681
|
+
if (!restored) await this.#lose(session);
|
|
24682
|
+
throw error62;
|
|
24384
24683
|
}
|
|
24385
24684
|
}
|
|
24386
|
-
async #
|
|
24387
|
-
if (!session.record
|
|
24388
|
-
const record2 =
|
|
24685
|
+
async #persistConfirmedConfig(session, configOptions = session.configOptions) {
|
|
24686
|
+
if (!session.record) return;
|
|
24687
|
+
const record2 = withConfirmedConfiguration(session.record, configOptions);
|
|
24688
|
+
if (record2 === session.record) return;
|
|
24389
24689
|
await this.#state?.write?.(session.conversationKey, record2);
|
|
24390
24690
|
session.record = record2;
|
|
24391
24691
|
}
|
|
@@ -24430,7 +24730,9 @@ var AcpExecutor = class {
|
|
|
24430
24730
|
}
|
|
24431
24731
|
if (session.historyGap || session.lost) return;
|
|
24432
24732
|
if (update.sessionUpdate === "config_option_update") {
|
|
24433
|
-
if (!session.configuring && !session.lost)
|
|
24733
|
+
if (!session.configuring && !session.lost) {
|
|
24734
|
+
session.configOptions = update.configOptions;
|
|
24735
|
+
}
|
|
24434
24736
|
return;
|
|
24435
24737
|
}
|
|
24436
24738
|
const active = session.active;
|
|
@@ -24555,10 +24857,26 @@ var AcpExecutor = class {
|
|
|
24555
24857
|
}
|
|
24556
24858
|
};
|
|
24557
24859
|
function currentAcpModel(options) {
|
|
24558
|
-
|
|
24559
|
-
|
|
24860
|
+
return acpOption(options, "model")?.currentValue;
|
|
24861
|
+
}
|
|
24862
|
+
function withConfirmedConfiguration(record2, options) {
|
|
24863
|
+
const model = currentAcpModel(options);
|
|
24864
|
+
const mode = acpOption(options, "mode")?.currentValue;
|
|
24865
|
+
const { confirmedModel, confirmedMode, ...base } = record2;
|
|
24866
|
+
if (confirmedModel === model && confirmedMode === mode) return record2;
|
|
24867
|
+
return {
|
|
24868
|
+
...base,
|
|
24869
|
+
...model ? { confirmedModel: model } : {},
|
|
24870
|
+
...mode ? { confirmedMode: mode } : {}
|
|
24871
|
+
};
|
|
24872
|
+
}
|
|
24873
|
+
function isAuthenticationFailure(error62) {
|
|
24874
|
+
return error62?.code === -32e3 || error62 instanceof Error && /authentication required|unauthorized/u.test(error62.message.toLowerCase());
|
|
24875
|
+
}
|
|
24876
|
+
function acpOption(options, key) {
|
|
24877
|
+
return options.find(
|
|
24878
|
+
(candidate) => candidate.type === "select" && (candidate.id === key || candidate.category === key)
|
|
24560
24879
|
);
|
|
24561
|
-
return option?.type === "select" ? option.currentValue : void 0;
|
|
24562
24880
|
}
|
|
24563
24881
|
function toolTextContent(content) {
|
|
24564
24882
|
return content.flatMap(
|
|
@@ -24566,14 +24884,19 @@ function toolTextContent(content) {
|
|
|
24566
24884
|
).join("\n");
|
|
24567
24885
|
}
|
|
24568
24886
|
var AcpRuntimeService = class {
|
|
24887
|
+
// Shared by every adapter below this ACP runtime Entry, including queued probes.
|
|
24888
|
+
#catalogAdmission = new AdmissionLimiter(2);
|
|
24569
24889
|
constructor(ctx) {
|
|
24570
24890
|
ctx.provide("acp", this);
|
|
24571
24891
|
}
|
|
24572
24892
|
register(consumer, adapter, config2) {
|
|
24573
24893
|
const storage = consumer.get("storage");
|
|
24574
24894
|
if (!storage) throw new Error("ACP continuity storage is unavailable");
|
|
24895
|
+
const directoryKey = `acp-catalog/${adapter.id}/${createHash("sha256").update(pluginIdentity(consumer).entryId).digest("hex")}`;
|
|
24575
24896
|
const provider = new AcpExecutor(adapter, config2, {
|
|
24576
|
-
state: pluginStateStore(storage, adapter.id)
|
|
24897
|
+
state: pluginStateStore(storage, adapter.id),
|
|
24898
|
+
catalogAdmission: this.#catalogAdmission,
|
|
24899
|
+
withCatalogDirectory: (signal, use) => storage.withScratchDirectory(directoryKey, signal, use)
|
|
24577
24900
|
});
|
|
24578
24901
|
consumer.effect(() => () => provider.dispose(), `acp.dispose(${JSON.stringify(adapter.id)})`);
|
|
24579
24902
|
return consumer.executors.register(provider);
|
|
@@ -24603,7 +24926,7 @@ function decodeContinuity(value) {
|
|
|
24603
24926
|
if (record2.version === 1) return "legacy";
|
|
24604
24927
|
if (record2.version !== 2 || typeof record2.cwd !== "string" || !isAbsolute2(record2.cwd) || typeof record2.binding !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(record2.binding) || !Number.isSafeInteger(record2.committedPrompts) || record2.committedPrompts < 0 || !["reserved", "established", "prompt_pending", "committed", "history_gap"].includes(
|
|
24605
24928
|
String(record2.phase)
|
|
24606
|
-
) || record2.sessionId !== void 0 && (typeof record2.sessionId !== "string" || !record2.sessionId || record2.sessionId.length > 4096) || record2.pendingTurnId !== void 0 && (typeof record2.pendingTurnId !== "string" || !record2.pendingTurnId) || record2.confirmedModel !== void 0 && (typeof record2.confirmedModel !== "string" || !record2.confirmedModel) || record2.phase === "reserved" && record2.sessionId !== void 0 || record2.phase !== "reserved" && !record2.sessionId || record2.phase === "prompt_pending" && !record2.pendingTurnId || record2.phase !== "prompt_pending" && record2.pendingTurnId !== void 0 || record2.gapEvidence !== void 0 && (record2.phase !== "history_gap" || !record2.gapEvidence || typeof record2.gapEvidence !== "object" || !Number.isSafeInteger(record2.gapEvidence.replayedUpdates) || !Number.isSafeInteger(record2.gapEvidence.replayedUserChunks) || record2.gapEvidence.replayedUpdates < 0 || record2.gapEvidence.replayedUserChunks < 0))
|
|
24929
|
+
) || record2.sessionId !== void 0 && (typeof record2.sessionId !== "string" || !record2.sessionId || record2.sessionId.length > 4096) || record2.pendingTurnId !== void 0 && (typeof record2.pendingTurnId !== "string" || !record2.pendingTurnId) || record2.confirmedModel !== void 0 && (typeof record2.confirmedModel !== "string" || !record2.confirmedModel) || record2.confirmedMode !== void 0 && (typeof record2.confirmedMode !== "string" || !record2.confirmedMode) || record2.phase === "reserved" && record2.sessionId !== void 0 || record2.phase !== "reserved" && !record2.sessionId || record2.phase === "prompt_pending" && !record2.pendingTurnId || record2.phase !== "prompt_pending" && record2.pendingTurnId !== void 0 || record2.gapEvidence !== void 0 && (record2.phase !== "history_gap" || !record2.gapEvidence || typeof record2.gapEvidence !== "object" || !Number.isSafeInteger(record2.gapEvidence.replayedUpdates) || !Number.isSafeInteger(record2.gapEvidence.replayedUserChunks) || record2.gapEvidence.replayedUpdates < 0 || record2.gapEvidence.replayedUserChunks < 0))
|
|
24607
24930
|
return "invalid";
|
|
24608
24931
|
return record2;
|
|
24609
24932
|
}
|