acp-kernel 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wire/anthropic.d.ts +60 -0
- package/dist/wire/anthropic.d.ts.map +1 -0
- package/dist/wire/bili-message.d.ts +67 -0
- package/dist/wire/bili-message.d.ts.map +1 -0
- package/dist/wire/index.d.ts +7 -0
- package/dist/wire/index.d.ts.map +1 -0
- package/dist/wire/index.js +676 -0
- package/dist/wire/index.js.map +1 -0
- package/dist/wire/message-id.d.ts +43 -0
- package/dist/wire/message-id.d.ts.map +1 -0
- package/dist/wire/openai.d.ts +56 -0
- package/dist/wire/openai.d.ts.map +1 -0
- package/dist/wire/responses.d.ts +82 -0
- package/dist/wire/responses.d.ts.map +1 -0
- package/dist/wire/util.d.ts +13 -0
- package/dist/wire/util.d.ts.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { BiliMessage } from "./bili-message.js";
|
|
2
|
+
export type AnthropicTextBlock = {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
cache_control?: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type AnthropicToolUse = {
|
|
8
|
+
type: "tool_use";
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
input: unknown;
|
|
12
|
+
cache_control?: unknown;
|
|
13
|
+
};
|
|
14
|
+
export type AnthropicToolResult = {
|
|
15
|
+
type: "tool_result";
|
|
16
|
+
tool_use_id: string;
|
|
17
|
+
content: string | AnthropicTextBlock[];
|
|
18
|
+
is_error?: boolean;
|
|
19
|
+
cache_control?: unknown;
|
|
20
|
+
};
|
|
21
|
+
export type AnthropicImage = {
|
|
22
|
+
type: "image";
|
|
23
|
+
source: unknown;
|
|
24
|
+
};
|
|
25
|
+
export type AnthropicThinking = {
|
|
26
|
+
type: "thinking";
|
|
27
|
+
thinking: string;
|
|
28
|
+
signature?: string;
|
|
29
|
+
};
|
|
30
|
+
export type AnthropicBlock = AnthropicTextBlock | AnthropicToolUse | AnthropicToolResult | AnthropicImage | AnthropicThinking;
|
|
31
|
+
export type AnthropicMessage = {
|
|
32
|
+
role: "user" | "assistant";
|
|
33
|
+
content: string | AnthropicBlock[];
|
|
34
|
+
};
|
|
35
|
+
export type AnthropicRequestBody = {
|
|
36
|
+
model?: string;
|
|
37
|
+
max_tokens?: number;
|
|
38
|
+
system?: string | AnthropicTextBlock[];
|
|
39
|
+
messages: AnthropicMessage[];
|
|
40
|
+
tools?: unknown[];
|
|
41
|
+
stream?: boolean;
|
|
42
|
+
temperature?: number;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
};
|
|
45
|
+
export declare function extractSystem(system: AnthropicRequestBody["system"]): string;
|
|
46
|
+
export declare function buildSystem(text: string, original: AnthropicRequestBody["system"]): string | AnthropicTextBlock[];
|
|
47
|
+
type Flat = {
|
|
48
|
+
msgs: BiliMessage[];
|
|
49
|
+
cacheControls: Map<string, unknown>;
|
|
50
|
+
};
|
|
51
|
+
export declare function anthropicToCore(body: AnthropicRequestBody): Flat;
|
|
52
|
+
export declare function coreToAnthropic(messages: BiliMessage[], cacheControls?: Map<string, unknown>): AnthropicMessage[];
|
|
53
|
+
/** Extract the conversation dimension for Anthropic: a client-provided
|
|
54
|
+
* session header if present, else a content fingerprint of the first user
|
|
55
|
+
* message. The protocol+upstream+key dimensions are mixed in by the caller
|
|
56
|
+
* (server.ts) via deriveSessionId() — this function contributes only the
|
|
57
|
+
* conversation axis. */
|
|
58
|
+
export declare function conversationSignalAnthropic(body: AnthropicRequestBody, headerValue?: string): string;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/wire/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AACzF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3F,MAAM,MAAM,cAAc,GACpB,kBAAkB,GAClB,gBAAgB,GAChB,mBAAmB,GACnB,cAAc,GACd,iBAAiB,CAAC;AAExB,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACvC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B,CAAC;AAGF,wBAAgB,aAAa,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,MAAM,CAI5E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,kBAAkB,EAAE,CAMjH;AAED,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAEzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAyEhE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,EAAE,CA0DjH;AAED;;;;yBAIyB;AACzB,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,oBAAoB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAKpG"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lossless message bridge between protocol-specific message formats and the
|
|
3
|
+
* kernel's CoreMessage.
|
|
4
|
+
*
|
|
5
|
+
* Problem: `anthropicToCore` / `openaiToCore` / `responsesToCore` flatten
|
|
6
|
+
* rich protocol blocks (images, thinking signatures, tool_result.is_error,
|
|
7
|
+
* developer-role messages, image_url) into plain `{ text }` placeholders.
|
|
8
|
+
* The reverse `coreToX` then can't reconstruct them — `is_error` is lost
|
|
9
|
+
* (upstream can't tell a tool error from a result), `thinking.signature` is
|
|
10
|
+
* lost (Anthropic rejects thinking blocks without a matching signature),
|
|
11
|
+
* images become "[image]" (the model never sees the picture).
|
|
12
|
+
*
|
|
13
|
+
* Solution: `BiliMessage` extends CoreMessage with optional sidecar fields.
|
|
14
|
+
* The kernel only reads `{ ...message }` (spread copy) and known fields, so
|
|
15
|
+
* the extra fields survive the compression pipeline unchanged and arrive back
|
|
16
|
+
* at `coreToX`, which prefers them over the flattened `text`. No `as any`
|
|
17
|
+
* needed — TypeScript array covariance lets `BiliMessage[]` satisfy a
|
|
18
|
+
* `CoreMessage[]` parameter.
|
|
19
|
+
*/
|
|
20
|
+
import type { CoreMessage } from "acp-kernel";
|
|
21
|
+
/** A message that carries its original protocol block(s) verbatim, so the
|
|
22
|
+
* reverse conversion can reconstruct losslessly. Every field is optional —
|
|
23
|
+
* plain text messages (the common case) have none set. */
|
|
24
|
+
export interface BiliMessage extends CoreMessage {
|
|
25
|
+
/** Anthropic: the original content block for an image or a structured
|
|
26
|
+
* tool_result. Restored verbatim by coreToAnthropic. */
|
|
27
|
+
rawAnthropicBlock?: unknown;
|
|
28
|
+
/** OpenAI chat: the original content part for an image_url, or the
|
|
29
|
+
* original message object for a developer-role message. */
|
|
30
|
+
rawOpenaiContent?: unknown;
|
|
31
|
+
/** Responses API: the original input item (for input_image, or a raw
|
|
32
|
+
* function_call / function_call_output we pass through). */
|
|
33
|
+
rawResponsesItem?: unknown;
|
|
34
|
+
/** Anthropic thinking signature. Anthropic verifies thinking+signature
|
|
35
|
+
* pairs; without it the request is rejected. Stored alongside the
|
|
36
|
+
* reasoning text so coreToAnthropic can reattach it. */
|
|
37
|
+
thinkingSignature?: string;
|
|
38
|
+
/** OpenAI reasoning_content (chain-of-thought from DeepSeek-R1, GLM-4.6
|
|
39
|
+
* thinking, Qwen-QwQ). These models require reasoning_content be echoed
|
|
40
|
+
* back on subsequent requests or the API returns HTTP 400; stored so
|
|
41
|
+
* coreToOpenai can reattach it. */
|
|
42
|
+
reasoningContent?: string;
|
|
43
|
+
/** Anthropic tool_result.is_error. Marks the tool result as an error so
|
|
44
|
+
* the model knows the tool failed (not just returned an error string). */
|
|
45
|
+
toolIsError?: boolean;
|
|
46
|
+
/** OpenAI: original role was "developer" (reconstructed as "system" by
|
|
47
|
+
* openaiToCore for the kernel; coreToOpenai restores "developer"). */
|
|
48
|
+
originalRole?: "system" | "developer";
|
|
49
|
+
/** The original media type for an image (image/png, image/jpeg, image/gif,
|
|
50
|
+
* image/webp). Lets coreToOpenai/coreToResponses rebuild image_url /
|
|
51
|
+
* input_image with the right data URL. */
|
|
52
|
+
imageMediaType?: string;
|
|
53
|
+
/** The base64 data of an image (without the data: prefix). Lets the
|
|
54
|
+
* reverse conversion rebuild the full image payload. */
|
|
55
|
+
imageBase64?: string;
|
|
56
|
+
}
|
|
57
|
+
/** Narrow a BiliMessage[] to CoreMessage[] for the kernel. The sidecar fields
|
|
58
|
+
* are transparently carried along — the kernel's `{ ...msg }` copies them. */
|
|
59
|
+
export declare function toCoreMessages(msgs: BiliMessage[]): CoreMessage[];
|
|
60
|
+
/** Re-decode a base64 data URL into media type + data. Returns undefined if
|
|
61
|
+
* the input is not a recognized data URL. Used by openaiToCore/responsesToCore
|
|
62
|
+
* to split image_url/input_image into the sidecar fields. */
|
|
63
|
+
export declare function parseDataUrl(url: string): {
|
|
64
|
+
mediaType: string;
|
|
65
|
+
base64: string;
|
|
66
|
+
} | undefined;
|
|
67
|
+
//# sourceMappingURL=bili-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bili-message.d.ts","sourceRoot":"","sources":["../../src/wire/bili-message.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;2DAE2D;AAC3D,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC5C;6DACyD;IACzD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;gEAC4D;IAC5D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;iEAC6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;6DAEyD;IACzD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;wCAGoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;+EAC2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;2EACuE;IACvE,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACtC;;+CAE2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;6DACyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;+EAC+E;AAC/E,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAEjE;AAED;;8DAE8D;AAC9D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAI3F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wire/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
// src/wire/util.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
function hashId(s) {
|
|
4
|
+
return createHash("sha256").update(s, "utf8").digest("hex").slice(0, 16);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// src/wire/message-id.ts
|
|
8
|
+
function deriveMessageId(role, contentType, text, options = {}) {
|
|
9
|
+
const seed = `${role}|${contentType}|${options.toolCallId ?? ""}|${options.toolName ?? ""}|${text}`;
|
|
10
|
+
return "h_" + hashId(seed);
|
|
11
|
+
}
|
|
12
|
+
var ClusterCounter = class {
|
|
13
|
+
counts = /* @__PURE__ */ new Map();
|
|
14
|
+
next(baseId) {
|
|
15
|
+
const n = this.counts.get(baseId) ?? 0;
|
|
16
|
+
this.counts.set(baseId, n + 1);
|
|
17
|
+
return n === 0 ? baseId : `${baseId}_${n}`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/wire/anthropic.ts
|
|
22
|
+
function extractSystem(system) {
|
|
23
|
+
if (!system) return "";
|
|
24
|
+
if (typeof system === "string") return system;
|
|
25
|
+
return system.map((b) => b.text).join("\n\n");
|
|
26
|
+
}
|
|
27
|
+
function buildSystem(text, original) {
|
|
28
|
+
if (Array.isArray(original) && original.length > 0) {
|
|
29
|
+
const ccBlock = original.find((b) => b.cache_control);
|
|
30
|
+
return [{ type: "text", text, ...ccBlock ? { cache_control: ccBlock.cache_control } : {} }];
|
|
31
|
+
}
|
|
32
|
+
return text;
|
|
33
|
+
}
|
|
34
|
+
function anthropicToCore(body) {
|
|
35
|
+
const msgs = [];
|
|
36
|
+
const cacheControls = /* @__PURE__ */ new Map();
|
|
37
|
+
const clusters = new ClusterCounter();
|
|
38
|
+
for (const m of body.messages) {
|
|
39
|
+
const blocks = typeof m.content === "string" ? [{ type: "text", text: m.content }] : m.content;
|
|
40
|
+
for (const b of blocks) {
|
|
41
|
+
switch (b.type) {
|
|
42
|
+
case "text": {
|
|
43
|
+
const base = deriveMessageId(m.role, "text", b.text);
|
|
44
|
+
const id = clusters.next(base);
|
|
45
|
+
msgs.push({ id, role: m.role, contentType: "text", text: b.text });
|
|
46
|
+
if (b.cache_control) cacheControls.set(id, b.cache_control);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case "tool_use": {
|
|
50
|
+
const base = deriveMessageId("assistant", "tool-call", safeStringify(b.input), {
|
|
51
|
+
toolCallId: b.id,
|
|
52
|
+
toolName: b.name
|
|
53
|
+
});
|
|
54
|
+
const id = clusters.next(base);
|
|
55
|
+
msgs.push({
|
|
56
|
+
id,
|
|
57
|
+
role: "assistant",
|
|
58
|
+
contentType: "tool-call",
|
|
59
|
+
toolName: b.name,
|
|
60
|
+
toolCallId: b.id,
|
|
61
|
+
text: safeStringify(b.input)
|
|
62
|
+
});
|
|
63
|
+
if (b.cache_control) cacheControls.set(id, b.cache_control);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case "tool_result": {
|
|
67
|
+
const text = typeof b.content === "string" ? b.content : b.content.map((c) => c.text).join("\n");
|
|
68
|
+
const base = deriveMessageId("tool", "tool-result", text, { toolCallId: b.tool_use_id });
|
|
69
|
+
const id = clusters.next(base);
|
|
70
|
+
msgs.push({
|
|
71
|
+
id,
|
|
72
|
+
role: "tool",
|
|
73
|
+
contentType: "tool-result",
|
|
74
|
+
toolCallId: b.tool_use_id,
|
|
75
|
+
text,
|
|
76
|
+
...b.is_error === true ? { toolIsError: true } : {}
|
|
77
|
+
});
|
|
78
|
+
if (b.cache_control) cacheControls.set(id, b.cache_control);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case "thinking": {
|
|
82
|
+
const base = deriveMessageId("assistant", "reasoning", b.thinking);
|
|
83
|
+
msgs.push({
|
|
84
|
+
id: clusters.next(base),
|
|
85
|
+
role: "assistant",
|
|
86
|
+
contentType: "reasoning",
|
|
87
|
+
text: b.thinking,
|
|
88
|
+
...b.signature ? { thinkingSignature: b.signature } : {}
|
|
89
|
+
});
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case "image": {
|
|
93
|
+
const base = deriveMessageId(m.role, "text", "[image]");
|
|
94
|
+
msgs.push({
|
|
95
|
+
id: clusters.next(base),
|
|
96
|
+
role: m.role,
|
|
97
|
+
contentType: "text",
|
|
98
|
+
text: "[image]",
|
|
99
|
+
rawAnthropicBlock: b
|
|
100
|
+
});
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { msgs, cacheControls };
|
|
107
|
+
}
|
|
108
|
+
function coreToAnthropic(messages, cacheControls) {
|
|
109
|
+
const out = [];
|
|
110
|
+
let current = null;
|
|
111
|
+
const flush = () => {
|
|
112
|
+
if (current && current.blocks.length > 0) {
|
|
113
|
+
out.push({ role: current.role, content: current.blocks });
|
|
114
|
+
}
|
|
115
|
+
current = null;
|
|
116
|
+
};
|
|
117
|
+
const cc = (id) => {
|
|
118
|
+
const v = cacheControls?.get(id);
|
|
119
|
+
return v ? { cache_control: v } : {};
|
|
120
|
+
};
|
|
121
|
+
for (const m of messages) {
|
|
122
|
+
const target = m.role === "assistant" ? "assistant" : "user";
|
|
123
|
+
if (!current || current.role !== target) {
|
|
124
|
+
flush();
|
|
125
|
+
current = { role: target, blocks: [] };
|
|
126
|
+
}
|
|
127
|
+
switch (m.contentType) {
|
|
128
|
+
case "text": {
|
|
129
|
+
if (m.rawAnthropicBlock) {
|
|
130
|
+
current.blocks.push(m.rawAnthropicBlock);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
current.blocks.push({ type: "text", text: m.text ?? "", ...cc(m.id) });
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case "tool-call":
|
|
137
|
+
current.blocks.push({
|
|
138
|
+
type: "tool_use",
|
|
139
|
+
id: m.toolCallId ?? `call_${m.id}`,
|
|
140
|
+
name: m.toolName ?? "unknown",
|
|
141
|
+
input: safeParse(m.text),
|
|
142
|
+
...cc(m.id)
|
|
143
|
+
});
|
|
144
|
+
break;
|
|
145
|
+
case "tool-result":
|
|
146
|
+
current.blocks.push({
|
|
147
|
+
type: "tool_result",
|
|
148
|
+
tool_use_id: m.toolCallId ?? "",
|
|
149
|
+
content: m.text ?? "",
|
|
150
|
+
...m.toolIsError ? { is_error: true } : {},
|
|
151
|
+
...cc(m.id)
|
|
152
|
+
});
|
|
153
|
+
break;
|
|
154
|
+
case "reasoning":
|
|
155
|
+
current.blocks.push({
|
|
156
|
+
type: "thinking",
|
|
157
|
+
thinking: m.text ?? "",
|
|
158
|
+
...m.thinkingSignature ? { signature: m.thinkingSignature } : {}
|
|
159
|
+
});
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
flush();
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
function conversationSignalAnthropic(body, headerValue) {
|
|
167
|
+
if (headerValue && headerValue.trim()) return headerValue.trim();
|
|
168
|
+
const firstUser = body.messages.find((m) => m.role === "user");
|
|
169
|
+
const seed = firstUser ? JSON.stringify(firstUser.content) : "default";
|
|
170
|
+
return hashId(seed);
|
|
171
|
+
}
|
|
172
|
+
function safeStringify(v) {
|
|
173
|
+
try {
|
|
174
|
+
return JSON.stringify(v ?? {});
|
|
175
|
+
} catch {
|
|
176
|
+
return "{}";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function safeParse(s) {
|
|
180
|
+
if (!s) return {};
|
|
181
|
+
try {
|
|
182
|
+
return JSON.parse(s);
|
|
183
|
+
} catch {
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/wire/bili-message.ts
|
|
189
|
+
function toCoreMessages(msgs) {
|
|
190
|
+
return msgs;
|
|
191
|
+
}
|
|
192
|
+
function parseDataUrl(url) {
|
|
193
|
+
const m = /^data:([^;,]+)(?:;base64)?,(.+)$/i.exec(url);
|
|
194
|
+
if (!m) return void 0;
|
|
195
|
+
return { mediaType: m[1], base64: m[2] };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/wire/openai.ts
|
|
199
|
+
function openaiToCore(body) {
|
|
200
|
+
const msgs = [];
|
|
201
|
+
const clusters = new ClusterCounter();
|
|
202
|
+
for (const m of body.messages) {
|
|
203
|
+
switch (m.role) {
|
|
204
|
+
case "system":
|
|
205
|
+
case "developer": {
|
|
206
|
+
const base = deriveMessageId(m.role, "text", stringContent(m.content));
|
|
207
|
+
msgs.push({ id: clusters.next(base), role: "system", contentType: "text", text: stringContent(m.content), originalRole: m.role });
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
case "user": {
|
|
211
|
+
const text = stringContent(m.content);
|
|
212
|
+
const img = firstImagePart(m.content);
|
|
213
|
+
const base = deriveMessageId("user", "text", text);
|
|
214
|
+
msgs.push({
|
|
215
|
+
id: clusters.next(base),
|
|
216
|
+
role: "user",
|
|
217
|
+
contentType: "text",
|
|
218
|
+
text,
|
|
219
|
+
...img ? { rawOpenaiContent: img.part, imageMediaType: img.mediaType, imageBase64: img.base64 } : {}
|
|
220
|
+
});
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case "assistant": {
|
|
224
|
+
const reasoning = typeof m.reasoning_content === "string" ? m.reasoning_content : "";
|
|
225
|
+
if (reasoning) {
|
|
226
|
+
const base = deriveMessageId("assistant", "reasoning", reasoning);
|
|
227
|
+
msgs.push({
|
|
228
|
+
id: clusters.next(base),
|
|
229
|
+
role: "assistant",
|
|
230
|
+
contentType: "reasoning",
|
|
231
|
+
text: reasoning,
|
|
232
|
+
reasoningContent: reasoning
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
const text = stringContent(m.content);
|
|
236
|
+
if (text) {
|
|
237
|
+
const base = deriveMessageId("assistant", "text", text);
|
|
238
|
+
msgs.push({ id: clusters.next(base), role: "assistant", contentType: "text", text });
|
|
239
|
+
}
|
|
240
|
+
if (Array.isArray(m.tool_calls)) {
|
|
241
|
+
for (const tc of m.tool_calls) {
|
|
242
|
+
const base = deriveMessageId("assistant", "tool-call", tc.function.arguments ?? "", {
|
|
243
|
+
toolCallId: tc.id,
|
|
244
|
+
toolName: tc.function.name
|
|
245
|
+
});
|
|
246
|
+
msgs.push({
|
|
247
|
+
id: clusters.next(base),
|
|
248
|
+
role: "assistant",
|
|
249
|
+
contentType: "tool-call",
|
|
250
|
+
toolName: tc.function.name,
|
|
251
|
+
toolCallId: tc.id,
|
|
252
|
+
text: tc.function.arguments ?? ""
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
case "tool": {
|
|
259
|
+
const base = deriveMessageId("tool", "tool-result", stringContent(m.content), {
|
|
260
|
+
toolCallId: m.tool_call_id ?? ""
|
|
261
|
+
});
|
|
262
|
+
msgs.push({
|
|
263
|
+
id: clusters.next(base),
|
|
264
|
+
role: "tool",
|
|
265
|
+
contentType: "tool-result",
|
|
266
|
+
toolCallId: m.tool_call_id ?? "",
|
|
267
|
+
text: stringContent(m.content)
|
|
268
|
+
});
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return { msgs };
|
|
274
|
+
}
|
|
275
|
+
function coreToOpenai(messages) {
|
|
276
|
+
const out = [];
|
|
277
|
+
let pending = null;
|
|
278
|
+
const flush = () => {
|
|
279
|
+
if (!pending) return;
|
|
280
|
+
const reasoning = pending.reasoning !== null && pending.reasoning.length > 0 ? pending.reasoning : void 0;
|
|
281
|
+
if (pending.toolCalls.length > 0) {
|
|
282
|
+
out.push({
|
|
283
|
+
role: "assistant",
|
|
284
|
+
content: pending.text ?? null,
|
|
285
|
+
tool_calls: pending.toolCalls,
|
|
286
|
+
...reasoning ? { reasoning_content: reasoning } : {}
|
|
287
|
+
});
|
|
288
|
+
} else if (pending.text !== null) {
|
|
289
|
+
out.push({ role: "assistant", content: pending.text, ...reasoning ? { reasoning_content: reasoning } : {} });
|
|
290
|
+
} else if (reasoning) {
|
|
291
|
+
out.push({ role: "assistant", content: null, reasoning_content: reasoning });
|
|
292
|
+
}
|
|
293
|
+
pending = null;
|
|
294
|
+
};
|
|
295
|
+
for (const m of messages) {
|
|
296
|
+
if (m.role === "assistant") {
|
|
297
|
+
if (!pending) pending = { text: null, toolCalls: [], reasoning: null };
|
|
298
|
+
if (m.contentType === "reasoning") {
|
|
299
|
+
pending.reasoning = (pending.reasoning ?? "") + (m.reasoningContent ?? m.text ?? "");
|
|
300
|
+
} else if (m.contentType === "text") {
|
|
301
|
+
pending.text = (pending.text ?? "") + (m.text ?? "");
|
|
302
|
+
} else if (m.contentType === "tool-call") {
|
|
303
|
+
pending.toolCalls.push({
|
|
304
|
+
id: m.toolCallId ?? `call_${m.id}`,
|
|
305
|
+
type: "function",
|
|
306
|
+
function: { name: m.toolName ?? "unknown", arguments: m.text ?? "" }
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
flush();
|
|
311
|
+
if (m.role === "system") {
|
|
312
|
+
out.push({ role: m.originalRole === "developer" ? "developer" : "system", content: m.text ?? "" });
|
|
313
|
+
} else if (m.role === "user") {
|
|
314
|
+
if (m.rawOpenaiContent || m.imageBase64) {
|
|
315
|
+
const parts = [];
|
|
316
|
+
if (m.text) parts.push({ type: "text", text: m.text });
|
|
317
|
+
if (m.rawOpenaiContent) {
|
|
318
|
+
parts.push(m.rawOpenaiContent);
|
|
319
|
+
} else if (m.imageBase64 && m.imageMediaType) {
|
|
320
|
+
parts.push({ type: "image_url", image_url: { url: `data:${m.imageMediaType};base64,${m.imageBase64}` } });
|
|
321
|
+
}
|
|
322
|
+
out.push({ role: "user", content: parts });
|
|
323
|
+
} else {
|
|
324
|
+
out.push({ role: "user", content: m.text ?? "" });
|
|
325
|
+
}
|
|
326
|
+
} else if (m.role === "tool") {
|
|
327
|
+
out.push({ role: "tool", tool_call_id: m.toolCallId ?? "", content: m.text ?? "" });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
flush();
|
|
332
|
+
return out;
|
|
333
|
+
}
|
|
334
|
+
function injectOpenaiSystem(messages, parts) {
|
|
335
|
+
if (parts.length === 0) return messages;
|
|
336
|
+
const extra = parts.join("\n\n");
|
|
337
|
+
if (messages.length > 0 && (messages[0]?.role === "system" || messages[0]?.role === "developer")) {
|
|
338
|
+
const head = messages[0];
|
|
339
|
+
const base = stringContent(head.content);
|
|
340
|
+
const merged = base ? `${base}
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
${extra}` : extra;
|
|
345
|
+
return [{ ...head, content: merged }, ...messages.slice(1)];
|
|
346
|
+
}
|
|
347
|
+
return [{ role: "system", content: extra }, ...messages];
|
|
348
|
+
}
|
|
349
|
+
function conversationSignalOpenai(body, headerValue) {
|
|
350
|
+
if (headerValue && headerValue.trim()) return headerValue.trim();
|
|
351
|
+
const firstUser = body.messages.find((m) => m.role === "user");
|
|
352
|
+
const seed = firstUser ? stringContent(firstUser.content) : "default";
|
|
353
|
+
return hashId(seed);
|
|
354
|
+
}
|
|
355
|
+
function stringContent(content) {
|
|
356
|
+
if (content == null) return "";
|
|
357
|
+
if (typeof content === "string") return content;
|
|
358
|
+
if (Array.isArray(content)) {
|
|
359
|
+
return content.map((p) => typeof p === "string" ? p : p.type === "text" ? p.text ?? "" : "").join("\n");
|
|
360
|
+
}
|
|
361
|
+
return "";
|
|
362
|
+
}
|
|
363
|
+
function firstImagePart(content) {
|
|
364
|
+
if (!Array.isArray(content)) return void 0;
|
|
365
|
+
for (const p of content) {
|
|
366
|
+
if (p && typeof p === "object" && p.type === "image_url") {
|
|
367
|
+
const iu = p.image_url;
|
|
368
|
+
const url = iu?.url;
|
|
369
|
+
if (typeof url === "string") {
|
|
370
|
+
const parsed = parseDataUrl(url);
|
|
371
|
+
if (parsed) return { part: p, mediaType: parsed.mediaType, base64: parsed.base64 };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return void 0;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/wire/responses.ts
|
|
379
|
+
var OPAQUE_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
380
|
+
"additional_tools",
|
|
381
|
+
"mcp_list_tools"
|
|
382
|
+
]);
|
|
383
|
+
function isOpaqueItem(item) {
|
|
384
|
+
return OPAQUE_ITEM_TYPES.has(item.type);
|
|
385
|
+
}
|
|
386
|
+
function shouldDropAllReasoning() {
|
|
387
|
+
return (process.env.ACP_REASONING_KEEP ?? "").trim().toLowerCase() === "none";
|
|
388
|
+
}
|
|
389
|
+
function partText(part) {
|
|
390
|
+
if (part.type === "input_text" || part.type === "output_text") {
|
|
391
|
+
return typeof part.text === "string" ? part.text : "";
|
|
392
|
+
}
|
|
393
|
+
return "";
|
|
394
|
+
}
|
|
395
|
+
function messageContent(content) {
|
|
396
|
+
return typeof content === "string" ? content : content.map(partText).join("\n");
|
|
397
|
+
}
|
|
398
|
+
function responsesToCore(body) {
|
|
399
|
+
const msgs = [];
|
|
400
|
+
const systemParts = [];
|
|
401
|
+
const preamble = [];
|
|
402
|
+
const customToolCallIds = /* @__PURE__ */ new Set();
|
|
403
|
+
const layout = [];
|
|
404
|
+
let droppedReasoning = 0;
|
|
405
|
+
const clusters = new ClusterCounter();
|
|
406
|
+
let idx = 0;
|
|
407
|
+
if (typeof body.instructions === "string" && body.instructions.trim()) systemParts.push(body.instructions);
|
|
408
|
+
if (typeof body.input === "string") {
|
|
409
|
+
const id = clusters.next(deriveMessageId("user", "text", body.input));
|
|
410
|
+
msgs.push({ id, role: "user", contentType: "text", text: body.input });
|
|
411
|
+
return { msgs, systemParts, preamble, customToolCallIds, layout, droppedReasoning, stringInput: { original: body.input, coreId: id } };
|
|
412
|
+
}
|
|
413
|
+
for (const item of body.input) {
|
|
414
|
+
let coreId;
|
|
415
|
+
if (isOpaqueItem(item)) preamble.push(item);
|
|
416
|
+
switch (item.type) {
|
|
417
|
+
case "reasoning": {
|
|
418
|
+
if (shouldDropAllReasoning()) {
|
|
419
|
+
droppedReasoning++;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const rid = typeof item.id === "string" ? String(item.id) : hashId(JSON.stringify(item));
|
|
423
|
+
coreId = clusters.next(deriveMessageId("assistant", "reasoning", rid));
|
|
424
|
+
msgs.push({
|
|
425
|
+
id: coreId,
|
|
426
|
+
role: "assistant",
|
|
427
|
+
contentType: "reasoning",
|
|
428
|
+
text: rid,
|
|
429
|
+
rawResponsesItem: item
|
|
430
|
+
});
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
case "message": {
|
|
434
|
+
const message = item;
|
|
435
|
+
const text = messageContent(message.content);
|
|
436
|
+
if (message.role === "system" || message.role === "developer") {
|
|
437
|
+
systemParts.push(text);
|
|
438
|
+
idx++;
|
|
439
|
+
continue;
|
|
440
|
+
} else if (message.role === "user" || message.role === "assistant" && text) {
|
|
441
|
+
const role = message.role;
|
|
442
|
+
coreId = clusters.next(deriveMessageId(role, "text", text));
|
|
443
|
+
const imageUrl = Array.isArray(message.content) ? message.content.find((part) => part.type === "input_image" && typeof part.image_url === "string")?.image_url : void 0;
|
|
444
|
+
const image = typeof imageUrl === "string" ? parseDataUrl(imageUrl) : void 0;
|
|
445
|
+
msgs.push({
|
|
446
|
+
id: coreId,
|
|
447
|
+
role,
|
|
448
|
+
contentType: "text",
|
|
449
|
+
text,
|
|
450
|
+
rawResponsesItem: item,
|
|
451
|
+
...image ? { imageMediaType: image.mediaType, imageBase64: image.base64 } : {}
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
case "function_call": {
|
|
457
|
+
const call = item;
|
|
458
|
+
coreId = clusters.next(deriveMessageId("assistant", "tool-call", call.arguments ?? "", {
|
|
459
|
+
toolCallId: call.call_id,
|
|
460
|
+
toolName: call.name
|
|
461
|
+
}));
|
|
462
|
+
msgs.push({
|
|
463
|
+
id: coreId,
|
|
464
|
+
role: "assistant",
|
|
465
|
+
contentType: "tool-call",
|
|
466
|
+
toolName: call.name,
|
|
467
|
+
toolCallId: call.call_id,
|
|
468
|
+
text: call.arguments ?? "",
|
|
469
|
+
rawResponsesItem: item
|
|
470
|
+
});
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
case "function_call_output": {
|
|
474
|
+
const output = item;
|
|
475
|
+
const text = typeof output.output === "string" ? output.output : JSON.stringify(output.output);
|
|
476
|
+
coreId = clusters.next(deriveMessageId("tool", "tool-result", text, { toolCallId: output.call_id }));
|
|
477
|
+
msgs.push({ id: coreId, role: "tool", contentType: "tool-result", toolCallId: output.call_id, text, rawResponsesItem: item });
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
case "computer_call":
|
|
481
|
+
case "computer_call_output":
|
|
482
|
+
case "file_search_call":
|
|
483
|
+
case "web_search_call":
|
|
484
|
+
case "image_generation_call":
|
|
485
|
+
case "code_interpreter_call":
|
|
486
|
+
case "mcp_call": {
|
|
487
|
+
const rid = typeof item.id === "string" ? String(item.id) : hashId(JSON.stringify(item));
|
|
488
|
+
coreId = clusters.next(deriveMessageId("assistant", "responses-call", rid));
|
|
489
|
+
msgs.push({ id: coreId, role: "assistant", contentType: "reasoning", text: rid, rawResponsesItem: item });
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
case "custom_tool_call": {
|
|
493
|
+
const ctc = item;
|
|
494
|
+
const callId = ctc.call_id ?? `call_${idx}`;
|
|
495
|
+
customToolCallIds.add(callId);
|
|
496
|
+
const argText = ctc.input ?? ctc.arguments ?? "";
|
|
497
|
+
coreId = clusters.next(deriveMessageId("assistant", "tool-call", argText, { toolCallId: callId, toolName: ctc.name ?? "custom" }));
|
|
498
|
+
msgs.push({ id: coreId, role: "assistant", contentType: "tool-call", toolName: ctc.name ?? "custom", toolCallId: callId, text: argText, rawResponsesItem: item });
|
|
499
|
+
break;
|
|
500
|
+
}
|
|
501
|
+
case "custom_tool_call_output": {
|
|
502
|
+
const ctco = item;
|
|
503
|
+
const callId = ctco.call_id ?? `call_${idx}`;
|
|
504
|
+
customToolCallIds.add(callId);
|
|
505
|
+
const outText = typeof ctco.output === "string" ? ctco.output : JSON.stringify(ctco.output ?? "");
|
|
506
|
+
coreId = clusters.next(deriveMessageId("tool", "tool-result", outText, { toolCallId: callId }));
|
|
507
|
+
msgs.push({ id: coreId, role: "tool", contentType: "tool-result", toolCallId: callId, text: outText, rawResponsesItem: item });
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
default:
|
|
511
|
+
if (!isOpaqueItem(item)) preamble.push(item);
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
layout.push({ original: item, coreId });
|
|
515
|
+
idx++;
|
|
516
|
+
}
|
|
517
|
+
return { msgs, systemParts, preamble, customToolCallIds, layout, droppedReasoning };
|
|
518
|
+
}
|
|
519
|
+
function patchTextParts(parts, text) {
|
|
520
|
+
const textIndexes = parts.flatMap(
|
|
521
|
+
(part, index) => part.type === "input_text" || part.type === "output_text" ? [index] : []
|
|
522
|
+
);
|
|
523
|
+
if (textIndexes.length === 0) return [{ type: "input_text", text }, ...parts];
|
|
524
|
+
const first = textIndexes[0];
|
|
525
|
+
const remaining = new Set(textIndexes.slice(1));
|
|
526
|
+
return parts.map((part, index) => {
|
|
527
|
+
if (index === first) return { ...part, text };
|
|
528
|
+
if (remaining.has(index)) return { ...part, text: "" };
|
|
529
|
+
return part;
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
function patchOriginalItem(original, source, next) {
|
|
533
|
+
if (source.text === next.text && source.toolName === next.toolName && source.toolCallId === next.toolCallId && source.role === next.role && source.contentType === next.contentType) return original;
|
|
534
|
+
if (original.type === "message") {
|
|
535
|
+
const message = original;
|
|
536
|
+
const content = typeof message.content === "string" ? next.text ?? "" : patchTextParts(message.content, next.text ?? "");
|
|
537
|
+
return { ...message, content };
|
|
538
|
+
}
|
|
539
|
+
if (original.type === "function_call") {
|
|
540
|
+
return {
|
|
541
|
+
...original,
|
|
542
|
+
name: next.toolName ?? String(original.name ?? "unknown"),
|
|
543
|
+
call_id: next.toolCallId ?? String(original.call_id ?? ""),
|
|
544
|
+
arguments: next.text ?? ""
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
if (original.type === "function_call_output") {
|
|
548
|
+
return { ...original, call_id: next.toolCallId ?? String(original.call_id ?? ""), output: next.text ?? "" };
|
|
549
|
+
}
|
|
550
|
+
return original;
|
|
551
|
+
}
|
|
552
|
+
function patchResponsesInput(projection, messages) {
|
|
553
|
+
if (projection.stringInput) {
|
|
554
|
+
const original = projection.msgs.find((message) => message.id === projection.stringInput?.coreId);
|
|
555
|
+
const next = messages.find((message) => message.id === projection.stringInput?.coreId);
|
|
556
|
+
if (original && next && messages.length === 1 && next.role === "user" && next.contentType === "text") {
|
|
557
|
+
return next.text === original.text ? projection.stringInput.original : next.text ?? "";
|
|
558
|
+
}
|
|
559
|
+
return coreToResponses(messages, projection.customToolCallIds);
|
|
560
|
+
}
|
|
561
|
+
const sourceById = new Map(projection.msgs.map((message) => [message.id, message]));
|
|
562
|
+
const nextById = new Map(messages.map((message) => [message.id, message]));
|
|
563
|
+
const slotById = /* @__PURE__ */ new Map();
|
|
564
|
+
projection.layout.forEach((slot, index) => {
|
|
565
|
+
if (slot.coreId) slotById.set(slot.coreId, index);
|
|
566
|
+
});
|
|
567
|
+
const insertions = /* @__PURE__ */ new Map();
|
|
568
|
+
for (let index = 0; index < messages.length; index++) {
|
|
569
|
+
const message = messages[index];
|
|
570
|
+
if (sourceById.has(message.id)) continue;
|
|
571
|
+
let target = projection.layout.length;
|
|
572
|
+
for (let nextIndex = index + 1; nextIndex < messages.length; nextIndex++) {
|
|
573
|
+
const slot = slotById.get(messages[nextIndex].id);
|
|
574
|
+
if (slot !== void 0) {
|
|
575
|
+
target = slot;
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const generated = coreToResponses([message], projection.customToolCallIds);
|
|
580
|
+
if (generated.length > 0) insertions.set(target, [...insertions.get(target) ?? [], ...generated]);
|
|
581
|
+
}
|
|
582
|
+
const out = [];
|
|
583
|
+
projection.layout.forEach((slot, index) => {
|
|
584
|
+
out.push(...insertions.get(index) ?? []);
|
|
585
|
+
if (!slot.coreId) {
|
|
586
|
+
out.push(slot.original);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
const source = sourceById.get(slot.coreId);
|
|
590
|
+
const next = nextById.get(slot.coreId);
|
|
591
|
+
if (source && next) out.push(patchOriginalItem(slot.original, source, next));
|
|
592
|
+
});
|
|
593
|
+
out.push(...insertions.get(projection.layout.length) ?? []);
|
|
594
|
+
return out;
|
|
595
|
+
}
|
|
596
|
+
function coreToResponses(messages, customToolCallIds = /* @__PURE__ */ new Set()) {
|
|
597
|
+
const out = [];
|
|
598
|
+
for (const message of messages) {
|
|
599
|
+
const biliMessage = message;
|
|
600
|
+
const raw = biliMessage.rawResponsesItem;
|
|
601
|
+
if (message.role === "system") {
|
|
602
|
+
out.push({ type: "message", role: "developer", content: message.text ?? "" });
|
|
603
|
+
} else if (message.role === "user") {
|
|
604
|
+
if (raw?.type === "message" && messageContent(raw.content) === (message.text ?? "")) out.push(raw);
|
|
605
|
+
else out.push({ type: "message", role: "user", content: message.text ?? "" });
|
|
606
|
+
} else if (message.role === "assistant") {
|
|
607
|
+
if (message.contentType === "text") {
|
|
608
|
+
out.push({ type: "message", role: "assistant", content: message.text ?? "" });
|
|
609
|
+
} else if (message.contentType === "tool-call") {
|
|
610
|
+
const callId = message.toolCallId ?? `call_${message.id}`;
|
|
611
|
+
if (customToolCallIds.has(callId)) {
|
|
612
|
+
out.push({ type: "custom_tool_call", call_id: callId, name: message.toolName ?? "unknown", input: message.text ?? "", status: "completed" });
|
|
613
|
+
} else {
|
|
614
|
+
out.push({ type: "function_call", call_id: callId, name: message.toolName ?? "unknown", arguments: message.text ?? "" });
|
|
615
|
+
}
|
|
616
|
+
} else if (message.contentType === "reasoning") {
|
|
617
|
+
if (raw) out.push(raw);
|
|
618
|
+
}
|
|
619
|
+
} else if (message.role === "tool") {
|
|
620
|
+
const callId = message.toolCallId ?? "";
|
|
621
|
+
if (customToolCallIds.has(callId)) {
|
|
622
|
+
out.push({ type: "custom_tool_call_output", call_id: callId, output: message.text ?? "" });
|
|
623
|
+
} else {
|
|
624
|
+
out.push({ type: "function_call_output", call_id: callId, output: message.text ?? "" });
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return out;
|
|
629
|
+
}
|
|
630
|
+
function injectResponsesDeveloperMessage(input, content) {
|
|
631
|
+
const items = typeof input === "string" ? [{ type: "message", role: "user", content: input }] : [...input];
|
|
632
|
+
let index = 0;
|
|
633
|
+
while (items[index]?.type === "additional_tools") index++;
|
|
634
|
+
items.splice(index, 0, { type: "message", role: "developer", content });
|
|
635
|
+
return items;
|
|
636
|
+
}
|
|
637
|
+
function conversationIdentityResponses(body, headerValue) {
|
|
638
|
+
if (headerValue?.trim()) return { value: headerValue.trim(), source: "header", clientProvided: true };
|
|
639
|
+
if (typeof body.session_id === "string" && body.session_id.trim()) {
|
|
640
|
+
return { value: body.session_id.trim(), source: "body-session", clientProvided: true };
|
|
641
|
+
}
|
|
642
|
+
const metadataSession = body.metadata?.session_id;
|
|
643
|
+
if (typeof metadataSession === "string" && metadataSession.trim()) {
|
|
644
|
+
return { value: metadataSession.trim(), source: "metadata-session", clientProvided: true };
|
|
645
|
+
}
|
|
646
|
+
if (typeof body.previous_response_id === "string" && body.previous_response_id.trim()) {
|
|
647
|
+
return { value: body.previous_response_id.trim(), source: "previous-response", clientProvided: false };
|
|
648
|
+
}
|
|
649
|
+
return { value: hashId(JSON.stringify(body.input ?? [])), source: "content-fingerprint", clientProvided: false };
|
|
650
|
+
}
|
|
651
|
+
function conversationSignalResponses(body, headerValue) {
|
|
652
|
+
return conversationIdentityResponses(body, headerValue).value;
|
|
653
|
+
}
|
|
654
|
+
export {
|
|
655
|
+
ClusterCounter,
|
|
656
|
+
anthropicToCore,
|
|
657
|
+
buildSystem,
|
|
658
|
+
conversationIdentityResponses,
|
|
659
|
+
conversationSignalAnthropic,
|
|
660
|
+
conversationSignalOpenai,
|
|
661
|
+
conversationSignalResponses,
|
|
662
|
+
coreToAnthropic,
|
|
663
|
+
coreToOpenai,
|
|
664
|
+
coreToResponses,
|
|
665
|
+
deriveMessageId,
|
|
666
|
+
extractSystem,
|
|
667
|
+
hashId,
|
|
668
|
+
injectOpenaiSystem,
|
|
669
|
+
injectResponsesDeveloperMessage,
|
|
670
|
+
openaiToCore,
|
|
671
|
+
parseDataUrl,
|
|
672
|
+
patchResponsesInput,
|
|
673
|
+
responsesToCore,
|
|
674
|
+
toCoreMessages
|
|
675
|
+
};
|
|
676
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/wire/util.ts","../../src/wire/message-id.ts","../../src/wire/anthropic.ts","../../src/wire/bili-message.ts","../../src/wire/openai.ts","../../src/wire/responses.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\n/** SHA-256-derived short id — kept verbatim from the proxy so message ids\n * stay byte-identical across the extraction (re-keying would orphan every\n * downstream map keyed on these ids). */\nexport function hashId(s: string): string {\n return createHash(\"sha256\").update(s, \"utf8\").digest(\"hex\").slice(0, 16);\n}\n\n/** How a conversation's identity was derived (kept verbatim from the proxy's\n * session-id.ts — only the TYPE moves; session-key derivation stays in the\n * proxy, which owns multi-tenant state). */\nexport type ConversationIdentity = {\n value: string;\n source: \"header\" | \"body-session\" | \"metadata-session\" | \"previous-response\" | \"content-fingerprint\" | \"generated\";\n clientProvided: boolean;\n};\n","import { hashId } from \"./util.js\";\n\n/**\n * Derive a stable, content-based message id.\n *\n * PROBLEM: none of the three wire protocols (Anthropic Messages, OpenAI Chat\n * Completions, OpenAI Responses) attach a stable id to request-side message\n * items. Historically each converter used `raw-${idx}` — a *position* index,\n * not an identity. As soon as a client deletes/reorders messages (other plugins\n * summarizing away old turns, multi-agent setups, etc.) the index drifts:\n * downstream ids shift, so\n * - assignRefs reuses stale `byRaw` entries, hiding new messages, and\n * - compression `effectiveMessageIds` start pointing at the *wrong* messages,\n * silently swallowing live content under an unrelated summary.\n *\n * FIX: derive the id from a SHA-256 of the message identity:\n * role + contentType + toolCallId + toolName + text\n * Two messages with identical identity collide. To keep duplicates distinct\n * (and avoid `covered` sets collapsing unrelated turns onto one id) we append a\n * within-conversation *cluster index* `_N`: the Nth occurrence of the same\n * identity, counting from 0 in arrival order.\n *\n * Trade-off vs a real client id:\n * - deleting a duplicated message only disturbs the cluster of that identity\n * (local damage), never the whole downstream (global damage like position).\n * - fully distinct messages are completely immune to reordering/deletion.\n *\n * `idx` is passed purely to break ties *within a single conversion pass*; it is\n * not part of the identity, so two passes over the same content produce the\n * same cluster numbering (deterministic).\n */\nexport function deriveMessageId(\n role: string,\n contentType: string,\n text: string,\n options: {\n toolCallId?: string;\n toolName?: string;\n } = {},\n): string {\n const seed = `${role}|${contentType}|${options.toolCallId ?? \"\"}|${options.toolName ?? \"\"}|${text}`;\n return \"h_\" + hashId(seed);\n}\n\n/**\n * Stateful cluster counter. Each converter instantiates one per conversion\n * pass; it tracks how many times each base identity has been seen so that the\n * Nth duplicate gets a `_${N}` suffix.\n */\nexport class ClusterCounter {\n private counts = new Map<string, number>();\n\n next(baseId: string): string {\n const n = this.counts.get(baseId) ?? 0;\n this.counts.set(baseId, n + 1);\n return n === 0 ? baseId : `${baseId}_${n}`;\n }\n}\n","import type { BiliMessage } from \"./bili-message.js\";\nimport { hashId } from \"./util.js\";\nimport { ClusterCounter, deriveMessageId } from \"./message-id.js\";\n\nexport type AnthropicTextBlock = { type: \"text\"; text: string; cache_control?: unknown };\nexport type AnthropicToolUse = {\n type: \"tool_use\";\n id: string;\n name: string;\n input: unknown;\n cache_control?: unknown;\n};\nexport type AnthropicToolResult = {\n type: \"tool_result\";\n tool_use_id: string;\n content: string | AnthropicTextBlock[];\n is_error?: boolean;\n cache_control?: unknown;\n};\nexport type AnthropicImage = { type: \"image\"; source: unknown };\nexport type AnthropicThinking = { type: \"thinking\"; thinking: string; signature?: string };\nexport type AnthropicBlock =\n | AnthropicTextBlock\n | AnthropicToolUse\n | AnthropicToolResult\n | AnthropicImage\n | AnthropicThinking;\n\nexport type AnthropicMessage = {\n role: \"user\" | \"assistant\";\n content: string | AnthropicBlock[];\n};\n\nexport type AnthropicRequestBody = {\n model?: string;\n max_tokens?: number;\n system?: string | AnthropicTextBlock[];\n messages: AnthropicMessage[];\n tools?: unknown[];\n stream?: boolean;\n temperature?: number;\n [key: string]: unknown;\n};\n\n\nexport function extractSystem(system: AnthropicRequestBody[\"system\"]): string {\n if (!system) return \"\";\n if (typeof system === \"string\") return system;\n return system.map((b) => b.text).join(\"\\n\\n\");\n}\n\nexport function buildSystem(text: string, original: AnthropicRequestBody[\"system\"]): string | AnthropicTextBlock[] {\n if (Array.isArray(original) && original.length > 0) {\n const ccBlock = original.find((b) => b.cache_control);\n return [{ type: \"text\", text, ...(ccBlock ? { cache_control: ccBlock.cache_control } : {}) }];\n }\n return text;\n}\n\ntype Flat = { msgs: BiliMessage[]; cacheControls: Map<string, unknown> };\n\nexport function anthropicToCore(body: AnthropicRequestBody): Flat {\n const msgs: BiliMessage[] = [];\n const cacheControls = new Map<string, unknown>();\n const clusters = new ClusterCounter();\n for (const m of body.messages) {\n const blocks = typeof m.content === \"string\" ? [{ type: \"text\" as const, text: m.content }] : m.content;\n for (const b of blocks) {\n switch (b.type) {\n case \"text\": {\n const base = deriveMessageId(m.role, \"text\", b.text);\n const id = clusters.next(base);\n msgs.push({ id, role: m.role, contentType: \"text\", text: b.text });\n if (b.cache_control) cacheControls.set(id, b.cache_control);\n break;\n }\n case \"tool_use\": {\n const base = deriveMessageId(\"assistant\", \"tool-call\", safeStringify(b.input), {\n toolCallId: b.id,\n toolName: b.name,\n });\n const id = clusters.next(base);\n msgs.push({\n id,\n role: \"assistant\",\n contentType: \"tool-call\",\n toolName: b.name,\n toolCallId: b.id,\n text: safeStringify(b.input),\n });\n if (b.cache_control) cacheControls.set(id, b.cache_control);\n break;\n }\n case \"tool_result\": {\n const text = typeof b.content === \"string\" ? b.content : b.content.map((c) => c.text).join(\"\\n\");\n const base = deriveMessageId(\"tool\", \"tool-result\", text, { toolCallId: b.tool_use_id });\n const id = clusters.next(base);\n msgs.push({\n id,\n role: \"tool\",\n contentType: \"tool-result\",\n toolCallId: b.tool_use_id,\n text,\n ...(b.is_error === true ? { toolIsError: true } : {}),\n });\n if (b.cache_control) cacheControls.set(id, b.cache_control);\n break;\n }\n case \"thinking\": {\n const base = deriveMessageId(\"assistant\", \"reasoning\", b.thinking);\n msgs.push({\n id: clusters.next(base),\n role: \"assistant\",\n contentType: \"reasoning\",\n text: b.thinking,\n ...(b.signature ? { thinkingSignature: b.signature } : {}),\n });\n break;\n }\n case \"image\": {\n const base = deriveMessageId(m.role, \"text\", \"[image]\");\n msgs.push({\n id: clusters.next(base),\n role: m.role,\n contentType: \"text\",\n text: \"[image]\",\n rawAnthropicBlock: b,\n });\n break;\n }\n }\n }\n }\n return { msgs, cacheControls };\n}\n\nexport function coreToAnthropic(messages: BiliMessage[], cacheControls?: Map<string, unknown>): AnthropicMessage[] {\n const out: AnthropicMessage[] = [];\n let current: { role: \"user\" | \"assistant\"; blocks: AnthropicBlock[] } | null = null;\n const flush = () => {\n if (current && current.blocks.length > 0) {\n out.push({ role: current.role, content: current.blocks });\n }\n current = null;\n };\n const cc = (id: string): { cache_control?: unknown } => {\n const v = cacheControls?.get(id);\n return v ? { cache_control: v } : {};\n };\n for (const m of messages) {\n const target: \"user\" | \"assistant\" =\n m.role === \"assistant\" ? \"assistant\" : \"user\";\n if (!current || current.role !== target) {\n flush();\n current = { role: target, blocks: [] };\n }\n switch (m.contentType) {\n case \"text\": {\n if (m.rawAnthropicBlock) {\n current.blocks.push(m.rawAnthropicBlock as AnthropicBlock);\n break;\n }\n current.blocks.push({ type: \"text\", text: m.text ?? \"\", ...cc(m.id) });\n break;\n }\n case \"tool-call\":\n current.blocks.push({\n type: \"tool_use\",\n id: m.toolCallId ?? `call_${m.id}`,\n name: m.toolName ?? \"unknown\",\n input: safeParse(m.text),\n ...cc(m.id),\n });\n break;\n case \"tool-result\":\n current.blocks.push({\n type: \"tool_result\",\n tool_use_id: m.toolCallId ?? \"\",\n content: m.text ?? \"\",\n ...(m.toolIsError ? { is_error: true } : {}),\n ...cc(m.id),\n });\n break;\n case \"reasoning\":\n current.blocks.push({\n type: \"thinking\",\n thinking: m.text ?? \"\",\n ...(m.thinkingSignature ? { signature: m.thinkingSignature } : {}),\n });\n break;\n }\n }\n flush();\n return out;\n}\n\n/** Extract the conversation dimension for Anthropic: a client-provided\n * session header if present, else a content fingerprint of the first user\n * message. The protocol+upstream+key dimensions are mixed in by the caller\n * (server.ts) via deriveSessionId() — this function contributes only the\n * conversation axis. */\nexport function conversationSignalAnthropic(body: AnthropicRequestBody, headerValue?: string): string {\n if (headerValue && headerValue.trim()) return headerValue.trim();\n const firstUser = body.messages.find((m) => m.role === \"user\");\n const seed = firstUser ? JSON.stringify(firstUser.content) : \"default\";\n return hashId(seed);\n}\n\nfunction safeStringify(v: unknown): string {\n try {\n return JSON.stringify(v ?? {});\n } catch {\n return \"{}\";\n }\n}\n\nfunction safeParse(s: string | undefined): unknown {\n if (!s) return {};\n try {\n return JSON.parse(s);\n } catch {\n return {};\n }\n}\n","/**\n * Lossless message bridge between protocol-specific message formats and the\n * kernel's CoreMessage.\n *\n * Problem: `anthropicToCore` / `openaiToCore` / `responsesToCore` flatten\n * rich protocol blocks (images, thinking signatures, tool_result.is_error,\n * developer-role messages, image_url) into plain `{ text }` placeholders.\n * The reverse `coreToX` then can't reconstruct them — `is_error` is lost\n * (upstream can't tell a tool error from a result), `thinking.signature` is\n * lost (Anthropic rejects thinking blocks without a matching signature),\n * images become \"[image]\" (the model never sees the picture).\n *\n * Solution: `BiliMessage` extends CoreMessage with optional sidecar fields.\n * The kernel only reads `{ ...message }` (spread copy) and known fields, so\n * the extra fields survive the compression pipeline unchanged and arrive back\n * at `coreToX`, which prefers them over the flattened `text`. No `as any`\n * needed — TypeScript array covariance lets `BiliMessage[]` satisfy a\n * `CoreMessage[]` parameter.\n */\n\nimport type { CoreMessage } from \"acp-kernel\";\n\n/** A message that carries its original protocol block(s) verbatim, so the\n * reverse conversion can reconstruct losslessly. Every field is optional —\n * plain text messages (the common case) have none set. */\nexport interface BiliMessage extends CoreMessage {\n /** Anthropic: the original content block for an image or a structured\n * tool_result. Restored verbatim by coreToAnthropic. */\n rawAnthropicBlock?: unknown;\n /** OpenAI chat: the original content part for an image_url, or the\n * original message object for a developer-role message. */\n rawOpenaiContent?: unknown;\n /** Responses API: the original input item (for input_image, or a raw\n * function_call / function_call_output we pass through). */\n rawResponsesItem?: unknown;\n /** Anthropic thinking signature. Anthropic verifies thinking+signature\n * pairs; without it the request is rejected. Stored alongside the\n * reasoning text so coreToAnthropic can reattach it. */\n thinkingSignature?: string;\n /** OpenAI reasoning_content (chain-of-thought from DeepSeek-R1, GLM-4.6\n * thinking, Qwen-QwQ). These models require reasoning_content be echoed\n * back on subsequent requests or the API returns HTTP 400; stored so\n * coreToOpenai can reattach it. */\n reasoningContent?: string;\n /** Anthropic tool_result.is_error. Marks the tool result as an error so\n * the model knows the tool failed (not just returned an error string). */\n toolIsError?: boolean;\n /** OpenAI: original role was \"developer\" (reconstructed as \"system\" by\n * openaiToCore for the kernel; coreToOpenai restores \"developer\"). */\n originalRole?: \"system\" | \"developer\";\n /** The original media type for an image (image/png, image/jpeg, image/gif,\n * image/webp). Lets coreToOpenai/coreToResponses rebuild image_url /\n * input_image with the right data URL. */\n imageMediaType?: string;\n /** The base64 data of an image (without the data: prefix). Lets the\n * reverse conversion rebuild the full image payload. */\n imageBase64?: string;\n}\n\n/** Narrow a BiliMessage[] to CoreMessage[] for the kernel. The sidecar fields\n * are transparently carried along — the kernel's `{ ...msg }` copies them. */\nexport function toCoreMessages(msgs: BiliMessage[]): CoreMessage[] {\n return msgs as CoreMessage[];\n}\n\n/** Re-decode a base64 data URL into media type + data. Returns undefined if\n * the input is not a recognized data URL. Used by openaiToCore/responsesToCore\n * to split image_url/input_image into the sidecar fields. */\nexport function parseDataUrl(url: string): { mediaType: string; base64: string } | undefined {\n const m = /^data:([^;,]+)(?:;base64)?,(.+)$/i.exec(url);\n if (!m) return undefined;\n return { mediaType: m[1]!, base64: m[2]! };\n}\n","import { hashId } from \"./util.js\";\nimport { ClusterCounter, deriveMessageId } from \"./message-id.js\";\nimport { parseDataUrl, type BiliMessage } from \"./bili-message.js\";\n\nexport type OpenAIContentPart =\n | { type: \"text\"; text: string }\n | { type: \"image_url\"; image_url: { url: string } }\n | { type: string; [k: string]: unknown };\n\nexport type OpenAIToolCall = {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n};\n\nexport type OpenAIMessage = {\n role: \"system\" | \"developer\" | \"user\" | \"assistant\" | \"tool\";\n content?: string | null | OpenAIContentPart[];\n reasoning_content?: string | null;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n name?: string;\n};\n\nexport type OpenAITool = {\n type: \"function\";\n function: { name: string; description?: string; parameters?: unknown };\n};\n\nexport type OpenAIRequestBody = {\n model?: string;\n messages: OpenAIMessage[];\n tools?: OpenAITool[];\n stream?: boolean;\n [key: string]: unknown;\n};\n\ntype Flat = { msgs: BiliMessage[] };\n\nexport function openaiToCore(body: OpenAIRequestBody): Flat {\n const msgs: BiliMessage[] = [];\n const clusters = new ClusterCounter();\n for (const m of body.messages) {\n switch (m.role) {\n case \"system\":\n case \"developer\": {\n const base = deriveMessageId(m.role, \"text\", stringContent(m.content));\n msgs.push({ id: clusters.next(base), role: \"system\", contentType: \"text\", text: stringContent(m.content), originalRole: m.role });\n break;\n }\n case \"user\": {\n const text = stringContent(m.content);\n const img = firstImagePart(m.content);\n const base = deriveMessageId(\"user\", \"text\", text);\n msgs.push({\n id: clusters.next(base),\n role: \"user\",\n contentType: \"text\",\n text,\n ...(img ? { rawOpenaiContent: img.part, imageMediaType: img.mediaType, imageBase64: img.base64 } : {}),\n });\n break;\n }\n case \"assistant\": {\n const reasoning = typeof m.reasoning_content === \"string\" ? m.reasoning_content : \"\";\n if (reasoning) {\n const base = deriveMessageId(\"assistant\", \"reasoning\", reasoning);\n msgs.push({\n id: clusters.next(base),\n role: \"assistant\",\n contentType: \"reasoning\",\n text: reasoning,\n reasoningContent: reasoning,\n });\n }\n const text = stringContent(m.content);\n if (text) {\n const base = deriveMessageId(\"assistant\", \"text\", text);\n msgs.push({ id: clusters.next(base), role: \"assistant\", contentType: \"text\", text });\n }\n if (Array.isArray(m.tool_calls)) {\n for (const tc of m.tool_calls) {\n const base = deriveMessageId(\"assistant\", \"tool-call\", tc.function.arguments ?? \"\", {\n toolCallId: tc.id,\n toolName: tc.function.name,\n });\n msgs.push({\n id: clusters.next(base),\n role: \"assistant\",\n contentType: \"tool-call\",\n toolName: tc.function.name,\n toolCallId: tc.id,\n text: tc.function.arguments ?? \"\",\n });\n }\n }\n break;\n }\n case \"tool\": {\n const base = deriveMessageId(\"tool\", \"tool-result\", stringContent(m.content), {\n toolCallId: m.tool_call_id ?? \"\",\n });\n msgs.push({\n id: clusters.next(base),\n role: \"tool\",\n contentType: \"tool-result\",\n toolCallId: m.tool_call_id ?? \"\",\n text: stringContent(m.content),\n });\n break;\n }\n }\n }\n return { msgs };\n}\n\nexport function coreToOpenai(messages: BiliMessage[]): OpenAIMessage[] {\n const out: OpenAIMessage[] = [];\n let pending: { text: string | null; toolCalls: OpenAIToolCall[]; reasoning: string | null } | null = null;\n const flush = () => {\n if (!pending) return;\n const reasoning = pending.reasoning !== null && pending.reasoning.length > 0 ? pending.reasoning : undefined;\n if (pending.toolCalls.length > 0) {\n out.push({\n role: \"assistant\",\n content: pending.text ?? null,\n tool_calls: pending.toolCalls,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n });\n } else if (pending.text !== null) {\n out.push({ role: \"assistant\", content: pending.text, ...(reasoning ? { reasoning_content: reasoning } : {}) });\n } else if (reasoning) {\n out.push({ role: \"assistant\", content: null, reasoning_content: reasoning });\n }\n pending = null;\n };\n for (const m of messages) {\n if (m.role === \"assistant\") {\n if (!pending) pending = { text: null, toolCalls: [], reasoning: null };\n if (m.contentType === \"reasoning\") {\n pending.reasoning = (pending.reasoning ?? \"\") + (m.reasoningContent ?? m.text ?? \"\");\n } else if (m.contentType === \"text\") {\n pending.text = (pending.text ?? \"\") + (m.text ?? \"\");\n } else if (m.contentType === \"tool-call\") {\n pending.toolCalls.push({\n id: m.toolCallId ?? `call_${m.id}`,\n type: \"function\",\n function: { name: m.toolName ?? \"unknown\", arguments: m.text ?? \"\" },\n });\n }\n } else {\n flush();\n if (m.role === \"system\") {\n out.push({ role: m.originalRole === \"developer\" ? \"developer\" : \"system\", content: m.text ?? \"\" });\n } else if (m.role === \"user\") {\n if (m.rawOpenaiContent || m.imageBase64) {\n const parts: OpenAIContentPart[] = [];\n if (m.text) parts.push({ type: \"text\", text: m.text });\n if (m.rawOpenaiContent) {\n parts.push(m.rawOpenaiContent as OpenAIContentPart);\n } else if (m.imageBase64 && m.imageMediaType) {\n parts.push({ type: \"image_url\", image_url: { url: `data:${m.imageMediaType};base64,${m.imageBase64}` } });\n }\n out.push({ role: \"user\", content: parts });\n } else {\n out.push({ role: \"user\", content: m.text ?? \"\" });\n }\n } else if (m.role === \"tool\") {\n out.push({ role: \"tool\", tool_call_id: m.toolCallId ?? \"\", content: m.text ?? \"\" });\n }\n }\n }\n flush();\n return out;\n}\n\nexport function injectOpenaiSystem(messages: OpenAIMessage[], parts: string[]): OpenAIMessage[] {\n if (parts.length === 0) return messages;\n const extra = parts.join(\"\\n\\n\");\n if (messages.length > 0 && (messages[0]?.role === \"system\" || messages[0]?.role === \"developer\")) {\n const head = messages[0] as OpenAIMessage;\n const base = stringContent(head.content);\n const merged = base ? `${base}\\n\\n---\\n\\n${extra}` : extra;\n return [{ ...head, content: merged }, ...messages.slice(1)];\n }\n return [{ role: \"system\", content: extra }, ...messages];\n}\n\n/** Extract the conversation dimension for OpenAI Chat: a client-provided\n * session header if present, else a content fingerprint of the first user\n * message. See conversationSignalAnthropic for the full rationale. */\nexport function conversationSignalOpenai(body: OpenAIRequestBody, headerValue?: string): string {\n if (headerValue && headerValue.trim()) return headerValue.trim();\n const firstUser = body.messages.find((m) => m.role === \"user\");\n const seed = firstUser ? stringContent(firstUser.content) : \"default\";\n return hashId(seed);\n}\n\nfunction stringContent(content: OpenAIMessage[\"content\"]): string {\n if (content == null) return \"\";\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((p) => (typeof p === \"string\" ? p : p.type === \"text\" ? (p as { text?: string }).text ?? \"\" : \"\"))\n .join(\"\\n\");\n }\n return \"\";\n}\n\nfunction firstImagePart(content: OpenAIMessage[\"content\"]): { part: OpenAIContentPart; mediaType: string; base64: string } | undefined {\n if (!Array.isArray(content)) return undefined;\n for (const p of content) {\n if (p && typeof p === \"object\" && p.type === \"image_url\") {\n const iu = (p as { image_url?: { url?: string } }).image_url;\n const url = iu?.url;\n if (typeof url === \"string\") {\n const parsed = parseDataUrl(url);\n if (parsed) return { part: p, mediaType: parsed.mediaType, base64: parsed.base64 };\n }\n }\n }\n return undefined;\n}\n","import type { CoreMessage } from \"../types.js\";\nimport { ClusterCounter, deriveMessageId } from \"./message-id.js\";\nimport type { ConversationIdentity } from \"./util.js\";\nimport { hashId } from \"./util.js\";\nimport { parseDataUrl, type BiliMessage } from \"./bili-message.js\";\n\nexport type ResponseContentPart =\n | { type: \"input_text\"; text: string; [key: string]: unknown }\n | { type: \"output_text\"; text: string; [key: string]: unknown }\n | { type: \"input_image\"; image_url: string; [key: string]: unknown }\n | { type: string; [key: string]: unknown };\n\nexport type ResponseInputMessage = {\n type: \"message\";\n role: \"system\" | \"developer\" | \"user\" | \"assistant\";\n content: string | ResponseContentPart[];\n [key: string]: unknown;\n};\n\nexport type ResponseFunctionCall = {\n type: \"function_call\";\n id?: string;\n call_id: string;\n name: string;\n arguments: string;\n [key: string]: unknown;\n};\n\nexport type ResponseFunctionCallOutput = {\n type: \"function_call_output\";\n call_id: string;\n output: string;\n [key: string]: unknown;\n};\n\nexport type ResponseInputItem =\n | ResponseInputMessage\n | ResponseFunctionCall\n | ResponseFunctionCallOutput\n | { type: string; [key: string]: unknown };\n\nexport type ResponsesRequestBody = {\n model?: string;\n input: string | ResponseInputItem[];\n instructions?: string;\n tools?: unknown[];\n stream?: boolean;\n session_id?: string;\n previous_response_id?: string;\n prompt_cache_key?: string;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ntype ResponseLayoutSlot = {\n original: ResponseInputItem;\n coreId?: string;\n};\n\nexport type ResponsesProjection = {\n msgs: BiliMessage[];\n systemParts: string[];\n preamble: ResponseInputItem[];\n customToolCallIds: Set<string>;\n layout: ResponseLayoutSlot[];\n stringInput?: { original: string; coreId: string };\n /** Reasoning items dropped because ACP_REASONING_KEEP=none. 0 by default —\n * reasoning is normally routed through the compression pipeline so it is\n * hidden automatically once its turn is summarized. */\n droppedReasoning: number;\n};\n\n/** Item types that are host DIRECTIVES (tool/definition listings), not\n * conversation history: preserved verbatim and re-prepended at input[0..].\n * `additional_tools` carries the Codex code_mode exec/wait tool definitions\n * and MUST stay at input[0]. `mcp_list_tools` is a stable per-session listing.\n *\n * Only definitions belong here. Output/action items from a prior response\n * (reasoning, computer_call, function_call, mcp_call, ...) ARE conversation\n * history and are routed as tracked BiliMessages, so the compression pipeline\n * hides them once their turn is summarized — preserving them verbatim in the\n * preamble instead made them accumulate unbounded every turn and broke Codex's\n * prompt-cache prefix. */\nconst OPAQUE_ITEM_TYPES = new Set([\n \"additional_tools\",\n \"mcp_list_tools\",\n]);\n\nfunction isOpaqueItem(item: ResponseInputItem): boolean {\n return OPAQUE_ITEM_TYPES.has(item.type);\n}\n\nfunction shouldDropAllReasoning(): boolean {\n return (process.env.ACP_REASONING_KEEP ?? \"\").trim().toLowerCase() === \"none\";\n}\n\nfunction partText(part: ResponseContentPart): string {\n if (part.type === \"input_text\" || part.type === \"output_text\") {\n return typeof part.text === \"string\" ? part.text : \"\";\n }\n return \"\";\n}\n\nfunction messageContent(content: string | ResponseContentPart[]): string {\n return typeof content === \"string\" ? content : content.map(partText).join(\"\\n\");\n}\n\nexport function responsesToCore(body: ResponsesRequestBody): ResponsesProjection {\n const msgs: BiliMessage[] = [];\n const systemParts: string[] = [];\n const preamble: ResponseInputItem[] = [];\n const customToolCallIds = new Set<string>();\n const layout: ResponseLayoutSlot[] = [];\n let droppedReasoning = 0;\n const clusters = new ClusterCounter();\n let idx = 0;\n if (typeof body.instructions === \"string\" && body.instructions.trim()) systemParts.push(body.instructions);\n if (typeof body.input === \"string\") {\n const id = clusters.next(deriveMessageId(\"user\", \"text\", body.input));\n msgs.push({ id, role: \"user\", contentType: \"text\", text: body.input });\n return { msgs, systemParts, preamble, customToolCallIds, layout, droppedReasoning, stringInput: { original: body.input, coreId: id } };\n }\n for (const item of body.input) {\n let coreId: string | undefined;\n if (isOpaqueItem(item)) preamble.push(item);\n switch (item.type) {\n case \"reasoning\": {\n if (shouldDropAllReasoning()) {\n droppedReasoning++;\n continue;\n }\n const rid =\n typeof (item as { id?: unknown }).id === \"string\"\n ? String((item as { id?: string }).id)\n : hashId(JSON.stringify(item));\n coreId = clusters.next(deriveMessageId(\"assistant\", \"reasoning\", rid));\n msgs.push({\n id: coreId,\n role: \"assistant\",\n contentType: \"reasoning\",\n text: rid,\n rawResponsesItem: item,\n });\n break;\n }\n case \"message\": {\n const message = item as ResponseInputMessage;\n const text = messageContent(message.content);\n if (message.role === \"system\" || message.role === \"developer\") {\n systemParts.push(text);\n idx++;\n continue;\n } else if (message.role === \"user\" || (message.role === \"assistant\" && text)) {\n const role = message.role;\n coreId = clusters.next(deriveMessageId(role, \"text\", text));\n const imageUrl = Array.isArray(message.content)\n ? message.content.find((part) => part.type === \"input_image\" && typeof part.image_url === \"string\")?.image_url\n : undefined;\n const image = typeof imageUrl === \"string\" ? parseDataUrl(imageUrl) : undefined;\n msgs.push({\n id: coreId,\n role,\n contentType: \"text\",\n text,\n rawResponsesItem: item,\n ...(image ? { imageMediaType: image.mediaType, imageBase64: image.base64 } : {}),\n });\n }\n break;\n }\n case \"function_call\": {\n const call = item as ResponseFunctionCall;\n coreId = clusters.next(deriveMessageId(\"assistant\", \"tool-call\", call.arguments ?? \"\", {\n toolCallId: call.call_id,\n toolName: call.name,\n }));\n msgs.push({\n id: coreId,\n role: \"assistant\",\n contentType: \"tool-call\",\n toolName: call.name,\n toolCallId: call.call_id,\n text: call.arguments ?? \"\",\n rawResponsesItem: item,\n });\n break;\n }\n case \"function_call_output\": {\n const output = item as ResponseFunctionCallOutput;\n const text = typeof output.output === \"string\" ? output.output : JSON.stringify(output.output);\n coreId = clusters.next(deriveMessageId(\"tool\", \"tool-result\", text, { toolCallId: output.call_id }));\n msgs.push({ id: coreId, role: \"tool\", contentType: \"tool-result\", toolCallId: output.call_id, text, rawResponsesItem: item });\n break;\n }\n case \"computer_call\":\n case \"computer_call_output\":\n case \"file_search_call\":\n case \"web_search_call\":\n case \"image_generation_call\":\n case \"code_interpreter_call\":\n case \"mcp_call\": {\n const rid =\n typeof (item as { id?: unknown }).id === \"string\"\n ? String((item as { id?: string }).id)\n : hashId(JSON.stringify(item));\n coreId = clusters.next(deriveMessageId(\"assistant\", \"responses-call\", rid));\n msgs.push({ id: coreId, role: \"assistant\", contentType: \"reasoning\", text: rid, rawResponsesItem: item });\n break;\n }\n case \"custom_tool_call\": {\n const ctc = item as { call_id?: string; name?: string; input?: string; arguments?: string };\n const callId = ctc.call_id ?? `call_${idx}`;\n customToolCallIds.add(callId);\n const argText = ctc.input ?? ctc.arguments ?? \"\";\n coreId = clusters.next(deriveMessageId(\"assistant\", \"tool-call\", argText, { toolCallId: callId, toolName: ctc.name ?? \"custom\" }));\n msgs.push({ id: coreId, role: \"assistant\", contentType: \"tool-call\", toolName: ctc.name ?? \"custom\", toolCallId: callId, text: argText, rawResponsesItem: item });\n break;\n }\n case \"custom_tool_call_output\": {\n const ctco = item as { call_id?: string; output?: string };\n const callId = ctco.call_id ?? `call_${idx}`;\n customToolCallIds.add(callId);\n const outText = typeof ctco.output === \"string\" ? ctco.output : JSON.stringify(ctco.output ?? \"\");\n coreId = clusters.next(deriveMessageId(\"tool\", \"tool-result\", outText, { toolCallId: callId }));\n msgs.push({ id: coreId, role: \"tool\", contentType: \"tool-result\", toolCallId: callId, text: outText, rawResponsesItem: item });\n break;\n }\n default:\n if (!isOpaqueItem(item)) preamble.push(item);\n break;\n }\n layout.push({ original: item, coreId });\n idx++;\n }\n return { msgs, systemParts, preamble, customToolCallIds, layout, droppedReasoning };\n}\n\nfunction patchTextParts(parts: ResponseContentPart[], text: string): ResponseContentPart[] {\n const textIndexes = parts.flatMap((part, index) =>\n part.type === \"input_text\" || part.type === \"output_text\" ? [index] : [],\n );\n if (textIndexes.length === 0) return [{ type: \"input_text\", text }, ...parts];\n const first = textIndexes[0];\n const remaining = new Set(textIndexes.slice(1));\n return parts.map((part, index) => {\n if (index === first) return { ...part, text };\n if (remaining.has(index)) return { ...part, text: \"\" };\n return part;\n });\n}\n\nfunction patchOriginalItem(original: ResponseInputItem, source: CoreMessage, next: CoreMessage): ResponseInputItem {\n if (\n source.text === next.text &&\n source.toolName === next.toolName &&\n source.toolCallId === next.toolCallId &&\n source.role === next.role &&\n source.contentType === next.contentType\n ) return original;\n if (original.type === \"message\") {\n const message = original as ResponseInputMessage;\n const content = typeof message.content === \"string\" ? next.text ?? \"\" : patchTextParts(message.content, next.text ?? \"\");\n return { ...message, content };\n }\n if (original.type === \"function_call\") {\n return {\n ...original,\n name: next.toolName ?? String(original.name ?? \"unknown\"),\n call_id: next.toolCallId ?? String(original.call_id ?? \"\"),\n arguments: next.text ?? \"\",\n };\n }\n if (original.type === \"function_call_output\") {\n return { ...original, call_id: next.toolCallId ?? String(original.call_id ?? \"\"), output: next.text ?? \"\" };\n }\n return original;\n}\n\nexport function patchResponsesInput(projection: ResponsesProjection, messages: CoreMessage[]): string | ResponseInputItem[] {\n if (projection.stringInput) {\n const original = projection.msgs.find((message) => message.id === projection.stringInput?.coreId);\n const next = messages.find((message) => message.id === projection.stringInput?.coreId);\n if (original && next && messages.length === 1 && next.role === \"user\" && next.contentType === \"text\") {\n return next.text === original.text ? projection.stringInput.original : next.text ?? \"\";\n }\n return coreToResponses(messages, projection.customToolCallIds);\n }\n const sourceById = new Map(projection.msgs.map((message) => [message.id, message]));\n const nextById = new Map(messages.map((message) => [message.id, message]));\n const slotById = new Map<string, number>();\n projection.layout.forEach((slot, index) => {\n if (slot.coreId) slotById.set(slot.coreId, index);\n });\n const insertions = new Map<number, ResponseInputItem[]>();\n for (let index = 0; index < messages.length; index++) {\n const message = messages[index]!;\n if (sourceById.has(message.id)) continue;\n let target = projection.layout.length;\n for (let nextIndex = index + 1; nextIndex < messages.length; nextIndex++) {\n const slot = slotById.get(messages[nextIndex]!.id);\n if (slot !== undefined) {\n target = slot;\n break;\n }\n }\n const generated = coreToResponses([message], projection.customToolCallIds);\n if (generated.length > 0) insertions.set(target, [...(insertions.get(target) ?? []), ...generated]);\n }\n const out: ResponseInputItem[] = [];\n projection.layout.forEach((slot, index) => {\n out.push(...(insertions.get(index) ?? []));\n if (!slot.coreId) {\n out.push(slot.original);\n return;\n }\n const source = sourceById.get(slot.coreId);\n const next = nextById.get(slot.coreId);\n if (source && next) out.push(patchOriginalItem(slot.original, source, next));\n });\n out.push(...(insertions.get(projection.layout.length) ?? []));\n return out;\n}\n\nexport function coreToResponses(\n messages: CoreMessage[],\n customToolCallIds: Set<string> = new Set(),\n): ResponseInputItem[] {\n const out: ResponseInputItem[] = [];\n for (const message of messages) {\n const biliMessage = message as BiliMessage;\n const raw = biliMessage.rawResponsesItem as ResponseInputItem | undefined;\n if (message.role === \"system\") {\n out.push({ type: \"message\", role: \"developer\", content: message.text ?? \"\" });\n } else if (message.role === \"user\") {\n if (raw?.type === \"message\" && messageContent((raw as ResponseInputMessage).content) === (message.text ?? \"\")) out.push(raw);\n else out.push({ type: \"message\", role: \"user\", content: message.text ?? \"\" });\n } else if (message.role === \"assistant\") {\n if (message.contentType === \"text\") {\n out.push({ type: \"message\", role: \"assistant\", content: message.text ?? \"\" });\n } else if (message.contentType === \"tool-call\") {\n const callId = message.toolCallId ?? `call_${message.id}`;\n if (customToolCallIds.has(callId)) {\n out.push({ type: \"custom_tool_call\", call_id: callId, name: message.toolName ?? \"unknown\", input: message.text ?? \"\", status: \"completed\" } as ResponseInputItem);\n } else {\n out.push({ type: \"function_call\", call_id: callId, name: message.toolName ?? \"unknown\", arguments: message.text ?? \"\" });\n }\n } else if (message.contentType === \"reasoning\") {\n if (raw) out.push(raw);\n }\n } else if (message.role === \"tool\") {\n const callId = message.toolCallId ?? \"\";\n if (customToolCallIds.has(callId)) {\n out.push({ type: \"custom_tool_call_output\", call_id: callId, output: message.text ?? \"\" } as ResponseInputItem);\n } else {\n out.push({ type: \"function_call_output\", call_id: callId, output: message.text ?? \"\" });\n }\n }\n }\n return out;\n}\n\nexport function injectResponsesDeveloperMessage(\n input: string | ResponseInputItem[],\n content: string,\n): ResponseInputItem[] {\n const items: ResponseInputItem[] = typeof input === \"string\"\n ? [{ type: \"message\", role: \"user\", content: input }]\n : [...input];\n let index = 0;\n while (items[index]?.type === \"additional_tools\") index++;\n items.splice(index, 0, { type: \"message\", role: \"developer\", content });\n return items;\n}\n\nexport function conversationIdentityResponses(\n body: ResponsesRequestBody,\n headerValue?: string,\n): ConversationIdentity {\n if (headerValue?.trim()) return { value: headerValue.trim(), source: \"header\", clientProvided: true };\n if (typeof body.session_id === \"string\" && body.session_id.trim()) {\n return { value: body.session_id.trim(), source: \"body-session\", clientProvided: true };\n }\n const metadataSession = body.metadata?.session_id;\n if (typeof metadataSession === \"string\" && metadataSession.trim()) {\n return { value: metadataSession.trim(), source: \"metadata-session\", clientProvided: true };\n }\n if (typeof body.previous_response_id === \"string\" && body.previous_response_id.trim()) {\n return { value: body.previous_response_id.trim(), source: \"previous-response\", clientProvided: false };\n }\n return { value: hashId(JSON.stringify(body.input ?? [])), source: \"content-fingerprint\", clientProvided: false };\n}\n\nexport function conversationSignalResponses(body: ResponsesRequestBody, headerValue?: string): string {\n return conversationIdentityResponses(body, headerValue).value;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a stable, content-based message id.
|
|
3
|
+
*
|
|
4
|
+
* PROBLEM: none of the three wire protocols (Anthropic Messages, OpenAI Chat
|
|
5
|
+
* Completions, OpenAI Responses) attach a stable id to request-side message
|
|
6
|
+
* items. Historically each converter used `raw-${idx}` — a *position* index,
|
|
7
|
+
* not an identity. As soon as a client deletes/reorders messages (other plugins
|
|
8
|
+
* summarizing away old turns, multi-agent setups, etc.) the index drifts:
|
|
9
|
+
* downstream ids shift, so
|
|
10
|
+
* - assignRefs reuses stale `byRaw` entries, hiding new messages, and
|
|
11
|
+
* - compression `effectiveMessageIds` start pointing at the *wrong* messages,
|
|
12
|
+
* silently swallowing live content under an unrelated summary.
|
|
13
|
+
*
|
|
14
|
+
* FIX: derive the id from a SHA-256 of the message identity:
|
|
15
|
+
* role + contentType + toolCallId + toolName + text
|
|
16
|
+
* Two messages with identical identity collide. To keep duplicates distinct
|
|
17
|
+
* (and avoid `covered` sets collapsing unrelated turns onto one id) we append a
|
|
18
|
+
* within-conversation *cluster index* `_N`: the Nth occurrence of the same
|
|
19
|
+
* identity, counting from 0 in arrival order.
|
|
20
|
+
*
|
|
21
|
+
* Trade-off vs a real client id:
|
|
22
|
+
* - deleting a duplicated message only disturbs the cluster of that identity
|
|
23
|
+
* (local damage), never the whole downstream (global damage like position).
|
|
24
|
+
* - fully distinct messages are completely immune to reordering/deletion.
|
|
25
|
+
*
|
|
26
|
+
* `idx` is passed purely to break ties *within a single conversion pass*; it is
|
|
27
|
+
* not part of the identity, so two passes over the same content produce the
|
|
28
|
+
* same cluster numbering (deterministic).
|
|
29
|
+
*/
|
|
30
|
+
export declare function deriveMessageId(role: string, contentType: string, text: string, options?: {
|
|
31
|
+
toolCallId?: string;
|
|
32
|
+
toolName?: string;
|
|
33
|
+
}): string;
|
|
34
|
+
/**
|
|
35
|
+
* Stateful cluster counter. Each converter instantiates one per conversion
|
|
36
|
+
* pass; it tracks how many times each base identity has been seen so that the
|
|
37
|
+
* Nth duplicate gets a `_${N}` suffix.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ClusterCounter {
|
|
40
|
+
private counts;
|
|
41
|
+
next(baseId: string): string;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=message-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-id.d.ts","sourceRoot":"","sources":["../../src/wire/message-id.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,eAAe,CAC3B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACL,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAChB,GACP,MAAM,CAGR;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAA6B;IAE3C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAK/B"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type BiliMessage } from "./bili-message.js";
|
|
2
|
+
export type OpenAIContentPart = {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: "image_url";
|
|
7
|
+
image_url: {
|
|
8
|
+
url: string;
|
|
9
|
+
};
|
|
10
|
+
} | {
|
|
11
|
+
type: string;
|
|
12
|
+
[k: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
export type OpenAIToolCall = {
|
|
15
|
+
id: string;
|
|
16
|
+
type: "function";
|
|
17
|
+
function: {
|
|
18
|
+
name: string;
|
|
19
|
+
arguments: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type OpenAIMessage = {
|
|
23
|
+
role: "system" | "developer" | "user" | "assistant" | "tool";
|
|
24
|
+
content?: string | null | OpenAIContentPart[];
|
|
25
|
+
reasoning_content?: string | null;
|
|
26
|
+
tool_calls?: OpenAIToolCall[];
|
|
27
|
+
tool_call_id?: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
};
|
|
30
|
+
export type OpenAITool = {
|
|
31
|
+
type: "function";
|
|
32
|
+
function: {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
parameters?: unknown;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export type OpenAIRequestBody = {
|
|
39
|
+
model?: string;
|
|
40
|
+
messages: OpenAIMessage[];
|
|
41
|
+
tools?: OpenAITool[];
|
|
42
|
+
stream?: boolean;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
};
|
|
45
|
+
type Flat = {
|
|
46
|
+
msgs: BiliMessage[];
|
|
47
|
+
};
|
|
48
|
+
export declare function openaiToCore(body: OpenAIRequestBody): Flat;
|
|
49
|
+
export declare function coreToOpenai(messages: BiliMessage[]): OpenAIMessage[];
|
|
50
|
+
export declare function injectOpenaiSystem(messages: OpenAIMessage[], parts: string[]): OpenAIMessage[];
|
|
51
|
+
/** Extract the conversation dimension for OpenAI Chat: a client-provided
|
|
52
|
+
* session header if present, else a content fingerprint of the first user
|
|
53
|
+
* message. See conversationSignalAnthropic for the full rationale. */
|
|
54
|
+
export declare function conversationSignalOpenai(body: OpenAIRequestBody, headerValue?: string): string;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/wire/openai.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,EAAE,CAAC;IAC9C,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1E,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B,CAAC;AAEF,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AAEpC,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA2E1D;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,aAAa,EAAE,CA0DrE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAU9F;AAED;;uEAEuE;AACvE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9F"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { CoreMessage } from "../types.js";
|
|
2
|
+
import type { ConversationIdentity } from "./util.js";
|
|
3
|
+
import { type BiliMessage } from "./bili-message.js";
|
|
4
|
+
export type ResponseContentPart = {
|
|
5
|
+
type: "input_text";
|
|
6
|
+
text: string;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
} | {
|
|
9
|
+
type: "output_text";
|
|
10
|
+
text: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
} | {
|
|
13
|
+
type: "input_image";
|
|
14
|
+
image_url: string;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
type: string;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
};
|
|
20
|
+
export type ResponseInputMessage = {
|
|
21
|
+
type: "message";
|
|
22
|
+
role: "system" | "developer" | "user" | "assistant";
|
|
23
|
+
content: string | ResponseContentPart[];
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
};
|
|
26
|
+
export type ResponseFunctionCall = {
|
|
27
|
+
type: "function_call";
|
|
28
|
+
id?: string;
|
|
29
|
+
call_id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
arguments: string;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
};
|
|
34
|
+
export type ResponseFunctionCallOutput = {
|
|
35
|
+
type: "function_call_output";
|
|
36
|
+
call_id: string;
|
|
37
|
+
output: string;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
};
|
|
40
|
+
export type ResponseInputItem = ResponseInputMessage | ResponseFunctionCall | ResponseFunctionCallOutput | {
|
|
41
|
+
type: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
};
|
|
44
|
+
export type ResponsesRequestBody = {
|
|
45
|
+
model?: string;
|
|
46
|
+
input: string | ResponseInputItem[];
|
|
47
|
+
instructions?: string;
|
|
48
|
+
tools?: unknown[];
|
|
49
|
+
stream?: boolean;
|
|
50
|
+
session_id?: string;
|
|
51
|
+
previous_response_id?: string;
|
|
52
|
+
prompt_cache_key?: string;
|
|
53
|
+
metadata?: Record<string, unknown>;
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
};
|
|
56
|
+
type ResponseLayoutSlot = {
|
|
57
|
+
original: ResponseInputItem;
|
|
58
|
+
coreId?: string;
|
|
59
|
+
};
|
|
60
|
+
export type ResponsesProjection = {
|
|
61
|
+
msgs: BiliMessage[];
|
|
62
|
+
systemParts: string[];
|
|
63
|
+
preamble: ResponseInputItem[];
|
|
64
|
+
customToolCallIds: Set<string>;
|
|
65
|
+
layout: ResponseLayoutSlot[];
|
|
66
|
+
stringInput?: {
|
|
67
|
+
original: string;
|
|
68
|
+
coreId: string;
|
|
69
|
+
};
|
|
70
|
+
/** Reasoning items dropped because ACP_REASONING_KEEP=none. 0 by default —
|
|
71
|
+
* reasoning is normally routed through the compression pipeline so it is
|
|
72
|
+
* hidden automatically once its turn is summarized. */
|
|
73
|
+
droppedReasoning: number;
|
|
74
|
+
};
|
|
75
|
+
export declare function responsesToCore(body: ResponsesRequestBody): ResponsesProjection;
|
|
76
|
+
export declare function patchResponsesInput(projection: ResponsesProjection, messages: CoreMessage[]): string | ResponseInputItem[];
|
|
77
|
+
export declare function coreToResponses(messages: CoreMessage[], customToolCallIds?: Set<string>): ResponseInputItem[];
|
|
78
|
+
export declare function injectResponsesDeveloperMessage(input: string | ResponseInputItem[], content: string): ResponseInputItem[];
|
|
79
|
+
export declare function conversationIdentityResponses(body: ResponsesRequestBody, headerValue?: string): ConversationIdentity;
|
|
80
|
+
export declare function conversationSignalResponses(body: ResponsesRequestBody, headerValue?: string): string;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/wire/responses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** SHA-256-derived short id — kept verbatim from the proxy so message ids
|
|
2
|
+
* stay byte-identical across the extraction (re-keying would orphan every
|
|
3
|
+
* downstream map keyed on these ids). */
|
|
4
|
+
export declare function hashId(s: string): string;
|
|
5
|
+
/** How a conversation's identity was derived (kept verbatim from the proxy's
|
|
6
|
+
* session-id.ts — only the TYPE moves; session-key derivation stays in the
|
|
7
|
+
* proxy, which owns multi-tenant state). */
|
|
8
|
+
export type ConversationIdentity = {
|
|
9
|
+
value: string;
|
|
10
|
+
source: "header" | "body-session" | "metadata-session" | "previous-response" | "content-fingerprint" | "generated";
|
|
11
|
+
clientProvided: boolean;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/wire/util.ts"],"names":[],"mappings":"AAEA;;0CAE0C;AAC1C,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAExC;AAED;;6CAE6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,kBAAkB,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,WAAW,CAAC;IACnH,cAAc,EAAE,OAAO,CAAC;CAC3B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "acp-kernel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "Framework-agnostic context-compression engine (model-driven, 3-tier LSM). Pure core: no host dependency.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ranxianglei",
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
".": {
|
|
30
30
|
"types": "./dist/index.d.ts",
|
|
31
31
|
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./wire": {
|
|
34
|
+
"types": "./dist/wire/index.d.ts",
|
|
35
|
+
"import": "./dist/wire/index.js"
|
|
32
36
|
}
|
|
33
37
|
},
|
|
34
38
|
"files": [
|