@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 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 = ["host_not_proxied", "machine_not_allowed"];
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 updates = parsed.map((update) => this.taskRecords.stamp(update));
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.138",
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 buffer = "";
66142
+ let partial2 = [];
65946
66143
  let pending = emptyEvent();
65947
66144
  for await (const chunk of body) {
65948
- buffer += decoder3.decode(chunk, { stream: true });
65949
- let newline = buffer.indexOf("\n");
66145
+ const text2 = decoder3.decode(chunk, { stream: true });
66146
+ let start = 0;
66147
+ let newline = text2.indexOf("\n");
65950
66148
  while (newline !== -1) {
65951
- const line = buffer.slice(0, newline).replace(/\r$/, "");
65952
- buffer = buffer.slice(newline + 1);
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(conversationId, limit, signal) {
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: { limit: String(limit) }
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 (conversationId, limit, before, signal) => {
66385
+ readConversationMessages: async (query, signal) => {
66175
66386
  const response = await send2(
66176
66387
  {
66177
- path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages`,
66178
- query: { limit: String(limit), ...before === null ? {} : { before } }
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
- if (ordinal === 0 && current === null || current?.nextExpectedOrdinal === ordinal)
67642
- await writeJsonFileAtomic(coveragePath, {
67643
- highestOrdinal: ordinal,
67644
- nextExpectedOrdinal: nextOrdinal
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 priorOffset = offset;
71221
- for (; ; ) {
71222
- const chunk = await reader.readFrom(offset, DEFAULT_RUN_LOG_LIMIT);
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 === void 0 && indexed[0]?.ordinal !== coverage.highestOrdinal)
71253
- return null;
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 !== 0) return null;
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
- var _stack = [];
71290
- try {
71291
- const previous = __using(_stack, await openLocalTurnProjection(
71292
- deps.runsDir,
71293
- runId,
71294
- conversationId,
71295
- meta3.userMessage.turnOrdinal
71296
- ), true);
71297
- return previous ? await previous.read() : null;
71298
- } catch (_) {
71299
- var _error = _, _hasError = true;
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 slot.current.read();
71543
+ return {
71544
+ projection: slot.current,
71545
+ changed: { ordinal: slot.current.ordinal, state: await slot.current.readState() }
71546
+ };
71317
71547
  }
71318
- async function streamLocalConversationMessages(deps, conversationId, limit, res, signal) {
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 pending = /* @__PURE__ */ new Set();
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
- let lastTurn = await slot.current?.read();
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
- if (pending.size === 0) {
71359
- await new Promise((resolve12) => {
71360
- wake = resolve12;
71361
- if (signal.aborted || pending.size > 0) resolve12();
71362
- });
71363
- wake = void 0;
71364
- }
71365
- if (signal.aborted) return;
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
- if (request2.req.method !== "GET") {
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
- return progressFromReceipt(receipt.receipt);
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
- const runId = runIdSchema.parse(run2.runId);
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 = ["host_not_proxied", "machine_not_allowed"];
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 updates = parsed.map((update) => this.taskRecords.stamp(update));
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
- if (ordinal === 0 && current === null || current?.nextExpectedOrdinal === ordinal)
47725
- await writeJsonFileAtomic(coveragePath, {
47726
- highestOrdinal: ordinal,
47727
- nextExpectedOrdinal: nextOrdinal
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.138",
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",