adp-openclaw 0.0.68 → 0.0.70

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.68",
3
+ "version": "0.0.70",
4
4
  "description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/src/channel.ts CHANGED
@@ -3,10 +3,10 @@
3
3
 
4
4
  import {
5
5
  type ChannelPlugin,
6
- type ClawdbotConfig,
7
- DEFAULT_ACCOUNT_ID,
6
+ type OpenClawConfig,
8
7
  } from "openclaw/plugin-sdk";
9
- import { adpOpenclawOnboardingAdapter } from "./onboarding.js";
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
12
  // Default WebSocket URL for ADP OpenClaw
@@ -61,7 +61,7 @@ function resolveAdpOpenclawCredentials(channelCfg?: AdpOpenclawChannelConfig): {
61
61
  return { wsUrl, clientToken, signKey };
62
62
  }
63
63
 
64
- function resolveAccount(cfg: ClawdbotConfig, accountId?: string): ResolvedAdpOpenclawAccount {
64
+ function resolveAccount(cfg: OpenClawConfig, accountId?: string): ResolvedAdpOpenclawAccount {
65
65
  const channelCfg = cfg.channels?.["adp-openclaw"] as AdpOpenclawChannelConfig | undefined;
66
66
  const enabled = channelCfg?.enabled !== false;
67
67
  const creds = resolveAdpOpenclawCredentials(channelCfg);
@@ -87,7 +87,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
87
87
  blurb: "ADP channel backed by a Go WebSocket server.",
88
88
  order: 999,
89
89
  },
90
- onboarding: adpOpenclawOnboardingAdapter,
90
+ setupWizard: adpOpenclawSetupWizard,
91
91
  capabilities: {
92
92
  chatTypes: ["direct"],
93
93
  polls: false,
@@ -128,7 +128,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
128
128
  },
129
129
  }),
130
130
  deleteAccount: ({ cfg }) => {
131
- const next = { ...cfg } as ClawdbotConfig;
131
+ const next = { ...cfg } as OpenClawConfig;
132
132
  const nextChannels = { ...cfg.channels };
133
133
  delete (nextChannels as Record<string, unknown>)["adp-openclaw"];
134
134
  if (Object.keys(nextChannels).length > 0) {
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, ClawdbotConfig } from "openclaw/plugin-sdk";
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?: ClawdbotConfig; // OpenClaw config for model settings
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?: ClawdbotConfig;
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?: ClawdbotConfig;
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
- // Onboarding adapter for ADP OpenClaw channel plugin
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
- ChannelOnboardingAdapter,
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
- async function noteAdpOpenclawSetup(prompter: WizardPrompter): Promise<void> {
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
- return {
63
- channel,
64
- configured,
65
- statusLines: [`ADP OpenClaw: ${configured ? "configured" : "needs clientToken"}`],
66
- selectionHint: configured ? "configured" : "requires clientToken",
67
- quickstartScore: configured ? 1 : 10,
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
- const channelCfg = getChannelConfig(next);
77
- const existingClientToken = channelCfg?.clientToken?.trim();
78
- const existingSignKey = channelCfg?.signKey?.trim();
79
-
80
- // Check for env vars
81
- const envClientToken = process.env.ADP_OPENCLAW_CLIENT_TOKEN?.trim();
82
- const envSignKey = process.env.ADP_OPENCLAW_SIGN_KEY?.trim();
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
- if (envClientToken) {
85
- const useEnv = await prompter.confirm({
86
- message: "ADP_OPENCLAW_CLIENT_TOKEN detected in env. Use environment variables?",
87
- initialValue: true,
88
- });
89
- if (useEnv) {
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
- // Prompt for clientToken (required)
96
- const clientTokenInput = await prompter.text({
97
- message: "Client Token",
98
- placeholder: "your-client-token",
99
- initialValue: existingClientToken || undefined,
100
- validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
101
- });
102
- const clientToken = String(clientTokenInput).trim();
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
- // Prompt for signKey (optional, has default)
105
- const signKeyInput = await prompter.text({
108
+ textInputs: [
109
+ {
110
+ inputKey: "name",
106
111
  message: "Sign Key (press Enter for default: ADPOpenClaw)",
107
112
  placeholder: "ADPOpenClaw",
108
- initialValue: existingSignKey || envSignKey || undefined,
109
- });
110
- const signKey = String(signKeyInput ?? "").trim() || undefined;
111
-
112
- next = updateAdpOpenclawConfig(next, {
113
- clientToken,
114
- ...(signKey ? { signKey } : {}),
115
- enabled: true,
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,
@@ -498,9 +498,10 @@ export async function getMergedChatHistory(
498
498
  options?: {
499
499
  limit?: number;
500
500
  log?: PluginLogger;
501
+ filterAfterNewSession?: boolean; // Default true: filter out messages before last /new
501
502
  },
502
503
  ): Promise<ChatHistoryResponse> {
503
- const { limit = 200, log } = options ?? {};
504
+ const { limit = 200, log, filterAfterNewSession = true } = options ?? {};
504
505
 
505
506
  // Build both old and new session key formats
506
507
  const oldSessionKey = `agent:main:direct:${conversationId}`;
@@ -511,6 +512,7 @@ export async function getMergedChatHistory(
511
512
  log?.info?.(`[session-history] New sessionKey: ${newSessionKey}`);
512
513
 
513
514
  // Fetch history from both session keys in parallel
515
+ // Note: getChatHistory already applies filterAfterNewSession for each session individually
514
516
  const [oldResult, newResult] = await Promise.all([
515
517
  getChatHistory(oldSessionKey, { limit, log }).catch((err) => {
516
518
  log?.debug?.(`[session-history] Failed to fetch old session history: ${err}`);
@@ -537,7 +539,7 @@ export async function getMergedChatHistory(
537
539
 
538
540
  // Deduplicate by message id (if available) or content+timestamp
539
541
  const seen = new Set<string>();
540
- const dedupedMessages = allMessages.filter((msg) => {
542
+ let dedupedMessages = allMessages.filter((msg) => {
541
543
  // Create a unique key for deduplication
542
544
  const key = msg.id || `${msg.role}:${msg.timestamp}:${msg.content.slice(0, 100)}`;
543
545
  if (seen.has(key)) {
@@ -547,6 +549,13 @@ export async function getMergedChatHistory(
547
549
  return true;
548
550
  });
549
551
 
552
+ // Filter out messages before the last /new session on the MERGED result
553
+ // This is important because the /new might be in the old sessionKey but we still
554
+ // want to filter the combined history based on the latest /new across both sessions
555
+ if (filterAfterNewSession) {
556
+ dedupedMessages = filterMessagesAfterLastNewSession(dedupedMessages, log);
557
+ }
558
+
550
559
  // Apply limit (return last N messages if exceeds limit)
551
560
  const limitedMessages = dedupedMessages.length > limit
552
561
  ? dedupedMessages.slice(-limit)