maka-agent 0.2.0-dev.53.20260927 → 0.2.0-dev.62.20260928
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/LICENSE +6 -5
- package/dist/workspace-root.js +2 -2
- 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/index.js +333 -28
- package/node_modules/@maka/acp-executor-plugin/dist/plugin.mjs +283 -27
- package/node_modules/@maka/core/dist/executor-catalog.js +10 -1
- package/node_modules/@maka/core/dist/message-queue-order.js +47 -0
- package/node_modules/@maka/core/dist/model-metadata.js +2 -1
- package/node_modules/@maka/core/dist/redaction.js +42 -3
- package/node_modules/@maka/core/dist/relative-time-policy.js +71 -0
- package/node_modules/@maka/core/dist/relative-time.js +3 -54
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/egress-audit.js +127 -0
- package/node_modules/@maka/eval/dist/harness-executor.js +16 -96
- package/node_modules/@maka/eval/harbor/egress-proxy/entrypoint.sh +4 -4
- package/node_modules/@maka/eval/harbor/egress_filter.py +153 -104
- package/node_modules/@maka/eval/harbor/eval_framework.py +37 -14
- package/node_modules/@maka/eval/harbor/relay_agent.py +4 -6
- package/node_modules/@maka/eval/harbor/run_trial.py +11 -4
- package/node_modules/@maka/runtime/dist/agent-graph-supervisor-wake.js +33 -6
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +1 -1
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +26 -5
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +36 -0
- package/node_modules/@maka/runtime/dist/provider-error-classification.js +8 -73
- package/node_modules/@maka/runtime/dist/provider-error-signals.js +31 -0
- package/node_modules/@maka/runtime/dist/provider-retry-policy.js +79 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +6 -4
- package/node_modules/@maka/runtime/dist/session-projection-helpers.js +2 -0
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +8 -8
- package/node_modules/@maka/runtime/dist/terminal-run-commit.js +7 -1
- package/node_modules/@maka/runtime/dist/tool-runtime.js +5 -4
- package/node_modules/@maka/runtime-host/dist/adapter/provider-retry-projector.js +63 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +7 -51
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -3
- package/node_modules/@maka/runtime-host/dist/protocol/message-queue-limits.js +21 -0
- package/node_modules/@maka/runtime-host/dist/protocol/message.js +6 -104
- package/node_modules/@maka/runtime-host/dist/protocol/queue-mutation.js +136 -0
- package/node_modules/@maka/runtime-host/dist/protocol/turn-provider-retry.js +69 -0
- package/node_modules/@maka/runtime-host/dist/protocol/turn.js +2 -43
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +42 -5
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +105 -233
- package/node_modules/@maka/runtime-host/dist/server/message-queue-state.js +69 -0
- package/node_modules/@maka/runtime-host/dist/server/provider-retry-projection.js +71 -0
- package/node_modules/@maka/runtime-host/dist/server/queued-mutation-executor.js +94 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +9 -58
- package/node_modules/@maka/storage/dist/agent-run-store-contract.js +0 -3
- package/node_modules/@maka/storage/dist/agent-run-store.js +15 -6
- package/node_modules/@maka/storage/dist/execution-persistence-provider.js +1 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +1 -0
- package/node_modules/@maka/storage/dist/project-catalog.js +41 -42
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +102 -31
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-schema.js +52 -1
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +34 -2
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
|
-
import { constants as constants2 } from "node:fs";
|
|
9
|
+
import { constants as constants2, createReadStream } from "node:fs";
|
|
10
10
|
import { access, mkdtemp, rm, realpath as realpath2, stat as stat2 } from "node:fs/promises";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { dirname as dirname2, isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
@@ -23915,17 +23915,52 @@ var AcpExecutor = class {
|
|
|
23915
23915
|
async inspectConversation(input2) {
|
|
23916
23916
|
const session = this.#sessions.get(input2.conversationKey);
|
|
23917
23917
|
if (this.#disposed) return this.#catalogEntry("unavailable");
|
|
23918
|
-
if (session
|
|
23919
|
-
return this.#catalogEntry("history_only");
|
|
23920
|
-
|
|
23918
|
+
if (session && session.cwd !== resolve2(input2.cwd))
|
|
23919
|
+
return this.#catalogEntry("history_only", [], input2.configuration?.model);
|
|
23920
|
+
if (session?.restoring)
|
|
23921
|
+
return this.#catalogEntry("restoring", session.configOptions, input2.configuration?.model);
|
|
23922
|
+
if (session?.restoreFailed)
|
|
23923
|
+
return this.#catalogEntry(
|
|
23924
|
+
"restore_failed",
|
|
23925
|
+
session.configOptions,
|
|
23926
|
+
input2.configuration?.model
|
|
23927
|
+
);
|
|
23928
|
+
if (session?.historyGap)
|
|
23929
|
+
return this.#catalogEntry("history_gap", session.configOptions, input2.configuration?.model);
|
|
23930
|
+
if (session && !session.lost)
|
|
23931
|
+
return this.#catalogEntry("ready", session.configOptions, input2.configuration?.model);
|
|
23932
|
+
if (session?.lost && !session.record)
|
|
23933
|
+
return this.#catalogEntry("history_only", session.configOptions, input2.configuration?.model);
|
|
23934
|
+
const stored = this.#state?.read ? decodeContinuity(await this.#state.read(input2.conversationKey)) : await this.#state?.has(input2.conversationKey, input2.cwd) ? "legacy" : void 0;
|
|
23935
|
+
if (!stored) return this.#catalogEntry("ready", [], input2.configuration?.model);
|
|
23936
|
+
if (stored === "invalid" || stored === "legacy" || stored.cwd !== resolve2(input2.cwd))
|
|
23937
|
+
return this.#catalogEntry("history_only", [], input2.configuration?.model);
|
|
23938
|
+
if (stored.phase === "reserved")
|
|
23939
|
+
return this.#catalogEntry("history_only", [], input2.configuration?.model);
|
|
23940
|
+
return this.#catalogEntry(
|
|
23941
|
+
stored.phase === "prompt_pending" || stored.phase === "history_gap" ? "history_gap" : "restorable",
|
|
23942
|
+
[],
|
|
23943
|
+
input2.configuration?.model ?? stored.confirmedModel
|
|
23944
|
+
);
|
|
23921
23945
|
}
|
|
23922
23946
|
async configureConversation(input2, signal) {
|
|
23923
|
-
|
|
23924
|
-
|
|
23925
|
-
|
|
23947
|
+
if (!input2.configuration?.model) throw new Error("ACP model change is unavailable");
|
|
23948
|
+
const session = await this.#session(input2);
|
|
23949
|
+
if (session.active || session.configuring) throw new Error("ACP model change is unavailable");
|
|
23926
23950
|
session.configuring = true;
|
|
23951
|
+
const wasConnected = !!session.connection;
|
|
23927
23952
|
try {
|
|
23953
|
+
await this.#ensureInitialized(session, signal);
|
|
23928
23954
|
await this.#applyInitialConfig(session, { model: input2.configuration.model }, signal, true);
|
|
23955
|
+
} catch (error62) {
|
|
23956
|
+
if (!wasConnected || session.lost) {
|
|
23957
|
+
await this.#lose(session);
|
|
23958
|
+
if (session.record?.sessionId && !session.historyGap) session.restoreFailed = true;
|
|
23959
|
+
const retryable = !session.acpSessionId && !session.continuityReserved && !session.record;
|
|
23960
|
+
if (retryable && this.#sessions.get(session.conversationKey) === session)
|
|
23961
|
+
this.#sessions.delete(session.conversationKey);
|
|
23962
|
+
}
|
|
23963
|
+
throw error62;
|
|
23929
23964
|
} finally {
|
|
23930
23965
|
session.configuring = false;
|
|
23931
23966
|
}
|
|
@@ -23934,12 +23969,15 @@ var AcpExecutor = class {
|
|
|
23934
23969
|
const model = options.find(
|
|
23935
23970
|
(option) => option.type === "select" && (option.category === "model" || option.id === "model")
|
|
23936
23971
|
);
|
|
23937
|
-
const models = model?.type === "select" ? model.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).map((entry) => ({ id: entry.value, name: entry.name })) : [];
|
|
23972
|
+
const models = model?.type === "select" ? model.options.flatMap((entry) => "options" in entry ? entry.options : [entry]).map((entry) => ({ id: entry.value, name: entry.name })) : this.#catalog?.models ?? [];
|
|
23938
23973
|
return {
|
|
23939
23974
|
id: this.id,
|
|
23940
23975
|
displayName: this.displayName,
|
|
23941
23976
|
readiness,
|
|
23942
|
-
...this.#adapter.describeModels?.(models) ?? { models }
|
|
23977
|
+
...model?.type === "select" ? this.#adapter.describeModels?.(models) ?? { models } : {
|
|
23978
|
+
models,
|
|
23979
|
+
...this.#catalog?.modelGroups ? { modelGroups: this.#catalog.modelGroups } : {}
|
|
23980
|
+
},
|
|
23943
23981
|
...model?.type === "select" ? { currentModel: model.currentValue } : selected ? { currentModel: selected } : {},
|
|
23944
23982
|
supportsAttachments: false,
|
|
23945
23983
|
supportsModelChange: model?.type === "select"
|
|
@@ -23959,11 +23997,11 @@ var AcpExecutor = class {
|
|
|
23959
23997
|
if (model) request = { ...request, configuration: { model } };
|
|
23960
23998
|
let session;
|
|
23961
23999
|
try {
|
|
23962
|
-
session = this.#session(request);
|
|
24000
|
+
session = await this.#session(request);
|
|
23963
24001
|
} catch (error62) {
|
|
23964
24002
|
return failure2(safeErrorMessage(error62), errorCode(error62));
|
|
23965
24003
|
}
|
|
23966
|
-
if (session.active || session.configuring)
|
|
24004
|
+
if (session.active || session.configuring || session.awaitingAck)
|
|
23967
24005
|
return failure2(`${this.displayName} ACP Session is busy`, "acp_busy", true);
|
|
23968
24006
|
const active = { context, tools: /* @__PURE__ */ new Map(), text: "" };
|
|
23969
24007
|
session.active = active;
|
|
@@ -23976,12 +24014,14 @@ var AcpExecutor = class {
|
|
|
23976
24014
|
{ model: request.configuration.model },
|
|
23977
24015
|
context.signal
|
|
23978
24016
|
);
|
|
24017
|
+
await this.#beginPrompt(session, request.turnId);
|
|
23979
24018
|
const prompt = session.connection.agent.request(methods.agent.session.prompt, {
|
|
23980
24019
|
sessionId: session.acpSessionId,
|
|
23981
24020
|
prompt: [{ type: "text", text: promptText(request) }]
|
|
23982
24021
|
});
|
|
23983
24022
|
const response = await this.#awaitPrompt(session, prompt, context.signal);
|
|
23984
24023
|
if (!response) return { status: "cancelled", reason: "timeout" };
|
|
24024
|
+
if (session.record) session.awaitingAck = request.turnId;
|
|
23985
24025
|
if (context.signal.aborted || response.stopReason === "cancelled") {
|
|
23986
24026
|
return { status: "cancelled", providerStopReason: response.stopReason };
|
|
23987
24027
|
}
|
|
@@ -23996,8 +24036,10 @@ var AcpExecutor = class {
|
|
|
23996
24036
|
}
|
|
23997
24037
|
return { status: "completed", text: active.text };
|
|
23998
24038
|
} catch (error62) {
|
|
24039
|
+
if (errorCode(error62) === "acp_history_gap") session.historyGap = true;
|
|
23999
24040
|
await this.#lose(session);
|
|
24000
|
-
|
|
24041
|
+
if (session.record?.sessionId && !session.historyGap) session.restoreFailed = true;
|
|
24042
|
+
const retryable = !session.acpSessionId && !session.continuityReserved && errorCode(error62) !== "acp_history_only" && errorCode(error62) !== "acp_history_gap";
|
|
24001
24043
|
if (retryable && this.#sessions.get(session.conversationKey) === session)
|
|
24002
24044
|
this.#sessions.delete(session.conversationKey);
|
|
24003
24045
|
if (context.signal.aborted) {
|
|
@@ -24027,18 +24069,23 @@ var AcpExecutor = class {
|
|
|
24027
24069
|
);
|
|
24028
24070
|
if (failures.length) throw new AggregateError(failures, "ACP process cleanup failed");
|
|
24029
24071
|
}
|
|
24030
|
-
#session(request) {
|
|
24072
|
+
async #session(request) {
|
|
24031
24073
|
const cwd = resolve2(request.cwd);
|
|
24032
24074
|
const existing = this.#sessions.get(request.conversationKey);
|
|
24033
24075
|
if (existing) {
|
|
24034
24076
|
if (existing.cwd !== cwd)
|
|
24035
24077
|
throw new AcpRuntimeError("ACP conversation cannot change workspace", "acp_cwd_changed");
|
|
24036
|
-
if (existing.lost)
|
|
24078
|
+
if (!existing.lost) return existing;
|
|
24079
|
+
if (existing.active || existing.configuring)
|
|
24080
|
+
throw new AcpRuntimeError("ACP Session is busy", "acp_busy");
|
|
24081
|
+
if (!existing.record)
|
|
24037
24082
|
throw new AcpRuntimeError(
|
|
24038
24083
|
"ACP conversation is history-only because its external process was lost",
|
|
24039
24084
|
"acp_history_only"
|
|
24040
24085
|
);
|
|
24041
|
-
|
|
24086
|
+
await existing.loss;
|
|
24087
|
+
if (this.#sessions.get(request.conversationKey) !== existing) return this.#session(request);
|
|
24088
|
+
this.#sessions.delete(request.conversationKey);
|
|
24042
24089
|
}
|
|
24043
24090
|
const created = {
|
|
24044
24091
|
conversationKey: request.conversationKey,
|
|
@@ -24058,20 +24105,40 @@ var AcpExecutor = class {
|
|
|
24058
24105
|
await initialization;
|
|
24059
24106
|
} catch (error62) {
|
|
24060
24107
|
session.initialization = void 0;
|
|
24108
|
+
session.restoring = false;
|
|
24109
|
+
session.replay = void 0;
|
|
24061
24110
|
throw error62;
|
|
24062
24111
|
}
|
|
24063
24112
|
}
|
|
24064
24113
|
async #initialize(session, signal, probe = false) {
|
|
24065
|
-
if (!probe && await this.#state?.has(session.conversationKey, session.cwd)) {
|
|
24066
|
-
throw new AcpRuntimeError(
|
|
24067
|
-
"ACP conversation is history-only after the Plugin or Host was restarted",
|
|
24068
|
-
"acp_history_only"
|
|
24069
|
-
);
|
|
24070
|
-
}
|
|
24071
24114
|
const timeout = AbortSignal.timeout(INITIALIZE_TIMEOUT_MS);
|
|
24072
24115
|
const startupSignal = AbortSignal.any([signal, timeout]);
|
|
24073
24116
|
startupSignal.throwIfAborted();
|
|
24074
24117
|
const launch = this.#configured.launch;
|
|
24118
|
+
const stored = probe ? void 0 : this.#state?.read ? decodeContinuity(await this.#state.read(session.conversationKey)) : await this.#state?.has(session.conversationKey, session.cwd) ? "legacy" : void 0;
|
|
24119
|
+
if (stored === "legacy")
|
|
24120
|
+
throw new AcpRuntimeError(
|
|
24121
|
+
"ACP conversation is history-only after the Plugin or Host was restarted",
|
|
24122
|
+
"acp_history_only"
|
|
24123
|
+
);
|
|
24124
|
+
if (stored === "invalid" || stored && stored.cwd !== session.cwd || stored?.phase === "reserved")
|
|
24125
|
+
throw new AcpRuntimeError(
|
|
24126
|
+
"ACP conversation has no recoverable external Session identity",
|
|
24127
|
+
"acp_history_only"
|
|
24128
|
+
);
|
|
24129
|
+
if (stored?.phase === "history_gap")
|
|
24130
|
+
throw new AcpRuntimeError(
|
|
24131
|
+
"External Session history cannot be aligned with saved conversation events",
|
|
24132
|
+
"acp_history_gap"
|
|
24133
|
+
);
|
|
24134
|
+
if (stored) {
|
|
24135
|
+
session.record = stored;
|
|
24136
|
+
session.acpSessionId = stored.sessionId;
|
|
24137
|
+
session.restoring = true;
|
|
24138
|
+
}
|
|
24139
|
+
const binding = !probe && this.#state?.write ? await launchBinding(this.id, launch, startupSignal) : void 0;
|
|
24140
|
+
if (stored && stored.binding !== binding)
|
|
24141
|
+
throw new AcpRuntimeError("ACP Agent installation changed", "acp_restore_identity_changed");
|
|
24075
24142
|
const executable = await checkedExecutable(launch.executable);
|
|
24076
24143
|
await Promise.all((launch.requiredExecutables ?? []).map(checkedExecutable));
|
|
24077
24144
|
const owner = this.#createConnection({
|
|
@@ -24101,9 +24168,62 @@ var AcpExecutor = class {
|
|
|
24101
24168
|
owner.failed
|
|
24102
24169
|
]);
|
|
24103
24170
|
if (initialized.protocolVersion !== 1) throw new Error("Unsupported ACP protocol version");
|
|
24171
|
+
if (stored) {
|
|
24172
|
+
session.replay = { updates: 0, userChunks: 0 };
|
|
24173
|
+
const pending = stored.phase === "prompt_pending";
|
|
24174
|
+
const supported = pending ? initialized.agentCapabilities?.loadSession : initialized.agentCapabilities?.sessionCapabilities?.resume;
|
|
24175
|
+
if (!supported)
|
|
24176
|
+
throw new AcpRuntimeError(
|
|
24177
|
+
"ACP Agent cannot restore this Session",
|
|
24178
|
+
"acp_restore_unsupported"
|
|
24179
|
+
);
|
|
24180
|
+
const restored = await Promise.race([
|
|
24181
|
+
owner.connection.agent.request(
|
|
24182
|
+
pending ? methods.agent.session.load : methods.agent.session.resume,
|
|
24183
|
+
{ sessionId: stored.sessionId, cwd: session.cwd, mcpServers: [] },
|
|
24184
|
+
{ cancellationSignal: startupSignal }
|
|
24185
|
+
),
|
|
24186
|
+
owner.failed
|
|
24187
|
+
]);
|
|
24188
|
+
session.configOptions = restored.configOptions ?? [];
|
|
24189
|
+
const restoredModel = currentAcpModel(session.configOptions);
|
|
24190
|
+
if (restoredModel) await this.#persistConfirmedModel(session, restoredModel);
|
|
24191
|
+
session.restoring = false;
|
|
24192
|
+
if (pending) {
|
|
24193
|
+
session.historyGap = true;
|
|
24194
|
+
session.record = {
|
|
24195
|
+
...session.record,
|
|
24196
|
+
phase: "history_gap",
|
|
24197
|
+
pendingTurnId: void 0,
|
|
24198
|
+
gapEvidence: {
|
|
24199
|
+
replayedUpdates: session.replay?.updates ?? 0,
|
|
24200
|
+
replayedUserChunks: session.replay?.userChunks ?? 0
|
|
24201
|
+
}
|
|
24202
|
+
};
|
|
24203
|
+
await this.#state?.write?.(session.conversationKey, session.record);
|
|
24204
|
+
session.replay = void 0;
|
|
24205
|
+
throw new AcpRuntimeError(
|
|
24206
|
+
"External Session was restored, but conversation history may have a gap",
|
|
24207
|
+
"acp_history_gap"
|
|
24208
|
+
);
|
|
24209
|
+
}
|
|
24210
|
+
session.replay = void 0;
|
|
24211
|
+
return;
|
|
24212
|
+
}
|
|
24104
24213
|
if (!probe) {
|
|
24105
24214
|
startupSignal.throwIfAborted();
|
|
24106
|
-
|
|
24215
|
+
if (this.#state?.write && binding) {
|
|
24216
|
+
session.record = {
|
|
24217
|
+
version: 2,
|
|
24218
|
+
cwd: session.cwd,
|
|
24219
|
+
binding,
|
|
24220
|
+
phase: "reserved",
|
|
24221
|
+
committedPrompts: 0
|
|
24222
|
+
};
|
|
24223
|
+
await this.#state.write(session.conversationKey, session.record);
|
|
24224
|
+
} else {
|
|
24225
|
+
await this.#state?.mark(session.conversationKey, session.cwd);
|
|
24226
|
+
}
|
|
24107
24227
|
session.continuityReserved = true;
|
|
24108
24228
|
}
|
|
24109
24229
|
const created = await Promise.race([
|
|
@@ -24116,6 +24236,17 @@ var AcpExecutor = class {
|
|
|
24116
24236
|
]);
|
|
24117
24237
|
session.acpSessionId = created.sessionId;
|
|
24118
24238
|
session.configOptions = created.configOptions ?? [];
|
|
24239
|
+
if (session.record) {
|
|
24240
|
+
const established = {
|
|
24241
|
+
...session.record,
|
|
24242
|
+
phase: "established",
|
|
24243
|
+
sessionId: created.sessionId
|
|
24244
|
+
};
|
|
24245
|
+
await this.#state?.write?.(session.conversationKey, established);
|
|
24246
|
+
session.record = established;
|
|
24247
|
+
const createdModel = currentAcpModel(session.configOptions);
|
|
24248
|
+
if (createdModel) await this.#persistConfirmedModel(session, createdModel);
|
|
24249
|
+
}
|
|
24119
24250
|
if (!probe) {
|
|
24120
24251
|
await this.#applyInitialConfig(
|
|
24121
24252
|
session,
|
|
@@ -24124,6 +24255,55 @@ var AcpExecutor = class {
|
|
|
24124
24255
|
);
|
|
24125
24256
|
}
|
|
24126
24257
|
}
|
|
24258
|
+
async #beginPrompt(session, turnId) {
|
|
24259
|
+
if (!session.record) return;
|
|
24260
|
+
const pending = {
|
|
24261
|
+
...session.record,
|
|
24262
|
+
phase: "prompt_pending",
|
|
24263
|
+
pendingTurnId: turnId
|
|
24264
|
+
};
|
|
24265
|
+
await this.#state?.write?.(session.conversationKey, pending);
|
|
24266
|
+
session.record = pending;
|
|
24267
|
+
}
|
|
24268
|
+
/** Called only after the Runtime Kernel has durably accepted the terminal event. */
|
|
24269
|
+
async acknowledgeExecution(conversationKey, turnId) {
|
|
24270
|
+
const session = this.#sessions.get(conversationKey);
|
|
24271
|
+
if (!session?.record || session.awaitingAck !== turnId || session.record.phase !== "prompt_pending" || session.record.pendingTurnId !== turnId)
|
|
24272
|
+
return;
|
|
24273
|
+
const committed = {
|
|
24274
|
+
...session.record,
|
|
24275
|
+
phase: "committed",
|
|
24276
|
+
committedPrompts: session.record.committedPrompts + 1,
|
|
24277
|
+
pendingTurnId: void 0
|
|
24278
|
+
};
|
|
24279
|
+
try {
|
|
24280
|
+
await this.#state?.write?.(conversationKey, committed);
|
|
24281
|
+
} catch (error62) {
|
|
24282
|
+
session.historyGap = true;
|
|
24283
|
+
await this.#lose(session);
|
|
24284
|
+
throw error62;
|
|
24285
|
+
}
|
|
24286
|
+
session.record = committed;
|
|
24287
|
+
session.awaitingAck = void 0;
|
|
24288
|
+
}
|
|
24289
|
+
/** The external turn settled, but Maka did not durably consume its terminal event. */
|
|
24290
|
+
async abandonExecution(conversationKey, turnId) {
|
|
24291
|
+
const session = this.#sessions.get(conversationKey);
|
|
24292
|
+
if (!session?.record || session.awaitingAck !== turnId || session.record.phase !== "prompt_pending" || session.record.pendingTurnId !== turnId)
|
|
24293
|
+
return;
|
|
24294
|
+
session.historyGap = true;
|
|
24295
|
+
session.awaitingAck = void 0;
|
|
24296
|
+
session.record = {
|
|
24297
|
+
...session.record,
|
|
24298
|
+
phase: "history_gap",
|
|
24299
|
+
pendingTurnId: void 0
|
|
24300
|
+
};
|
|
24301
|
+
try {
|
|
24302
|
+
await this.#state?.write?.(conversationKey, session.record);
|
|
24303
|
+
} finally {
|
|
24304
|
+
await this.#lose(session);
|
|
24305
|
+
}
|
|
24306
|
+
}
|
|
24127
24307
|
async #applyInitialConfig(session, values, signal, restoreOnFailure = false) {
|
|
24128
24308
|
for (const [key, value] of Object.entries(values)) {
|
|
24129
24309
|
const option = session.configOptions.find(
|
|
@@ -24142,7 +24322,10 @@ var AcpExecutor = class {
|
|
|
24142
24322
|
`ACP configuration value is unavailable: ${key}`,
|
|
24143
24323
|
"acp_config_invalid"
|
|
24144
24324
|
);
|
|
24145
|
-
if (option.currentValue === value)
|
|
24325
|
+
if (option.currentValue === value) {
|
|
24326
|
+
if (key === "model") await this.#persistConfirmedModel(session, value);
|
|
24327
|
+
continue;
|
|
24328
|
+
}
|
|
24146
24329
|
signal.throwIfAborted();
|
|
24147
24330
|
try {
|
|
24148
24331
|
const updated = await session.connection.agent.request(
|
|
@@ -24157,6 +24340,7 @@ var AcpExecutor = class {
|
|
|
24157
24340
|
"acp_config_unconfirmed"
|
|
24158
24341
|
);
|
|
24159
24342
|
session.configOptions = updated.configOptions;
|
|
24343
|
+
if (key === "model") await this.#persistConfirmedModel(session, value);
|
|
24160
24344
|
} catch (error62) {
|
|
24161
24345
|
let restored = false;
|
|
24162
24346
|
if (restoreOnFailure && !session.lost && !signal.aborted) {
|
|
@@ -24171,6 +24355,7 @@ var AcpExecutor = class {
|
|
|
24171
24355
|
);
|
|
24172
24356
|
if (confirmed?.type === "select" && confirmed.currentValue === option.currentValue && !session.lost) {
|
|
24173
24357
|
session.configOptions = rollback.configOptions;
|
|
24358
|
+
if (key === "model") await this.#persistConfirmedModel(session, option.currentValue);
|
|
24174
24359
|
restored = true;
|
|
24175
24360
|
}
|
|
24176
24361
|
} catch {
|
|
@@ -24181,16 +24366,22 @@ var AcpExecutor = class {
|
|
|
24181
24366
|
}
|
|
24182
24367
|
}
|
|
24183
24368
|
}
|
|
24369
|
+
async #persistConfirmedModel(session, model) {
|
|
24370
|
+
if (!session.record || session.record.confirmedModel === model) return;
|
|
24371
|
+
const record2 = { ...session.record, confirmedModel: model };
|
|
24372
|
+
await this.#state?.write?.(session.conversationKey, record2);
|
|
24373
|
+
session.record = record2;
|
|
24374
|
+
}
|
|
24184
24375
|
#configureClient(session, app) {
|
|
24185
24376
|
app.onNotification(methods.client.session.update, ({ params }) => {
|
|
24186
24377
|
if (params.sessionId === session.acpSessionId) this.#acceptUpdate(session, params.update);
|
|
24187
24378
|
}).onRequest(methods.client.fs.readTextFile, async ({ params }) => {
|
|
24188
|
-
this.#
|
|
24379
|
+
this.#assertWorkspaceAccess(session, params.sessionId);
|
|
24189
24380
|
return {
|
|
24190
24381
|
content: await readWorkspaceTextFile(session.cwd, params.path, params.line, params.limit)
|
|
24191
24382
|
};
|
|
24192
24383
|
}).onRequest(methods.client.fs.writeTextFile, async ({ params }) => {
|
|
24193
|
-
this.#
|
|
24384
|
+
this.#assertWorkspaceAccess(session, params.sessionId);
|
|
24194
24385
|
await writeWorkspaceTextFile(session.cwd, params.path, params.content);
|
|
24195
24386
|
return {};
|
|
24196
24387
|
}).onRequest(
|
|
@@ -24200,6 +24391,8 @@ var AcpExecutor = class {
|
|
|
24200
24391
|
}
|
|
24201
24392
|
async #requestPermission(session, request) {
|
|
24202
24393
|
this.#assertSession(session, request.sessionId);
|
|
24394
|
+
if (session.restoring || session.historyGap || session.lost)
|
|
24395
|
+
return { outcome: { outcome: "cancelled" } };
|
|
24203
24396
|
const active = session.active;
|
|
24204
24397
|
if (!active) return { outcome: { outcome: "cancelled" } };
|
|
24205
24398
|
const outcome = await active.context.requestPermission({
|
|
@@ -24211,6 +24404,14 @@ var AcpExecutor = class {
|
|
|
24211
24404
|
return { outcome };
|
|
24212
24405
|
}
|
|
24213
24406
|
#acceptUpdate(session, update) {
|
|
24407
|
+
if (session.restoring) {
|
|
24408
|
+
if (session.replay) {
|
|
24409
|
+
session.replay.updates++;
|
|
24410
|
+
if (update.sessionUpdate === "user_message_chunk") session.replay.userChunks++;
|
|
24411
|
+
}
|
|
24412
|
+
return;
|
|
24413
|
+
}
|
|
24414
|
+
if (session.historyGap || session.lost) return;
|
|
24214
24415
|
if (update.sessionUpdate === "config_option_update") {
|
|
24215
24416
|
if (!session.configuring && !session.lost) session.configOptions = update.configOptions;
|
|
24216
24417
|
return;
|
|
@@ -24229,6 +24430,15 @@ var AcpExecutor = class {
|
|
|
24229
24430
|
if (update.sessionUpdate === "tool_call") this.#acceptTool(active, update);
|
|
24230
24431
|
if (update.sessionUpdate === "tool_call_update") this.#acceptTool(active, update);
|
|
24231
24432
|
}
|
|
24433
|
+
#assertWorkspaceAccess(session, sessionId) {
|
|
24434
|
+
this.#assertSession(session, sessionId);
|
|
24435
|
+
if (session.restoring || session.historyGap || session.lost) {
|
|
24436
|
+
throw new AcpRuntimeError(
|
|
24437
|
+
"ACP filesystem access is unavailable while Session history is untrusted",
|
|
24438
|
+
"acp_history_gap"
|
|
24439
|
+
);
|
|
24440
|
+
}
|
|
24441
|
+
}
|
|
24232
24442
|
#acceptTool(active, update) {
|
|
24233
24443
|
const snapshot = active.tools.get(update.toolCallId) ?? {
|
|
24234
24444
|
id: update.toolCallId,
|
|
@@ -24327,6 +24537,12 @@ var AcpExecutor = class {
|
|
|
24327
24537
|
if (owner) await owner.dispose();
|
|
24328
24538
|
}
|
|
24329
24539
|
};
|
|
24540
|
+
function currentAcpModel(options) {
|
|
24541
|
+
const option = options.find(
|
|
24542
|
+
(candidate) => candidate.type === "select" && (candidate.id === "model" || candidate.category === "model")
|
|
24543
|
+
);
|
|
24544
|
+
return option?.type === "select" ? option.currentValue : void 0;
|
|
24545
|
+
}
|
|
24330
24546
|
function toolTextContent(content) {
|
|
24331
24547
|
return content.flatMap(
|
|
24332
24548
|
(item) => item.type === "content" && item.content.type === "text" ? [item.content.text] : []
|
|
@@ -24350,14 +24566,54 @@ function pluginStateStore(storage, executorId) {
|
|
|
24350
24566
|
const key = (conversationKey) => `acp/${executorId}/${createHash("sha256").update(conversationKey).digest("hex")}`;
|
|
24351
24567
|
return {
|
|
24352
24568
|
async has(conversationKey) {
|
|
24353
|
-
|
|
24354
|
-
return value?.version === 1;
|
|
24569
|
+
return (await storage.get(key(conversationKey))).value !== void 0;
|
|
24355
24570
|
},
|
|
24356
24571
|
async mark(conversationKey, cwd) {
|
|
24357
24572
|
await storage.set(key(conversationKey), { version: 1, cwd });
|
|
24573
|
+
},
|
|
24574
|
+
async read(conversationKey) {
|
|
24575
|
+
return (await storage.get(key(conversationKey))).value;
|
|
24576
|
+
},
|
|
24577
|
+
async write(conversationKey, state) {
|
|
24578
|
+
await storage.set(key(conversationKey), state);
|
|
24358
24579
|
}
|
|
24359
24580
|
};
|
|
24360
24581
|
}
|
|
24582
|
+
function decodeContinuity(value) {
|
|
24583
|
+
if (value === void 0) return void 0;
|
|
24584
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "invalid";
|
|
24585
|
+
const record2 = value;
|
|
24586
|
+
if (record2.version === 1) return "legacy";
|
|
24587
|
+
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(
|
|
24588
|
+
String(record2.phase)
|
|
24589
|
+
) || 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))
|
|
24590
|
+
return "invalid";
|
|
24591
|
+
return record2;
|
|
24592
|
+
}
|
|
24593
|
+
async function launchBinding(adapterId, launch, signal) {
|
|
24594
|
+
const paths = [launch.executable, ...launch.requiredExecutables ?? []];
|
|
24595
|
+
const files = [];
|
|
24596
|
+
for (const path of paths) {
|
|
24597
|
+
signal.throwIfAborted();
|
|
24598
|
+
const resolved = await checkedExecutable(path);
|
|
24599
|
+
const hash2 = createHash("sha256");
|
|
24600
|
+
for await (const chunk of createReadStream(resolved)) {
|
|
24601
|
+
signal.throwIfAborted();
|
|
24602
|
+
hash2.update(chunk);
|
|
24603
|
+
}
|
|
24604
|
+
files.push({ path: resolved, digest: hash2.digest("hex") });
|
|
24605
|
+
}
|
|
24606
|
+
return `sha256:${createHash("sha256").update(
|
|
24607
|
+
JSON.stringify({
|
|
24608
|
+
adapterId,
|
|
24609
|
+
files,
|
|
24610
|
+
args: launch.args ?? [],
|
|
24611
|
+
cwd: launch.cwd ?? dirname2(files[0].path),
|
|
24612
|
+
platform: process.platform,
|
|
24613
|
+
arch: process.arch
|
|
24614
|
+
})
|
|
24615
|
+
).digest("hex")}`;
|
|
24616
|
+
}
|
|
24361
24617
|
function validateAdapter(adapter) {
|
|
24362
24618
|
if (!adapter || typeof adapter !== "object" || typeof adapter.id !== "string" || !/^[a-z][a-z0-9]*(?:[-_.][a-z0-9]+)*$/u.test(adapter.id) || typeof adapter.displayName !== "string" || !adapter.displayName.trim() || adapter.clientName !== void 0 && (typeof adapter.clientName !== "string" || !adapter.clientName.trim()) || typeof adapter.configure !== "function") {
|
|
24363
24619
|
throw new TypeError("Invalid ACP Agent adapter");
|
|
@@ -35,7 +35,16 @@ export function normalizeCatalogEntry(value, id) {
|
|
|
35
35
|
!isExecutorId(id) ||
|
|
36
36
|
value.id !== id ||
|
|
37
37
|
!isCatalogText(value.displayName) ||
|
|
38
|
-
![
|
|
38
|
+
![
|
|
39
|
+
'ready',
|
|
40
|
+
'unavailable',
|
|
41
|
+
'authentication_required',
|
|
42
|
+
'history_only',
|
|
43
|
+
'restorable',
|
|
44
|
+
'restoring',
|
|
45
|
+
'restore_failed',
|
|
46
|
+
'history_gap',
|
|
47
|
+
].includes(value.readiness) ||
|
|
39
48
|
!Array.isArray(value.models) ||
|
|
40
49
|
value.models.length > 256 ||
|
|
41
50
|
!Array.from(value.models).every((model) => model &&
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
export function exactQueueReorder(current, requestedEntryIds) {
|
|
20
|
+
if (requestedEntryIds.length !== current.length)
|
|
21
|
+
return undefined;
|
|
22
|
+
const remaining = new Map(current.map((entry) => [entry.entryId, entry]));
|
|
23
|
+
if (remaining.size !== current.length)
|
|
24
|
+
return undefined;
|
|
25
|
+
const entries = [];
|
|
26
|
+
for (const entryId of requestedEntryIds) {
|
|
27
|
+
const entry = remaining.get(entryId);
|
|
28
|
+
if (!entry)
|
|
29
|
+
return undefined;
|
|
30
|
+
remaining.delete(entryId);
|
|
31
|
+
entries.push(entry);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
entries,
|
|
35
|
+
changed: entries.some((entry, index) => current[index] !== entry),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function moveQueueEntryId(currentEntryIds, sourceEntryId, targetEntryId) {
|
|
39
|
+
const sourceIndex = currentEntryIds.indexOf(sourceEntryId);
|
|
40
|
+
const targetIndex = currentEntryIds.indexOf(targetEntryId);
|
|
41
|
+
if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex)
|
|
42
|
+
return undefined;
|
|
43
|
+
const entries = [...currentEntryIds];
|
|
44
|
+
entries.splice(sourceIndex, 1);
|
|
45
|
+
entries.splice(targetIndex, 0, sourceEntryId);
|
|
46
|
+
return entries;
|
|
47
|
+
}
|
|
@@ -137,7 +137,8 @@ export function lookupModelRuntimeOverride(providerType, modelId) {
|
|
|
137
137
|
export function openAiAdapterApiProtocol(modelId, providerType) {
|
|
138
138
|
const id = modelId.trim();
|
|
139
139
|
return (providerType === 'deepseek' && deepSeekModelSupportsResponses(id)) ||
|
|
140
|
-
(providerType === 'opencode-go' &&
|
|
140
|
+
(providerType === 'opencode-go' &&
|
|
141
|
+
(id === 'muse-spark-1.2-contributor' || id === 'muse-spark-1.3-contributor')) ||
|
|
141
142
|
((providerType === 'alibaba-token-plan-cn' || providerType === 'alibaba-token-plan') &&
|
|
142
143
|
id === 'qwen3.8-max') ||
|
|
143
144
|
/^gpt-[56]/i.test(id) ||
|
|
@@ -36,7 +36,15 @@ const AWS_CONFIG_SECRET_KEY_SOURCE = posixContinuedTokenSource('aws_secret_acces
|
|
|
36
36
|
const AWS_SECRET_ACCESS_KEY_FLAG_SOURCE = posixContinuedTokenSource('--secret-access-key');
|
|
37
37
|
const AWS_SECRET_ACCESS_KEY_ENV_SOURCE = posixContinuedTokenSource('AWS_SECRET_ACCESS_KEY');
|
|
38
38
|
const QUOTED_SECRET_KEY_VALUE_PATTERN = /((?:"([^"\\]+)"\s*:\s*"))(?:\\.|[^"\\])*/g;
|
|
39
|
-
|
|
39
|
+
// The prefix lookahead and the value pattern share this source, so the sticky
|
|
40
|
+
// value pattern always matches where a prefix ends.
|
|
41
|
+
const ASSIGNED_SECRET_VALUE_CHARACTER_SOURCE = `${POSIX_LINE_CONTINUATION_SOURCE}|[^\\s"'&<>]`;
|
|
42
|
+
// The prefix matches a whole key-character run once, and the key starts at the
|
|
43
|
+
// run's first word-initial letter. Trying each such letter as its own start
|
|
44
|
+
// would rescan a long hyphenated run (base64url) once per hyphen.
|
|
45
|
+
const ASSIGNED_SECRET_PREFIX_PATTERN = new RegExp(`(?<![A-Za-z0-9_-])([A-Za-z0-9_-]+)${OPTIONAL_SHELL_SEPARATOR_SOURCE}[:=]${OPTIONAL_SHELL_SEPARATOR_SOURCE}['"]?(?=${ASSIGNED_SECRET_VALUE_CHARACTER_SOURCE})`, 'g');
|
|
46
|
+
const ASSIGNED_SECRET_KEY_PATTERN = /(?<![A-Za-z0-9_])[A-Za-z][A-Za-z0-9_-]*/;
|
|
47
|
+
const ASSIGNED_SECRET_VALUE_PATTERN = new RegExp(`(?:${ASSIGNED_SECRET_VALUE_CHARACTER_SOURCE})+`, 'y');
|
|
40
48
|
const AUTHORIZATION_HEADER_PATTERN = /(^|[^A-Za-z0-9_])(['"]?(?:proxy[-_]?authorization|authorization)['"]?\s*:\s*['"]?(?:bearer|basic|token)\s+)[^\s"'<>]+/gim;
|
|
41
49
|
const AWS_CLI_SPACE_SECRET_PATTERN = new RegExp(`(^|[\\s;&|()])((?:aws${SHELL_SEPARATOR_SOURCE}configure${SHELL_SEPARATOR_SOURCE}set${SHELL_SEPARATOR_SOURCE}${AWS_CONFIG_SECRET_KEY_SOURCE}|${AWS_SECRET_ACCESS_KEY_FLAG_SOURCE})${SHELL_SEPARATOR_SOURCE})${SHELL_SECRET_TOKEN_SOURCE}`, 'gm');
|
|
42
50
|
const AWS_SECRET_ASSIGNMENT_PATTERN = new RegExp(`\\b(${AWS_SECRET_ACCESS_KEY_ENV_SOURCE}${OPTIONAL_SHELL_SEPARATOR_SOURCE}[:=]${OPTIONAL_SHELL_SEPARATOR_SOURCE}['"]?)(?:${POSIX_LINE_CONTINUATION_SOURCE}|[^\\s"'&<>])+`, 'gi');
|
|
@@ -59,7 +67,7 @@ function redactTextSecrets(value) {
|
|
|
59
67
|
next = next.replace(AUTHORIZATION_HEADER_PATTERN, (_match, boundary, prefix) => `${boundary}${prefix}[redacted]`);
|
|
60
68
|
next = next.replace(AWS_CLI_SPACE_SECRET_PATTERN, (_match, boundary, prefix, token) => `${boundary}${prefix}${redactShellToken(token)}`);
|
|
61
69
|
next = next.replace(AWS_SECRET_ASSIGNMENT_PATTERN, (_match, prefix) => `${prefix}[redacted]`);
|
|
62
|
-
next = next
|
|
70
|
+
next = redactAssignedSecrets(next);
|
|
63
71
|
for (const pattern of SECRET_PATTERNS) {
|
|
64
72
|
// Each pattern's single capture group matches only the secret token, so the
|
|
65
73
|
// replacement is always the full redaction marker. Never echo any part of
|
|
@@ -69,6 +77,34 @@ function redactTextSecrets(value) {
|
|
|
69
77
|
}
|
|
70
78
|
return next;
|
|
71
79
|
}
|
|
80
|
+
function redactAssignedSecrets(value) {
|
|
81
|
+
let next = '';
|
|
82
|
+
let copied = 0;
|
|
83
|
+
ASSIGNED_SECRET_PREFIX_PATTERN.lastIndex = 0;
|
|
84
|
+
for (let match = ASSIGNED_SECRET_PREFIX_PATTERN.exec(value); match; match = ASSIGNED_SECRET_PREFIX_PATTERN.exec(value)) {
|
|
85
|
+
// The prefix stops where the value starts, so every value is still searched
|
|
86
|
+
// for a nested sensitive assignment (`excerpt: password=…`). This includes a
|
|
87
|
+
// redacted value: a key with an empty value takes the next `KEY=` as its
|
|
88
|
+
// value (`token= password="…"`), and that key's own value follows the quote.
|
|
89
|
+
const key = ASSIGNED_SECRET_KEY_PATTERN.exec(match[1] ?? '')?.[0] ?? '';
|
|
90
|
+
if (!isAssignmentSensitiveKey(key))
|
|
91
|
+
continue;
|
|
92
|
+
const valueStart = ASSIGNED_SECRET_PREFIX_PATTERN.lastIndex;
|
|
93
|
+
// A value that starts inside the last redacted value ends with it.
|
|
94
|
+
if (valueStart < copied)
|
|
95
|
+
continue;
|
|
96
|
+
ASSIGNED_SECRET_VALUE_PATTERN.lastIndex = valueStart;
|
|
97
|
+
const valueMatch = ASSIGNED_SECRET_VALUE_PATTERN.exec(value);
|
|
98
|
+
// The prefix lookahead promises a value here. Should the two patterns ever
|
|
99
|
+
// disagree, skip: a failed sticky match resets lastIndex, and copying from
|
|
100
|
+
// there would echo the value after its marker.
|
|
101
|
+
if (!valueMatch)
|
|
102
|
+
continue;
|
|
103
|
+
next += `${value.slice(copied, valueStart)}[redacted]`;
|
|
104
|
+
copied = valueStart + valueMatch[0].length;
|
|
105
|
+
}
|
|
106
|
+
return next + value.slice(copied);
|
|
107
|
+
}
|
|
72
108
|
function posixContinuedTokenSource(token) {
|
|
73
109
|
return [...token]
|
|
74
110
|
.map((character) => escapeRegExpLiteral(character))
|
|
@@ -173,9 +209,12 @@ export function isSensitiveKey(key) {
|
|
|
173
209
|
return qualifiedKey === 'service_account_key' || qualifiedKey === 'secret_access_key';
|
|
174
210
|
}
|
|
175
211
|
function sensitiveKeySegments(key) {
|
|
212
|
+
// The second split marks one capital per step, which keeps a long uppercase
|
|
213
|
+
// run (zero-filled base64) linear; `([A-Z]+)([A-Z][a-z])` backtracks through
|
|
214
|
+
// the run from every capital.
|
|
176
215
|
return key
|
|
177
216
|
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
178
|
-
.replace(/([A-Z]
|
|
217
|
+
.replace(/([A-Z])(?=[A-Z][a-z])/g, '$1 ')
|
|
179
218
|
.toLowerCase()
|
|
180
219
|
.split(/[^a-z0-9]+/)
|
|
181
220
|
.filter(Boolean);
|