@alan-ai-hq/agent-manager-darwin-arm64 0.1.138 → 0.1.139
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/alan-agent.cjs +422 -142
- package/alan-holder.cjs +41 -14
- package/package.json +1 -1
package/alan-agent.cjs
CHANGED
|
@@ -20782,7 +20782,11 @@ var init_github_proxy = __esm({
|
|
|
20782
20782
|
];
|
|
20783
20783
|
gitHubProxyUpstreamSchema = external_exports.enum(GITHUB_PROXY_UPSTREAMS);
|
|
20784
20784
|
GITHUB_PROXY_PLACEHOLDER_TOKEN = "proxy-injected";
|
|
20785
|
-
GITHUB_PROXY_REFUSAL_CODES = [
|
|
20785
|
+
GITHUB_PROXY_REFUSAL_CODES = [
|
|
20786
|
+
"host_not_proxied",
|
|
20787
|
+
"machine_not_allowed",
|
|
20788
|
+
"github_not_connected"
|
|
20789
|
+
];
|
|
20786
20790
|
gitHubProxyErrorSchema = external_exports.object({
|
|
20787
20791
|
message: external_exports.string().min(1),
|
|
20788
20792
|
documentation_url: external_exports.string(),
|
|
@@ -24779,12 +24783,58 @@ function conversationTurnView(ordinal, state, previousDisplay = []) {
|
|
|
24779
24783
|
read: prepareConversationTurnRead(state)
|
|
24780
24784
|
};
|
|
24781
24785
|
}
|
|
24786
|
+
function diffArray(previous, next) {
|
|
24787
|
+
const changes = [];
|
|
24788
|
+
for (const [index, value2] of next.entries()) {
|
|
24789
|
+
if (previous[index] !== value2)
|
|
24790
|
+
changes.push({ index, value: value2 });
|
|
24791
|
+
}
|
|
24792
|
+
return { length: next.length, changes };
|
|
24793
|
+
}
|
|
24794
|
+
function stateFields(state) {
|
|
24795
|
+
const { entries: _entries, unknown: _unknown2, presentation: _presentation, ...fields } = state;
|
|
24796
|
+
return fields;
|
|
24797
|
+
}
|
|
24798
|
+
function diffTranscriptState(previous, next) {
|
|
24799
|
+
return {
|
|
24800
|
+
entries: diffArray(previous.entries, next.entries),
|
|
24801
|
+
unknown: diffArray(previous.unknown, next.unknown),
|
|
24802
|
+
fields: stateFields(next)
|
|
24803
|
+
};
|
|
24804
|
+
}
|
|
24805
|
+
function createLiveTurnFrameEncoder() {
|
|
24806
|
+
const sent = /* @__PURE__ */ new Map();
|
|
24807
|
+
return (ordinal, state) => {
|
|
24808
|
+
const previous = sent.get(ordinal);
|
|
24809
|
+
sent.delete(ordinal);
|
|
24810
|
+
sent.set(ordinal, state);
|
|
24811
|
+
for (const oldest of sent.keys()) {
|
|
24812
|
+
if (sent.size <= SENT_LIVE_TURNS)
|
|
24813
|
+
break;
|
|
24814
|
+
sent.delete(oldest);
|
|
24815
|
+
}
|
|
24816
|
+
return previous ? { kind: "patch", ordinal, patch: diffTranscriptState(previous, state) } : { kind: "snapshot", ordinal, state };
|
|
24817
|
+
};
|
|
24818
|
+
}
|
|
24782
24819
|
function isRecord8(value2) {
|
|
24783
24820
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
24784
24821
|
}
|
|
24785
24822
|
function isTranscriptState(value2) {
|
|
24786
24823
|
return isRecord8(value2) && typeof value2.state === "string" && Array.isArray(value2.entries) && Array.isArray(value2.notices) && Array.isArray(value2.unknown);
|
|
24787
24824
|
}
|
|
24825
|
+
function isArrayPatch(value2) {
|
|
24826
|
+
return isRecord8(value2) && Number.isSafeInteger(value2.length) && Array.isArray(value2.changes) && value2.changes.every((change) => isRecord8(change) && Number.isSafeInteger(change.index) && "value" in change);
|
|
24827
|
+
}
|
|
24828
|
+
function isTranscriptStatePatch(value2) {
|
|
24829
|
+
return isRecord8(value2) && isArrayPatch(value2.entries) && isArrayPatch(value2.unknown) && isRecord8(value2.fields) && typeof value2.fields.state === "string" && Array.isArray(value2.fields.notices);
|
|
24830
|
+
}
|
|
24831
|
+
function isLiveTurnFrame(value2) {
|
|
24832
|
+
if (!isRecord8(value2) || !Number.isSafeInteger(value2.ordinal))
|
|
24833
|
+
return false;
|
|
24834
|
+
if (value2.kind === "snapshot")
|
|
24835
|
+
return isTranscriptState(value2.state);
|
|
24836
|
+
return value2.kind === "patch" && isTranscriptStatePatch(value2.patch);
|
|
24837
|
+
}
|
|
24788
24838
|
function isPendingAsk(value2) {
|
|
24789
24839
|
return value2 === null || isRecord8(value2) && typeof value2.toolCallId === "string" && isRecord8(value2.rawInput) && Array.isArray(value2.questions) && value2.questions.every((question) => isRecord8(question) && typeof question.question === "string" && (question.header === void 0 || typeof question.header === "string") && typeof question.multiSelect === "boolean" && Array.isArray(question.options) && question.options.every((option2) => isRecord8(option2) && typeof option2.label === "string" && (option2.description === void 0 || typeof option2.description === "string")));
|
|
24790
24840
|
}
|
|
@@ -24800,6 +24850,7 @@ function isConversationMessageTurn(value2) {
|
|
|
24800
24850
|
function isConversationMessagesPage(value2) {
|
|
24801
24851
|
return isRecord8(value2) && typeof value2.revision === "string" && typeof value2.streamCursor === "string" && (value2.before === null || typeof value2.before === "string") && Array.isArray(value2.turns) && value2.turns.every(isConversationMessageTurn);
|
|
24802
24852
|
}
|
|
24853
|
+
var LIVE_TURN_FRAMES, LIVE_TURN_EVENT, SENT_LIVE_TURNS;
|
|
24803
24854
|
var init_conversation_messages = __esm({
|
|
24804
24855
|
"../shared/dist/agent/acp/conversation-messages.js"() {
|
|
24805
24856
|
"use strict";
|
|
@@ -24810,6 +24861,9 @@ var init_conversation_messages = __esm({
|
|
|
24810
24861
|
init_prepare_conversation_turns();
|
|
24811
24862
|
init_reduce();
|
|
24812
24863
|
init_transcript_http();
|
|
24864
|
+
LIVE_TURN_FRAMES = "patch";
|
|
24865
|
+
LIVE_TURN_EVENT = "live_turn";
|
|
24866
|
+
SENT_LIVE_TURNS = 8;
|
|
24813
24867
|
}
|
|
24814
24868
|
});
|
|
24815
24869
|
|
|
@@ -24835,15 +24889,6 @@ var init_transcript_byte_decoder = __esm({
|
|
|
24835
24889
|
});
|
|
24836
24890
|
|
|
24837
24891
|
// ../shared/dist/agent/acp/transcript-fold.js
|
|
24838
|
-
function snapshotTranscriptState(state) {
|
|
24839
|
-
return {
|
|
24840
|
-
...state,
|
|
24841
|
-
entries: state.entries.map((entry) => entry.kind === "message" ? { ...entry, content: [...entry.content] } : { ...entry, content: [...entry.content], locations: [...entry.locations] }),
|
|
24842
|
-
notices: [...state.notices],
|
|
24843
|
-
unknown: [...state.unknown],
|
|
24844
|
-
...state.activities ? { activities: state.activities.map((activity) => ({ ...activity })) } : {}
|
|
24845
|
-
};
|
|
24846
|
-
}
|
|
24847
24892
|
function isRecord9(value2) {
|
|
24848
24893
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
24849
24894
|
}
|
|
@@ -24884,9 +24929,130 @@ function scopeTranscriptEvent(value2) {
|
|
|
24884
24929
|
scoped.content = scopedContent(update.content, turnId);
|
|
24885
24930
|
return { ...event, update: scoped };
|
|
24886
24931
|
}
|
|
24932
|
+
function placeMessage(cache2, message2, updateOffset, entryOffset, startsWithPrompt) {
|
|
24933
|
+
const cached2 = cache2.get(message2.messageId);
|
|
24934
|
+
const source = message2.state;
|
|
24935
|
+
const sameSource = cached2?.source === source;
|
|
24936
|
+
if (sameSource && cached2.updateCount === source.updateCount && cached2.updateOffset === updateOffset && cached2.entryOffset === entryOffset && cached2.startsWithPrompt === startsWithPrompt)
|
|
24937
|
+
return cached2.state;
|
|
24938
|
+
const replacedEntries = cached2 && !sameSource ? cached2.source.entries : void 0;
|
|
24939
|
+
const entries = source.entries.map((entry, index) => {
|
|
24940
|
+
const previous = cached2?.state.entries[index];
|
|
24941
|
+
const lastUpdateIndex = entry.lastUpdateIndex === void 0 ? void 0 : entry.lastUpdateIndex + updateOffset;
|
|
24942
|
+
if (previous && cached2.updateOffset === updateOffset && previous.id === entry.id && previous.kind === entry.kind && (sameSource ? entry.lastUpdateIndex !== void 0 && previous.lastUpdateIndex === lastUpdateIndex : replacedEntries?.[index] === entry))
|
|
24943
|
+
return previous;
|
|
24944
|
+
return entry.kind === "message" ? { ...entry, lastUpdateIndex, content: [...entry.content] } : {
|
|
24945
|
+
...entry,
|
|
24946
|
+
lastUpdateIndex,
|
|
24947
|
+
content: [...entry.content],
|
|
24948
|
+
locations: [...entry.locations]
|
|
24949
|
+
};
|
|
24950
|
+
});
|
|
24951
|
+
const state = {
|
|
24952
|
+
...source,
|
|
24953
|
+
entries,
|
|
24954
|
+
notices: [...source.notices],
|
|
24955
|
+
unknown: [...source.unknown],
|
|
24956
|
+
...source.activities ? {
|
|
24957
|
+
activities: source.activities.map((activity) => ({
|
|
24958
|
+
...activity,
|
|
24959
|
+
firstEntryIndex: entryOffset + activity.firstEntryIndex - (startsWithPrompt && activity.firstEntryIndex === 0 ? 1 : 0)
|
|
24960
|
+
}))
|
|
24961
|
+
} : {}
|
|
24962
|
+
};
|
|
24963
|
+
cache2.set(message2.messageId, {
|
|
24964
|
+
source,
|
|
24965
|
+
updateCount: source.updateCount,
|
|
24966
|
+
updateOffset,
|
|
24967
|
+
entryOffset,
|
|
24968
|
+
startsWithPrompt,
|
|
24969
|
+
state
|
|
24970
|
+
});
|
|
24971
|
+
return state;
|
|
24972
|
+
}
|
|
24973
|
+
function anchoredUpdateOffset(ordered, cache2) {
|
|
24974
|
+
let natural = 0;
|
|
24975
|
+
for (const message2 of ordered) {
|
|
24976
|
+
const placed = cache2.get(message2.messageId);
|
|
24977
|
+
if (placed)
|
|
24978
|
+
return natural - placed.updateOffset;
|
|
24979
|
+
natural += message2.state.updateCount ?? 0;
|
|
24980
|
+
}
|
|
24981
|
+
return 0;
|
|
24982
|
+
}
|
|
24983
|
+
function mergeTranscriptMessages(messages, cache2) {
|
|
24984
|
+
const merged = emptyTranscript();
|
|
24985
|
+
const ordered = [...messages].sort((left, right) => (left.turnOrdinal ?? 0) - (right.turnOrdinal ?? 0) || left.messageId.localeCompare(right.messageId));
|
|
24986
|
+
let updateOffset = -anchoredUpdateOffset(ordered, cache2);
|
|
24987
|
+
const seenToolIds = /* @__PURE__ */ new Set();
|
|
24988
|
+
const seenNotices = /* @__PURE__ */ new Set();
|
|
24989
|
+
for (const message2 of ordered) {
|
|
24990
|
+
const entryOffset = merged.entries.length;
|
|
24991
|
+
const previous = merged.entries.at(-1);
|
|
24992
|
+
const startsWithPrompt = message2.role !== "user" && previous?.kind === "message" && previous.role === "user";
|
|
24993
|
+
const state = placeMessage(cache2, message2, updateOffset, entryOffset, startsWithPrompt);
|
|
24994
|
+
const removedBefore = [0];
|
|
24995
|
+
const duplicateToolIds = /* @__PURE__ */ new Set();
|
|
24996
|
+
for (const entry of state.entries) {
|
|
24997
|
+
const parentId = entry._meta?.["alan.dev/parentToolCallId"];
|
|
24998
|
+
const rawId = entry._meta?.[TRANSCRIPT_TOOL_RESPONSE_ID_META];
|
|
24999
|
+
const providerEvent = entry._meta?.["alan.dev/providerEvent"];
|
|
25000
|
+
const providerEventId = providerEvent && typeof providerEvent === "object" && "id" in providerEvent ? providerEvent.id : void 0;
|
|
25001
|
+
const toolId = entry.kind === "tool_call" && typeof rawId === "string" && typeof providerEventId === "string" ? `${rawId}:${providerEventId}` : void 0;
|
|
25002
|
+
const duplicate = toolId !== void 0 && seenToolIds.has(toolId) || typeof parentId === "string" && duplicateToolIds.has(parentId);
|
|
25003
|
+
if (!duplicate) {
|
|
25004
|
+
merged.entries.push(entry);
|
|
25005
|
+
if (toolId)
|
|
25006
|
+
seenToolIds.add(toolId);
|
|
25007
|
+
}
|
|
25008
|
+
if (duplicate && toolId)
|
|
25009
|
+
duplicateToolIds.add(entry.id);
|
|
25010
|
+
removedBefore.push((removedBefore.at(-1) ?? 0) + Number(duplicate));
|
|
25011
|
+
}
|
|
25012
|
+
if (state.activities?.length) {
|
|
25013
|
+
merged.activities ??= [];
|
|
25014
|
+
merged.activities.push(...state.activities.map((activity, index) => ({
|
|
25015
|
+
...activity,
|
|
25016
|
+
firstEntryIndex: activity.firstEntryIndex - (removedBefore[message2.state.activities?.[index]?.firstEntryIndex ?? 0] ?? 0)
|
|
25017
|
+
})));
|
|
25018
|
+
}
|
|
25019
|
+
for (const notice2 of state.notices) {
|
|
25020
|
+
const key = JSON.stringify([notice2.level, notice2.message]);
|
|
25021
|
+
if (seenNotices.has(key))
|
|
25022
|
+
continue;
|
|
25023
|
+
seenNotices.add(key);
|
|
25024
|
+
merged.notices.push({
|
|
25025
|
+
...notice2,
|
|
25026
|
+
firstEntryIndex: startsWithPrompt ? entryOffset - 1 : entryOffset
|
|
25027
|
+
});
|
|
25028
|
+
}
|
|
25029
|
+
merged.unknown.push(...state.unknown);
|
|
25030
|
+
if (state.userMessageAt !== void 0)
|
|
25031
|
+
merged.userMessageAt = Math.max(merged.userMessageAt ?? state.userMessageAt, state.userMessageAt);
|
|
25032
|
+
if (message2.role !== "user") {
|
|
25033
|
+
merged.state = state.state;
|
|
25034
|
+
merged.stopReason = state.stopReason;
|
|
25035
|
+
merged.thinkingTokens = state.thinkingTokens;
|
|
25036
|
+
if (state.awaitingToolCallIds)
|
|
25037
|
+
merged.awaitingToolCallIds = state.awaitingToolCallIds;
|
|
25038
|
+
else
|
|
25039
|
+
delete merged.awaitingToolCallIds;
|
|
25040
|
+
}
|
|
25041
|
+
if (state.plan)
|
|
25042
|
+
merged.plan = state.plan;
|
|
25043
|
+
if (state.usage)
|
|
25044
|
+
merged.usage = state.usage;
|
|
25045
|
+
if (state.title)
|
|
25046
|
+
merged.title = state.title;
|
|
25047
|
+
updateOffset += state.updateCount ?? 0;
|
|
25048
|
+
}
|
|
25049
|
+
merged.updateCount = updateOffset;
|
|
25050
|
+
return merged;
|
|
25051
|
+
}
|
|
24887
25052
|
var init_transcript_fold = __esm({
|
|
24888
25053
|
"../shared/dist/agent/acp/transcript-fold.js"() {
|
|
24889
25054
|
"use strict";
|
|
25055
|
+
init_reduce();
|
|
24890
25056
|
init_transcript_http();
|
|
24891
25057
|
init_types2();
|
|
24892
25058
|
}
|
|
@@ -27985,6 +28151,9 @@ function classifyResultError(event, context) {
|
|
|
27985
28151
|
if (classified.errorKind !== "unknown_cli_error" || !isApiError) return classified;
|
|
27986
28152
|
return { ...specForErrorKind("provider_error"), message: classified.message };
|
|
27987
28153
|
}
|
|
28154
|
+
function isIdleUpdate(update) {
|
|
28155
|
+
return isUpdate(update, "state_update") && update.state === "idle";
|
|
28156
|
+
}
|
|
27988
28157
|
function isSettled22(update) {
|
|
27989
28158
|
return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
|
|
27990
28159
|
}
|
|
@@ -28721,6 +28890,7 @@ var init_claude = __esm({
|
|
|
28721
28890
|
#failure;
|
|
28722
28891
|
#authFailure;
|
|
28723
28892
|
#resultSeen = false;
|
|
28893
|
+
#heldIdle;
|
|
28724
28894
|
constructor(options = {}) {
|
|
28725
28895
|
this.#options = options;
|
|
28726
28896
|
this.taskRecords = options.taskRecords ?? new TaskRecords(options.now ?? (() => systemClock2.now()));
|
|
@@ -28768,7 +28938,17 @@ var init_claude = __esm({
|
|
|
28768
28938
|
readEvent(event) {
|
|
28769
28939
|
const parsed = this.#revise(parseClaudeEvent(event, this.grammar), event);
|
|
28770
28940
|
parsed.push(...this.#handle(event));
|
|
28771
|
-
const
|
|
28941
|
+
const kept = parsed.filter((update) => {
|
|
28942
|
+
if (!isIdleUpdate(update)) return true;
|
|
28943
|
+
if (this.#finalized) return true;
|
|
28944
|
+
this.#heldIdle = update;
|
|
28945
|
+
return false;
|
|
28946
|
+
});
|
|
28947
|
+
if (this.#finalized && this.#heldIdle !== void 0) {
|
|
28948
|
+
if (!kept.some(isIdleUpdate)) kept.push(this.#heldIdle);
|
|
28949
|
+
this.#heldIdle = void 0;
|
|
28950
|
+
}
|
|
28951
|
+
const updates = kept.map((update) => this.taskRecords.stamp(update));
|
|
28772
28952
|
for (const update of updates) this.#applyRunState(update);
|
|
28773
28953
|
return updates;
|
|
28774
28954
|
}
|
|
@@ -44092,15 +44272,16 @@ function createPersistentDriver(provider4, options) {
|
|
|
44092
44272
|
return void 0;
|
|
44093
44273
|
};
|
|
44094
44274
|
const resumeNotice = (spec, session, sink) => {
|
|
44275
|
+
if (spec.resumeFallbackContext) {
|
|
44276
|
+
log.info("holder.session_resume_fallback", { harness: provider4.harness, runId: spec.runId });
|
|
44277
|
+
return { session, contextPrefix: spec.resumeFallbackContext };
|
|
44278
|
+
}
|
|
44095
44279
|
sink.onEvent({
|
|
44096
44280
|
seq: 0,
|
|
44097
44281
|
at: clock.now(),
|
|
44098
44282
|
update: noticeUpdate("warning", "session_resume_failed", RESUME_UNAVAILABLE)
|
|
44099
44283
|
});
|
|
44100
|
-
return {
|
|
44101
|
-
session,
|
|
44102
|
-
...spec.resumeFallbackContext ? { contextPrefix: spec.resumeFallbackContext } : {}
|
|
44103
|
-
};
|
|
44284
|
+
return { session };
|
|
44104
44285
|
};
|
|
44105
44286
|
const managedMcpAccess = async (signal) => {
|
|
44106
44287
|
const managed = options.managedMcp;
|
|
@@ -44175,6 +44356,7 @@ function createPersistentDriver(provider4, options) {
|
|
|
44175
44356
|
};
|
|
44176
44357
|
const _events = __using(_stack, session.onEvent(forward));
|
|
44177
44358
|
live.turn = turn;
|
|
44359
|
+
record2({ sessionUpdate: "state_update", state: "running" });
|
|
44178
44360
|
if (session.pid !== void 0) sink.onSpawned(session.pid);
|
|
44179
44361
|
const onAbort = () => {
|
|
44180
44362
|
void session.cancel();
|
|
@@ -46106,7 +46288,7 @@ function createAlanCodeHolderDriver(options) {
|
|
|
46106
46288
|
open: open6,
|
|
46107
46289
|
turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
|
|
46108
46290
|
attachments: inputs.attachments,
|
|
46109
|
-
skills:
|
|
46291
|
+
skills: inputs.skills,
|
|
46110
46292
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
46111
46293
|
})
|
|
46112
46294
|
},
|
|
@@ -47122,7 +47304,7 @@ function createDroidHolderDriver(options) {
|
|
|
47122
47304
|
},
|
|
47123
47305
|
turnInput: (spec, inputs, contextPrefix) => droidTurnInput(spec, {
|
|
47124
47306
|
attachments: inputs.attachments,
|
|
47125
|
-
skills:
|
|
47307
|
+
skills: inputs.skills,
|
|
47126
47308
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
47127
47309
|
})
|
|
47128
47310
|
},
|
|
@@ -47170,7 +47352,7 @@ function createOpenCodeHolderDriver(options) {
|
|
|
47170
47352
|
},
|
|
47171
47353
|
turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
|
|
47172
47354
|
attachments: inputs.attachments,
|
|
47173
|
-
skills:
|
|
47355
|
+
skills: inputs.skills,
|
|
47174
47356
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
47175
47357
|
})
|
|
47176
47358
|
},
|
|
@@ -53929,7 +54111,7 @@ var require_websocket_server = __commonJS({
|
|
|
53929
54111
|
// package.json
|
|
53930
54112
|
var package_default = {
|
|
53931
54113
|
name: "@alan-ai-hq/agent-manager",
|
|
53932
|
-
version: "0.1.
|
|
54114
|
+
version: "0.1.139",
|
|
53933
54115
|
private: true,
|
|
53934
54116
|
type: "module",
|
|
53935
54117
|
description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
|
|
@@ -54823,7 +55005,8 @@ var openTurnResponseSchema = external_exports.object({
|
|
|
54823
55005
|
runId: external_exports.string().min(1),
|
|
54824
55006
|
userMessageId: external_exports.string().min(1),
|
|
54825
55007
|
assistantMessageId: external_exports.string().min(1),
|
|
54826
|
-
created: external_exports.boolean()
|
|
55008
|
+
created: external_exports.boolean(),
|
|
55009
|
+
turnOrdinals: external_exports.object({ user: external_exports.number().int().nonnegative(), assistant: external_exports.number().int().nonnegative() }).optional()
|
|
54827
55010
|
});
|
|
54828
55011
|
var errorBodySchema2 = external_exports.object({ code: external_exports.string() });
|
|
54829
55012
|
function createNativeSessionsClient({
|
|
@@ -61599,9 +61782,23 @@ async function ingestTurn(ctx, worker, entry, turn) {
|
|
|
61599
61782
|
},
|
|
61600
61783
|
ctx.shutdown
|
|
61601
61784
|
);
|
|
61785
|
+
const ordinals = opened.turnOrdinals;
|
|
61602
61786
|
await ctx.publisher.publish({
|
|
61603
61787
|
runId: opened.runId,
|
|
61604
61788
|
conversationId: entry.conversationId,
|
|
61789
|
+
...ordinals ? {
|
|
61790
|
+
userMessage: {
|
|
61791
|
+
id: opened.userMessageId,
|
|
61792
|
+
content: userMessage,
|
|
61793
|
+
turnOrdinal: ordinals.user,
|
|
61794
|
+
createdAt: startedAt
|
|
61795
|
+
},
|
|
61796
|
+
assistantMessage: {
|
|
61797
|
+
id: opened.assistantMessageId,
|
|
61798
|
+
turnOrdinal: ordinals.assistant,
|
|
61799
|
+
createdAt: startedAt
|
|
61800
|
+
}
|
|
61801
|
+
} : {},
|
|
61605
61802
|
records: nativeTurnRecords({
|
|
61606
61803
|
updates: withTerminalIdle(turn.updates, startedAt),
|
|
61607
61804
|
startedAt,
|
|
@@ -65942,14 +66139,18 @@ function applyField(pending, line) {
|
|
|
65942
66139
|
}
|
|
65943
66140
|
async function* readServerSentEvents(body) {
|
|
65944
66141
|
const decoder3 = new TextDecoder();
|
|
65945
|
-
let
|
|
66142
|
+
let partial2 = [];
|
|
65946
66143
|
let pending = emptyEvent();
|
|
65947
66144
|
for await (const chunk of body) {
|
|
65948
|
-
|
|
65949
|
-
let
|
|
66145
|
+
const text2 = decoder3.decode(chunk, { stream: true });
|
|
66146
|
+
let start = 0;
|
|
66147
|
+
let newline = text2.indexOf("\n");
|
|
65950
66148
|
while (newline !== -1) {
|
|
65951
|
-
|
|
65952
|
-
|
|
66149
|
+
partial2.push(text2.slice(start, newline));
|
|
66150
|
+
const line = partial2.join("").replace(/\r$/, "");
|
|
66151
|
+
partial2 = [];
|
|
66152
|
+
start = newline + 1;
|
|
66153
|
+
newline = text2.indexOf("\n", start);
|
|
65953
66154
|
if (line.length === 0) {
|
|
65954
66155
|
if (pending.data.length > 0) {
|
|
65955
66156
|
yield { event: pending.event, id: pending.id, data: pending.data.join("\n") };
|
|
@@ -65958,8 +66159,8 @@ async function* readServerSentEvents(body) {
|
|
|
65958
66159
|
} else if (!line.startsWith(":")) {
|
|
65959
66160
|
applyField(pending, line);
|
|
65960
66161
|
}
|
|
65961
|
-
newline = buffer.indexOf("\n");
|
|
65962
66162
|
}
|
|
66163
|
+
if (start < text2.length) partial2.push(text2.slice(start));
|
|
65963
66164
|
}
|
|
65964
66165
|
}
|
|
65965
66166
|
|
|
@@ -65996,6 +66197,23 @@ async function readDiscovery(path4) {
|
|
|
65996
66197
|
}
|
|
65997
66198
|
return parsed.data;
|
|
65998
66199
|
}
|
|
66200
|
+
function conversationQuery(query) {
|
|
66201
|
+
return {
|
|
66202
|
+
limit: String(query.limit),
|
|
66203
|
+
...query.before ? { before: query.before } : {},
|
|
66204
|
+
...query.runtimeId ? { runtimeId: query.runtimeId } : {}
|
|
66205
|
+
};
|
|
66206
|
+
}
|
|
66207
|
+
function conversationUpdate(event) {
|
|
66208
|
+
const value2 = JSON.parse(event.data);
|
|
66209
|
+
if (event.event === "snapshot" && isConversationMessagesPage(value2))
|
|
66210
|
+
return { kind: "snapshot", page: value2 };
|
|
66211
|
+
if (event.event === "turn" && isConversationMessageTurn(value2))
|
|
66212
|
+
return { kind: "turn", turn: value2 };
|
|
66213
|
+
if (event.event === LIVE_TURN_EVENT && isLiveTurnFrame(value2))
|
|
66214
|
+
return { kind: "live_turn", frame: value2 };
|
|
66215
|
+
throw new RuntimeClientError("protocol", "Invalid local conversation update");
|
|
66216
|
+
}
|
|
65999
66217
|
function parseWith(schema, raw, what) {
|
|
66000
66218
|
const parsed = schema.safeParse(raw);
|
|
66001
66219
|
if (!parsed.success) {
|
|
@@ -66141,24 +66359,17 @@ function createRuntimeClient(options) {
|
|
|
66141
66359
|
throw new RuntimeClientError("unavailable", "The run log stream closed before the run ended");
|
|
66142
66360
|
}
|
|
66143
66361
|
const runs = async (signal) => (await json2({ path: LOCAL_API_ROUTES.runs }, runsResponseSchema, signal)).runs;
|
|
66144
|
-
async function* followConversationMessages(
|
|
66362
|
+
async function* followConversationMessages(query, signal) {
|
|
66145
66363
|
const stopped = new AbortController();
|
|
66146
66364
|
try {
|
|
66147
66365
|
const body = await openStream(
|
|
66148
66366
|
{
|
|
66149
|
-
path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages/sse`,
|
|
66150
|
-
query: {
|
|
66367
|
+
path: `/v2/conversations/${encodeURIComponent(query.conversationId)}/messages/sse`,
|
|
66368
|
+
query: { ...conversationQuery(query), frames: LIVE_TURN_FRAMES }
|
|
66151
66369
|
},
|
|
66152
66370
|
AbortSignal.any([signal, stopped.signal])
|
|
66153
66371
|
);
|
|
66154
|
-
for await (const event of readServerSentEvents(body))
|
|
66155
|
-
const value2 = JSON.parse(event.data);
|
|
66156
|
-
if (event.event === "snapshot" && isConversationMessagesPage(value2))
|
|
66157
|
-
yield { kind: "snapshot", page: value2 };
|
|
66158
|
-
else if (event.event === "turn" && isConversationMessageTurn(value2))
|
|
66159
|
-
yield { kind: "turn", turn: value2 };
|
|
66160
|
-
else throw new RuntimeClientError("protocol", "Invalid local conversation update");
|
|
66161
|
-
}
|
|
66372
|
+
for await (const event of readServerSentEvents(body)) yield conversationUpdate(event);
|
|
66162
66373
|
if (!signal.aborted)
|
|
66163
66374
|
throw new RuntimeClientError("unavailable", "The local conversation stream closed");
|
|
66164
66375
|
} finally {
|
|
@@ -66171,11 +66382,11 @@ function createRuntimeClient(options) {
|
|
|
66171
66382
|
followConversationMessages,
|
|
66172
66383
|
runs,
|
|
66173
66384
|
conversationRuns: async (conversationId, signal) => (await runs(signal)).filter((run2) => run2.conversationId === conversationId),
|
|
66174
|
-
readConversationMessages: async (
|
|
66385
|
+
readConversationMessages: async (query, signal) => {
|
|
66175
66386
|
const response = await send2(
|
|
66176
66387
|
{
|
|
66177
|
-
path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages`,
|
|
66178
|
-
query:
|
|
66388
|
+
path: `/v2/conversations/${encodeURIComponent(query.conversationId)}/messages`,
|
|
66389
|
+
query: conversationQuery(query)
|
|
66179
66390
|
},
|
|
66180
66391
|
signal
|
|
66181
66392
|
);
|
|
@@ -67616,6 +67827,8 @@ var indexRecordSchema = external_exports.object({
|
|
|
67616
67827
|
runId: runIdSchema
|
|
67617
67828
|
});
|
|
67618
67829
|
var coverageSchema = external_exports.object({
|
|
67830
|
+
// Files written before ranges could start mid-conversation always started at turn 0.
|
|
67831
|
+
lowestOrdinal: external_exports.number().int().nonnegative().default(0),
|
|
67619
67832
|
highestOrdinal: external_exports.number().int().nonnegative(),
|
|
67620
67833
|
nextExpectedOrdinal: external_exports.number().int().positive()
|
|
67621
67834
|
});
|
|
@@ -67638,11 +67851,16 @@ async function indexConversationRun(runsDir, conversationId, ordinal, assistantO
|
|
|
67638
67851
|
const coveragePath = (0, import_node_path61.join)((0, import_node_path61.dirname)((0, import_node_path61.dirname)(path4)), "coverage.json");
|
|
67639
67852
|
const coverage = await readJsonFile(coveragePath, coverageSchema);
|
|
67640
67853
|
const current = coverage.kind === "ok" ? coverage.value : null;
|
|
67641
|
-
|
|
67642
|
-
|
|
67643
|
-
|
|
67644
|
-
|
|
67645
|
-
|
|
67854
|
+
const next = nextCoverage(current, ordinal, nextOrdinal);
|
|
67855
|
+
if (next) await writeJsonFileAtomic(coveragePath, next);
|
|
67856
|
+
}
|
|
67857
|
+
function nextCoverage(current, ordinal, nextOrdinal) {
|
|
67858
|
+
if (current === null || ordinal > current.nextExpectedOrdinal)
|
|
67859
|
+
return { lowestOrdinal: ordinal, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
|
|
67860
|
+
if (ordinal === current.nextExpectedOrdinal)
|
|
67861
|
+
return { ...current, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
|
|
67862
|
+
if (ordinal === current.highestOrdinal) return { ...current, nextExpectedOrdinal: nextOrdinal };
|
|
67863
|
+
return null;
|
|
67646
67864
|
}
|
|
67647
67865
|
async function readConversationIndexCoverage(runsDir, conversationId) {
|
|
67648
67866
|
const path4 = (0, import_node_path61.join)((0, import_node_path61.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
|
|
@@ -71211,22 +71429,34 @@ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal)
|
|
|
71211
71429
|
if (!reader) return null;
|
|
71212
71430
|
let offset = toByteOffset(0);
|
|
71213
71431
|
let ended = false;
|
|
71432
|
+
let snapshot2;
|
|
71214
71433
|
let prepared;
|
|
71434
|
+
const merge2 = /* @__PURE__ */ new Map();
|
|
71215
71435
|
const decoder3 = new TextDecoder();
|
|
71436
|
+
const readState = async () => {
|
|
71437
|
+
const priorOffset = offset;
|
|
71438
|
+
for (; ; ) {
|
|
71439
|
+
const chunk = await reader.readFrom(offset, DEFAULT_RUN_LOG_LIMIT);
|
|
71440
|
+
if (chunk.bytes.length === 0) break;
|
|
71441
|
+
if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
|
|
71442
|
+
offset = chunk.to;
|
|
71443
|
+
}
|
|
71444
|
+
if (offset === priorOffset && snapshot2) return snapshot2;
|
|
71445
|
+
if (ended) state.state = "idle";
|
|
71446
|
+
snapshot2 = mergeTranscriptMessages(
|
|
71447
|
+
[{ messageId: assistantMessageId, turnOrdinal: ordinal, role: "assistant", state }],
|
|
71448
|
+
merge2
|
|
71449
|
+
);
|
|
71450
|
+
return snapshot2;
|
|
71451
|
+
};
|
|
71216
71452
|
return {
|
|
71217
71453
|
runId,
|
|
71218
71454
|
ordinal,
|
|
71455
|
+
readState,
|
|
71219
71456
|
read: async () => {
|
|
71220
|
-
const
|
|
71221
|
-
|
|
71222
|
-
|
|
71223
|
-
if (chunk.bytes.length === 0) break;
|
|
71224
|
-
if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
|
|
71225
|
-
offset = chunk.to;
|
|
71226
|
-
}
|
|
71227
|
-
if (offset === priorOffset && prepared) return prepared;
|
|
71228
|
-
if (ended) state.state = "idle";
|
|
71229
|
-
prepared = { ...conversationTurnView(ordinal, snapshotTranscriptState(state)), markdown: "" };
|
|
71457
|
+
const current = await readState();
|
|
71458
|
+
if (prepared?.state !== current)
|
|
71459
|
+
prepared = { ...conversationTurnView(ordinal, current, prepared?.display), markdown: "" };
|
|
71230
71460
|
return prepared;
|
|
71231
71461
|
},
|
|
71232
71462
|
[Symbol.asyncDispose]: async () => {
|
|
@@ -71247,14 +71477,14 @@ async function projectLocalRun(runsDir, runId, conversationId, ordinal) {
|
|
|
71247
71477
|
}
|
|
71248
71478
|
}
|
|
71249
71479
|
async function readLocalConversationMessages(runsDir, conversationId, limit, before, projection) {
|
|
71250
|
-
const indexed = await readConversationRunIndex(runsDir, conversationId, before, limit + 1);
|
|
71251
71480
|
const coverage = await readConversationIndexCoverage(runsDir, conversationId);
|
|
71252
|
-
if (coverage === null || before
|
|
71253
|
-
|
|
71481
|
+
if (coverage === null || before !== void 0 && before <= coverage.lowestOrdinal) return null;
|
|
71482
|
+
const indexed = (await readConversationRunIndex(runsDir, conversationId, before, limit + 1)).filter((entry) => entry.ordinal >= coverage.lowestOrdinal);
|
|
71483
|
+
if (before === void 0 && indexed[0]?.ordinal !== coverage.highestOrdinal) return null;
|
|
71254
71484
|
if (before !== void 0 && indexed[0]?.nextOrdinal !== before) return null;
|
|
71255
71485
|
if (indexed.some((entry, index) => index > 0 && entry.nextOrdinal !== indexed[index - 1].ordinal))
|
|
71256
71486
|
return null;
|
|
71257
|
-
if (indexed.length < limit && indexed.at(-1)?.ordinal !==
|
|
71487
|
+
if (indexed.length < limit && indexed.at(-1)?.ordinal !== coverage.lowestOrdinal) return null;
|
|
71258
71488
|
const selected = indexed.slice(0, limit);
|
|
71259
71489
|
if (selected.length === 0) return null;
|
|
71260
71490
|
const turns = await Promise.all(
|
|
@@ -71273,6 +71503,7 @@ async function readLocalConversationMessages(runsDir, conversationId, limit, bef
|
|
|
71273
71503
|
}
|
|
71274
71504
|
|
|
71275
71505
|
// src/local-api/conversation-messages-stream.ts
|
|
71506
|
+
init_acp();
|
|
71276
71507
|
async function readChangedTurn(deps, conversationId, runId, slot) {
|
|
71277
71508
|
const meta3 = await readRunMeta(runDirectory(deps.runsDir, runId).meta);
|
|
71278
71509
|
if (meta3?.conversationId !== conversationId || meta3.userMessage?.turnOrdinal == null) return null;
|
|
@@ -71286,21 +71517,17 @@ async function readChangedTurn(deps, conversationId, runId, slot) {
|
|
|
71286
71517
|
if (latest?.runId !== runId) return null;
|
|
71287
71518
|
}
|
|
71288
71519
|
if (slot.current && meta3.userMessage.turnOrdinal < slot.current.ordinal) {
|
|
71289
|
-
|
|
71290
|
-
|
|
71291
|
-
|
|
71292
|
-
|
|
71293
|
-
|
|
71294
|
-
|
|
71295
|
-
|
|
71296
|
-
|
|
71297
|
-
|
|
71298
|
-
|
|
71299
|
-
|
|
71300
|
-
} finally {
|
|
71301
|
-
var _promise2 = __callDispose(_stack, _error, _hasError);
|
|
71302
|
-
_promise2 && await _promise2;
|
|
71303
|
-
}
|
|
71520
|
+
const previous = await openLocalTurnProjection(
|
|
71521
|
+
deps.runsDir,
|
|
71522
|
+
runId,
|
|
71523
|
+
conversationId,
|
|
71524
|
+
meta3.userMessage.turnOrdinal
|
|
71525
|
+
);
|
|
71526
|
+
if (!previous) return null;
|
|
71527
|
+
return {
|
|
71528
|
+
projection: previous,
|
|
71529
|
+
changed: { ordinal: previous.ordinal, state: await previous.readState() }
|
|
71530
|
+
};
|
|
71304
71531
|
}
|
|
71305
71532
|
if (slot.current?.runId !== runId) {
|
|
71306
71533
|
const next = await openLocalTurnProjection(
|
|
@@ -71313,20 +71540,48 @@ async function readChangedTurn(deps, conversationId, runId, slot) {
|
|
|
71313
71540
|
slot.current = next;
|
|
71314
71541
|
}
|
|
71315
71542
|
if (!slot.current) throw new Error("Local transcript metadata is incomplete");
|
|
71316
|
-
return
|
|
71543
|
+
return {
|
|
71544
|
+
projection: slot.current,
|
|
71545
|
+
changed: { ordinal: slot.current.ordinal, state: await slot.current.readState() }
|
|
71546
|
+
};
|
|
71317
71547
|
}
|
|
71318
|
-
async function
|
|
71548
|
+
async function nextChangedRuns(bell, signal) {
|
|
71549
|
+
if (bell.pending.size === 0) {
|
|
71550
|
+
await new Promise((resolve12) => {
|
|
71551
|
+
bell.wake = resolve12;
|
|
71552
|
+
if (signal.aborted || bell.pending.size > 0) resolve12();
|
|
71553
|
+
});
|
|
71554
|
+
bell.wake = void 0;
|
|
71555
|
+
}
|
|
71556
|
+
if (signal.aborted) return [];
|
|
71557
|
+
await systemClock.sleep(50, signal);
|
|
71558
|
+
const changed = [...bell.pending];
|
|
71559
|
+
bell.pending.clear();
|
|
71560
|
+
return changed;
|
|
71561
|
+
}
|
|
71562
|
+
async function writeChangedTurn(writer, runId, read) {
|
|
71563
|
+
const { ordinal, state } = read.changed;
|
|
71564
|
+
if (state === writer.lastState) return;
|
|
71565
|
+
writer.lastState = state;
|
|
71566
|
+
const patch = writer.frames === "patch";
|
|
71567
|
+
const data = patch ? JSON.stringify(writer.encode(ordinal, state)) : JSON.stringify(await read.projection.read());
|
|
71568
|
+
await writeEvent(writer.res, {
|
|
71569
|
+
name: patch ? LIVE_TURN_EVENT : "turn",
|
|
71570
|
+
id: `${runId}`,
|
|
71571
|
+
dataLines: [data]
|
|
71572
|
+
});
|
|
71573
|
+
}
|
|
71574
|
+
async function streamLocalConversationMessages(deps, conversationId, limit, frames, res, signal) {
|
|
71319
71575
|
var _stack = [];
|
|
71320
71576
|
try {
|
|
71321
|
-
const
|
|
71322
|
-
let wake;
|
|
71577
|
+
const bell = { pending: /* @__PURE__ */ new Set(), wake: void 0 };
|
|
71323
71578
|
const slot = { current: null };
|
|
71324
71579
|
const _subscription = __using(_stack, deps.appends.subscribe((runId) => {
|
|
71325
71580
|
const changed = runId ?? slot.current?.runId;
|
|
71326
|
-
if (changed) pending.add(changed);
|
|
71327
|
-
wake?.();
|
|
71581
|
+
if (changed) bell.pending.add(changed);
|
|
71582
|
+
bell.wake?.();
|
|
71328
71583
|
}));
|
|
71329
|
-
signal.addEventListener("abort", () => wake?.(), { once: true });
|
|
71584
|
+
signal.addEventListener("abort", () => bell.wake?.(), { once: true });
|
|
71330
71585
|
try {
|
|
71331
71586
|
const [newest] = await readConversationRunIndex(deps.runsDir, conversationId, void 0, 1);
|
|
71332
71587
|
if (newest)
|
|
@@ -71336,7 +71591,12 @@ async function streamLocalConversationMessages(deps, conversationId, limit, res,
|
|
|
71336
71591
|
conversationId,
|
|
71337
71592
|
newest.ordinal
|
|
71338
71593
|
);
|
|
71339
|
-
|
|
71594
|
+
const writer = {
|
|
71595
|
+
frames,
|
|
71596
|
+
encode: createLiveTurnFrameEncoder(),
|
|
71597
|
+
res,
|
|
71598
|
+
lastState: await slot.current?.readState()
|
|
71599
|
+
};
|
|
71340
71600
|
const page = await readLocalConversationMessages(
|
|
71341
71601
|
deps.runsDir,
|
|
71342
71602
|
conversationId,
|
|
@@ -71355,22 +71615,14 @@ async function streamLocalConversationMessages(deps, conversationId, limit, res,
|
|
|
71355
71615
|
dataLines: [JSON.stringify(page)]
|
|
71356
71616
|
});
|
|
71357
71617
|
while (!signal.aborted) {
|
|
71358
|
-
|
|
71359
|
-
await
|
|
71360
|
-
|
|
71361
|
-
|
|
71362
|
-
|
|
71363
|
-
|
|
71364
|
-
|
|
71365
|
-
|
|
71366
|
-
await systemClock.sleep(50, signal);
|
|
71367
|
-
const changed = [...pending];
|
|
71368
|
-
pending.clear();
|
|
71369
|
-
for (const runId of changed) {
|
|
71370
|
-
const turn = await readChangedTurn(deps, conversationId, runId, slot);
|
|
71371
|
-
if (!turn || turn === lastTurn) continue;
|
|
71372
|
-
lastTurn = turn;
|
|
71373
|
-
await writeEvent(res, { name: "turn", id: `${runId}`, dataLines: [JSON.stringify(turn)] });
|
|
71618
|
+
for (const runId of await nextChangedRuns(bell, signal)) {
|
|
71619
|
+
const read = await readChangedTurn(deps, conversationId, runId, slot);
|
|
71620
|
+
if (!read) continue;
|
|
71621
|
+
try {
|
|
71622
|
+
await writeChangedTurn(writer, runId, read);
|
|
71623
|
+
} finally {
|
|
71624
|
+
if (read.projection !== slot.current) await read.projection[Symbol.asyncDispose]();
|
|
71625
|
+
}
|
|
71374
71626
|
}
|
|
71375
71627
|
}
|
|
71376
71628
|
} finally {
|
|
@@ -71584,7 +71836,9 @@ var RUN_PATH = /^\/v2\/runs\/([^/]+)\/(log|log\/stream|abort)$/;
|
|
|
71584
71836
|
var CONVERSATION_MESSAGES_PATH = /^\/v2\/conversations\/([^/]+)\/messages(\/sse)?$/;
|
|
71585
71837
|
var conversationMessagesQuerySchema = external_exports.object({
|
|
71586
71838
|
limit: external_exports.coerce.number().int().min(1).max(100).default(10),
|
|
71587
|
-
before: external_exports.coerce.number().int().nonnegative().optional()
|
|
71839
|
+
before: external_exports.coerce.number().int().nonnegative().optional(),
|
|
71840
|
+
runtimeId: external_exports.string().uuid().optional(),
|
|
71841
|
+
frames: external_exports.enum(["turn", "patch"]).default("turn")
|
|
71588
71842
|
});
|
|
71589
71843
|
var emptyBodySchema = external_exports.object({});
|
|
71590
71844
|
function activeRunIds(runs) {
|
|
@@ -71805,6 +72059,44 @@ var FIXED_ROUTES = new Map([
|
|
|
71805
72059
|
[LOCAL_API_ROUTES.providerExternal, { method: "POST", handle: providerExternal }],
|
|
71806
72060
|
...machineFeatureRoutes
|
|
71807
72061
|
]);
|
|
72062
|
+
async function routeConversationMessages(deps, request2, conversationMatch) {
|
|
72063
|
+
if (request2.req.method !== "GET") {
|
|
72064
|
+
sendError(request2.res, 405, "method_not_allowed", "Use GET");
|
|
72065
|
+
return;
|
|
72066
|
+
}
|
|
72067
|
+
const conversationId = conversationIdSchema.safeParse(conversationMatch[1]);
|
|
72068
|
+
const query = conversationMessagesQuerySchema.safeParse(
|
|
72069
|
+
Object.fromEntries(request2.url.searchParams)
|
|
72070
|
+
);
|
|
72071
|
+
if (!conversationId.success || !query.success) {
|
|
72072
|
+
sendError(request2.res, 400, "invalid_request", "Invalid conversation messages request");
|
|
72073
|
+
return;
|
|
72074
|
+
}
|
|
72075
|
+
if (query.data.runtimeId && query.data.runtimeId !== deps.readFacts().machineId) {
|
|
72076
|
+
sendError(request2.res, 404, "not_found", "This conversation runs on another computer");
|
|
72077
|
+
return;
|
|
72078
|
+
}
|
|
72079
|
+
if (conversationMatch[2])
|
|
72080
|
+
return streamLocalConversationMessages(
|
|
72081
|
+
deps,
|
|
72082
|
+
conversationId.data,
|
|
72083
|
+
query.data.limit,
|
|
72084
|
+
query.data.frames,
|
|
72085
|
+
request2.res,
|
|
72086
|
+
request2.signal
|
|
72087
|
+
);
|
|
72088
|
+
const page = await readLocalConversationMessages(
|
|
72089
|
+
deps.runsDir,
|
|
72090
|
+
conversationId.data,
|
|
72091
|
+
query.data.limit,
|
|
72092
|
+
query.data.before
|
|
72093
|
+
);
|
|
72094
|
+
if (page === null) {
|
|
72095
|
+
sendError(request2.res, 404, "not_found", "This computer has no complete local page");
|
|
72096
|
+
return;
|
|
72097
|
+
}
|
|
72098
|
+
sendJson(request2.res, 200, page);
|
|
72099
|
+
}
|
|
71808
72100
|
async function routeRun(deps, request2, match) {
|
|
71809
72101
|
const runId = runIdSchema.safeParse(match[1]);
|
|
71810
72102
|
const action = match[2];
|
|
@@ -71833,40 +72125,8 @@ async function route(deps, request2) {
|
|
|
71833
72125
|
const match = RUN_PATH.exec(request2.url.pathname);
|
|
71834
72126
|
if (match !== null) return routeRun(deps, request2, match);
|
|
71835
72127
|
const conversationMatch = CONVERSATION_MESSAGES_PATH.exec(request2.url.pathname);
|
|
71836
|
-
if (conversationMatch !== null)
|
|
71837
|
-
|
|
71838
|
-
sendError(request2.res, 405, "method_not_allowed", "Use GET");
|
|
71839
|
-
return;
|
|
71840
|
-
}
|
|
71841
|
-
const conversationId = conversationIdSchema.safeParse(conversationMatch[1]);
|
|
71842
|
-
const query = conversationMessagesQuerySchema.safeParse(
|
|
71843
|
-
Object.fromEntries(request2.url.searchParams)
|
|
71844
|
-
);
|
|
71845
|
-
if (!conversationId.success || !query.success) {
|
|
71846
|
-
sendError(request2.res, 400, "invalid_request", "Invalid conversation messages request");
|
|
71847
|
-
return;
|
|
71848
|
-
}
|
|
71849
|
-
if (conversationMatch[2])
|
|
71850
|
-
return streamLocalConversationMessages(
|
|
71851
|
-
deps,
|
|
71852
|
-
conversationId.data,
|
|
71853
|
-
query.data.limit,
|
|
71854
|
-
request2.res,
|
|
71855
|
-
request2.signal
|
|
71856
|
-
);
|
|
71857
|
-
const page = await readLocalConversationMessages(
|
|
71858
|
-
deps.runsDir,
|
|
71859
|
-
conversationId.data,
|
|
71860
|
-
query.data.limit,
|
|
71861
|
-
query.data.before
|
|
71862
|
-
);
|
|
71863
|
-
if (page === null) {
|
|
71864
|
-
sendError(request2.res, 404, "not_found", "This computer has no complete local page");
|
|
71865
|
-
return;
|
|
71866
|
-
}
|
|
71867
|
-
sendJson(request2.res, 200, page);
|
|
71868
|
-
return;
|
|
71869
|
-
}
|
|
72128
|
+
if (conversationMatch !== null)
|
|
72129
|
+
return routeConversationMessages(deps, request2, conversationMatch);
|
|
71870
72130
|
sendError(request2.res, 404, "not_found", "Not found");
|
|
71871
72131
|
}
|
|
71872
72132
|
|
|
@@ -71974,6 +72234,7 @@ async function serveLocalApi(deps) {
|
|
|
71974
72234
|
const appAttachments = createAppAttachments(clock);
|
|
71975
72235
|
const routeDeps = {
|
|
71976
72236
|
feed,
|
|
72237
|
+
readFacts: deps.readFacts,
|
|
71977
72238
|
appAttachments,
|
|
71978
72239
|
actions: deps.actions,
|
|
71979
72240
|
runsDir: deps.runsDir,
|
|
@@ -76318,12 +76579,15 @@ function startUploader({ api, runsDir, clock, log }) {
|
|
|
76318
76579
|
if (stored.kind === "ok") return stored.value;
|
|
76319
76580
|
const receipt = await api.readReceipt(target, controller.signal);
|
|
76320
76581
|
switch (receipt.kind) {
|
|
76321
|
-
case "read":
|
|
76582
|
+
case "read": {
|
|
76322
76583
|
log.debug("upload.resumed", {
|
|
76323
76584
|
runId,
|
|
76324
76585
|
admittedOffset: receipt.receipt?.admittedOffset ?? 0
|
|
76325
76586
|
});
|
|
76326
|
-
|
|
76587
|
+
const progress = progressFromReceipt(receipt.receipt);
|
|
76588
|
+
if (progress.sealed) await writeJsonFileAtomic(path4, progress);
|
|
76589
|
+
return progress;
|
|
76590
|
+
}
|
|
76327
76591
|
case "rejected":
|
|
76328
76592
|
await reject(runId, path4, progressFromReceipt(null), receipt);
|
|
76329
76593
|
return null;
|
|
@@ -76573,6 +76837,28 @@ function unwrap(outcome2, what) {
|
|
|
76573
76837
|
outcome2.code
|
|
76574
76838
|
);
|
|
76575
76839
|
}
|
|
76840
|
+
async function writeNativeTurnRun(runsDir, run2, log) {
|
|
76841
|
+
const runId = runIdSchema.parse(run2.runId);
|
|
76842
|
+
const conversationId = conversationIdSchema.parse(run2.conversationId);
|
|
76843
|
+
const { userMessage, assistantMessage } = run2;
|
|
76844
|
+
await writeCompleteRunLog(
|
|
76845
|
+
runsDir,
|
|
76846
|
+
{ runId, conversationId, userMessage, assistantMessage },
|
|
76847
|
+
run2.records
|
|
76848
|
+
);
|
|
76849
|
+
if (userMessage?.turnOrdinal != null && assistantMessage?.turnOrdinal != null) {
|
|
76850
|
+
await indexConversationRun(
|
|
76851
|
+
runsDir,
|
|
76852
|
+
conversationId,
|
|
76853
|
+
userMessage.turnOrdinal,
|
|
76854
|
+
assistantMessage.turnOrdinal,
|
|
76855
|
+
runId
|
|
76856
|
+
).catch(
|
|
76857
|
+
(error61) => log.warn("native_ingest.conversation_index_failed", { runId, error: error61 })
|
|
76858
|
+
);
|
|
76859
|
+
}
|
|
76860
|
+
return runId;
|
|
76861
|
+
}
|
|
76576
76862
|
async function startMachineNativeIngest(deps) {
|
|
76577
76863
|
const client = createNativeSessionsClient({
|
|
76578
76864
|
apiUrl: deps.apiUrl,
|
|
@@ -76589,13 +76875,7 @@ async function startMachineNativeIngest(deps) {
|
|
|
76589
76875
|
api,
|
|
76590
76876
|
publisher: {
|
|
76591
76877
|
publish: async (run2) => {
|
|
76592
|
-
|
|
76593
|
-
await writeCompleteRunLog(
|
|
76594
|
-
deps.runsDir,
|
|
76595
|
-
{ runId, conversationId: conversationIdSchema.parse(run2.conversationId) },
|
|
76596
|
-
run2.records
|
|
76597
|
-
);
|
|
76598
|
-
deps.onPublished(runId);
|
|
76878
|
+
deps.onPublished(await writeNativeTurnRun(deps.runsDir, run2, deps.log));
|
|
76599
76879
|
}
|
|
76600
76880
|
},
|
|
76601
76881
|
clock: deps.clock,
|
package/alan-holder.cjs
CHANGED
|
@@ -20742,7 +20742,11 @@ var init_github_proxy = __esm({
|
|
|
20742
20742
|
"github.com"
|
|
20743
20743
|
];
|
|
20744
20744
|
gitHubProxyUpstreamSchema = external_exports.enum(GITHUB_PROXY_UPSTREAMS);
|
|
20745
|
-
GITHUB_PROXY_REFUSAL_CODES = [
|
|
20745
|
+
GITHUB_PROXY_REFUSAL_CODES = [
|
|
20746
|
+
"host_not_proxied",
|
|
20747
|
+
"machine_not_allowed",
|
|
20748
|
+
"github_not_connected"
|
|
20749
|
+
];
|
|
20746
20750
|
gitHubProxyErrorSchema = external_exports.object({
|
|
20747
20751
|
message: external_exports.string().min(1),
|
|
20748
20752
|
documentation_url: external_exports.string(),
|
|
@@ -26664,6 +26668,9 @@ function classifyResultError(event, context) {
|
|
|
26664
26668
|
if (classified.errorKind !== "unknown_cli_error" || !isApiError) return classified;
|
|
26665
26669
|
return { ...specForErrorKind("provider_error"), message: classified.message };
|
|
26666
26670
|
}
|
|
26671
|
+
function isIdleUpdate(update) {
|
|
26672
|
+
return isUpdate(update, "state_update") && update.state === "idle";
|
|
26673
|
+
}
|
|
26667
26674
|
function isSettled2(update) {
|
|
26668
26675
|
return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
|
|
26669
26676
|
}
|
|
@@ -27206,6 +27213,7 @@ var init_claude = __esm({
|
|
|
27206
27213
|
#failure;
|
|
27207
27214
|
#authFailure;
|
|
27208
27215
|
#resultSeen = false;
|
|
27216
|
+
#heldIdle;
|
|
27209
27217
|
constructor(options = {}) {
|
|
27210
27218
|
this.#options = options;
|
|
27211
27219
|
this.taskRecords = options.taskRecords ?? new TaskRecords(options.now ?? (() => systemClock2.now()));
|
|
@@ -27253,7 +27261,17 @@ var init_claude = __esm({
|
|
|
27253
27261
|
readEvent(event) {
|
|
27254
27262
|
const parsed = this.#revise(parseClaudeEvent(event, this.grammar), event);
|
|
27255
27263
|
parsed.push(...this.#handle(event));
|
|
27256
|
-
const
|
|
27264
|
+
const kept = parsed.filter((update) => {
|
|
27265
|
+
if (!isIdleUpdate(update)) return true;
|
|
27266
|
+
if (this.#finalized) return true;
|
|
27267
|
+
this.#heldIdle = update;
|
|
27268
|
+
return false;
|
|
27269
|
+
});
|
|
27270
|
+
if (this.#finalized && this.#heldIdle !== void 0) {
|
|
27271
|
+
if (!kept.some(isIdleUpdate)) kept.push(this.#heldIdle);
|
|
27272
|
+
this.#heldIdle = void 0;
|
|
27273
|
+
}
|
|
27274
|
+
const updates = kept.map((update) => this.taskRecords.stamp(update));
|
|
27257
27275
|
for (const update of updates) this.#applyRunState(update);
|
|
27258
27276
|
return updates;
|
|
27259
27277
|
}
|
|
@@ -39432,15 +39450,16 @@ function createPersistentDriver(provider4, options) {
|
|
|
39432
39450
|
return void 0;
|
|
39433
39451
|
};
|
|
39434
39452
|
const resumeNotice = (spec, session, sink) => {
|
|
39453
|
+
if (spec.resumeFallbackContext) {
|
|
39454
|
+
log.info("holder.session_resume_fallback", { harness: provider4.harness, runId: spec.runId });
|
|
39455
|
+
return { session, contextPrefix: spec.resumeFallbackContext };
|
|
39456
|
+
}
|
|
39435
39457
|
sink.onEvent({
|
|
39436
39458
|
seq: 0,
|
|
39437
39459
|
at: clock.now(),
|
|
39438
39460
|
update: noticeUpdate("warning", "session_resume_failed", RESUME_UNAVAILABLE)
|
|
39439
39461
|
});
|
|
39440
|
-
return {
|
|
39441
|
-
session,
|
|
39442
|
-
...spec.resumeFallbackContext ? { contextPrefix: spec.resumeFallbackContext } : {}
|
|
39443
|
-
};
|
|
39462
|
+
return { session };
|
|
39444
39463
|
};
|
|
39445
39464
|
const managedMcpAccess = async (signal) => {
|
|
39446
39465
|
const managed = options.managedMcp;
|
|
@@ -39515,6 +39534,7 @@ function createPersistentDriver(provider4, options) {
|
|
|
39515
39534
|
};
|
|
39516
39535
|
const _events = __using(_stack, session.onEvent(forward));
|
|
39517
39536
|
live.turn = turn;
|
|
39537
|
+
record2({ sessionUpdate: "state_update", state: "running" });
|
|
39518
39538
|
if (session.pid !== void 0) sink.onSpawned(session.pid);
|
|
39519
39539
|
const onAbort = () => {
|
|
39520
39540
|
void session.cancel();
|
|
@@ -41446,7 +41466,7 @@ function createAlanCodeHolderDriver(options) {
|
|
|
41446
41466
|
open: open4,
|
|
41447
41467
|
turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
|
|
41448
41468
|
attachments: inputs.attachments,
|
|
41449
|
-
skills:
|
|
41469
|
+
skills: inputs.skills,
|
|
41450
41470
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
41451
41471
|
})
|
|
41452
41472
|
},
|
|
@@ -42462,7 +42482,7 @@ function createDroidHolderDriver(options) {
|
|
|
42462
42482
|
},
|
|
42463
42483
|
turnInput: (spec, inputs, contextPrefix) => droidTurnInput(spec, {
|
|
42464
42484
|
attachments: inputs.attachments,
|
|
42465
|
-
skills:
|
|
42485
|
+
skills: inputs.skills,
|
|
42466
42486
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
42467
42487
|
})
|
|
42468
42488
|
},
|
|
@@ -42510,7 +42530,7 @@ function createOpenCodeHolderDriver(options) {
|
|
|
42510
42530
|
},
|
|
42511
42531
|
turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
|
|
42512
42532
|
attachments: inputs.attachments,
|
|
42513
|
-
skills:
|
|
42533
|
+
skills: inputs.skills,
|
|
42514
42534
|
...contextPrefix === void 0 ? {} : { contextPrefix }
|
|
42515
42535
|
})
|
|
42516
42536
|
},
|
|
@@ -47699,6 +47719,8 @@ var indexRecordSchema = external_exports.object({
|
|
|
47699
47719
|
runId: runIdSchema
|
|
47700
47720
|
});
|
|
47701
47721
|
var coverageSchema = external_exports.object({
|
|
47722
|
+
// Files written before ranges could start mid-conversation always started at turn 0.
|
|
47723
|
+
lowestOrdinal: external_exports.number().int().nonnegative().default(0),
|
|
47702
47724
|
highestOrdinal: external_exports.number().int().nonnegative(),
|
|
47703
47725
|
nextExpectedOrdinal: external_exports.number().int().positive()
|
|
47704
47726
|
});
|
|
@@ -47721,11 +47743,16 @@ async function indexConversationRun(runsDir, conversationId, ordinal, assistantO
|
|
|
47721
47743
|
const coveragePath = (0, import_node_path24.join)((0, import_node_path24.dirname)((0, import_node_path24.dirname)(path)), "coverage.json");
|
|
47722
47744
|
const coverage = await readJsonFile(coveragePath, coverageSchema);
|
|
47723
47745
|
const current = coverage.kind === "ok" ? coverage.value : null;
|
|
47724
|
-
|
|
47725
|
-
|
|
47726
|
-
|
|
47727
|
-
|
|
47728
|
-
|
|
47746
|
+
const next = nextCoverage(current, ordinal, nextOrdinal);
|
|
47747
|
+
if (next) await writeJsonFileAtomic(coveragePath, next);
|
|
47748
|
+
}
|
|
47749
|
+
function nextCoverage(current, ordinal, nextOrdinal) {
|
|
47750
|
+
if (current === null || ordinal > current.nextExpectedOrdinal)
|
|
47751
|
+
return { lowestOrdinal: ordinal, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
|
|
47752
|
+
if (ordinal === current.nextExpectedOrdinal)
|
|
47753
|
+
return { ...current, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
|
|
47754
|
+
if (ordinal === current.highestOrdinal) return { ...current, nextExpectedOrdinal: nextOrdinal };
|
|
47755
|
+
return null;
|
|
47729
47756
|
}
|
|
47730
47757
|
|
|
47731
47758
|
// src/run-log/tail.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alan-ai-hq/agent-manager-darwin-arm64",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.139",
|
|
4
4
|
"description": "Alan machine runtime (alan-agent) for one platform: the official Node.js binary, the runtime bundle and its launcher. Installed by @alan-ai-hq/agent-manager.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://tryalan.ai",
|