mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
b080dd1e76
* refactor: consolidate coercion contracts Centralize exact string, record, numeric, date, Boolean, argument, and structured-error coercions while preserving call-site semantics. Migrate canonical-name collisions and deprecated internal SDK bypasses, deleting 55 net production/tooling lines. Expand declaration ownership enforcement to 101 allowed helpers and add a narrow export-completeness audit. * fix: preserve standalone script coercions Keep copied Control UI tooling self-contained and retain the trusted release harness module-relative source seam when the harness runs against an old target cwd.
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import type { AgentMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
|
import { parseDateStringTimestampMs } from "openclaw/plugin-sdk/number-runtime";
|
|
import { withSessionTranscriptWriteLock } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
import { CLAUDE_CLI_BACKEND_ID } from "./cli-constants.js";
|
|
import type { ClaudeTranscriptItem } from "./session-catalog-transcript.js";
|
|
|
|
function importedClaudeMessage(
|
|
item: ClaudeTranscriptItem,
|
|
fallbackTimestamp: number,
|
|
): AgentMessage | undefined {
|
|
const timestamp = parseDateStringTimestampMs(item.timestamp) ?? fallbackTimestamp;
|
|
const importedText = item.text?.trim();
|
|
if (!importedText && item.type === "reasoning") {
|
|
return undefined;
|
|
}
|
|
const text = importedText || "[Unsupported Claude transcript item]";
|
|
if (item.type === "userMessage") {
|
|
// Imported native rows are not OpenClaw-authored; mirrorOrigin excludes them
|
|
// from self-echo provenance so a repeated native prompt stays observable.
|
|
return {
|
|
role: "user",
|
|
content: text,
|
|
timestamp,
|
|
__openclaw: { mirrorOrigin: "claude-catalog-import" },
|
|
} as AgentMessage;
|
|
}
|
|
const prefix =
|
|
item.type === "reasoning"
|
|
? "Thinking\n\n"
|
|
: item.type === "toolCall"
|
|
? "Tool call\n\n"
|
|
: item.type === "toolResult"
|
|
? "Tool result\n\n"
|
|
: "";
|
|
return {
|
|
role: "assistant",
|
|
content: [{ type: "text", text: `${prefix}${text}` }],
|
|
timestamp,
|
|
api: "anthropic-messages",
|
|
provider: CLAUDE_CLI_BACKEND_ID,
|
|
model: "native-history",
|
|
usage: {
|
|
input: 0,
|
|
output: 0,
|
|
cacheRead: 0,
|
|
cacheWrite: 0,
|
|
totalTokens: 0,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
},
|
|
stopReason: "stop",
|
|
} as AgentMessage;
|
|
}
|
|
|
|
export async function importClaudeHistory(params: {
|
|
items: ClaudeTranscriptItem[];
|
|
threadId: string;
|
|
sessionId: string;
|
|
sessionKey: string;
|
|
agentId: string;
|
|
storePath: string;
|
|
cwd?: string;
|
|
config: OpenClawConfig;
|
|
}): Promise<void> {
|
|
const items = params.items.toReversed();
|
|
await withSessionTranscriptWriteLock(params, async (transcript) => {
|
|
for (const [index, item] of items.entries()) {
|
|
const imported = importedClaudeMessage(item, Date.now() + index);
|
|
if (!imported) {
|
|
continue;
|
|
}
|
|
// The idempotency key rides on the message so recovery re-imports dedupe.
|
|
const message = {
|
|
...(imported as unknown as Record<string, unknown>),
|
|
idempotencyKey: `claude-catalog:${params.threadId}:${item.uuid ?? index}`,
|
|
} as unknown as AgentMessage;
|
|
await transcript.appendMessage({
|
|
message,
|
|
idempotencyLookup: "scan",
|
|
cwd: params.cwd,
|
|
});
|
|
}
|
|
});
|
|
}
|