@oh-my-pi/pi-agent-core 18.11.1 → 18.11.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.11.2] - 2026-10-16
6
+
7
+ ### Added
8
+
9
+ - `agent_start` carries `resumedToolCallIds` when a continued run first executes the calls of an unpaired assistant tail
10
+
11
+ ### Fixed
12
+
13
+ - Cancelling an `ask` after a background job finishes now reports the user cancellation instead of telling the model to retry a skipped tool ([#15985](https://github.com/can1357/oh-my-pi/issues/15985))
14
+
5
15
  ## [18.11.1] - 2026-10-15
6
16
 
7
17
  ### Added
@@ -1106,6 +1106,11 @@ export interface AgentContext {
1106
1106
  */
1107
1107
  export type AgentEvent = {
1108
1108
  type: "agent_start";
1109
+ /**
1110
+ * Calls of the unpaired assistant tail a continued run executes before its
1111
+ * first model request. They run without a new assistant `message_end`.
1112
+ */
1113
+ resumedToolCallIds?: string[];
1109
1114
  } | {
1110
1115
  type: "agent_end";
1111
1116
  messages: AgentMessage[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-agent-core",
4
- "version": "18.11.1",
4
+ "version": "18.11.2",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -38,16 +38,16 @@
38
38
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
39
39
  },
40
40
  "dependencies": {
41
- "@oh-my-pi/pi-ai": "18.11.1",
42
- "@oh-my-pi/pi-catalog": "18.11.1",
43
- "@oh-my-pi/pi-natives": "18.11.1",
44
- "@oh-my-pi/pi-utils": "18.11.1",
45
- "@oh-my-pi/pi-wire": "18.11.1",
46
- "@oh-my-pi/snapcompact": "18.11.1",
41
+ "@oh-my-pi/pi-ai": "18.11.2",
42
+ "@oh-my-pi/pi-catalog": "18.11.2",
43
+ "@oh-my-pi/pi-natives": "18.11.2",
44
+ "@oh-my-pi/pi-utils": "18.11.2",
45
+ "@oh-my-pi/pi-wire": "18.11.2",
46
+ "@oh-my-pi/snapcompact": "18.11.2",
47
47
  "@opentelemetry/api": "^1.9.1"
48
48
  },
49
49
  "devDependencies": {
50
- "@oh-my-pi/omptype": "18.11.1",
50
+ "@oh-my-pi/omptype": "18.11.2",
51
51
  "@opentelemetry/context-async-hooks": "^2.9.0",
52
52
  "@opentelemetry/sdk-trace-base": "^2.9.0",
53
53
  "@types/bun": "^1.3.14"
package/src/agent-loop.ts CHANGED
@@ -700,7 +700,17 @@ export function agentLoopContinue(
700
700
  const newMessages: AgentMessage[] = [];
701
701
  const currentContext: AgentContext = { ...context, messages: [...context.messages] };
702
702
 
703
- stream.push({ type: "agent_start" });
703
+ const resumeTail = unpairedToolCallTail(currentContext.messages);
704
+ stream.push(
705
+ resumeTail
706
+ ? {
707
+ type: "agent_start",
708
+ resumedToolCallIds: resumeTail.content.flatMap(block =>
709
+ block.type === "toolCall" ? [block.id] : [],
710
+ ),
711
+ }
712
+ : { type: "agent_start" },
713
+ );
704
714
 
705
715
  await runLoop(currentContext, newMessages, config, signal, stream, streamFn);
706
716
  } catch (err) {
@@ -3642,20 +3652,17 @@ async function executeToolCalls(
3642
3652
  const interrupted = interruptState.triggered;
3643
3653
  const perToolAborted = record.signal.aborted;
3644
3654
  const abortedDuringExecution = perToolAborted && isError && !completedToolExecution;
3645
- if (interrupted && abortedDuringExecution) {
3646
- // This tool's own signal fired AND it failed to produce a result. The
3647
- // execution may already have performed partial work before throwing on
3648
- // abort, so preserve that distinction in the placeholder metadata.
3655
+ if (record.interruptible && interrupted && abortedDuringExecution) {
3656
+ // Queued steering/asides abort only interruptible tools. An external
3657
+ // user abort can also fail a non-interruptible tool (e.g. cancelled
3658
+ // ask); keep its actual error instead of attributing it to the queue.
3649
3659
  record.skipped = true;
3650
3660
  emitToolResult(record, createSkippedToolResult(interruptState.source, executionStarted), true);
3651
3661
  } else {
3652
- // No interrupt on this signal, or the tool finished before the interrupt landed
3653
- // (`completedToolExecution`) — even if the signal aborted around completion. Keep
3654
- // its real result: a completed tool already ran its side effects, so the model must
3655
- // see what actually happened (a genuine non-zero exit / error result) rather than a
3656
- // false "skipped" that discards work the tool performed (#4752). A peer-IRC interrupt
3657
- // on the batch leaves non-interruptible tools' signals untouched — their genuine
3658
- // errors survive here too.
3662
+ // A tool that finished before the interrupt landed (`completedToolExecution`)
3663
+ // keeps its real result even if its signal aborted around completion:
3664
+ // the model must see the work it actually performed (#4752).
3665
+ // Non-interruptible tools also retain errors from external user aborts.
3659
3666
  emitToolResult(record, result, isError);
3660
3667
  }
3661
3668
 
@@ -42,6 +42,7 @@ import {
42
42
  getOpenAIResponsesHistoryPayload,
43
43
  normalizeResponsesToolCallId,
44
44
  stripOpenAIResponsesOutputOnlyStatusesForReplay,
45
+ truncateResponseItemId,
45
46
  } from "@oh-my-pi/pi-ai/utils";
46
47
  import { captureOpenAIHttpError } from "@oh-my-pi/pi-ai/utils/openai-http";
47
48
  import { isBedrockOpenAIUrl } from "@oh-my-pi/pi-catalog/hosts";
@@ -713,8 +714,8 @@ export function buildOpenAiNativeHistory(
713
714
  let msgId = parsedSignature?.id;
714
715
  if (!msgId) {
715
716
  msgId = `msg_${msgIndex}`;
716
- } else if (msgId.length > 64) {
717
- msgId = `msg_${Bun.hash(msgId).toString(36)}`;
717
+ } else {
718
+ msgId = truncateResponseItemId(msgId, "msg");
718
719
  }
719
720
  input.push({
720
721
  type: "message",
package/src/types.ts CHANGED
@@ -1252,7 +1252,14 @@ export interface AgentContext {
1252
1252
  */
1253
1253
  export type AgentEvent =
1254
1254
  // Agent lifecycle
1255
- | { type: "agent_start" }
1255
+ | {
1256
+ type: "agent_start";
1257
+ /**
1258
+ * Calls of the unpaired assistant tail a continued run executes before its
1259
+ * first model request. They run without a new assistant `message_end`.
1260
+ */
1261
+ resumedToolCallIds?: string[];
1262
+ }
1256
1263
  | {
1257
1264
  type: "agent_end";
1258
1265
  messages: AgentMessage[];