@invago/mixin 1.0.9 → 1.0.11

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.
@@ -32,6 +32,21 @@ export const MixinConversationConfigSchema = z.object({
32
32
 
33
33
  export type MixinConversationConfig = z.infer<typeof MixinConversationConfigSchema>;
34
34
 
35
+ export const MixinMixpayConfigSchema = z.object({
36
+ enabled: z.boolean().optional().default(false),
37
+ apiBaseUrl: z.string().optional(),
38
+ payeeId: z.string().optional(),
39
+ defaultQuoteAssetId: z.string().optional(),
40
+ defaultSettlementAssetId: z.string().optional(),
41
+ expireMinutes: z.number().positive().optional().default(15),
42
+ pollIntervalSec: z.number().positive().optional().default(30),
43
+ allowedCreators: z.array(z.string()).optional().default([]),
44
+ notifyOnPending: z.boolean().optional().default(false),
45
+ notifyOnPaidLess: z.boolean().optional().default(true),
46
+ });
47
+
48
+ export type MixinMixpayConfig = z.infer<typeof MixinMixpayConfigSchema>;
49
+
35
50
  export const MixinAccountConfigSchema = z.object({
36
51
  name: z.string().optional(),
37
52
  enabled: z.boolean().optional().default(true),
@@ -49,6 +64,7 @@ export const MixinAccountConfigSchema = z.object({
49
64
  audioAutoDetectDuration: z.boolean().optional().default(true),
50
65
  audioSendAsVoiceByDefault: z.boolean().optional().default(true),
51
66
  audioRequireFfprobe: z.boolean().optional().default(false),
67
+ mixpay: MixinMixpayConfigSchema.optional(),
52
68
  conversations: z.record(z.string(), MixinConversationConfigSchema.optional()).optional(),
53
69
  debug: z.boolean().optional().default(false),
54
70
  proxy: MixinProxyConfigSchema.optional(),
package/src/config.ts CHANGED
@@ -1,9 +1,10 @@
1
- import type { OpenClawConfig } from "openclaw/plugin-sdk";
1
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
2
2
  import {
3
3
  MixinAccountConfigSchema,
4
4
  MixinConversationConfigSchema,
5
5
  type MixinAccountConfig,
6
6
  type MixinConversationConfig,
7
+ type MixinMixpayConfig,
7
8
  } from "./config-schema.js";
8
9
 
9
10
  type RawMixinConfig = Partial<MixinAccountConfig> & {
@@ -11,8 +12,53 @@ type RawMixinConfig = Partial<MixinAccountConfig> & {
11
12
  accounts?: Record<string, Partial<MixinAccountConfig> | undefined>;
12
13
  };
13
14
 
15
+ function isRecord(value: unknown): value is Record<string, unknown> {
16
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17
+ }
18
+
19
+ function hasLegacyMixinConfig(raw: Record<string, unknown>): boolean {
20
+ const typed = raw as Partial<MixinAccountConfig> & {
21
+ defaultAccount?: unknown;
22
+ accounts?: unknown;
23
+ };
24
+
25
+ return Boolean(
26
+ typed.defaultAccount ||
27
+ typed.accounts ||
28
+ typed.appId ||
29
+ typed.sessionId ||
30
+ typed.serverPublicKey ||
31
+ typed.sessionPrivateKey ||
32
+ typed.name,
33
+ );
34
+ }
35
+
14
36
  function getRawConfig(cfg: OpenClawConfig): RawMixinConfig {
15
- return ((cfg.channels as Record<string, unknown>)?.mixin ?? {}) as RawMixinConfig;
37
+ const root = cfg as unknown as Record<string, unknown>;
38
+ const channels = isRecord(root.channels) ? root.channels : undefined;
39
+ const channelConfig = channels && isRecord(channels.mixin) ? channels.mixin : undefined;
40
+ if (channelConfig) {
41
+ return channelConfig as RawMixinConfig;
42
+ }
43
+ const plugins = isRecord(root.plugins) ? root.plugins : undefined;
44
+ const entries = plugins && isRecord(plugins.entries) ? plugins.entries : undefined;
45
+ const mixinEntry = entries && isRecord(entries.mixin) ? entries.mixin : undefined;
46
+ const pluginEntryConfig = mixinEntry && isRecord(mixinEntry.config) ? mixinEntry.config : undefined;
47
+ if (pluginEntryConfig) {
48
+ return pluginEntryConfig as RawMixinConfig;
49
+ }
50
+
51
+
52
+ const legacyNamedConfig = isRecord(root.mixin) ? root.mixin : undefined;
53
+ if (legacyNamedConfig) {
54
+ return legacyNamedConfig as RawMixinConfig;
55
+ }
56
+
57
+ if (hasLegacyMixinConfig(root)) {
58
+ return root as RawMixinConfig;
59
+ }
60
+
61
+ return {};
16
62
  }
17
63
 
18
64
  function hasTopLevelAccountConfig(raw: RawMixinConfig): boolean {
@@ -58,7 +104,9 @@ export function getAccountConfig(cfg: OpenClawConfig, accountId?: string): Mixin
58
104
  }
59
105
 
60
106
  const result = MixinAccountConfigSchema.safeParse(accountRaw);
61
- if (result.success) return result.data;
107
+ if (result.success) {
108
+ return result.data;
109
+ }
62
110
  return MixinAccountConfigSchema.parse({});
63
111
  }
64
112
 
@@ -87,6 +135,10 @@ export function resolveMediaMaxMb(cfg: OpenClawConfig, accountId?: string): numb
87
135
  return getAccountConfig(cfg, accountId).mediaMaxMb;
88
136
  }
89
137
 
138
+ export function getMixpayConfig(cfg: OpenClawConfig, accountId?: string): MixinMixpayConfig | undefined {
139
+ return getAccountConfig(cfg, accountId).mixpay;
140
+ }
141
+
90
142
  function getRawAccountConfig(cfg: OpenClawConfig, accountId?: string): Partial<MixinAccountConfig> {
91
143
  const raw = getRawConfig(cfg);
92
144
  const resolvedAccountId = accountId ?? resolveDefaultAccountId(cfg);
@@ -149,4 +201,6 @@ export function describeAccount(account: ReturnType<typeof resolveAccount>) {
149
201
  configured: account.configured,
150
202
  enabled: account.enabled,
151
203
  };
152
- }
204
+ }
205
+
206
+
package/src/crypto.ts CHANGED
@@ -12,6 +12,11 @@ function aes256CbcDecrypt(key: Buffer, iv: Buffer, ciphertext: Buffer): Buffer {
12
12
  const final = Buffer.concat([decrypted, decipher.final()]);
13
13
  const padLen = final[final.length - 1];
14
14
  if (padLen > 0 && padLen <= 16) {
15
+ for (let i = final.length - padLen; i < final.length; i++) {
16
+ if (final[i] !== padLen) {
17
+ return final;
18
+ }
19
+ }
15
20
  return final.slice(0, final.length - padLen);
16
21
  }
17
22
  return final;