adp-openclaw 0.0.69 → 0.0.71
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/package.json +1 -1
- package/src/channel.ts +35 -21
- package/src/config-schema.ts +1 -1
- package/src/monitor.ts +4 -4
- package/src/onboarding.ts +76 -69
- package/src/session-history.ts +72 -18
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -3,14 +3,28 @@
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
type ChannelPlugin,
|
|
6
|
-
type
|
|
7
|
-
DEFAULT_ACCOUNT_ID,
|
|
6
|
+
type OpenClawConfig,
|
|
8
7
|
} from "openclaw/plugin-sdk";
|
|
9
|
-
import {
|
|
8
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/core";
|
|
9
|
+
import { adpOpenclawSetupWizard } from "./onboarding.js";
|
|
10
10
|
import { getActiveWebSocket } from "./runtime.js";
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
const
|
|
12
|
+
// WebSocket URLs for ADP OpenClaw (domestic vs international)
|
|
13
|
+
const WS_URL_DOMESTIC = "wss://wss.lke.cloud.tencent.com/bot/gateway/conn";
|
|
14
|
+
const WS_URL_INTL = "wss://wss.lke.tencentcloud.com/bot/gateway/conn";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolve WebSocket URL based on clientToken prefix.
|
|
18
|
+
* - Domestic token: sk-adp-{part1}-{part2} → WS_URL_DOMESTIC
|
|
19
|
+
* - International token: sk-adp_intl-{part1}-{part2} → WS_URL_INTL
|
|
20
|
+
* - Fallback: domestic URL
|
|
21
|
+
*/
|
|
22
|
+
function resolveWsUrlFromToken(clientToken?: string): string {
|
|
23
|
+
if (clientToken?.startsWith("sk-adp_intl-")) {
|
|
24
|
+
return WS_URL_INTL;
|
|
25
|
+
}
|
|
26
|
+
return WS_URL_DOMESTIC;
|
|
27
|
+
}
|
|
14
28
|
|
|
15
29
|
// Channel-level config type (from channels["adp-openclaw"])
|
|
16
30
|
export type AdpOpenclawChannelConfig = {
|
|
@@ -35,33 +49,33 @@ function resolveAdpOpenclawCredentials(channelCfg?: AdpOpenclawChannelConfig): {
|
|
|
35
49
|
clientToken: string;
|
|
36
50
|
signKey: string;
|
|
37
51
|
} | null {
|
|
38
|
-
// Get wsUrl from config or env (has default value)
|
|
39
|
-
let wsUrl = channelCfg?.wsUrl?.trim();
|
|
40
|
-
if (!wsUrl) {
|
|
41
|
-
wsUrl = process.env.ADP_OPENCLAW_WS_URL || DEFAULT_WS_URL;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
52
|
// Get clientToken from config or env
|
|
45
53
|
let clientToken = channelCfg?.clientToken?.trim();
|
|
46
54
|
if (!clientToken) {
|
|
47
55
|
clientToken = process.env.ADP_OPENCLAW_CLIENT_TOKEN || "";
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
// clientToken is required for configured status
|
|
59
|
+
if (!clientToken) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Get wsUrl: explicit config > env var > auto-detect from clientToken prefix
|
|
64
|
+
let wsUrl = channelCfg?.wsUrl?.trim();
|
|
65
|
+
if (!wsUrl) {
|
|
66
|
+
wsUrl = process.env.ADP_OPENCLAW_WS_URL || resolveWsUrlFromToken(clientToken);
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
// Get signKey from config or env (default: ADPOpenClaw)
|
|
51
70
|
let signKey = channelCfg?.signKey?.trim();
|
|
52
71
|
if (!signKey) {
|
|
53
72
|
signKey = process.env.ADP_OPENCLAW_SIGN_KEY || "ADPOpenClaw";
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
// clientToken is required for configured status (wsUrl has default)
|
|
57
|
-
if (!clientToken) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
75
|
return { wsUrl, clientToken, signKey };
|
|
62
76
|
}
|
|
63
77
|
|
|
64
|
-
function resolveAccount(cfg:
|
|
78
|
+
function resolveAccount(cfg: OpenClawConfig, accountId?: string): ResolvedAdpOpenclawAccount {
|
|
65
79
|
const channelCfg = cfg.channels?.["adp-openclaw"] as AdpOpenclawChannelConfig | undefined;
|
|
66
80
|
const enabled = channelCfg?.enabled !== false;
|
|
67
81
|
const creds = resolveAdpOpenclawCredentials(channelCfg);
|
|
@@ -71,7 +85,7 @@ function resolveAccount(cfg: ClawdbotConfig, accountId?: string): ResolvedAdpOpe
|
|
|
71
85
|
name: "ADP OpenClaw",
|
|
72
86
|
enabled,
|
|
73
87
|
configured: Boolean(creds),
|
|
74
|
-
wsUrl: creds?.wsUrl ||
|
|
88
|
+
wsUrl: creds?.wsUrl || resolveWsUrlFromToken(creds?.clientToken),
|
|
75
89
|
clientToken: creds?.clientToken || "",
|
|
76
90
|
signKey: creds?.signKey || "ADPOpenClaw",
|
|
77
91
|
};
|
|
@@ -87,7 +101,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
|
|
|
87
101
|
blurb: "ADP channel backed by a Go WebSocket server.",
|
|
88
102
|
order: 999,
|
|
89
103
|
},
|
|
90
|
-
|
|
104
|
+
setupWizard: adpOpenclawSetupWizard,
|
|
91
105
|
capabilities: {
|
|
92
106
|
chatTypes: ["direct"],
|
|
93
107
|
polls: false,
|
|
@@ -107,7 +121,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
|
|
|
107
121
|
additionalProperties: false,
|
|
108
122
|
properties: {
|
|
109
123
|
enabled: { type: "boolean" },
|
|
110
|
-
wsUrl: { type: "string" }, // WebSocket URL (optional,
|
|
124
|
+
wsUrl: { type: "string" }, // WebSocket URL (optional, auto-detected from clientToken prefix)
|
|
111
125
|
clientToken: { type: "string" },
|
|
112
126
|
signKey: { type: "string" },
|
|
113
127
|
},
|
|
@@ -128,7 +142,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
|
|
|
128
142
|
},
|
|
129
143
|
}),
|
|
130
144
|
deleteAccount: ({ cfg }) => {
|
|
131
|
-
const next = { ...cfg } as
|
|
145
|
+
const next = { ...cfg } as OpenClawConfig;
|
|
132
146
|
const nextChannels = { ...cfg.channels };
|
|
133
147
|
delete (nextChannels as Record<string, unknown>)["adp-openclaw"];
|
|
134
148
|
if (Object.keys(nextChannels).length > 0) {
|
package/src/config-schema.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
export const AdpOpenclawConfigSchema = z.object({
|
|
4
4
|
enabled: z.boolean().optional(),
|
|
5
|
-
wsUrl: z.string().optional(), // WebSocket URL (optional,
|
|
5
|
+
wsUrl: z.string().optional(), // WebSocket URL (optional, auto-detected from clientToken prefix: sk-adp- → domestic, sk-adp_intl- → international)
|
|
6
6
|
clientToken: z.string().optional(),
|
|
7
7
|
signKey: z.string().optional(),
|
|
8
8
|
});
|
package/src/monitor.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Monitor: WebSocket connection to Go server for real-time message handling
|
|
2
2
|
// Supports: API Token auth, conversation tracking for multi-turn dialogues
|
|
3
3
|
|
|
4
|
-
import type { PluginLogger,
|
|
4
|
+
import type { PluginLogger, OpenClawConfig } from "openclaw/plugin-sdk";
|
|
5
5
|
import { getAdpOpenclawRuntime, setActiveWebSocket } from "./runtime.js";
|
|
6
6
|
import {
|
|
7
7
|
getChatHistory,
|
|
@@ -40,7 +40,7 @@ export type MonitorParams = {
|
|
|
40
40
|
signKey?: string; // HMAC key for signature generation
|
|
41
41
|
abortSignal?: AbortSignal;
|
|
42
42
|
log?: PluginLogger;
|
|
43
|
-
cfg?:
|
|
43
|
+
cfg?: OpenClawConfig; // OpenClaw config for model settings
|
|
44
44
|
setStatus?: (next: Record<string, unknown>) => void; // SDK health-monitor status reporter
|
|
45
45
|
};
|
|
46
46
|
|
|
@@ -127,7 +127,7 @@ function generateRequestId(): string {
|
|
|
127
127
|
async function markSessionAborted(params: {
|
|
128
128
|
sessionKey: string;
|
|
129
129
|
runtime: ReturnType<typeof getAdpOpenclawRuntime>;
|
|
130
|
-
cfg?:
|
|
130
|
+
cfg?: OpenClawConfig;
|
|
131
131
|
log?: PluginLogger;
|
|
132
132
|
}): Promise<void> {
|
|
133
133
|
const { sessionKey, runtime, cfg, log } = params;
|
|
@@ -206,7 +206,7 @@ type ConnectParams = {
|
|
|
206
206
|
abortSignal?: AbortSignal;
|
|
207
207
|
log?: PluginLogger;
|
|
208
208
|
runtime: ReturnType<typeof getAdpOpenclawRuntime>;
|
|
209
|
-
cfg?:
|
|
209
|
+
cfg?: OpenClawConfig;
|
|
210
210
|
setStatus?: (next: Record<string, unknown>) => void;
|
|
211
211
|
};
|
|
212
212
|
|
package/src/onboarding.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Setup wizard adapter for ADP OpenClaw channel plugin
|
|
2
|
+
// Migrated from ChannelOnboardingAdapter to ChannelSetupWizard for openclaw >= 2026.3.22
|
|
2
3
|
import type {
|
|
3
|
-
|
|
4
|
+
ChannelSetupWizard,
|
|
4
5
|
OpenClawConfig,
|
|
5
|
-
WizardPrompter,
|
|
6
6
|
} from "openclaw/plugin-sdk";
|
|
7
|
-
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk";
|
|
8
7
|
|
|
9
8
|
const channel = "adp-openclaw" as const;
|
|
10
9
|
|
|
@@ -42,81 +41,89 @@ function updateAdpOpenclawConfig(
|
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
await prompter.note(
|
|
47
|
-
[
|
|
48
|
-
"ADP OpenClaw connects to a WebSocket server for real-time messaging.",
|
|
49
|
-
"You need a clientToken to authenticate with the server.",
|
|
50
|
-
"The signKey is used for HMAC signature generation (default: ADPOpenClaw).",
|
|
51
|
-
].join("\n"),
|
|
52
|
-
"ADP OpenClaw setup",
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const adpOpenclawOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
44
|
+
export const adpOpenclawSetupWizard: ChannelSetupWizard = {
|
|
57
45
|
channel,
|
|
58
|
-
getStatus: async ({ cfg }) => {
|
|
59
|
-
const channelCfg = getChannelConfig(cfg);
|
|
60
|
-
const configured = isConfigured(channelCfg);
|
|
61
46
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
47
|
+
status: {
|
|
48
|
+
configuredLabel: "configured",
|
|
49
|
+
unconfiguredLabel: "needs clientToken",
|
|
50
|
+
configuredHint: "configured",
|
|
51
|
+
unconfiguredHint: "requires clientToken",
|
|
52
|
+
configuredScore: 1,
|
|
53
|
+
unconfiguredScore: 10,
|
|
54
|
+
resolveConfigured: ({ cfg }) => {
|
|
55
|
+
const channelCfg = getChannelConfig(cfg);
|
|
56
|
+
return isConfigured(channelCfg);
|
|
57
|
+
},
|
|
58
|
+
resolveStatusLines: ({ cfg, configured }) => {
|
|
59
|
+
return [`ADP OpenClaw: ${configured ? "configured" : "needs clientToken"}`];
|
|
60
|
+
},
|
|
69
61
|
},
|
|
70
|
-
configure: async ({ cfg, prompter }) => {
|
|
71
|
-
let next = cfg;
|
|
72
|
-
const accountId = DEFAULT_ACCOUNT_ID;
|
|
73
|
-
|
|
74
|
-
await noteAdpOpenclawSetup(prompter);
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
63
|
+
introNote: {
|
|
64
|
+
title: "ADP OpenClaw setup",
|
|
65
|
+
lines: [
|
|
66
|
+
"ADP OpenClaw connects to a WebSocket server for real-time messaging.",
|
|
67
|
+
"You need a clientToken to authenticate with the server.",
|
|
68
|
+
"The signKey is used for HMAC signature generation (default: ADPOpenClaw).",
|
|
69
|
+
],
|
|
70
|
+
},
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
next = updateAdpOpenclawConfig(next, { enabled: true });
|
|
91
|
-
return { cfg: next, accountId };
|
|
92
|
-
}
|
|
93
|
-
}
|
|
72
|
+
envShortcut: {
|
|
73
|
+
prompt: "ADP_OPENCLAW_CLIENT_TOKEN detected in env. Use environment variables?",
|
|
74
|
+
preferredEnvVar: "ADP_OPENCLAW_CLIENT_TOKEN",
|
|
75
|
+
isAvailable: () => Boolean(process.env.ADP_OPENCLAW_CLIENT_TOKEN?.trim()),
|
|
76
|
+
apply: ({ cfg }) => updateAdpOpenclawConfig(cfg, { enabled: true }),
|
|
77
|
+
},
|
|
94
78
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
79
|
+
credentials: [
|
|
80
|
+
{
|
|
81
|
+
inputKey: "token",
|
|
82
|
+
providerHint: "ADP OpenClaw",
|
|
83
|
+
credentialLabel: "Client Token",
|
|
84
|
+
preferredEnvVar: "ADP_OPENCLAW_CLIENT_TOKEN",
|
|
85
|
+
envPrompt: "ADP_OPENCLAW_CLIENT_TOKEN detected. Use it?",
|
|
86
|
+
keepPrompt: "Client Token already set. Keep it?",
|
|
87
|
+
inputPrompt: "Client Token",
|
|
88
|
+
inspect: ({ cfg }) => {
|
|
89
|
+
const channelCfg = getChannelConfig(cfg);
|
|
90
|
+
const configuredValue = channelCfg?.clientToken?.trim();
|
|
91
|
+
const envValue = process.env.ADP_OPENCLAW_CLIENT_TOKEN?.trim();
|
|
92
|
+
return {
|
|
93
|
+
accountConfigured: Boolean(configuredValue || envValue),
|
|
94
|
+
hasConfiguredValue: Boolean(configuredValue),
|
|
95
|
+
resolvedValue: configuredValue || envValue,
|
|
96
|
+
envValue,
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
applySet: ({ cfg, resolvedValue }) => {
|
|
100
|
+
return updateAdpOpenclawConfig(cfg, { clientToken: resolvedValue, enabled: true });
|
|
101
|
+
},
|
|
102
|
+
applyUseEnv: ({ cfg }) => {
|
|
103
|
+
return updateAdpOpenclawConfig(cfg, { enabled: true });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
],
|
|
103
107
|
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
textInputs: [
|
|
109
|
+
{
|
|
110
|
+
inputKey: "name",
|
|
106
111
|
message: "Sign Key (press Enter for default: ADPOpenClaw)",
|
|
107
112
|
placeholder: "ADPOpenClaw",
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
required: false,
|
|
114
|
+
currentValue: ({ cfg }) => {
|
|
115
|
+
const channelCfg = getChannelConfig(cfg);
|
|
116
|
+
return channelCfg?.signKey?.trim() || process.env.ADP_OPENCLAW_SIGN_KEY?.trim();
|
|
117
|
+
},
|
|
118
|
+
applySet: ({ cfg, value }) => {
|
|
119
|
+
return updateAdpOpenclawConfig(cfg, {
|
|
120
|
+
...(value ? { signKey: value } : {}),
|
|
121
|
+
enabled: true,
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
],
|
|
117
126
|
|
|
118
|
-
return { cfg: next, accountId };
|
|
119
|
-
},
|
|
120
127
|
disable: (cfg) => {
|
|
121
128
|
return {
|
|
122
129
|
...cfg,
|
package/src/session-history.ts
CHANGED
|
@@ -191,20 +191,46 @@ function resolveSessionTranscriptCandidates(
|
|
|
191
191
|
return candidates;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Sanitize string to ensure it's valid for JSON serialization.
|
|
196
|
+
* Removes or replaces characters that could cause JSON parsing issues.
|
|
197
|
+
*/
|
|
198
|
+
function sanitizeForJson(str: string): string {
|
|
199
|
+
if (!str) return str;
|
|
200
|
+
|
|
201
|
+
let result = str;
|
|
202
|
+
|
|
203
|
+
// Remove EXTERNAL_UNTRUSTED_CONTENT blocks which often contain binary garbage (e.g., images as text)
|
|
204
|
+
// These blocks are from web_fetch and contain external webpage content that may have encoding issues
|
|
205
|
+
result = result.replace(
|
|
206
|
+
/<<<EXTERNAL_UNTRUSTED_CONTENT>>>[\s\S]*?<<<\/EXTERNAL_UNTRUSTED_CONTENT>>>/g,
|
|
207
|
+
"[External content removed]"
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Remove null characters and other control characters (except common whitespace)
|
|
211
|
+
// Control characters: 0x00-0x1F (except 0x09 tab, 0x0A newline, 0x0D carriage return)
|
|
212
|
+
// Also remove 0x7F (DEL) and other problematic chars
|
|
213
|
+
result = result.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
214
|
+
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
|
|
194
218
|
/**
|
|
195
219
|
* Extract text content from message content (handles both string and array formats)
|
|
196
220
|
*/
|
|
197
221
|
function extractMessageContent(content: string | Array<{ type: string; text?: string }>): string {
|
|
222
|
+
let text: string;
|
|
198
223
|
if (typeof content === "string") {
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return content
|
|
224
|
+
text = content;
|
|
225
|
+
} else if (Array.isArray(content)) {
|
|
226
|
+
text = content
|
|
203
227
|
.filter((part) => part.type === "text" && part.text)
|
|
204
228
|
.map((part) => part.text)
|
|
205
229
|
.join("\n");
|
|
230
|
+
} else {
|
|
231
|
+
text = String(content);
|
|
206
232
|
}
|
|
207
|
-
return
|
|
233
|
+
return sanitizeForJson(text);
|
|
208
234
|
}
|
|
209
235
|
|
|
210
236
|
/**
|
|
@@ -857,27 +883,55 @@ export async function getOpenClawChatHistoryViaCli(
|
|
|
857
883
|
);
|
|
858
884
|
|
|
859
885
|
// Parse JSON result
|
|
886
|
+
// OpenClaw CLI returns messages with content that can be:
|
|
887
|
+
// - string: plain text content
|
|
888
|
+
// - array: mixed content parts including text, toolCall, etc.
|
|
889
|
+
// Timestamp can be either number (ms) or ISO string
|
|
860
890
|
const parsed = JSON.parse(result) as {
|
|
861
891
|
messages?: Array<{
|
|
862
892
|
role: string;
|
|
863
|
-
content: string | Array<{ type: string; text?: string }>;
|
|
893
|
+
content: string | Array<{ type: string; text?: string; [key: string]: unknown }>;
|
|
864
894
|
id?: string;
|
|
865
|
-
timestamp?: string;
|
|
895
|
+
timestamp?: string | number;
|
|
866
896
|
}>;
|
|
867
897
|
sessionId?: string; // OpenClaw may return the current sessionId
|
|
868
898
|
};
|
|
869
899
|
|
|
870
|
-
let messages: OpenClawMessage[] = (parsed.messages ?? []).map((msg) =>
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
900
|
+
let messages: OpenClawMessage[] = (parsed.messages ?? []).map((msg) => {
|
|
901
|
+
// Extract text content from message
|
|
902
|
+
let textContent: string;
|
|
903
|
+
if (typeof msg.content === "string") {
|
|
904
|
+
textContent = msg.content;
|
|
905
|
+
} else if (Array.isArray(msg.content)) {
|
|
906
|
+
// Filter for text parts only (skip toolCall, toolResult, etc.)
|
|
907
|
+
textContent = msg.content
|
|
908
|
+
.filter((p): p is { type: string; text: string } =>
|
|
909
|
+
p.type === "text" && typeof p.text === "string"
|
|
910
|
+
)
|
|
911
|
+
.map((p) => p.text)
|
|
912
|
+
.join("\n");
|
|
913
|
+
} else {
|
|
914
|
+
textContent = String(msg.content ?? "");
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Sanitize content to remove invalid characters that break JSON serialization
|
|
918
|
+
textContent = sanitizeForJson(textContent);
|
|
919
|
+
|
|
920
|
+
// Handle timestamp: can be number (ms) or ISO string
|
|
921
|
+
let timestamp: number | undefined;
|
|
922
|
+
if (typeof msg.timestamp === "number") {
|
|
923
|
+
timestamp = msg.timestamp;
|
|
924
|
+
} else if (typeof msg.timestamp === "string") {
|
|
925
|
+
timestamp = new Date(msg.timestamp).getTime();
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return {
|
|
929
|
+
role: msg.role as "user" | "assistant" | "system",
|
|
930
|
+
content: textContent,
|
|
931
|
+
id: msg.id,
|
|
932
|
+
timestamp,
|
|
933
|
+
};
|
|
934
|
+
});
|
|
881
935
|
|
|
882
936
|
log?.info?.(`[session-history] Got ${messages.length} messages via CLI`);
|
|
883
937
|
|