@aiden-ade/sandbox-agent 0.1.82 → 0.1.83
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/dist/index.cjs +509 -205
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1477,30 +1477,30 @@ var require_permessage_deflate = __commonJS({
|
|
|
1477
1477
|
*/
|
|
1478
1478
|
acceptAsServer(offers) {
|
|
1479
1479
|
const opts = this._options;
|
|
1480
|
-
const
|
|
1480
|
+
const accepted2 = offers.find((params) => {
|
|
1481
1481
|
if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
|
|
1482
1482
|
return false;
|
|
1483
1483
|
}
|
|
1484
1484
|
return true;
|
|
1485
1485
|
});
|
|
1486
|
-
if (!
|
|
1486
|
+
if (!accepted2) {
|
|
1487
1487
|
throw new Error("None of the extension offers can be accepted");
|
|
1488
1488
|
}
|
|
1489
1489
|
if (opts.serverNoContextTakeover) {
|
|
1490
|
-
|
|
1490
|
+
accepted2.server_no_context_takeover = true;
|
|
1491
1491
|
}
|
|
1492
1492
|
if (opts.clientNoContextTakeover) {
|
|
1493
|
-
|
|
1493
|
+
accepted2.client_no_context_takeover = true;
|
|
1494
1494
|
}
|
|
1495
1495
|
if (typeof opts.serverMaxWindowBits === "number") {
|
|
1496
|
-
|
|
1496
|
+
accepted2.server_max_window_bits = opts.serverMaxWindowBits;
|
|
1497
1497
|
}
|
|
1498
1498
|
if (typeof opts.clientMaxWindowBits === "number") {
|
|
1499
|
-
|
|
1500
|
-
} else if (
|
|
1501
|
-
delete
|
|
1499
|
+
accepted2.client_max_window_bits = opts.clientMaxWindowBits;
|
|
1500
|
+
} else if (accepted2.client_max_window_bits === true || opts.clientMaxWindowBits === false) {
|
|
1501
|
+
delete accepted2.client_max_window_bits;
|
|
1502
1502
|
}
|
|
1503
|
-
return
|
|
1503
|
+
return accepted2;
|
|
1504
1504
|
}
|
|
1505
1505
|
/**
|
|
1506
1506
|
* Accept the extension negotiation response.
|
|
@@ -15240,7 +15240,7 @@ function describeError(error61) {
|
|
|
15240
15240
|
}
|
|
15241
15241
|
|
|
15242
15242
|
// src/version.ts
|
|
15243
|
-
var AGENT_VERSION = "0.1.
|
|
15243
|
+
var AGENT_VERSION = "0.1.83";
|
|
15244
15244
|
|
|
15245
15245
|
// src/daemon-worktree.ts
|
|
15246
15246
|
var import_node_child_process3 = require("child_process");
|
|
@@ -40308,7 +40308,7 @@ function resolveAntigravityParentTranscriptPath(conversationId, context) {
|
|
|
40308
40308
|
"transcript.jsonl"
|
|
40309
40309
|
);
|
|
40310
40310
|
}
|
|
40311
|
-
function
|
|
40311
|
+
function syncAntigravityParentTranscript(context, state) {
|
|
40312
40312
|
const parent = state.antigravityParentTranscript;
|
|
40313
40313
|
if (!parent?.transcriptPath) return 0;
|
|
40314
40314
|
const lines = readAntigravityTranscriptLines(parent.transcriptPath);
|
|
@@ -40329,6 +40329,14 @@ function syncAntigravityParentThinkingFromTranscript(context, state) {
|
|
|
40329
40329
|
}
|
|
40330
40330
|
processedLineCount = lineIndex + 1;
|
|
40331
40331
|
if (stringField2(entry, "source") !== "MODEL") continue;
|
|
40332
|
+
const content = stringField2(entry, "content");
|
|
40333
|
+
if (content?.includes("[diff_block_start]") && isAntigravityToolResultEntry(entry) && typeof entry.step_index === "number") {
|
|
40334
|
+
emittedEventCount += 1;
|
|
40335
|
+
void context.presenter.onToolResult?.(
|
|
40336
|
+
liveStepId({ ...entry, conversation_id: parent.conversationId }),
|
|
40337
|
+
stripAntigravityToolResultEnvelope(content)
|
|
40338
|
+
);
|
|
40339
|
+
}
|
|
40332
40340
|
const thinking = stringField2(entry, "thinking") ?? stringField2(entry, "thinking_delta");
|
|
40333
40341
|
if (!thinking) continue;
|
|
40334
40342
|
emittedEventCount += 1;
|
|
@@ -40338,7 +40346,7 @@ function syncAntigravityParentThinkingFromTranscript(context, state) {
|
|
|
40338
40346
|
return emittedEventCount;
|
|
40339
40347
|
}
|
|
40340
40348
|
function syncAntigravitySubagentEventsFromTranscripts(context, state) {
|
|
40341
|
-
let emittedEventCount =
|
|
40349
|
+
let emittedEventCount = syncAntigravityParentTranscript(context, state);
|
|
40342
40350
|
for (const [launcherId, task] of state.antigravitySubagentTranscripts ?? []) {
|
|
40343
40351
|
if (!task.transcriptPath) continue;
|
|
40344
40352
|
const replay = syncAntigravitySubagentTranscript(
|
|
@@ -42958,10 +42966,7 @@ var parseCopilotStructuredLine = createStructuredLineParser(
|
|
|
42958
42966
|
);
|
|
42959
42967
|
function buildCopilotCliArgs(context, prompt, defaultArgs = []) {
|
|
42960
42968
|
const args = [
|
|
42961
|
-
"--autopilot",
|
|
42962
42969
|
"--yolo",
|
|
42963
|
-
"--max-autopilot-continues",
|
|
42964
|
-
"20",
|
|
42965
42970
|
"-s",
|
|
42966
42971
|
"--stream",
|
|
42967
42972
|
"on",
|
|
@@ -44771,36 +44776,6 @@ function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
|
44771
44776
|
}
|
|
44772
44777
|
};
|
|
44773
44778
|
}
|
|
44774
|
-
var AUTONOMOUS_OPENCODE_CONFIG_CONTENT = JSON.stringify({
|
|
44775
|
-
$schema: "https://opencode.ai/config.json",
|
|
44776
|
-
permission: "allow"
|
|
44777
|
-
});
|
|
44778
|
-
function buildAutonomousOpenCodeConfigContent(existing) {
|
|
44779
|
-
if (!existing?.trim()) return AUTONOMOUS_OPENCODE_CONFIG_CONTENT;
|
|
44780
|
-
try {
|
|
44781
|
-
const parsed = JSON.parse(existing);
|
|
44782
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
44783
|
-
return JSON.stringify({
|
|
44784
|
-
...parsed,
|
|
44785
|
-
permission: "allow"
|
|
44786
|
-
});
|
|
44787
|
-
}
|
|
44788
|
-
} catch {
|
|
44789
|
-
}
|
|
44790
|
-
return AUTONOMOUS_OPENCODE_CONFIG_CONTENT;
|
|
44791
|
-
}
|
|
44792
|
-
function withAutonomousOpenCodePermissions(context) {
|
|
44793
|
-
if (shouldUseReadOnlyRuntimePermissions(context.config)) return context;
|
|
44794
|
-
return {
|
|
44795
|
-
...context,
|
|
44796
|
-
env: {
|
|
44797
|
-
...context.env,
|
|
44798
|
-
OPENCODE_CONFIG_CONTENT: buildAutonomousOpenCodeConfigContent(
|
|
44799
|
-
context.env.OPENCODE_CONFIG_CONTENT
|
|
44800
|
-
)
|
|
44801
|
-
}
|
|
44802
|
-
};
|
|
44803
|
-
}
|
|
44804
44779
|
function getRecord(value2) {
|
|
44805
44780
|
return typeof value2 === "object" && value2 !== null ? value2 : null;
|
|
44806
44781
|
}
|
|
@@ -45094,7 +45069,6 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
|
|
|
45094
45069
|
context.cwd
|
|
45095
45070
|
);
|
|
45096
45071
|
try {
|
|
45097
|
-
const runContext = withAutonomousOpenCodePermissions(context);
|
|
45098
45072
|
return await createGenericCliBackend({
|
|
45099
45073
|
kind: "opencode_cli",
|
|
45100
45074
|
supportTier: "structured",
|
|
@@ -45103,7 +45077,7 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
|
|
|
45103
45077
|
buildArgs: (ctx, prompt) => {
|
|
45104
45078
|
const args = ["run", "--format", "json", "--thinking"];
|
|
45105
45079
|
if (!shouldUseReadOnlyRuntimePermissions(ctx.config)) {
|
|
45106
|
-
args.push("--
|
|
45080
|
+
args.push("--auto");
|
|
45107
45081
|
}
|
|
45108
45082
|
const resumeId = ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim();
|
|
45109
45083
|
if (resumeId) args.push("--session", resumeId);
|
|
@@ -45124,7 +45098,7 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
|
|
|
45124
45098
|
return ctx.config.mode === "plan" ? buildPlanModePrefix(base) : base;
|
|
45125
45099
|
},
|
|
45126
45100
|
parseStructuredLine: parseOpencodeStructuredLine
|
|
45127
|
-
}).run(
|
|
45101
|
+
}).run(context);
|
|
45128
45102
|
} finally {
|
|
45129
45103
|
cleanup();
|
|
45130
45104
|
cleanupFiles();
|
|
@@ -45132,6 +45106,36 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
|
|
|
45132
45106
|
}
|
|
45133
45107
|
};
|
|
45134
45108
|
}
|
|
45109
|
+
var AUTONOMOUS_OPENCODE_CONFIG_CONTENT = JSON.stringify({
|
|
45110
|
+
$schema: "https://opencode.ai/config.json",
|
|
45111
|
+
permission: "allow"
|
|
45112
|
+
});
|
|
45113
|
+
function buildAutonomousOpenCodeConfigContent(existing) {
|
|
45114
|
+
if (!existing?.trim()) return AUTONOMOUS_OPENCODE_CONFIG_CONTENT;
|
|
45115
|
+
try {
|
|
45116
|
+
const parsed = JSON.parse(existing);
|
|
45117
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
45118
|
+
return JSON.stringify({
|
|
45119
|
+
...parsed,
|
|
45120
|
+
permission: "allow"
|
|
45121
|
+
});
|
|
45122
|
+
}
|
|
45123
|
+
} catch {
|
|
45124
|
+
}
|
|
45125
|
+
return AUTONOMOUS_OPENCODE_CONFIG_CONTENT;
|
|
45126
|
+
}
|
|
45127
|
+
function withAutonomousOpenCodePermissions(context) {
|
|
45128
|
+
if (shouldUseReadOnlyRuntimePermissions(context.config)) return context;
|
|
45129
|
+
return {
|
|
45130
|
+
...context,
|
|
45131
|
+
env: {
|
|
45132
|
+
...context.env,
|
|
45133
|
+
OPENCODE_CONFIG_CONTENT: buildAutonomousOpenCodeConfigContent(
|
|
45134
|
+
context.env.OPENCODE_CONFIG_CONTENT
|
|
45135
|
+
)
|
|
45136
|
+
}
|
|
45137
|
+
};
|
|
45138
|
+
}
|
|
45135
45139
|
function parseSseEventBlock(block) {
|
|
45136
45140
|
const dataLines = block.split("\n").map((line) => line.endsWith("\r") ? line.slice(0, -1) : line).filter((line) => line.startsWith("data:")).map((line) => line.slice("data:".length).replace(/^ /, ""));
|
|
45137
45141
|
if (dataLines.length === 0) return null;
|
|
@@ -46077,7 +46081,7 @@ function defaultSelectedModelForBackend(backendKind) {
|
|
|
46077
46081
|
case "droid_cli":
|
|
46078
46082
|
return DROID_DEFAULT_MODEL;
|
|
46079
46083
|
case "copilot_cli":
|
|
46080
|
-
return
|
|
46084
|
+
return void 0;
|
|
46081
46085
|
case "kimi_cli":
|
|
46082
46086
|
return void 0;
|
|
46083
46087
|
case "grok_cli":
|
|
@@ -46879,6 +46883,7 @@ ${output2.stderr}`;
|
|
|
46879
46883
|
var import_node_crypto2 = require("crypto");
|
|
46880
46884
|
var import_node_fs7 = require("fs");
|
|
46881
46885
|
var import_node_path6 = require("path");
|
|
46886
|
+
var import_node_util = require("util");
|
|
46882
46887
|
var OUTBOX_VERSION = 1;
|
|
46883
46888
|
var MAX_INTERMEDIATE_EVENTS_PER_RUN = 200;
|
|
46884
46889
|
var MAX_ENCRYPTED_OUTBOX_BYTES = 64 * 1024 * 1024;
|
|
@@ -47040,6 +47045,7 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47040
47045
|
inFlightEventId = null;
|
|
47041
47046
|
ackTimer = null;
|
|
47042
47047
|
retryTimer = null;
|
|
47048
|
+
acknowledgementWaiters = /* @__PURE__ */ new Map();
|
|
47043
47049
|
/** Latch so a persistent disk failure logs once per streak, not per event. */
|
|
47044
47050
|
persistFailureLogged = false;
|
|
47045
47051
|
/**
|
|
@@ -47058,7 +47064,7 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47058
47064
|
maxIntermediateEventsPerRun;
|
|
47059
47065
|
enqueue(conversationId, runId, event) {
|
|
47060
47066
|
const last = this.entries[this.entries.length - 1];
|
|
47061
|
-
if (last && last.eventId !== this.inFlightEventId && !this.transmittedEventIds.has(last.eventId) && last.kind !== "condensation_marker" && last.conversationId === conversationId && last.runId === runId && canCoalesceEvents(last.event, event)) {
|
|
47067
|
+
if (last && !last.explicitSource && last.eventId !== this.inFlightEventId && !this.transmittedEventIds.has(last.eventId) && last.kind !== "condensation_marker" && last.conversationId === conversationId && last.runId === runId && canCoalesceEvents(last.event, event)) {
|
|
47062
47068
|
last.event = coalesceEvents(last.event, event);
|
|
47063
47069
|
last.createdAtMs = Date.now();
|
|
47064
47070
|
this.enforceCaps(runId);
|
|
@@ -47077,12 +47083,48 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47077
47083
|
this.persist();
|
|
47078
47084
|
return entry.eventId;
|
|
47079
47085
|
}
|
|
47086
|
+
/**
|
|
47087
|
+
* Durably enqueue an event whose id is derived from an external source cursor.
|
|
47088
|
+
* Identical retries are idempotent, while reusing an id for different content
|
|
47089
|
+
* fails closed so the backend can never observe divergent payloads under one
|
|
47090
|
+
* receipt key.
|
|
47091
|
+
*/
|
|
47092
|
+
enqueueSource(conversationId, runId, eventId, event) {
|
|
47093
|
+
if (!eventId.trim()) throw new Error("event outbox source event id must not be empty");
|
|
47094
|
+
const existing = this.entries.find((entry) => entry.eventId === eventId);
|
|
47095
|
+
if (existing) {
|
|
47096
|
+
if (existing.explicitSource === true && existing.conversationId === conversationId && existing.runId === runId && (0, import_node_util.isDeepStrictEqual)(existing.event, event)) {
|
|
47097
|
+
return eventId;
|
|
47098
|
+
}
|
|
47099
|
+
throw new Error(`event outbox source event id ${eventId} has divergent payload`);
|
|
47100
|
+
}
|
|
47101
|
+
this.entries.push({
|
|
47102
|
+
eventId,
|
|
47103
|
+
conversationId,
|
|
47104
|
+
runId,
|
|
47105
|
+
event,
|
|
47106
|
+
createdAtMs: Date.now(),
|
|
47107
|
+
explicitSource: true
|
|
47108
|
+
});
|
|
47109
|
+
this.enforceCaps(runId);
|
|
47110
|
+
this.persist();
|
|
47111
|
+
return eventId;
|
|
47112
|
+
}
|
|
47080
47113
|
hasTerminalEvent(runId) {
|
|
47081
47114
|
return this.entries.some((entry) => entry.runId === runId && isTerminal(entry.event));
|
|
47082
47115
|
}
|
|
47083
47116
|
pendingCount() {
|
|
47084
47117
|
return this.entries.length;
|
|
47085
47118
|
}
|
|
47119
|
+
/** Resolve only after the backend has durably acknowledged this queued event. */
|
|
47120
|
+
waitForAcknowledgement(eventId) {
|
|
47121
|
+
if (!this.entries.some((entry) => entry.eventId === eventId)) return Promise.resolve();
|
|
47122
|
+
return new Promise((resolve15) => {
|
|
47123
|
+
const waiters = this.acknowledgementWaiters.get(eventId) ?? [];
|
|
47124
|
+
waiters.push(resolve15);
|
|
47125
|
+
this.acknowledgementWaiters.set(eventId, waiters);
|
|
47126
|
+
});
|
|
47127
|
+
}
|
|
47086
47128
|
disconnect() {
|
|
47087
47129
|
this.clearAckTimer();
|
|
47088
47130
|
this.clearRetryTimer();
|
|
@@ -47111,6 +47153,8 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47111
47153
|
this.condensedRunIds.add(entry.runId);
|
|
47112
47154
|
}
|
|
47113
47155
|
this.persist();
|
|
47156
|
+
for (const resolve15 of this.acknowledgementWaiters.get(entry.eventId) ?? []) resolve15();
|
|
47157
|
+
this.acknowledgementWaiters.delete(entry.eventId);
|
|
47114
47158
|
queueMicrotask(() => this.flush(socket));
|
|
47115
47159
|
return;
|
|
47116
47160
|
}
|
|
@@ -47130,7 +47174,7 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47130
47174
|
);
|
|
47131
47175
|
}
|
|
47132
47176
|
isDroppable(entry) {
|
|
47133
|
-
return entry.eventId !== this.inFlightEventId && entry.kind !== "condensation_marker" && !isTerminal(entry.event);
|
|
47177
|
+
return entry.eventId !== this.inFlightEventId && !entry.explicitSource && entry.kind !== "condensation_marker" && !isTerminal(entry.event);
|
|
47134
47178
|
}
|
|
47135
47179
|
/**
|
|
47136
47180
|
* Pick the next droppable entry to evict. Heartbeats are always evicted
|
|
@@ -47201,7 +47245,7 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
47201
47245
|
continue;
|
|
47202
47246
|
}
|
|
47203
47247
|
const terminal = this.entries.find(
|
|
47204
|
-
(entry) => entry.eventId !== this.inFlightEventId && isTerminal(entry.event) && !entry.terminalCondensed
|
|
47248
|
+
(entry) => entry.eventId !== this.inFlightEventId && !entry.explicitSource && isTerminal(entry.event) && !entry.terminalCondensed
|
|
47205
47249
|
);
|
|
47206
47250
|
if (!terminal) break;
|
|
47207
47251
|
terminal.event = condenseTerminalEvent(terminal.event);
|
|
@@ -61692,10 +61736,10 @@ function isPlainObject2(value2) {
|
|
|
61692
61736
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
61693
61737
|
}
|
|
61694
61738
|
function partitionInputResponses(inputResponses) {
|
|
61695
|
-
const
|
|
61739
|
+
const accepted2 = {};
|
|
61696
61740
|
const droppedKeys = [];
|
|
61697
61741
|
if (!isPlainObject2(inputResponses)) return {
|
|
61698
|
-
accepted,
|
|
61742
|
+
accepted: accepted2,
|
|
61699
61743
|
droppedKeys
|
|
61700
61744
|
};
|
|
61701
61745
|
for (const [key, entry] of Object.entries(inputResponses)) {
|
|
@@ -61703,10 +61747,10 @@ function partitionInputResponses(inputResponses) {
|
|
|
61703
61747
|
droppedKeys.push(key);
|
|
61704
61748
|
continue;
|
|
61705
61749
|
}
|
|
61706
|
-
|
|
61750
|
+
accepted2[key] = entry;
|
|
61707
61751
|
}
|
|
61708
61752
|
return {
|
|
61709
|
-
accepted,
|
|
61753
|
+
accepted: accepted2,
|
|
61710
61754
|
droppedKeys
|
|
61711
61755
|
};
|
|
61712
61756
|
}
|
|
@@ -73862,15 +73906,18 @@ async function drainNativeHookInbox(input2) {
|
|
|
73862
73906
|
return input2.inbox.drain(async (envelope) => {
|
|
73863
73907
|
const isStart = envelope.eventType === "session_start" || envelope.eventType === "subagent_start";
|
|
73864
73908
|
const isTerminal2 = envelope.eventType === "stop" || envelope.eventType === "session_end" || envelope.eventType === "subagent_end";
|
|
73909
|
+
let binding = envelope.eventType === "user_prompt" ? void 0 : input2.transcriptStreamer?.bindingFor?.(envelope);
|
|
73865
73910
|
const streamTranscript = async () => {
|
|
73866
73911
|
if (isStart || !input2.transcriptStreamer || !envelope.transcriptPath) {
|
|
73867
73912
|
return "unavailable";
|
|
73868
73913
|
}
|
|
73869
73914
|
try {
|
|
73870
|
-
const streamed = await input2.transcriptStreamer.stream(
|
|
73871
|
-
|
|
73872
|
-
|
|
73873
|
-
|
|
73915
|
+
const streamed = await input2.transcriptStreamer.stream(envelope, async (event) => {
|
|
73916
|
+
if (binding && input2.sink.deliverCanonical) {
|
|
73917
|
+
return input2.sink.deliverCanonical(binding, event);
|
|
73918
|
+
}
|
|
73919
|
+
return accepted(await input2.sink.deliver(event));
|
|
73920
|
+
});
|
|
73874
73921
|
return streamed.complete ? streamed.assistantOutputDelivered ? "replayed" : "unavailable" : "deferred";
|
|
73875
73922
|
} catch (error61) {
|
|
73876
73923
|
if (error61 instanceof PermanentNativeHookDeliveryError) throw error61;
|
|
@@ -73892,14 +73939,27 @@ async function drainNativeHookInbox(input2) {
|
|
|
73892
73939
|
if (isTerminal2) {
|
|
73893
73940
|
const transcriptReplay = await streamTranscript();
|
|
73894
73941
|
if (transcriptReplay === "deferred") return false;
|
|
73895
|
-
return
|
|
73896
|
-
|
|
73942
|
+
return accepted(
|
|
73943
|
+
await input2.sink.deliver(
|
|
73944
|
+
transcriptReplay === "replayed" ? { ...envelope, assistantOutputReplayed: true } : envelope
|
|
73945
|
+
)
|
|
73897
73946
|
);
|
|
73898
73947
|
}
|
|
73899
|
-
|
|
73948
|
+
const lifecycleDelivery = normalizeDelivery(await input2.sink.deliver(envelope));
|
|
73949
|
+
if (!lifecycleDelivery.accepted) return false;
|
|
73950
|
+
if (envelope.eventType === "user_prompt") {
|
|
73951
|
+
binding = lifecycleDelivery.binding;
|
|
73952
|
+
input2.transcriptStreamer?.setBinding?.(envelope, binding);
|
|
73953
|
+
}
|
|
73900
73954
|
return await streamTranscript() !== "deferred";
|
|
73901
73955
|
}, input2.limit);
|
|
73902
73956
|
}
|
|
73957
|
+
function normalizeDelivery(result) {
|
|
73958
|
+
return typeof result === "boolean" ? { accepted: result } : result;
|
|
73959
|
+
}
|
|
73960
|
+
function accepted(result) {
|
|
73961
|
+
return normalizeDelivery(result).accepted;
|
|
73962
|
+
}
|
|
73903
73963
|
function isMissingTranscriptError(error61) {
|
|
73904
73964
|
return error61.code === "ENOENT";
|
|
73905
73965
|
}
|
|
@@ -74112,6 +74172,24 @@ var NativeTranscriptStreamer = class {
|
|
|
74112
74172
|
throw new Error("native transcript maxReadBytes must be a positive integer");
|
|
74113
74173
|
}
|
|
74114
74174
|
}
|
|
74175
|
+
bindingFor(hook) {
|
|
74176
|
+
if (!hook.transcriptPath) return void 0;
|
|
74177
|
+
return this.cursorStore.get(this.cursorKey(hook))?.binding;
|
|
74178
|
+
}
|
|
74179
|
+
setBinding(hook, binding) {
|
|
74180
|
+
if (!hook.transcriptPath) return;
|
|
74181
|
+
const key = this.cursorKey(hook);
|
|
74182
|
+
const previous = this.cursorStore.get(key);
|
|
74183
|
+
this.cursorStore.commit(key, {
|
|
74184
|
+
offset: previous?.offset ?? 0,
|
|
74185
|
+
generation: previous?.generation ?? 0,
|
|
74186
|
+
device: previous?.device ?? 0,
|
|
74187
|
+
inode: previous?.inode ?? 0,
|
|
74188
|
+
assistantOutputSeen: previous?.assistantOutputSeen,
|
|
74189
|
+
assistantOutputTurnId: previous?.assistantOutputTurnId,
|
|
74190
|
+
...binding ? { binding } : {}
|
|
74191
|
+
});
|
|
74192
|
+
}
|
|
74115
74193
|
async stream(hook, deliver) {
|
|
74116
74194
|
if (!hook.transcriptPath) {
|
|
74117
74195
|
return {
|
|
@@ -74121,11 +74199,7 @@ var NativeTranscriptStreamer = class {
|
|
|
74121
74199
|
assistantOutputDelivered: false
|
|
74122
74200
|
};
|
|
74123
74201
|
}
|
|
74124
|
-
const key =
|
|
74125
|
-
provider: hook.provider,
|
|
74126
|
-
externalSessionId: hook.externalSessionId,
|
|
74127
|
-
transcriptPath: hook.transcriptPath
|
|
74128
|
-
});
|
|
74202
|
+
const key = this.cursorKey(hook);
|
|
74129
74203
|
let previous = this.cursorStore.get(key);
|
|
74130
74204
|
if (hook.eventType === "user_prompt" && previous && previous.assistantOutputTurnId !== hook.eventId) {
|
|
74131
74205
|
previous = {
|
|
@@ -74136,15 +74210,17 @@ var NativeTranscriptStreamer = class {
|
|
|
74136
74210
|
this.cursorStore.commit(key, previous);
|
|
74137
74211
|
}
|
|
74138
74212
|
const file2 = (0, import_node_fs18.statSync)(hook.transcriptPath);
|
|
74139
|
-
const
|
|
74213
|
+
const hasFileIdentity = Boolean(previous && (previous.device !== 0 || previous.inode !== 0));
|
|
74214
|
+
const replaced = hasFileIdentity && (previous.device !== file2.dev || previous.inode !== file2.ino);
|
|
74140
74215
|
const truncated = Boolean(previous) && file2.size < previous.offset;
|
|
74141
|
-
const start = !previous || replaced || truncated ? {
|
|
74216
|
+
const start = !previous || !hasFileIdentity || replaced || truncated ? {
|
|
74142
74217
|
offset: 0,
|
|
74143
|
-
generation: previous ? previous.generation + 1 : 0,
|
|
74218
|
+
generation: previous ? previous.generation + (hasFileIdentity ? 1 : 0) : 0,
|
|
74144
74219
|
device: file2.dev,
|
|
74145
74220
|
inode: file2.ino,
|
|
74146
74221
|
assistantOutputSeen: previous?.assistantOutputSeen ?? false,
|
|
74147
|
-
assistantOutputTurnId: hook.eventType === "user_prompt" ? hook.eventId : previous?.assistantOutputTurnId
|
|
74222
|
+
assistantOutputTurnId: hook.eventType === "user_prompt" ? hook.eventId : previous?.assistantOutputTurnId,
|
|
74223
|
+
binding: previous?.binding
|
|
74148
74224
|
} : previous;
|
|
74149
74225
|
let assistantOutputSeen = start.assistantOutputSeen ?? false;
|
|
74150
74226
|
if (file2.size <= start.offset) {
|
|
@@ -74197,9 +74273,10 @@ var NativeTranscriptStreamer = class {
|
|
|
74197
74273
|
const events = parsed ? providerRecordToAgentEvents(hook.provider, parsed) : [];
|
|
74198
74274
|
for (let index = 0; index < events.length; index += 1) {
|
|
74199
74275
|
const deliveredEvent = events[index];
|
|
74276
|
+
if (deliveredEvent.type === "start" && start.binding) continue;
|
|
74200
74277
|
const sourceCursor = `${start.generation}:${recordEndOffset}:${index}`;
|
|
74201
74278
|
const eventId = stableSourceEventId(hook, sourceCursor);
|
|
74202
|
-
const
|
|
74279
|
+
const accepted2 = await deliver({
|
|
74203
74280
|
schemaVersion: 1,
|
|
74204
74281
|
eventId,
|
|
74205
74282
|
provider: hook.provider,
|
|
@@ -74208,7 +74285,7 @@ var NativeTranscriptStreamer = class {
|
|
|
74208
74285
|
observedAt: timestampOf(parsed) ?? hook.observedAt,
|
|
74209
74286
|
event: deliveredEvent
|
|
74210
74287
|
});
|
|
74211
|
-
if (!
|
|
74288
|
+
if (!accepted2) {
|
|
74212
74289
|
return {
|
|
74213
74290
|
complete: false,
|
|
74214
74291
|
recordsRead,
|
|
@@ -74238,6 +74315,14 @@ var NativeTranscriptStreamer = class {
|
|
|
74238
74315
|
cursor: `${start.generation}:${committedOffset}`
|
|
74239
74316
|
};
|
|
74240
74317
|
}
|
|
74318
|
+
cursorKey(hook) {
|
|
74319
|
+
if (!hook.transcriptPath) throw new Error("native transcript hook has no transcript path");
|
|
74320
|
+
return nativeTranscriptCursorKey({
|
|
74321
|
+
provider: hook.provider,
|
|
74322
|
+
externalSessionId: hook.externalSessionId,
|
|
74323
|
+
transcriptPath: hook.transcriptPath
|
|
74324
|
+
});
|
|
74325
|
+
}
|
|
74241
74326
|
};
|
|
74242
74327
|
function stableSourceEventId(hook, sourceCursor) {
|
|
74243
74328
|
const bytes = (0, import_node_crypto10.createHash)("sha256").update(`${hook.provider}\0${hook.externalSessionId}\0${hook.transcriptPath}\0${sourceCursor}`).digest().subarray(0, 16);
|
|
@@ -74257,8 +74342,19 @@ function parseJsonObject3(value2) {
|
|
|
74257
74342
|
function providerRecordToAgentEvents(provider, record2) {
|
|
74258
74343
|
if (provider === "codex") return codexRecordToAgentEvents(record2);
|
|
74259
74344
|
if (provider === "copilot") return copilotRecordToAgentEvents(record2);
|
|
74345
|
+
if (provider === "cursor") return cursorRecordToAgentEvents(record2);
|
|
74260
74346
|
return claudeCompatibleRecordToAgentEvents(record2);
|
|
74261
74347
|
}
|
|
74348
|
+
function cursorRecordToAgentEvents(record2) {
|
|
74349
|
+
const message = isRecord2(record2.message) ? record2.message : record2;
|
|
74350
|
+
const role = stringValue(message.role, record2.role);
|
|
74351
|
+
if (role !== "user") return claudeCompatibleRecordToAgentEvents(record2);
|
|
74352
|
+
const rawPrompt = extractText2(message.content).trim();
|
|
74353
|
+
if (!rawPrompt) return [];
|
|
74354
|
+
const wrappedPrompt = rawPrompt.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/i)?.[1];
|
|
74355
|
+
const prompt = (wrappedPrompt ?? rawPrompt).trim();
|
|
74356
|
+
return prompt ? [{ type: "start", task: prompt, ts: Date.now() }] : [];
|
|
74357
|
+
}
|
|
74262
74358
|
function copilotRecordToAgentEvents(record2) {
|
|
74263
74359
|
if (typeof record2.type !== "string" || !isRecord2(record2.data)) return [];
|
|
74264
74360
|
const timestamp = timestampOf(record2) ? Date.parse(timestampOf(record2)) : Date.now();
|
|
@@ -74684,9 +74780,9 @@ var import_yaml = __toESM(require_dist2(), 1);
|
|
|
74684
74780
|
// ../shared/dist/skills/domain.js
|
|
74685
74781
|
var SKILLS_PROTOCOL_VERSION = 1;
|
|
74686
74782
|
var SKILL_PACKAGE_LIMITS = {
|
|
74687
|
-
maxArchiveBytes:
|
|
74688
|
-
maxExpandedBytes:
|
|
74689
|
-
maxFileBytes:
|
|
74783
|
+
maxArchiveBytes: 20 * 1024 * 1024,
|
|
74784
|
+
maxExpandedBytes: 20 * 1024 * 1024,
|
|
74785
|
+
maxFileBytes: 20 * 1024 * 1024,
|
|
74690
74786
|
maxSkillMarkdownBytes: 2 * 1024 * 1024,
|
|
74691
74787
|
maxFiles: 1e3,
|
|
74692
74788
|
maxPathBytes: 240,
|
|
@@ -74711,14 +74807,16 @@ var skillInvocationSchema = defineWireSchema()(external_exports.discriminatedUni
|
|
|
74711
74807
|
kind: external_exports.literal("skill_version"),
|
|
74712
74808
|
skillId: skillIdSchema,
|
|
74713
74809
|
versionId: skillVersionIdSchema,
|
|
74714
|
-
displayName: external_exports.string().trim().min(1).max(128)
|
|
74810
|
+
displayName: external_exports.string().trim().min(1).max(128),
|
|
74811
|
+
textOffset: external_exports.number().int().nonnegative().optional()
|
|
74715
74812
|
}),
|
|
74716
74813
|
external_exports.object({
|
|
74717
74814
|
kind: external_exports.literal("local_skill"),
|
|
74718
74815
|
runtimeId: runtimeIdSchema,
|
|
74719
74816
|
localKey: external_exports.string().min(1).max(256),
|
|
74720
74817
|
contentHash: sha256Schema,
|
|
74721
|
-
displayName: external_exports.string().trim().min(1).max(128)
|
|
74818
|
+
displayName: external_exports.string().trim().min(1).max(128),
|
|
74819
|
+
textOffset: external_exports.number().int().nonnegative().optional()
|
|
74722
74820
|
})
|
|
74723
74821
|
]));
|
|
74724
74822
|
var runtimeUploadGrantSchema = external_exports.object({
|
|
@@ -74886,12 +74984,7 @@ var discoveredSkillCandidateSchema = external_exports.object({
|
|
|
74886
74984
|
repositoryId: external_exports.string().min(1).max(128)
|
|
74887
74985
|
})
|
|
74888
74986
|
]),
|
|
74889
|
-
diagnostics: external_exports.array(skillPackageDiagnosticSchema).max(100)
|
|
74890
|
-
publication: external_exports.object({
|
|
74891
|
-
skillId: skillIdSchema,
|
|
74892
|
-
versionId: skillVersionIdSchema,
|
|
74893
|
-
contentHash: sha256Schema
|
|
74894
|
-
}).optional()
|
|
74987
|
+
diagnostics: external_exports.array(skillPackageDiagnosticSchema).max(100)
|
|
74895
74988
|
});
|
|
74896
74989
|
var skillScanOutcomeSchema = defineWireSchema()(external_exports.discriminatedUnion("status", [
|
|
74897
74990
|
external_exports.object({
|
|
@@ -74925,6 +75018,19 @@ var desiredSkillManifestEntrySchema = external_exports.object({
|
|
|
74925
75018
|
downloadUrl: external_exports.url(),
|
|
74926
75019
|
downloadUrlExpiresAt: external_exports.iso.datetime()
|
|
74927
75020
|
});
|
|
75021
|
+
var skillInstallConflictSchema = external_exports.object({
|
|
75022
|
+
kind: external_exports.enum(["managed_destination", "compatibility_destination"]),
|
|
75023
|
+
runtimeDirectory: external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/),
|
|
75024
|
+
observedHash: sha256Schema,
|
|
75025
|
+
observedName: external_exports.string().min(1).max(64).regex(SKILL_NAME_PATTERN, "Invalid")
|
|
75026
|
+
});
|
|
75027
|
+
var skillConflictResolutionSchema = external_exports.discriminatedUnion("kind", [
|
|
75028
|
+
external_exports.object({
|
|
75029
|
+
kind: external_exports.literal("rename_local"),
|
|
75030
|
+
name: external_exports.string().min(1).max(64).regex(SKILL_NAME_PATTERN, "Invalid")
|
|
75031
|
+
}),
|
|
75032
|
+
external_exports.object({ kind: external_exports.literal("overwrite_local") })
|
|
75033
|
+
]);
|
|
74928
75034
|
var desiredSkillManifestSchema = defineWireSchema()(external_exports.object({
|
|
74929
75035
|
protocolVersion: external_exports.literal(SKILLS_PROTOCOL_VERSION),
|
|
74930
75036
|
revision: sha256Schema,
|
|
@@ -74958,7 +75064,8 @@ var reconcileSkillResultSchema = external_exports.object({
|
|
|
74958
75064
|
observedHash: sha256Schema.optional(),
|
|
74959
75065
|
state: external_exports.enum(["applied", "conflict", "failed"]),
|
|
74960
75066
|
errorCode: external_exports.string().max(128).optional(),
|
|
74961
|
-
errorMessage: external_exports.string().max(2048).optional()
|
|
75067
|
+
errorMessage: external_exports.string().max(2048).optional(),
|
|
75068
|
+
conflict: skillInstallConflictSchema.optional()
|
|
74962
75069
|
});
|
|
74963
75070
|
var reconcileSkillsResultSchema = defineWireSchema()(external_exports.object({
|
|
74964
75071
|
attemptId: external_exports.string().min(1).max(128),
|
|
@@ -74985,14 +75092,23 @@ var runtimeSkillCommandSchema = defineWireSchema()(external_exports.discriminate
|
|
|
74985
75092
|
uploadGrant: runtimeUploadGrantSchema
|
|
74986
75093
|
}),
|
|
74987
75094
|
external_exports.object({
|
|
74988
|
-
kind: external_exports.literal("
|
|
75095
|
+
kind: external_exports.literal("resolve_conflict"),
|
|
74989
75096
|
commandId: skillCommandIdSchema,
|
|
74990
|
-
|
|
74991
|
-
expectedContentHash: sha256Schema,
|
|
75097
|
+
manifest: desiredSkillManifestSchema,
|
|
74992
75098
|
skillId: skillIdSchema,
|
|
74993
|
-
versionId: skillVersionIdSchema
|
|
75099
|
+
versionId: skillVersionIdSchema,
|
|
75100
|
+
expectedConflict: skillInstallConflictSchema,
|
|
75101
|
+
resolution: skillConflictResolutionSchema
|
|
74994
75102
|
})
|
|
74995
75103
|
]));
|
|
75104
|
+
var skillConflictResolutionResultSchema = defineWireSchema()(external_exports.object({
|
|
75105
|
+
commandId: skillCommandIdSchema,
|
|
75106
|
+
skillId: skillIdSchema,
|
|
75107
|
+
versionId: skillVersionIdSchema,
|
|
75108
|
+
state: external_exports.enum(["applied", "stale", "failed"]),
|
|
75109
|
+
errorCode: external_exports.string().max(128).optional(),
|
|
75110
|
+
errorMessage: external_exports.string().max(2048).optional()
|
|
75111
|
+
}));
|
|
74996
75112
|
var publishSkillResultSchema = defineWireSchema()(external_exports.object({
|
|
74997
75113
|
commandId: skillCommandIdSchema,
|
|
74998
75114
|
previewId: skillPreviewIdSchema,
|
|
@@ -75012,6 +75128,7 @@ var runtimeSkillSyncRequestSchema = defineWireSchema()(external_exports.object({
|
|
|
75012
75128
|
inventoryAttempt: skillScanOutcomeSchema.optional(),
|
|
75013
75129
|
appliedResult: reconcileSkillsResultSchema.optional(),
|
|
75014
75130
|
publishedPreviews: external_exports.array(publishSkillResultSchema).max(100).optional(),
|
|
75131
|
+
resolvedConflicts: external_exports.array(skillConflictResolutionResultSchema).max(100).optional(),
|
|
75015
75132
|
completedCommandIds: external_exports.array(skillCommandIdSchema).max(100).optional()
|
|
75016
75133
|
}));
|
|
75017
75134
|
var runtimeSkillSyncResponseSchema = defineWireSchema()(external_exports.object({
|
|
@@ -75535,7 +75652,6 @@ var DEFAULT_SKILL_CONFIG = `version = 1
|
|
|
75535
75652
|
|
|
75536
75653
|
[skills]
|
|
75537
75654
|
enabled = true
|
|
75538
|
-
publish_changes = "prompt"
|
|
75539
75655
|
discover_repository_skills = true
|
|
75540
75656
|
ignore = ["**/.git/**", "**/node_modules/**"]
|
|
75541
75657
|
|
|
@@ -75887,7 +76003,6 @@ function parseSkillSourceConfig(content, homeDirectory2) {
|
|
|
75887
76003
|
}
|
|
75888
76004
|
const skills = parsed.skills;
|
|
75889
76005
|
const enabled = optionalBoolean(skills.enabled, true, "skills.enabled");
|
|
75890
|
-
const publishChanges = optionalPublishChanges(skills.publish_changes);
|
|
75891
76006
|
const discoverRepositorySkills = optionalBoolean(
|
|
75892
76007
|
skills.discover_repository_skills,
|
|
75893
76008
|
true,
|
|
@@ -75929,7 +76044,7 @@ function parseSkillSourceConfig(content, homeDirectory2) {
|
|
|
75929
76044
|
if (duplicateId) {
|
|
75930
76045
|
throw new Error(`skills.sources contains duplicate source id ${duplicateId.declarationId}`);
|
|
75931
76046
|
}
|
|
75932
|
-
return { enabled,
|
|
76047
|
+
return { enabled, discoverRepositorySkills, ignoredPaths, sources };
|
|
75933
76048
|
}
|
|
75934
76049
|
function stableSourceDeclarationId(sourcePath) {
|
|
75935
76050
|
const digest = (0, import_node_crypto12.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
|
|
@@ -75955,11 +76070,6 @@ function optionalBoolean(value2, fallback, field) {
|
|
|
75955
76070
|
if (typeof value2 !== "boolean") throw new Error(`${field} must be true or false`);
|
|
75956
76071
|
return value2;
|
|
75957
76072
|
}
|
|
75958
|
-
function optionalPublishChanges(value2) {
|
|
75959
|
-
if (value2 === void 0) return "prompt";
|
|
75960
|
-
if (value2 === "prompt" || value2 === "automatic" || value2 === "never") return value2;
|
|
75961
|
-
throw new Error('skills.publish_changes must be "prompt", "automatic", or "never"');
|
|
75962
|
-
}
|
|
75963
76073
|
function optionalStringArray(value2, field) {
|
|
75964
76074
|
if (value2 === void 0) return [];
|
|
75965
76075
|
if (!Array.isArray(value2) || value2.some((item) => typeof item !== "string")) {
|
|
@@ -76068,6 +76178,7 @@ var RuntimeSkillCoordinator = class {
|
|
|
76068
76178
|
pendingInventory;
|
|
76069
76179
|
pendingApplied;
|
|
76070
76180
|
pendingPublished = /* @__PURE__ */ new Map();
|
|
76181
|
+
pendingResolvedConflicts = /* @__PURE__ */ new Map();
|
|
76071
76182
|
completedCommandIds = /* @__PURE__ */ new Set();
|
|
76072
76183
|
tail = Promise.resolve();
|
|
76073
76184
|
lastScanInput;
|
|
@@ -76133,16 +76244,22 @@ var RuntimeSkillCoordinator = class {
|
|
|
76133
76244
|
producedWork = true;
|
|
76134
76245
|
break;
|
|
76135
76246
|
}
|
|
76136
|
-
case "
|
|
76137
|
-
await this.manager.
|
|
76138
|
-
|
|
76139
|
-
|
|
76247
|
+
case "resolve_conflict": {
|
|
76248
|
+
const resolved = await this.manager.resolveConflict({
|
|
76249
|
+
commandId: command.commandId,
|
|
76250
|
+
manifest: command.manifest,
|
|
76140
76251
|
skillId: command.skillId,
|
|
76141
|
-
versionId: command.versionId
|
|
76252
|
+
versionId: command.versionId,
|
|
76253
|
+
expectedConflict: command.expectedConflict,
|
|
76254
|
+
resolution: command.resolution
|
|
76142
76255
|
});
|
|
76143
|
-
this.
|
|
76256
|
+
this.pendingResolvedConflicts.set(resolved.commandId, resolved);
|
|
76257
|
+
if (resolved.state === "applied") {
|
|
76258
|
+
this.pendingApplied = await this.manager.reconcile({ manifest: command.manifest });
|
|
76259
|
+
}
|
|
76144
76260
|
producedWork = true;
|
|
76145
76261
|
break;
|
|
76262
|
+
}
|
|
76146
76263
|
}
|
|
76147
76264
|
}
|
|
76148
76265
|
if (!producedWork && !this.hasPendingReports()) return;
|
|
@@ -76157,6 +76274,7 @@ var RuntimeSkillCoordinator = class {
|
|
|
76157
76274
|
...this.pendingInventory ? { inventoryAttempt: this.pendingInventory } : {},
|
|
76158
76275
|
...this.pendingApplied ? { appliedResult: this.pendingApplied } : {},
|
|
76159
76276
|
...this.pendingPublished.size > 0 ? { publishedPreviews: [...this.pendingPublished.values()] } : {},
|
|
76277
|
+
...this.pendingResolvedConflicts.size > 0 ? { resolvedConflicts: [...this.pendingResolvedConflicts.values()] } : {},
|
|
76160
76278
|
...this.completedCommandIds.size > 0 ? { completedCommandIds: [...this.completedCommandIds] } : {}
|
|
76161
76279
|
};
|
|
76162
76280
|
}
|
|
@@ -76166,23 +76284,26 @@ var RuntimeSkillCoordinator = class {
|
|
|
76166
76284
|
return this.manager.scan(prepared);
|
|
76167
76285
|
}
|
|
76168
76286
|
accept(attemptIds) {
|
|
76169
|
-
const
|
|
76170
|
-
if (this.pendingInventory &&
|
|
76287
|
+
const accepted2 = new Set(attemptIds);
|
|
76288
|
+
if (this.pendingInventory && accepted2.has(this.pendingInventory.attemptId)) {
|
|
76171
76289
|
this.pendingInventory = void 0;
|
|
76172
76290
|
}
|
|
76173
|
-
if (this.pendingApplied &&
|
|
76291
|
+
if (this.pendingApplied && accepted2.has(this.pendingApplied.attemptId)) {
|
|
76174
76292
|
this.pendingApplied = void 0;
|
|
76175
76293
|
}
|
|
76176
76294
|
for (const commandId of this.pendingPublished.keys()) {
|
|
76177
|
-
if (
|
|
76295
|
+
if (accepted2.has(commandId)) this.pendingPublished.delete(commandId);
|
|
76296
|
+
}
|
|
76297
|
+
for (const commandId of this.pendingResolvedConflicts.keys()) {
|
|
76298
|
+
if (accepted2.has(commandId)) this.pendingResolvedConflicts.delete(commandId);
|
|
76178
76299
|
}
|
|
76179
76300
|
for (const commandId of this.completedCommandIds) {
|
|
76180
|
-
if (
|
|
76301
|
+
if (accepted2.has(commandId)) this.completedCommandIds.delete(commandId);
|
|
76181
76302
|
}
|
|
76182
76303
|
}
|
|
76183
76304
|
hasPendingReports() {
|
|
76184
76305
|
return Boolean(
|
|
76185
|
-
this.pendingInventory || this.pendingApplied || this.pendingPublished.size > 0 || this.completedCommandIds.size > 0
|
|
76306
|
+
this.pendingInventory || this.pendingApplied || this.pendingPublished.size > 0 || this.pendingResolvedConflicts.size > 0 || this.completedCommandIds.size > 0
|
|
76186
76307
|
);
|
|
76187
76308
|
}
|
|
76188
76309
|
async runExclusively(work) {
|
|
@@ -76249,36 +76370,6 @@ var ManagedSkillStore = class _ManagedSkillStore {
|
|
|
76249
76370
|
resolveSource(localKey) {
|
|
76250
76371
|
return this.state.sources[localKey] ?? null;
|
|
76251
76372
|
}
|
|
76252
|
-
publicationFor(localKey, contentHash) {
|
|
76253
|
-
const source = this.state.sources[localKey];
|
|
76254
|
-
return source?.contentHash === contentHash && source.publication?.contentHash === contentHash ? source.publication : null;
|
|
76255
|
-
}
|
|
76256
|
-
sourceForPublication(projection) {
|
|
76257
|
-
return Object.values(this.state.sources).find(
|
|
76258
|
-
(source) => source.contentHash === projection.contentHash && source.publication?.skillId === projection.skillId && source.publication.versionId === projection.versionId && source.publication.contentHash === projection.contentHash
|
|
76259
|
-
) ?? null;
|
|
76260
|
-
}
|
|
76261
|
-
async bindSource(input2) {
|
|
76262
|
-
const source = this.state.sources[input2.localKey];
|
|
76263
|
-
if (!source || source.contentHash !== input2.expectedContentHash) {
|
|
76264
|
-
throw new Error("Skill source changed before its publication binding was applied");
|
|
76265
|
-
}
|
|
76266
|
-
this.state = {
|
|
76267
|
-
...this.state,
|
|
76268
|
-
sources: {
|
|
76269
|
-
...this.state.sources,
|
|
76270
|
-
[input2.localKey]: {
|
|
76271
|
-
...source,
|
|
76272
|
-
publication: {
|
|
76273
|
-
skillId: input2.skillId,
|
|
76274
|
-
versionId: input2.versionId,
|
|
76275
|
-
contentHash: input2.expectedContentHash
|
|
76276
|
-
}
|
|
76277
|
-
}
|
|
76278
|
-
}
|
|
76279
|
-
};
|
|
76280
|
-
await this.persist();
|
|
76281
|
-
}
|
|
76282
76373
|
appliedRevision() {
|
|
76283
76374
|
return this.state.appliedRevision ?? null;
|
|
76284
76375
|
}
|
|
@@ -76295,19 +76386,10 @@ var ManagedSkillStore = class _ManagedSkillStore {
|
|
|
76295
76386
|
}
|
|
76296
76387
|
async recordCompleteScan(input2) {
|
|
76297
76388
|
const sources = Object.fromEntries(
|
|
76298
|
-
input2.candidates.map((candidate) =>
|
|
76299
|
-
|
|
76300
|
-
|
|
76301
|
-
|
|
76302
|
-
return [
|
|
76303
|
-
candidate.localKey,
|
|
76304
|
-
{
|
|
76305
|
-
absolutePath: candidate.absolutePath,
|
|
76306
|
-
contentHash: candidate.contentHash,
|
|
76307
|
-
...publication ? { publication } : {}
|
|
76308
|
-
}
|
|
76309
|
-
];
|
|
76310
|
-
})
|
|
76389
|
+
input2.candidates.map((candidate) => [
|
|
76390
|
+
candidate.localKey,
|
|
76391
|
+
{ absolutePath: candidate.absolutePath, contentHash: candidate.contentHash }
|
|
76392
|
+
])
|
|
76311
76393
|
);
|
|
76312
76394
|
this.state = {
|
|
76313
76395
|
...this.state,
|
|
@@ -76355,11 +76437,9 @@ function parseState(value2) {
|
|
|
76355
76437
|
if (!localKey.startsWith("local:") || !isRecord5(source) || typeof source.absolutePath !== "string" || !isSha256(source.contentHash)) {
|
|
76356
76438
|
throw new Error("invalid Skill source state");
|
|
76357
76439
|
}
|
|
76358
|
-
const publication = parsePublication(source.publication, source.contentHash);
|
|
76359
76440
|
sources[localKey] = {
|
|
76360
76441
|
absolutePath: source.absolutePath,
|
|
76361
|
-
contentHash: source.contentHash
|
|
76362
|
-
...publication ? { publication } : {}
|
|
76442
|
+
contentHash: source.contentHash
|
|
76363
76443
|
};
|
|
76364
76444
|
}
|
|
76365
76445
|
const projections = {};
|
|
@@ -76383,17 +76463,6 @@ function parseState(value2) {
|
|
|
76383
76463
|
projections
|
|
76384
76464
|
};
|
|
76385
76465
|
}
|
|
76386
|
-
function parsePublication(value2, sourceHash) {
|
|
76387
|
-
if (value2 === void 0) return void 0;
|
|
76388
|
-
if (!isRecord5(value2) || typeof value2.skillId !== "string" || typeof value2.versionId !== "string" || !isSha256(value2.contentHash) || value2.contentHash !== sourceHash) {
|
|
76389
|
-
throw new Error("invalid Skill source publication state");
|
|
76390
|
-
}
|
|
76391
|
-
return {
|
|
76392
|
-
skillId: value2.skillId,
|
|
76393
|
-
versionId: value2.versionId,
|
|
76394
|
-
contentHash: value2.contentHash
|
|
76395
|
-
};
|
|
76396
|
-
}
|
|
76397
76466
|
function optionalSha256(value2) {
|
|
76398
76467
|
if (value2 === void 0) return void 0;
|
|
76399
76468
|
if (!isSha256(value2)) throw new Error("invalid Skill state hash");
|
|
@@ -76417,8 +76486,8 @@ var import_node_path21 = require("path");
|
|
|
76417
76486
|
var import_node_stream = require("stream");
|
|
76418
76487
|
var import_node_zlib = require("zlib");
|
|
76419
76488
|
var import_tar_stream = __toESM(require_tar_stream(), 1);
|
|
76420
|
-
async function createSkillBundle(packageRoot) {
|
|
76421
|
-
const before = await inspectSkillPackage(packageRoot);
|
|
76489
|
+
async function createSkillBundle(packageRoot, options = {}) {
|
|
76490
|
+
const before = await inspectSkillPackage(packageRoot, options);
|
|
76422
76491
|
const archive = (0, import_tar_stream.pack)();
|
|
76423
76492
|
const tarPromise = collectStream(archive);
|
|
76424
76493
|
for (const file2 of before.files) {
|
|
@@ -76440,7 +76509,7 @@ async function createSkillBundle(packageRoot) {
|
|
|
76440
76509
|
if (bytes.byteLength > SKILL_PACKAGE_LIMITS.maxArchiveBytes) {
|
|
76441
76510
|
throw new Error(`Skill archive exceeds ${SKILL_PACKAGE_LIMITS.maxArchiveBytes} bytes`);
|
|
76442
76511
|
}
|
|
76443
|
-
const after = await inspectSkillPackage(packageRoot);
|
|
76512
|
+
const after = await inspectSkillPackage(packageRoot, options);
|
|
76444
76513
|
if (after.contentHash !== before.contentHash) {
|
|
76445
76514
|
throw new Error("Skill source changed while its archive was being created");
|
|
76446
76515
|
}
|
|
@@ -76637,17 +76706,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76637
76706
|
);
|
|
76638
76707
|
}
|
|
76639
76708
|
async scan(input2) {
|
|
76640
|
-
const
|
|
76641
|
-
const outcome = scanned.status === "complete" ? {
|
|
76642
|
-
...scanned,
|
|
76643
|
-
candidates: scanned.candidates.map((candidate) => {
|
|
76644
|
-
const publication = this.store.publicationFor(
|
|
76645
|
-
candidate.localKey,
|
|
76646
|
-
candidate.contentHash
|
|
76647
|
-
);
|
|
76648
|
-
return publication ? { ...candidate, publication } : candidate;
|
|
76649
|
-
})
|
|
76650
|
-
} : scanned;
|
|
76709
|
+
const outcome = await this.localSource.scan(input2);
|
|
76651
76710
|
if (outcome.status === "complete") {
|
|
76652
76711
|
await this.store.recordCompleteScan({
|
|
76653
76712
|
revision: outcome.inventoryRevision,
|
|
@@ -76664,9 +76723,6 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76664
76723
|
}
|
|
76665
76724
|
return outcome;
|
|
76666
76725
|
}
|
|
76667
|
-
async bindSource(input2) {
|
|
76668
|
-
await this.store.bindSource(input2);
|
|
76669
|
-
}
|
|
76670
76726
|
async publish(input2) {
|
|
76671
76727
|
const source = this.store.resolveSource(input2.localKey);
|
|
76672
76728
|
if (!source) throw new Error("Skill source is not present in the last complete scan");
|
|
@@ -76754,6 +76810,11 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76754
76810
|
() => this.withMachineLock(() => this.reconcileUnlocked(input2.manifest))
|
|
76755
76811
|
);
|
|
76756
76812
|
}
|
|
76813
|
+
async resolveConflict(input2) {
|
|
76814
|
+
return this.runExclusively(
|
|
76815
|
+
() => this.withMachineLock(() => this.resolveConflictUnlocked(input2))
|
|
76816
|
+
);
|
|
76817
|
+
}
|
|
76757
76818
|
async inspect() {
|
|
76758
76819
|
const status = this.store.inspect();
|
|
76759
76820
|
return {
|
|
@@ -76815,11 +76876,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76815
76876
|
await this.adoptLegacyProjection(entry);
|
|
76816
76877
|
await this.requireReplaceable(entry);
|
|
76817
76878
|
const observedHash = await this.reuseCurrentProjection(entry);
|
|
76818
|
-
const
|
|
76819
|
-
const appliedHash = observedHash ?? await this.project(
|
|
76820
|
-
entry,
|
|
76821
|
-
publishedSource && await packageMatches(publishedSource.absolutePath, entry.contentHash) ? publishedSource.absolutePath : await this.ensureCached(entry)
|
|
76822
|
-
);
|
|
76879
|
+
const appliedHash = observedHash ?? await this.project(entry, await this.ensureCached(entry));
|
|
76823
76880
|
nextProjections[entry.runtimeDirectory] = {
|
|
76824
76881
|
skillId: entry.skillId,
|
|
76825
76882
|
versionId: entry.versionId,
|
|
@@ -76833,13 +76890,16 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76833
76890
|
state: "applied"
|
|
76834
76891
|
});
|
|
76835
76892
|
} catch (error61) {
|
|
76893
|
+
const code = errorCode(error61);
|
|
76894
|
+
const conflict = isUnmanagedConflict(error61) ? await this.observeConflict(entry, code).catch(() => null) : null;
|
|
76836
76895
|
results.push({
|
|
76837
76896
|
skillId: entry.skillId,
|
|
76838
76897
|
versionId: entry.versionId,
|
|
76839
76898
|
contentHash: entry.contentHash,
|
|
76840
76899
|
state: isUnmanagedConflict(error61) ? "conflict" : "failed",
|
|
76841
|
-
errorCode:
|
|
76842
|
-
errorMessage: error61 instanceof Error ? error61.message : String(error61)
|
|
76900
|
+
errorCode: code,
|
|
76901
|
+
errorMessage: error61 instanceof Error ? error61.message : String(error61),
|
|
76902
|
+
...conflict ? { conflict } : {}
|
|
76843
76903
|
});
|
|
76844
76904
|
}
|
|
76845
76905
|
}
|
|
@@ -76856,6 +76916,147 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76856
76916
|
skills: results
|
|
76857
76917
|
};
|
|
76858
76918
|
}
|
|
76919
|
+
async resolveConflictUnlocked(input2) {
|
|
76920
|
+
const manifest = desiredSkillManifestSchema.parse(input2.manifest);
|
|
76921
|
+
const entry = manifest.skills.find(
|
|
76922
|
+
(candidate) => candidate.skillId === input2.skillId && candidate.versionId === input2.versionId
|
|
76923
|
+
);
|
|
76924
|
+
if (!entry || entry.runtimeDirectory !== input2.expectedConflict.runtimeDirectory) {
|
|
76925
|
+
return resolutionFailure(
|
|
76926
|
+
input2,
|
|
76927
|
+
"stale",
|
|
76928
|
+
"SKILL_CONFLICT_STALE",
|
|
76929
|
+
"The Skill conflict changed. Refresh and try again."
|
|
76930
|
+
);
|
|
76931
|
+
}
|
|
76932
|
+
const current = await this.observeConflict(
|
|
76933
|
+
entry,
|
|
76934
|
+
input2.expectedConflict.kind === "managed_destination" ? "UNMANAGED_PATH_CONFLICT" : "COMPATIBILITY_PATH_CONFLICT"
|
|
76935
|
+
).catch(() => null);
|
|
76936
|
+
if (!current || !sameConflict(current, input2.expectedConflict)) {
|
|
76937
|
+
return resolutionFailure(
|
|
76938
|
+
input2,
|
|
76939
|
+
"stale",
|
|
76940
|
+
"SKILL_CONFLICT_STALE",
|
|
76941
|
+
"The local Skill changed. Refresh and try again."
|
|
76942
|
+
);
|
|
76943
|
+
}
|
|
76944
|
+
try {
|
|
76945
|
+
if (input2.resolution.kind === "rename_local") {
|
|
76946
|
+
await this.renameLocalConflict(entry, current, input2.resolution.name);
|
|
76947
|
+
const reconciled = await this.reconcileUnlocked(manifest);
|
|
76948
|
+
return resolutionFromReconcile(input2, reconciled);
|
|
76949
|
+
}
|
|
76950
|
+
return await this.overwriteLocalConflict(input2, entry, current, manifest);
|
|
76951
|
+
} catch (error61) {
|
|
76952
|
+
return resolutionFailure(
|
|
76953
|
+
input2,
|
|
76954
|
+
errorCode(error61) === "SKILL_CONFLICT_STALE" ? "stale" : "failed",
|
|
76955
|
+
errorCode(error61),
|
|
76956
|
+
error61 instanceof Error ? error61.message : String(error61)
|
|
76957
|
+
);
|
|
76958
|
+
}
|
|
76959
|
+
}
|
|
76960
|
+
async observeConflict(entry, code) {
|
|
76961
|
+
const kind = code === "COMPATIBILITY_PATH_CONFLICT" ? "compatibility_destination" : "managed_destination";
|
|
76962
|
+
const directory = this.conflictDirectory(entry.runtimeDirectory, kind);
|
|
76963
|
+
const inspected = await inspectSkillPackage(directory, { expectedName: null });
|
|
76964
|
+
return {
|
|
76965
|
+
kind,
|
|
76966
|
+
runtimeDirectory: entry.runtimeDirectory,
|
|
76967
|
+
observedHash: inspected.contentHash,
|
|
76968
|
+
observedName: inspected.metadata.name
|
|
76969
|
+
};
|
|
76970
|
+
}
|
|
76971
|
+
conflictDirectory(runtimeDirectory, kind) {
|
|
76972
|
+
requireSafeRuntimeDirectory(runtimeDirectory);
|
|
76973
|
+
return (0, import_node_path22.join)(
|
|
76974
|
+
kind === "managed_destination" ? this.managedSkillsDirectory : this.compatibilitySkillsDirectory,
|
|
76975
|
+
runtimeDirectory
|
|
76976
|
+
);
|
|
76977
|
+
}
|
|
76978
|
+
async renameLocalConflict(entry, conflict, name) {
|
|
76979
|
+
requirePortableSkillName(name);
|
|
76980
|
+
const source = this.conflictDirectory(entry.runtimeDirectory, conflict.kind);
|
|
76981
|
+
const destination = (0, import_node_path22.join)((0, import_node_path22.dirname)(source), name);
|
|
76982
|
+
if (await pathExists2(destination)) {
|
|
76983
|
+
throw Object.assign(new Error(`A local Skill named ${name} already exists`), {
|
|
76984
|
+
code: "SKILL_LOCAL_NAME_CONFLICT"
|
|
76985
|
+
});
|
|
76986
|
+
}
|
|
76987
|
+
const suffix = `${process.pid}-${(0, import_node_crypto15.randomBytes)(8).toString("hex")}`;
|
|
76988
|
+
const backup = `${source}.rename-backup-${suffix}`;
|
|
76989
|
+
const pending = `${source}.rename-pending-${suffix}`;
|
|
76990
|
+
let sourceMoved = false;
|
|
76991
|
+
let destinationInstalled = false;
|
|
76992
|
+
try {
|
|
76993
|
+
await (0, import_promises5.rename)(source, backup);
|
|
76994
|
+
sourceMoved = true;
|
|
76995
|
+
await (0, import_promises5.cp)(backup, pending, { recursive: true, errorOnExist: true, force: false });
|
|
76996
|
+
const skillMarkdown = (0, import_node_path22.join)(pending, "SKILL.md");
|
|
76997
|
+
await (0, import_promises5.writeFile)(
|
|
76998
|
+
skillMarkdown,
|
|
76999
|
+
rewriteSkillMarkdownName(await (0, import_promises5.readFile)(skillMarkdown, "utf8"), name),
|
|
77000
|
+
{
|
|
77001
|
+
encoding: "utf8",
|
|
77002
|
+
mode: 420
|
|
77003
|
+
}
|
|
77004
|
+
);
|
|
77005
|
+
await inspectSkillPackage(pending, { expectedName: name });
|
|
77006
|
+
await (0, import_promises5.rename)(pending, destination);
|
|
77007
|
+
destinationInstalled = true;
|
|
77008
|
+
await (0, import_promises5.rm)(backup, { recursive: true, force: true });
|
|
77009
|
+
} catch (error61) {
|
|
77010
|
+
if (destinationInstalled) await (0, import_promises5.rm)(destination, { recursive: true, force: true });
|
|
77011
|
+
if (sourceMoved && await pathExists2(backup) && !await pathExists2(source)) {
|
|
77012
|
+
await (0, import_promises5.rename)(backup, source);
|
|
77013
|
+
}
|
|
77014
|
+
throw error61;
|
|
77015
|
+
} finally {
|
|
77016
|
+
await (0, import_promises5.rm)(pending, { recursive: true, force: true });
|
|
77017
|
+
if (!sourceMoved || destinationInstalled) {
|
|
77018
|
+
await (0, import_promises5.rm)(backup, { recursive: true, force: true });
|
|
77019
|
+
}
|
|
77020
|
+
}
|
|
77021
|
+
}
|
|
77022
|
+
async overwriteLocalConflict(input2, entry, conflict, manifest) {
|
|
77023
|
+
const source = this.conflictDirectory(entry.runtimeDirectory, conflict.kind);
|
|
77024
|
+
const backup = `${source}.overwrite-backup-${process.pid}-${(0, import_node_crypto15.randomBytes)(8).toString("hex")}`;
|
|
77025
|
+
await (0, import_promises5.rename)(source, backup);
|
|
77026
|
+
try {
|
|
77027
|
+
const reconciled = await this.reconcileUnlocked(manifest);
|
|
77028
|
+
const result = resolutionFromReconcile(input2, reconciled);
|
|
77029
|
+
if (result.state !== "applied") {
|
|
77030
|
+
await this.removeResolvedProjection(entry, conflict.kind);
|
|
77031
|
+
await (0, import_promises5.rename)(backup, source);
|
|
77032
|
+
return result;
|
|
77033
|
+
}
|
|
77034
|
+
await (0, import_promises5.rm)(backup, { recursive: true, force: true });
|
|
77035
|
+
return result;
|
|
77036
|
+
} catch (error61) {
|
|
77037
|
+
await this.removeResolvedProjection(entry, conflict.kind).catch(() => void 0);
|
|
77038
|
+
if (!await pathExists2(source) && await pathExists2(backup)) await (0, import_promises5.rename)(backup, source);
|
|
77039
|
+
throw error61;
|
|
77040
|
+
}
|
|
77041
|
+
}
|
|
77042
|
+
async removeResolvedProjection(entry, conflictKind) {
|
|
77043
|
+
const destination = this.conflictDirectory(entry.runtimeDirectory, conflictKind);
|
|
77044
|
+
if (!await pathExists2(destination)) return;
|
|
77045
|
+
if (conflictKind === "managed_destination") {
|
|
77046
|
+
const marker = await readMarker(destination);
|
|
77047
|
+
if (marker?.skillId === entry.skillId && marker.versionId === entry.versionId && marker.contentHash === entry.contentHash) {
|
|
77048
|
+
await (0, import_promises5.rm)(destination, { recursive: true, force: true });
|
|
77049
|
+
}
|
|
77050
|
+
return;
|
|
77051
|
+
}
|
|
77052
|
+
const canonical = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
77053
|
+
const projection = {
|
|
77054
|
+
skillId: entry.skillId,
|
|
77055
|
+
versionId: entry.versionId,
|
|
77056
|
+
contentHash: entry.contentHash
|
|
77057
|
+
};
|
|
77058
|
+
await removeCompatibilityProjection(destination, canonical, projection);
|
|
77059
|
+
}
|
|
76859
77060
|
async reuseCurrentProjection(entry) {
|
|
76860
77061
|
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
76861
77062
|
const marker = await readMarker(destination);
|
|
@@ -77233,6 +77434,66 @@ function requireSafeRuntimeDirectory(value2) {
|
|
|
77233
77434
|
throw new Error(`Unsafe managed Skill directory: ${value2}`);
|
|
77234
77435
|
}
|
|
77235
77436
|
}
|
|
77437
|
+
function requirePortableSkillName(value2) {
|
|
77438
|
+
if (!/^(?!-)(?!.*--)[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value2) || value2.length > 64) {
|
|
77439
|
+
throw Object.assign(
|
|
77440
|
+
new Error("Local Skill names use lowercase letters, numbers, and single hyphens"),
|
|
77441
|
+
{ code: "INVALID_SKILL_NAME" }
|
|
77442
|
+
);
|
|
77443
|
+
}
|
|
77444
|
+
}
|
|
77445
|
+
function rewriteSkillMarkdownName(markdown, name) {
|
|
77446
|
+
const lineEnding = markdown.includes("\r\n") ? "\r\n" : "\n";
|
|
77447
|
+
const lines = markdown.split(/\r?\n/);
|
|
77448
|
+
if (lines[0]?.trim() !== "---") {
|
|
77449
|
+
throw Object.assign(new Error("The local Skill has invalid SKILL.md frontmatter"), {
|
|
77450
|
+
code: "INVALID_FRONTMATTER"
|
|
77451
|
+
});
|
|
77452
|
+
}
|
|
77453
|
+
const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
|
|
77454
|
+
const nameIndex = lines.findIndex(
|
|
77455
|
+
(line, index) => index > 0 && index < end && /^name\s*:/.test(line)
|
|
77456
|
+
);
|
|
77457
|
+
if (end < 0 || nameIndex < 0) {
|
|
77458
|
+
throw Object.assign(new Error("The local Skill has invalid SKILL.md frontmatter"), {
|
|
77459
|
+
code: "INVALID_FRONTMATTER"
|
|
77460
|
+
});
|
|
77461
|
+
}
|
|
77462
|
+
lines[nameIndex] = `name: ${name}`;
|
|
77463
|
+
return lines.join(lineEnding);
|
|
77464
|
+
}
|
|
77465
|
+
function sameConflict(left, right) {
|
|
77466
|
+
return left.kind === right.kind && left.runtimeDirectory === right.runtimeDirectory && left.observedHash === right.observedHash && left.observedName === right.observedName;
|
|
77467
|
+
}
|
|
77468
|
+
function resolutionFromReconcile(input2, result) {
|
|
77469
|
+
const resolved = result.skills.find(
|
|
77470
|
+
(candidate) => candidate.skillId === input2.skillId && candidate.versionId === input2.versionId
|
|
77471
|
+
);
|
|
77472
|
+
if (resolved?.state === "applied") {
|
|
77473
|
+
return {
|
|
77474
|
+
commandId: input2.commandId,
|
|
77475
|
+
skillId: input2.skillId,
|
|
77476
|
+
versionId: input2.versionId,
|
|
77477
|
+
state: "applied"
|
|
77478
|
+
};
|
|
77479
|
+
}
|
|
77480
|
+
return resolutionFailure(
|
|
77481
|
+
input2,
|
|
77482
|
+
"failed",
|
|
77483
|
+
resolved?.errorCode ?? "SKILL_RECONCILE_FAILED",
|
|
77484
|
+
resolved?.errorMessage ?? "The Skill could not be installed after resolving the conflict"
|
|
77485
|
+
);
|
|
77486
|
+
}
|
|
77487
|
+
function resolutionFailure(input2, state, errorCodeValue, errorMessage) {
|
|
77488
|
+
return {
|
|
77489
|
+
commandId: input2.commandId,
|
|
77490
|
+
skillId: input2.skillId,
|
|
77491
|
+
versionId: input2.versionId,
|
|
77492
|
+
state,
|
|
77493
|
+
errorCode: errorCodeValue,
|
|
77494
|
+
errorMessage
|
|
77495
|
+
};
|
|
77496
|
+
}
|
|
77236
77497
|
function localRasterMediaType(path2) {
|
|
77237
77498
|
const lower = path2.toLowerCase();
|
|
77238
77499
|
if (lower.endsWith(".gif")) return "image/gif";
|
|
@@ -77556,12 +77817,13 @@ async function startDaemon(args) {
|
|
|
77556
77817
|
transcriptStreamer: nativeTranscriptStreamer,
|
|
77557
77818
|
sink: {
|
|
77558
77819
|
deliver: (envelope) => new Promise((resolveDelivery, rejectDelivery) => {
|
|
77820
|
+
const payload = "eventType" in envelope ? { ...envelope, canonicalSourceDelivery: true } : envelope;
|
|
77559
77821
|
socket.timeout(5e3).emit(
|
|
77560
77822
|
"native.session.event",
|
|
77561
|
-
|
|
77823
|
+
payload,
|
|
77562
77824
|
(error61, acknowledgement) => {
|
|
77563
|
-
const
|
|
77564
|
-
if (!
|
|
77825
|
+
const accepted2 = !error61 && acknowledgement?.ok === true;
|
|
77826
|
+
if (!accepted2) {
|
|
77565
77827
|
pushLog(
|
|
77566
77828
|
`native-hook-delivery-deferred event=${envelope.eventId} provider=${envelope.provider} error=${error61?.message ?? "none"} ack=${acknowledgement?.ok ?? "missing"} retryable=${acknowledgement?.retryable ?? "missing"}`
|
|
77567
77829
|
);
|
|
@@ -77574,10 +77836,24 @@ async function startDaemon(args) {
|
|
|
77574
77836
|
);
|
|
77575
77837
|
return;
|
|
77576
77838
|
}
|
|
77577
|
-
resolveDelivery(
|
|
77839
|
+
resolveDelivery({
|
|
77840
|
+
accepted: accepted2,
|
|
77841
|
+
...!error61 && acknowledgement?.binding ? { binding: acknowledgement.binding } : {}
|
|
77842
|
+
});
|
|
77578
77843
|
}
|
|
77579
77844
|
);
|
|
77580
|
-
})
|
|
77845
|
+
}),
|
|
77846
|
+
deliverCanonical: async (binding, source) => {
|
|
77847
|
+
eventOutbox.enqueueSource(
|
|
77848
|
+
binding.conversationId,
|
|
77849
|
+
binding.runId,
|
|
77850
|
+
source.eventId,
|
|
77851
|
+
source.event
|
|
77852
|
+
);
|
|
77853
|
+
eventOutbox.flush(socket);
|
|
77854
|
+
await eventOutbox.waitForAcknowledgement(source.eventId);
|
|
77855
|
+
return true;
|
|
77856
|
+
}
|
|
77581
77857
|
},
|
|
77582
77858
|
onTranscriptError: ({ envelope, error: error61 }) => pushLog(
|
|
77583
77859
|
`native-transcript-unavailable event=${envelope.eventId} provider=${envelope.provider} error=${error61.message}`
|
|
@@ -80085,31 +80361,40 @@ function configFileContainsMarker(path2, marker) {
|
|
|
80085
80361
|
return false;
|
|
80086
80362
|
}
|
|
80087
80363
|
}
|
|
80088
|
-
function inspectNativeHooksConfigured(providerKind, homeDir = (0, import_node_os14.homedir)()) {
|
|
80364
|
+
function inspectNativeHooksConfigured(providerKind, homeDir = (0, import_node_os14.homedir)(), expectedConfigPath) {
|
|
80365
|
+
const matchesActiveProfile = (path2, marker) => {
|
|
80366
|
+
if (!configFileContainsMarker(path2, marker)) return false;
|
|
80367
|
+
if (!expectedConfigPath) return true;
|
|
80368
|
+
try {
|
|
80369
|
+
return extractNativeHookConfigPath((0, import_node_fs22.readFileSync)(path2, "utf8")) === expectedConfigPath;
|
|
80370
|
+
} catch {
|
|
80371
|
+
return false;
|
|
80372
|
+
}
|
|
80373
|
+
};
|
|
80089
80374
|
switch (providerKind) {
|
|
80090
80375
|
case "claude_cli":
|
|
80091
|
-
return
|
|
80376
|
+
return matchesActiveProfile((0, import_node_path25.join)(homeDir, ".claude", "settings.json"), ALAN_HOOK_MARKER);
|
|
80092
80377
|
case "codex_app_server":
|
|
80093
|
-
return
|
|
80378
|
+
return matchesActiveProfile((0, import_node_path25.join)(homeDir, ".codex", "hooks.json"), ALAN_HOOK_MARKER);
|
|
80094
80379
|
case "copilot_cli":
|
|
80095
|
-
return
|
|
80380
|
+
return matchesActiveProfile(
|
|
80096
80381
|
(0, import_node_path25.join)(homeDir, ".copilot", "hooks", "alan-native-session.json"),
|
|
80097
80382
|
ALAN_HOOK_MARKER
|
|
80098
80383
|
);
|
|
80099
80384
|
case "cursor_agent_cli":
|
|
80100
|
-
return
|
|
80385
|
+
return matchesActiveProfile((0, import_node_path25.join)(homeDir, ".cursor", "hooks.json"), ALAN_HOOK_MARKER);
|
|
80101
80386
|
case "kimi_cli":
|
|
80102
|
-
return
|
|
80387
|
+
return matchesActiveProfile(
|
|
80103
80388
|
(0, import_node_path25.join)(homeDir, ".kimi-code", "config.toml"),
|
|
80104
80389
|
ALAN_KIMI_HOOKS_START
|
|
80105
80390
|
);
|
|
80106
80391
|
case "grok_cli":
|
|
80107
|
-
return
|
|
80392
|
+
return matchesActiveProfile(
|
|
80108
80393
|
(0, import_node_path25.join)(homeDir, ".grok", "hooks", "alan-native-session.json"),
|
|
80109
80394
|
ALAN_HOOK_MARKER
|
|
80110
80395
|
);
|
|
80111
80396
|
case "opencode_cli":
|
|
80112
|
-
return
|
|
80397
|
+
return matchesActiveProfile(
|
|
80113
80398
|
(0, import_node_path25.join)(homeDir, ".config", "opencode", "plugins", "alan-native-session.js"),
|
|
80114
80399
|
ALAN_OPENCODE_PLUGIN_MARKER
|
|
80115
80400
|
);
|
|
@@ -80117,6 +80402,24 @@ function inspectNativeHooksConfigured(providerKind, homeDir = (0, import_node_os
|
|
|
80117
80402
|
return false;
|
|
80118
80403
|
}
|
|
80119
80404
|
}
|
|
80405
|
+
function extractNativeHookConfigPath(text) {
|
|
80406
|
+
const jsonMatch = text.match(/"--config-path"\s*,\s*"((?:\\"|[^"])*)"/);
|
|
80407
|
+
if (jsonMatch?.[1]) {
|
|
80408
|
+
try {
|
|
80409
|
+
return JSON.parse(`"${jsonMatch[1]}"`);
|
|
80410
|
+
} catch {
|
|
80411
|
+
}
|
|
80412
|
+
}
|
|
80413
|
+
const match = text.match(
|
|
80414
|
+
/(?:['"])?--config-path(?:['"])?(?:=|\s+)('(?:\\'|[^'])*'|"(?:\\"|[^"])*"|[^\s#]+)/
|
|
80415
|
+
);
|
|
80416
|
+
if (!match?.[1]) return null;
|
|
80417
|
+
const raw = match[1];
|
|
80418
|
+
if (raw.startsWith("'") || raw.startsWith('"')) {
|
|
80419
|
+
return raw.slice(1, -1).replaceAll(String.raw`\'`, "'").replaceAll(String.raw`\"`, '"');
|
|
80420
|
+
}
|
|
80421
|
+
return raw;
|
|
80422
|
+
}
|
|
80120
80423
|
|
|
80121
80424
|
// src/integration-cli.ts
|
|
80122
80425
|
function alanMcpServers(apiUrl) {
|
|
@@ -80733,13 +81036,14 @@ function runNativeHookCommand(args) {
|
|
|
80733
81036
|
function collectNativeIntegrationStatus(args = []) {
|
|
80734
81037
|
bindConfigPath(args);
|
|
80735
81038
|
const config2 = readConfig();
|
|
81039
|
+
const configPath = getConfigPath();
|
|
80736
81040
|
const env = getDaemonCliEnvironment();
|
|
80737
81041
|
const homeDir = (0, import_node_os15.homedir)();
|
|
80738
81042
|
return NATIVE_SESSION_PROVIDER_CAPABILITIES.map((capability) => ({
|
|
80739
81043
|
provider: capability.providerKind,
|
|
80740
81044
|
command: capability.command,
|
|
80741
81045
|
installed: resolveCliExecutable(capability.command, env) !== null,
|
|
80742
|
-
hooksConfigured: inspectNativeHooksConfigured(capability.providerKind, homeDir),
|
|
81046
|
+
hooksConfigured: inspectNativeHooksConfigured(capability.providerKind, homeDir, configPath),
|
|
80743
81047
|
hookCoverage: capability.capabilities.lifecycleHooks ? "lifecycle" : capability.capabilities.state === "degraded" ? "notification" : "none",
|
|
80744
81048
|
transcriptStreaming: capability.capabilities.transcriptDelta,
|
|
80745
81049
|
inboxReady: Boolean(config2.eventSpoolKey)
|