@inline-openclaw/inline 0.0.21 → 0.0.22

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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +696 -144
  5. package/dist/index.js.map +19 -17
  6. package/dist/inline/accounts.d.ts +1 -1
  7. package/dist/inline/accounts.d.ts.map +1 -1
  8. package/dist/inline/actions.d.ts +30 -3
  9. package/dist/inline/actions.d.ts.map +1 -1
  10. package/dist/inline/bot-commands-sync.d.ts +1 -1
  11. package/dist/inline/bot-commands-sync.d.ts.map +1 -1
  12. package/dist/inline/bot-commands-tool.d.ts +1 -1
  13. package/dist/inline/bot-commands-tool.d.ts.map +1 -1
  14. package/dist/inline/channel.d.ts +1 -1
  15. package/dist/inline/channel.d.ts.map +1 -1
  16. package/dist/inline/config-schema.d.ts +14 -14
  17. package/dist/inline/config-schema.d.ts.map +1 -1
  18. package/dist/inline/media.d.ts +1 -1
  19. package/dist/inline/media.d.ts.map +1 -1
  20. package/dist/inline/members-tool.d.ts +1 -1
  21. package/dist/inline/members-tool.d.ts.map +1 -1
  22. package/dist/inline/message-tools.d.ts +1 -1
  23. package/dist/inline/message-tools.d.ts.map +1 -1
  24. package/dist/inline/monitor.d.ts +2 -1
  25. package/dist/inline/monitor.d.ts.map +1 -1
  26. package/dist/inline/policy.d.ts +1 -1
  27. package/dist/inline/policy.d.ts.map +1 -1
  28. package/dist/inline/profile-tool.d.ts +1 -1
  29. package/dist/inline/profile-tool.d.ts.map +1 -1
  30. package/dist/openclaw-compat.d.ts +141 -0
  31. package/dist/openclaw-compat.d.ts.map +1 -0
  32. package/dist/runtime.d.ts +1 -1
  33. package/dist/runtime.d.ts.map +1 -1
  34. package/dist/sdk-runtime-compat.d.ts +83 -0
  35. package/dist/sdk-runtime-compat.d.ts.map +1 -0
  36. package/dist/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -5539,17 +5539,6 @@ var require_websocket_server = __commonJS((exports, module) => {
5539
5539
  }
5540
5540
  });
5541
5541
 
5542
- // src/index.ts
5543
- import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
5544
-
5545
- // src/inline/channel.ts
5546
- import {
5547
- buildChannelConfigSchema,
5548
- DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID2,
5549
- formatPairingApproveHint,
5550
- PAIRING_APPROVED_MESSAGE
5551
- } from "openclaw/plugin-sdk";
5552
-
5553
5542
  // ../protocol/dist/core.js
5554
5543
  var import_runtime = __toESM(require_commonjs(), 1);
5555
5544
  var import_runtime2 = __toESM(require_commonjs(), 1);
@@ -19960,15 +19949,6 @@ class JsonFileStateStore {
19960
19949
  await rename(tempPath, this.path);
19961
19950
  }
19962
19951
  }
19963
- // src/inline/config-schema.ts
19964
- import {
19965
- BlockStreamingCoalesceSchema,
19966
- DmPolicySchema,
19967
- GroupPolicySchema,
19968
- ToolPolicySchema,
19969
- requireOpenAllowFrom
19970
- } from "openclaw/plugin-sdk";
19971
-
19972
19952
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
19973
19953
  var exports_external = {};
19974
19954
  __export(exports_external, {
@@ -33501,6 +33481,246 @@ function date4(params) {
33501
33481
 
33502
33482
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
33503
33483
  config(en_default());
33484
+ // src/openclaw-compat.ts
33485
+ var MB = 1024 * 1024;
33486
+ var VALID_ACCOUNT_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
33487
+ var INVALID_ACCOUNT_ID_CHARS_RE = /[^a-z0-9_-]+/g;
33488
+ var LEADING_DASH_RE = /^-+/g;
33489
+ var TRAILING_DASH_RE = /-+$/g;
33490
+ var BLOCKED_OBJECT_KEYS = new Set(["__proto__", "constructor", "prototype"]);
33491
+ var DEFAULT_ACCOUNT_ID = "default";
33492
+ var PAIRING_APPROVED_MESSAGE = "✅ OpenClaw access approved. Send a message to start chatting.";
33493
+ function normalizeAccountId(value) {
33494
+ const trimmed = (value ?? "").trim();
33495
+ if (!trimmed)
33496
+ return DEFAULT_ACCOUNT_ID;
33497
+ const normalized = VALID_ACCOUNT_ID_RE.test(trimmed) ? trimmed.toLowerCase() : trimmed.toLowerCase().replace(INVALID_ACCOUNT_ID_CHARS_RE, "-").replace(LEADING_DASH_RE, "").replace(TRAILING_DASH_RE, "").slice(0, 64);
33498
+ if (!normalized || BLOCKED_OBJECT_KEYS.has(normalized)) {
33499
+ return DEFAULT_ACCOUNT_ID;
33500
+ }
33501
+ return normalized;
33502
+ }
33503
+ function emptyPluginConfigSchema() {
33504
+ function error48(message) {
33505
+ return { success: false, error: { issues: [{ path: [], message }] } };
33506
+ }
33507
+ return {
33508
+ safeParse(value) {
33509
+ if (value === undefined) {
33510
+ return { success: true, data: undefined };
33511
+ }
33512
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
33513
+ return error48("expected config object");
33514
+ }
33515
+ if (Object.keys(value).length > 0) {
33516
+ return error48("config must be empty");
33517
+ }
33518
+ return { success: true, data: value };
33519
+ },
33520
+ jsonSchema: {
33521
+ type: "object",
33522
+ additionalProperties: false,
33523
+ properties: {}
33524
+ }
33525
+ };
33526
+ }
33527
+ function buildChannelConfigSchema(schema) {
33528
+ const schemaWithJson = schema;
33529
+ if (typeof schemaWithJson.toJSONSchema === "function") {
33530
+ return {
33531
+ schema: schemaWithJson.toJSONSchema({
33532
+ target: "draft-07",
33533
+ unrepresentable: "any"
33534
+ })
33535
+ };
33536
+ }
33537
+ return {
33538
+ schema: {
33539
+ type: "object",
33540
+ additionalProperties: true
33541
+ }
33542
+ };
33543
+ }
33544
+ function formatPairingApproveHint(channelId) {
33545
+ return `Approve via: openclaw pairing list ${channelId} / openclaw pairing approve ${channelId} <code>`;
33546
+ }
33547
+ var GroupPolicySchema = exports_external.enum(["open", "disabled", "allowlist"]);
33548
+ var DmPolicySchema = exports_external.enum(["pairing", "allowlist", "open", "disabled"]);
33549
+ var BlockStreamingCoalesceSchema = exports_external.object({
33550
+ minChars: exports_external.number().int().positive().optional(),
33551
+ maxChars: exports_external.number().int().positive().optional(),
33552
+ idleMs: exports_external.number().int().nonnegative().optional()
33553
+ }).strict();
33554
+ var ToolPolicyBaseSchema = exports_external.object({
33555
+ allow: exports_external.array(exports_external.string()).optional(),
33556
+ alsoAllow: exports_external.array(exports_external.string()).optional(),
33557
+ deny: exports_external.array(exports_external.string()).optional()
33558
+ }).strict();
33559
+ var ToolPolicySchema = ToolPolicyBaseSchema.superRefine((value, ctx) => {
33560
+ if (value.allow && value.allow.length > 0 && value.alsoAllow && value.alsoAllow.length > 0) {
33561
+ ctx.addIssue({
33562
+ code: exports_external.ZodIssueCode.custom,
33563
+ message: "tools policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)"
33564
+ });
33565
+ }
33566
+ }).optional();
33567
+ function requireOpenAllowFrom(params) {
33568
+ if (params.policy !== "open") {
33569
+ return;
33570
+ }
33571
+ const allow = (params.allowFrom ?? []).map((entry) => String(entry).trim()).filter(Boolean);
33572
+ if (allow.includes("*")) {
33573
+ return;
33574
+ }
33575
+ params.ctx.addIssue({
33576
+ code: exports_external.ZodIssueCode.custom,
33577
+ path: params.path,
33578
+ message: params.message
33579
+ });
33580
+ }
33581
+ function resolveControlCommandGate(params) {
33582
+ const mode = params.modeWhenAccessGroupsOff ?? "allow";
33583
+ let commandAuthorized = false;
33584
+ if (!params.useAccessGroups) {
33585
+ if (mode === "allow") {
33586
+ commandAuthorized = true;
33587
+ } else if (mode === "deny") {
33588
+ commandAuthorized = false;
33589
+ } else {
33590
+ const anyConfigured = params.authorizers.some((entry) => entry.configured);
33591
+ commandAuthorized = !anyConfigured || params.authorizers.some((entry) => entry.configured && entry.allowed);
33592
+ }
33593
+ } else {
33594
+ commandAuthorized = params.authorizers.some((entry) => entry.configured && entry.allowed);
33595
+ }
33596
+ return {
33597
+ commandAuthorized,
33598
+ shouldBlock: params.allowTextCommands && params.hasControlCommand && !commandAuthorized
33599
+ };
33600
+ }
33601
+ function resolveMentionGatingWithBypass(params) {
33602
+ const shouldBypassMention = params.isGroup && params.requireMention && !params.wasMentioned && !(params.hasAnyMention ?? false) && params.allowTextCommands && params.commandAuthorized && params.hasControlCommand;
33603
+ const effectiveWasMentioned = params.wasMentioned || params.implicitMention === true || shouldBypassMention;
33604
+ return {
33605
+ effectiveWasMentioned,
33606
+ shouldSkip: params.requireMention && params.canDetectMention && !effectiveWasMentioned,
33607
+ shouldBypassMention
33608
+ };
33609
+ }
33610
+ function logInboundDrop(params) {
33611
+ const target = params.target ? ` target=${params.target}` : "";
33612
+ params.log(`${params.channel}: drop ${params.reason}${target}`);
33613
+ }
33614
+ function resolveChannelMediaMaxBytes(params) {
33615
+ const accountId = normalizeAccountId(params.accountId);
33616
+ const channelLimit = params.resolveChannelLimitMb({
33617
+ cfg: params.cfg,
33618
+ accountId
33619
+ });
33620
+ if (channelLimit) {
33621
+ return channelLimit * MB;
33622
+ }
33623
+ if (params.cfg.agents?.defaults?.mediaMaxMb) {
33624
+ return params.cfg.agents.defaults.mediaMaxMb * MB;
33625
+ }
33626
+ return;
33627
+ }
33628
+ function createActionGate(actions) {
33629
+ return (key, defaultValue = true) => {
33630
+ const value = actions?.[key];
33631
+ if (value === undefined) {
33632
+ return defaultValue;
33633
+ }
33634
+ return value !== false;
33635
+ };
33636
+ }
33637
+ function toSnakeCaseKey(key) {
33638
+ return key.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
33639
+ }
33640
+ function readSnakeCaseParamRaw(params, key) {
33641
+ if (Object.hasOwn(params, key)) {
33642
+ return params[key];
33643
+ }
33644
+ const snakeKey = toSnakeCaseKey(key);
33645
+ if (snakeKey !== key && Object.hasOwn(params, snakeKey)) {
33646
+ return params[snakeKey];
33647
+ }
33648
+ return;
33649
+ }
33650
+
33651
+ class ToolInputError extends Error {
33652
+ status = 400;
33653
+ constructor(message) {
33654
+ super(message);
33655
+ this.name = "ToolInputError";
33656
+ }
33657
+ }
33658
+ function readStringParam(params, key, options = {}) {
33659
+ const { required: required2 = false, trim = true, label = key, allowEmpty = false } = options;
33660
+ const raw = readSnakeCaseParamRaw(params, key);
33661
+ if (typeof raw !== "string") {
33662
+ if (required2) {
33663
+ throw new ToolInputError(`${label} required`);
33664
+ }
33665
+ return;
33666
+ }
33667
+ const value = trim ? raw.trim() : raw;
33668
+ if (!value && !allowEmpty) {
33669
+ if (required2) {
33670
+ throw new ToolInputError(`${label} required`);
33671
+ }
33672
+ return;
33673
+ }
33674
+ return value;
33675
+ }
33676
+ function readNumberParam(params, key, options = {}) {
33677
+ const { required: required2 = false, label = key, integer: integer2 = false, strict = false } = options;
33678
+ const raw = readSnakeCaseParamRaw(params, key);
33679
+ let value;
33680
+ if (typeof raw === "number" && Number.isFinite(raw)) {
33681
+ value = raw;
33682
+ } else if (typeof raw === "string") {
33683
+ const trimmed = raw.trim();
33684
+ if (trimmed) {
33685
+ const parsed = strict ? Number(trimmed) : Number.parseFloat(trimmed);
33686
+ if (Number.isFinite(parsed)) {
33687
+ value = parsed;
33688
+ }
33689
+ }
33690
+ }
33691
+ if (value === undefined) {
33692
+ if (required2) {
33693
+ throw new ToolInputError(`${label} required`);
33694
+ }
33695
+ return;
33696
+ }
33697
+ return integer2 ? Math.trunc(value) : value;
33698
+ }
33699
+ function readReactionParams(params, options) {
33700
+ const emojiKey = options.emojiKey ?? "emoji";
33701
+ const removeKey = options.removeKey ?? "remove";
33702
+ const remove = typeof params[removeKey] === "boolean" ? params[removeKey] : false;
33703
+ const emoji3 = readStringParam(params, emojiKey, {
33704
+ required: true,
33705
+ allowEmpty: true
33706
+ });
33707
+ if (remove && !emoji3) {
33708
+ throw new ToolInputError(options.removeErrorMessage);
33709
+ }
33710
+ return { emoji: emoji3 ?? "", remove, isEmpty: !emoji3 };
33711
+ }
33712
+ function jsonResult(payload) {
33713
+ return {
33714
+ content: [
33715
+ {
33716
+ type: "text",
33717
+ text: JSON.stringify(payload, (_key, value) => typeof value === "bigint" ? value.toString() : value, 2)
33718
+ }
33719
+ ],
33720
+ details: payload
33721
+ };
33722
+ }
33723
+
33504
33724
  // src/inline/config-schema.ts
33505
33725
  var InlineActionsSchema = exports_external.object({
33506
33726
  send: exports_external.boolean().optional(),
@@ -33577,7 +33797,6 @@ var InlineConfigSchema = InlineAccountSchemaBase.extend({
33577
33797
  });
33578
33798
 
33579
33799
  // src/inline/accounts.ts
33580
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk";
33581
33800
  import { readFile as readFile2 } from "node:fs/promises";
33582
33801
  var DEFAULT_BASE_URL = "https://api.inline.chat";
33583
33802
  function normalizeInlineAccountId(raw) {
@@ -33683,17 +33902,255 @@ function looksLikeInlineTargetId(raw, normalizedInput) {
33683
33902
  // src/inline/monitor.ts
33684
33903
  import { mkdir } from "node:fs/promises";
33685
33904
  import path2 from "node:path";
33686
- import {
33687
- buildPendingHistoryContextFromMap,
33688
- clearHistoryEntriesIfEnabled,
33689
- createReplyPrefixOptions,
33690
- createTypingCallbacks,
33691
- logInboundDrop,
33692
- recordPendingHistoryEntryIfEnabled,
33693
- resolveChannelMediaMaxBytes as resolveChannelMediaMaxBytes2,
33694
- resolveControlCommandGate,
33695
- resolveMentionGatingWithBypass
33696
- } from "openclaw/plugin-sdk";
33905
+
33906
+ // src/sdk-runtime-compat.ts
33907
+ var HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
33908
+ var CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
33909
+ var MAX_HISTORY_KEYS = 1000;
33910
+ var DEFAULT_GROUP_HISTORY_LIMIT = 50;
33911
+ function evictOldHistoryKeys(historyMap, maxKeys = MAX_HISTORY_KEYS) {
33912
+ if (historyMap.size <= maxKeys) {
33913
+ return;
33914
+ }
33915
+ const keysToDelete = historyMap.size - maxKeys;
33916
+ const iterator = historyMap.keys();
33917
+ for (let index = 0;index < keysToDelete; index += 1) {
33918
+ const key = iterator.next().value;
33919
+ if (key !== undefined) {
33920
+ historyMap.delete(key);
33921
+ }
33922
+ }
33923
+ }
33924
+ function buildHistoryContext(params) {
33925
+ const lineBreak = params.lineBreak ?? `
33926
+ `;
33927
+ if (!params.historyText.trim()) {
33928
+ return params.currentMessage;
33929
+ }
33930
+ return [
33931
+ HISTORY_CONTEXT_MARKER,
33932
+ params.historyText,
33933
+ "",
33934
+ CURRENT_MESSAGE_MARKER,
33935
+ params.currentMessage
33936
+ ].join(lineBreak);
33937
+ }
33938
+ function appendHistoryEntry(params) {
33939
+ if (params.limit <= 0) {
33940
+ return [];
33941
+ }
33942
+ const history = params.historyMap.get(params.historyKey) ?? [];
33943
+ history.push(params.entry);
33944
+ while (history.length > params.limit) {
33945
+ history.shift();
33946
+ }
33947
+ if (params.historyMap.has(params.historyKey)) {
33948
+ params.historyMap.delete(params.historyKey);
33949
+ }
33950
+ params.historyMap.set(params.historyKey, history);
33951
+ evictOldHistoryKeys(params.historyMap);
33952
+ return history;
33953
+ }
33954
+ function buildHistoryContextFromEntries(params) {
33955
+ const lineBreak = params.lineBreak ?? `
33956
+ `;
33957
+ const entries = params.excludeLast === false ? params.entries : params.entries.slice(0, -1);
33958
+ if (entries.length === 0) {
33959
+ return params.currentMessage;
33960
+ }
33961
+ return buildHistoryContext({
33962
+ historyText: entries.map(params.formatEntry).join(lineBreak),
33963
+ currentMessage: params.currentMessage,
33964
+ lineBreak
33965
+ });
33966
+ }
33967
+ function buildPendingHistoryContextFromMap(params) {
33968
+ if (params.limit <= 0) {
33969
+ return params.currentMessage;
33970
+ }
33971
+ const entries = params.historyMap.get(params.historyKey) ?? [];
33972
+ return buildHistoryContextFromEntries({
33973
+ entries,
33974
+ currentMessage: params.currentMessage,
33975
+ formatEntry: params.formatEntry,
33976
+ ...params.lineBreak !== undefined ? { lineBreak: params.lineBreak } : {},
33977
+ excludeLast: false
33978
+ });
33979
+ }
33980
+ function clearHistoryEntriesIfEnabled(params) {
33981
+ if (params.limit <= 0) {
33982
+ return;
33983
+ }
33984
+ params.historyMap.set(params.historyKey, []);
33985
+ }
33986
+ function recordPendingHistoryEntryIfEnabled(params) {
33987
+ if (!params.entry || params.limit <= 0) {
33988
+ return [];
33989
+ }
33990
+ return appendHistoryEntry({
33991
+ historyMap: params.historyMap,
33992
+ historyKey: params.historyKey,
33993
+ entry: params.entry,
33994
+ limit: params.limit
33995
+ });
33996
+ }
33997
+ function createMessageToolButtonsSchemaCompat() {
33998
+ return {
33999
+ type: "array",
34000
+ description: "Button rows for channels that support button-style actions.",
34001
+ items: {
34002
+ type: "array",
34003
+ items: {
34004
+ type: "object",
34005
+ additionalProperties: false,
34006
+ required: ["text", "callback_data"],
34007
+ properties: {
34008
+ text: { type: "string" },
34009
+ callback_data: { type: "string" },
34010
+ style: { type: "string", enum: ["danger", "success", "primary"] }
34011
+ }
34012
+ }
34013
+ }
34014
+ };
34015
+ }
34016
+ function extensionForMimeCompat(mime) {
34017
+ const normalized = mime?.trim().toLowerCase();
34018
+ if (!normalized)
34019
+ return;
34020
+ const directMap = {
34021
+ "image/jpeg": "jpg",
34022
+ "image/jpg": "jpg",
34023
+ "image/png": "png",
34024
+ "image/gif": "gif",
34025
+ "image/webp": "webp",
34026
+ "video/mp4": "mp4",
34027
+ "audio/mpeg": "mp3",
34028
+ "audio/mp4": "m4a",
34029
+ "audio/wav": "wav",
34030
+ "audio/ogg": "ogg",
34031
+ "application/pdf": "pdf",
34032
+ "text/plain": "txt"
34033
+ };
34034
+ const mapped = directMap[normalized];
34035
+ if (mapped)
34036
+ return mapped;
34037
+ const [, subtype] = normalized.split("/", 2);
34038
+ return subtype?.split("+", 1)[0] || undefined;
34039
+ }
34040
+ function createInlineTypingCallbacks(params) {
34041
+ const keepaliveIntervalMs = params.keepaliveIntervalMs ?? 3000;
34042
+ const maxConsecutiveFailures = Math.max(1, params.maxConsecutiveFailures ?? 2);
34043
+ const maxDurationMs = params.maxDurationMs ?? 60000;
34044
+ let closed = false;
34045
+ let stopSent = false;
34046
+ let consecutiveFailures = 0;
34047
+ let keepaliveTimer;
34048
+ let ttlTimer;
34049
+ const clearTimers = () => {
34050
+ if (keepaliveTimer) {
34051
+ clearInterval(keepaliveTimer);
34052
+ keepaliveTimer = undefined;
34053
+ }
34054
+ if (ttlTimer) {
34055
+ clearTimeout(ttlTimer);
34056
+ ttlTimer = undefined;
34057
+ }
34058
+ };
34059
+ const fireStop = () => {
34060
+ closed = true;
34061
+ clearTimers();
34062
+ if (!params.stop || stopSent) {
34063
+ return;
34064
+ }
34065
+ stopSent = true;
34066
+ params.stop().catch((err) => (params.onStopError ?? params.onStartError)(err));
34067
+ };
34068
+ const fireStart = async () => {
34069
+ if (closed)
34070
+ return;
34071
+ try {
34072
+ await params.start();
34073
+ consecutiveFailures = 0;
34074
+ } catch (err) {
34075
+ consecutiveFailures += 1;
34076
+ params.onStartError(err);
34077
+ if (consecutiveFailures >= maxConsecutiveFailures) {
34078
+ fireStop();
34079
+ }
34080
+ }
34081
+ };
34082
+ return {
34083
+ onReplyStart: async () => {
34084
+ if (closed)
34085
+ return;
34086
+ stopSent = false;
34087
+ consecutiveFailures = 0;
34088
+ clearTimers();
34089
+ await fireStart();
34090
+ if (closed)
34091
+ return;
34092
+ keepaliveTimer = setInterval(() => {
34093
+ fireStart();
34094
+ }, keepaliveIntervalMs);
34095
+ if (maxDurationMs > 0) {
34096
+ ttlTimer = setTimeout(() => {
34097
+ fireStop();
34098
+ }, maxDurationMs);
34099
+ }
34100
+ },
34101
+ onIdle: fireStop,
34102
+ onCleanup: fireStop
34103
+ };
34104
+ }
34105
+ async function createChannelReplyPipelineCompat(params) {
34106
+ try {
34107
+ const sdk = await import("openclaw/plugin-sdk/channel-reply-pipeline");
34108
+ return sdk.createChannelReplyPipeline(params);
34109
+ } catch {
34110
+ return {
34111
+ onModelSelected: () => {},
34112
+ ...params.typingCallbacks ? { typingCallbacks: params.typingCallbacks } : params.typing ? { typingCallbacks: createInlineTypingCallbacks(params.typing) } : {}
34113
+ };
34114
+ }
34115
+ }
34116
+ async function loadNativeCommandHelpersCompat() {
34117
+ try {
34118
+ const sdk = await import("openclaw/plugin-sdk/command-auth");
34119
+ const listNativeCommandSpecsForConfig = typeof sdk.listNativeCommandSpecsForConfig === "function" ? sdk.listNativeCommandSpecsForConfig : null;
34120
+ const listSkillCommandsForAgents = typeof sdk.listSkillCommandsForAgents === "function" ? sdk.listSkillCommandsForAgents : null;
34121
+ if (!listNativeCommandSpecsForConfig || !listSkillCommandsForAgents) {
34122
+ throw new Error("command-auth helpers unavailable");
34123
+ }
34124
+ return {
34125
+ available: true,
34126
+ listNativeCommandSpecsForConfig,
34127
+ listSkillCommandsForAgents
34128
+ };
34129
+ } catch {
34130
+ return {
34131
+ available: false,
34132
+ listNativeCommandSpecsForConfig: () => [],
34133
+ listSkillCommandsForAgents: () => []
34134
+ };
34135
+ }
34136
+ }
34137
+ async function loadPluginCommandSpecsCompat(provider) {
34138
+ try {
34139
+ const sdk = await import("openclaw/plugin-sdk/plugin-runtime");
34140
+ if (typeof sdk.getPluginCommandSpecs !== "function") {
34141
+ throw new Error("plugin runtime command helper unavailable");
34142
+ }
34143
+ return {
34144
+ available: true,
34145
+ specs: sdk.getPluginCommandSpecs(provider)
34146
+ };
34147
+ } catch {
34148
+ return {
34149
+ available: false,
34150
+ specs: []
34151
+ };
34152
+ }
34153
+ }
33697
34154
 
33698
34155
  // src/inline/message-formatting.ts
33699
34156
  var INLINE_FORMATTING_NOTE = "Inline formatting note: prefer bullet lists over markdown tables. If a table is necessary, render it inside a fenced code block. Do not wrap bare URLs in inline code or backticks. Use plain URLs or markdown links. Use inline code only for actual code, commands, file paths, env vars, or identifiers.";
@@ -33720,9 +34177,8 @@ function sanitizeInlineOutgoingText(text) {
33720
34177
  }
33721
34178
 
33722
34179
  // src/inline/policy.ts
33723
- import { normalizeAccountId as normalizePluginAccountId } from "openclaw/plugin-sdk";
33724
34180
  function normalizeAccountId2(raw) {
33725
- return normalizePluginAccountId(raw);
34181
+ return normalizeAccountId(raw);
33726
34182
  }
33727
34183
  function resolveInlineGroups(cfg, accountId) {
33728
34184
  const inline = cfg.channels?.inline;
@@ -33840,19 +34296,12 @@ function getInlineRuntime() {
33840
34296
 
33841
34297
  // src/inline/media.ts
33842
34298
  import path from "node:path";
33843
- import {
33844
- detectMime,
33845
- extensionForMime,
33846
- loadWebMedia,
33847
- resolveChannelMediaMaxBytes
33848
- } from "openclaw/plugin-sdk";
33849
34299
  var DEFAULT_MEDIA_MAX_MB = 300;
33850
34300
  var SUPPORTED_INLINE_PHOTO_MIME = new Set(["image/jpeg", "image/png", "image/gif"]);
33851
34301
  var SUPPORTED_INLINE_VIDEO_MIME = new Set(["video/mp4"]);
33852
34302
  var DEFAULT_VIDEO_WIDTH = 1280;
33853
34303
  var DEFAULT_VIDEO_HEIGHT = 720;
33854
34304
  var DEFAULT_VIDEO_DURATION = 1;
33855
- var loadWebMediaCompat = loadWebMedia;
33856
34305
  function looksLikeLocalMediaSource(mediaUrl) {
33857
34306
  return !/^https?:\/\//i.test(mediaUrl.trim());
33858
34307
  }
@@ -33895,7 +34344,7 @@ function ensureUploadFileName(params) {
33895
34344
  if (ext)
33896
34345
  return baseName;
33897
34346
  }
33898
- const inferredExt = params.ext ?? extensionForMime(params.mime) ?? undefined;
34347
+ const inferredExt = params.ext ?? extensionForMimeCompat(params.mime) ?? undefined;
33899
34348
  const fallbackExt = inferredExt ?? (params.uploadType === "photo" ? "jpg" : params.uploadType === "video" ? "mp4" : "bin");
33900
34349
  return `attachment.${fallbackExt}`;
33901
34350
  }
@@ -33973,13 +34422,15 @@ async function uploadInlineMediaFromUrl(params) {
33973
34422
  cfg: params.cfg,
33974
34423
  accountId: params.accountId ?? null
33975
34424
  });
34425
+ const runtimeMedia = getInlineRuntime().media;
34426
+ const loadWebMediaCompat = runtimeMedia.loadWebMedia;
33976
34427
  let loaded;
33977
34428
  let detectedMime;
33978
34429
  let uploadType;
33979
34430
  let fileName;
33980
34431
  try {
33981
34432
  try {
33982
- loaded = await loadWebMedia(params.mediaUrl, maxBytes);
34433
+ loaded = await runtimeMedia.loadWebMedia(params.mediaUrl, maxBytes);
33983
34434
  } catch (error48) {
33984
34435
  const message = String(error48);
33985
34436
  const deniedLocalPath = /not under an allowed directory/i.test(message);
@@ -33993,7 +34444,7 @@ async function uploadInlineMediaFromUrl(params) {
33993
34444
  if (!loaded) {
33994
34445
  throw new Error("inline media upload: media load returned no data");
33995
34446
  }
33996
- detectedMime = normalizeMime(loaded.contentType ?? await detectMime({
34447
+ detectedMime = normalizeMime(loaded.contentType ?? await runtimeMedia.detectMime({
33997
34448
  buffer: loaded.buffer,
33998
34449
  ...loaded.fileName ? { filePath: loaded.fileName } : {}
33999
34450
  }));
@@ -34583,7 +35034,6 @@ function resolveInlineCompatNativeCommandMenu(commandBody) {
34583
35034
 
34584
35035
  // src/inline/monitor.ts
34585
35036
  var CHANNEL_ID = "inline";
34586
- var DEFAULT_GROUP_HISTORY_LIMIT = 12;
34587
35037
  var DEFAULT_DM_HISTORY_LIMIT = 6;
34588
35038
  var HISTORY_LINE_MAX_CHARS = 280;
34589
35039
  var BOT_MESSAGE_CACHE_LIMIT = 500;
@@ -34939,12 +35389,46 @@ function resolveHistorySenderLabel(params) {
34939
35389
  }
34940
35390
  function resolveHistoryLimit(params) {
34941
35391
  if (params.isGroup) {
34942
- return params.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT;
35392
+ return Math.max(0, params.historyLimit ?? params.cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT);
35393
+ }
35394
+ return Math.max(0, params.dmHistoryLimit ?? params.historyLimit ?? DEFAULT_DM_HISTORY_LIMIT);
35395
+ }
35396
+ function historyEntryDedupeKey(entry) {
35397
+ if (entry.messageId)
35398
+ return `id:${entry.messageId}`;
35399
+ return `ts:${entry.timestamp ?? "unknown"}:${entry.sender}:${entry.body}`;
35400
+ }
35401
+ function mergeInboundHistoryEntries(params) {
35402
+ if (params.limit <= 0)
35403
+ return [];
35404
+ const deduped = [];
35405
+ const seen = new Set;
35406
+ for (const entry of [...params.historyContextEntries, ...params.pendingEntries]) {
35407
+ const key = historyEntryDedupeKey(entry);
35408
+ if (seen.has(key))
35409
+ continue;
35410
+ seen.add(key);
35411
+ deduped.push(entry);
34943
35412
  }
34944
- return params.dmHistoryLimit ?? params.historyLimit ?? DEFAULT_DM_HISTORY_LIMIT;
35413
+ return deduped.slice(-params.limit).map((entry) => ({
35414
+ sender: entry.sender,
35415
+ body: entry.body,
35416
+ ...entry.timestamp != null ? { timestamp: entry.timestamp } : {}
35417
+ }));
35418
+ }
35419
+ function buildInlineBodyForAgent(params) {
35420
+ return [
35421
+ params.rawBody,
35422
+ params.currentAttachmentText && params.currentAttachmentText !== params.rawBody ? `Current media/attachments:
35423
+ ${params.currentAttachmentText}` : null,
35424
+ params.currentEntityText ? `Current message entities:
35425
+ ${params.currentEntityText}` : null
35426
+ ].filter(Boolean).join(`
35427
+
35428
+ `) || params.rawBody;
34945
35429
  }
34946
35430
  function resolveInlineMediaMaxBytes(params) {
34947
- return resolveChannelMediaMaxBytes2({
35431
+ return resolveChannelMediaMaxBytes({
34948
35432
  cfg: params.cfg,
34949
35433
  accountId: params.account.accountId,
34950
35434
  resolveChannelLimitMb: ({ accountId }) => {
@@ -35035,7 +35519,7 @@ async function resolveInlineInboundMedia(params) {
35035
35519
  }
35036
35520
  return out;
35037
35521
  }
35038
- async function buildHistoryContext(params) {
35522
+ async function buildHistoryContext2(params) {
35039
35523
  const cachedReplyToBot = params.replyToMsgId != null && hasBotMessageId(params.botMessageIdsByChat, params.chatId, params.replyToMsgId);
35040
35524
  let repliedToBot = cachedReplyToBot;
35041
35525
  let replyToSenderId = null;
@@ -35043,6 +35527,7 @@ async function buildHistoryContext(params) {
35043
35527
  const lines = [];
35044
35528
  const attachmentLines = [];
35045
35529
  const entityLines = [];
35530
+ const inboundHistory = [];
35046
35531
  if (params.historyLimit > 0) {
35047
35532
  const messages = await loadChatHistoryMessages({
35048
35533
  client: params.client,
@@ -35079,6 +35564,12 @@ async function buildHistoryContext(params) {
35079
35564
  meId: params.meId,
35080
35565
  senderProfilesById: params.senderProfilesById
35081
35566
  });
35567
+ inboundHistory.push({
35568
+ sender: label,
35569
+ body: text,
35570
+ ...item.date != null ? { timestamp: Number(item.date) * 1000 } : {},
35571
+ messageId: String(item.id)
35572
+ });
35082
35573
  const replySuffix = item.replyToMsgId != null ? ` ->${String(item.replyToMsgId)}` : "";
35083
35574
  lines.push(`#${String(item.id)}${replySuffix} ${label}: ${text}`);
35084
35575
  const attachmentText = normalizeHistoryText(content.attachmentText);
@@ -35115,6 +35606,7 @@ async function buildHistoryContext(params) {
35115
35606
  `) : null,
35116
35607
  entityText: entityLines.length ? entityLines.slice(-ATTACHMENT_CONTEXT_LIMIT).join(`
35117
35608
  `) : null,
35609
+ inboundHistory,
35118
35610
  repliedToBot,
35119
35611
  replyToSenderId
35120
35612
  };
@@ -35129,6 +35621,7 @@ ${attachmentLines.slice(-ATTACHMENT_CONTEXT_LIMIT).join(`
35129
35621
  entityText: entityLines.length ? `Recent message entities:
35130
35622
  ${entityLines.slice(-ATTACHMENT_CONTEXT_LIMIT).join(`
35131
35623
  `)}` : null,
35624
+ inboundHistory,
35132
35625
  repliedToBot,
35133
35626
  replyToSenderId
35134
35627
  };
@@ -35477,7 +35970,7 @@ ${JSON.stringify(payload)}`;
35477
35970
  }
35478
35971
  }
35479
35972
  }
35480
- if (commandGate.shouldBlock) {
35973
+ if (isGroup && commandGate.shouldBlock) {
35481
35974
  logInboundDrop({
35482
35975
  log: (m) => runtime2.log?.(m),
35483
35976
  channel: CHANNEL_ID,
@@ -35506,11 +35999,12 @@ ${JSON.stringify(payload)}`;
35506
35999
  const groupHistoryKey = isGroup ? route.sessionKey : null;
35507
36000
  const pendingHistorySender = senderUsername ? `@${senderUsername}` : senderName ?? `user:${senderId}`;
35508
36001
  const historyLimit = resolveHistoryLimit({
36002
+ cfg,
35509
36003
  isGroup,
35510
36004
  historyLimit: account.config.historyLimit,
35511
36005
  dmHistoryLimit: account.config.dmHistoryLimit
35512
36006
  });
35513
- const historyContext = await buildHistoryContext({
36007
+ const historyContext = await buildHistoryContext2({
35514
36008
  client,
35515
36009
  chatId,
35516
36010
  currentMessageId: msg.id,
@@ -35521,7 +36015,14 @@ ${JSON.stringify(payload)}`;
35521
36015
  botMessageIdsByChat
35522
36016
  }).catch((err) => {
35523
36017
  statusSink?.({ lastError: `getChatHistory failed: ${String(err)}` });
35524
- return { historyText: null, attachmentText: null, entityText: null, repliedToBot: false, replyToSenderId: null };
36018
+ return {
36019
+ historyText: null,
36020
+ attachmentText: null,
36021
+ entityText: null,
36022
+ inboundHistory: [],
36023
+ repliedToBot: false,
36024
+ replyToSenderId: null
36025
+ };
35525
36026
  });
35526
36027
  const implicitMention = (reactionEvent != null || callbackActionEvent != null) && isGroup || isGroup && (account.config.replyToBotWithoutMention ?? false) && msg.replyToMsgId != null && historyContext.repliedToBot;
35527
36028
  const requireMention = isGroup ? resolveInlineGroupRequireMention({
@@ -35630,6 +36131,16 @@ ${currentEntityText}` : null
35630
36131
  })
35631
36132
  });
35632
36133
  }
36134
+ const inboundHistory = isGroup && groupHistoryKey ? mergeInboundHistoryEntries({
36135
+ historyContextEntries: historyContext.inboundHistory,
36136
+ pendingEntries: groupPendingHistories.get(groupHistoryKey) ?? [],
36137
+ limit: historyLimit
36138
+ }) : [];
36139
+ const bodyForAgent = buildInlineBodyForAgent({
36140
+ rawBody,
36141
+ currentAttachmentText,
36142
+ currentEntityText
36143
+ });
35633
36144
  const effectiveSurface = shouldUseTelegramSurfaceForModelCommands(normalizedCommandBody) ? "telegram" : CHANNEL_ID;
35634
36145
  const systemPrompt = resolveInlineSystemPrompt({
35635
36146
  account,
@@ -35637,6 +36148,8 @@ ${currentEntityText}` : null
35637
36148
  });
35638
36149
  const ctxPayload = core3.channel.reply.finalizeInboundContext({
35639
36150
  Body: body,
36151
+ BodyForAgent: bodyForAgent,
36152
+ ...isGroup ? { InboundHistory: inboundHistory } : {},
35640
36153
  RawBody: rawBody,
35641
36154
  CommandBody: normalizedCommandBody,
35642
36155
  From: isGroup ? `inline:chat:${String(chatId)}` : `inline:${senderId}`,
@@ -35683,20 +36196,27 @@ ${currentEntityText}` : null
35683
36196
  } : {},
35684
36197
  onRecordError: (err) => runtime2.error?.(`inline: failed updating session meta: ${String(err)}`)
35685
36198
  });
35686
- const prefixConfig = typeof createReplyPrefixOptions === "function" ? createReplyPrefixOptions({
36199
+ const replyPipeline = await createChannelReplyPipelineCompat({
35687
36200
  cfg,
35688
36201
  agentId: route.agentId,
35689
36202
  channel: CHANNEL_ID,
35690
- accountId: account.accountId
35691
- }) : {};
35692
- const onModelSelected = typeof prefixConfig.onModelSelected === "function" ? prefixConfig.onModelSelected : undefined;
35693
- const { onModelSelected: _ignoredOnModelSelected, ...prefixOptions } = prefixConfig;
35694
- const typingCallbacks = typeof createTypingCallbacks === "function" ? createTypingCallbacks({
35695
- start: () => client.sendTyping({ chatId, typing: true }),
35696
- stop: () => client.sendTyping({ chatId, typing: false }),
35697
- onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
35698
- onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
35699
- }) : {};
36203
+ accountId: account.accountId,
36204
+ typing: {
36205
+ start: () => client.sendTyping({ chatId, typing: true }),
36206
+ stop: () => client.sendTyping({ chatId, typing: false }),
36207
+ onStartError: (err) => runtime2.error?.(`inline typing start failed: ${String(err)}`),
36208
+ onStopError: (err) => runtime2.error?.(`inline typing stop failed: ${String(err)}`)
36209
+ }
36210
+ });
36211
+ const onModelSelected = replyPipeline.onModelSelected;
36212
+ const typingCallbacks = replyPipeline.typingCallbacks;
36213
+ const prefixOptions = {
36214
+ ...replyPipeline.responsePrefix !== undefined ? { responsePrefix: replyPipeline.responsePrefix } : {},
36215
+ ...replyPipeline.enableSlackInteractiveReplies !== undefined ? { enableSlackInteractiveReplies: replyPipeline.enableSlackInteractiveReplies } : {},
36216
+ ...replyPipeline.responsePrefixContextProvider ? {
36217
+ responsePrefixContextProvider: replyPipeline.responsePrefixContextProvider
36218
+ } : {}
36219
+ };
35700
36220
  const streamViaEditMessage = account.config.streamViaEditMessage === true && !shouldEditCallbackTargetInPlace;
35701
36221
  const defaultReplyToMsgId = isGroup && msg.replyToMsgId != null ? msg.id : undefined;
35702
36222
  const disableBlockStreaming = streamViaEditMessage ? true : typeof account.config.blockStreaming === "boolean" ? !account.config.blockStreaming : undefined;
@@ -35774,7 +36294,7 @@ ${currentEntityText}` : null
35774
36294
  cfg,
35775
36295
  dispatcherOptions: {
35776
36296
  ...prefixOptions,
35777
- ...typingCallbacks,
36297
+ ...typingCallbacks ? { typingCallbacks } : {},
35778
36298
  deliver: async (payload) => {
35779
36299
  const rawText = payload.text ?? "";
35780
36300
  const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
@@ -35935,15 +36455,6 @@ Attachment: ${mediaUrl}` : `Attachment: ${mediaUrl}`;
35935
36455
  return { stop, done: loop.catch(() => {}) };
35936
36456
  }
35937
36457
 
35938
- // src/inline/actions.ts
35939
- import {
35940
- createActionGate,
35941
- jsonResult,
35942
- readReactionParams,
35943
- readNumberParam,
35944
- readStringParam
35945
- } from "openclaw/plugin-sdk";
35946
-
35947
36458
  // src/inline/space-members.ts
35948
36459
  function buildInlineUserDisplayName(user) {
35949
36460
  const explicit = [user.firstName?.trim(), user.lastName?.trim()].filter(Boolean).join(" ");
@@ -36575,6 +37086,50 @@ function listAllActions() {
36575
37086
  }
36576
37087
  return Array.from(out);
36577
37088
  }
37089
+ function listEnabledInlineActions(cfg) {
37090
+ const account = resolveInlineAccount({ cfg, accountId: null });
37091
+ if (!account.enabled || !account.configured)
37092
+ return [];
37093
+ const gate = createActionGate(account.config.actions ?? {});
37094
+ const actions = new Set;
37095
+ for (const group of ACTION_GROUPS) {
37096
+ if (!gate(group.key, group.defaultEnabled))
37097
+ continue;
37098
+ for (const action of group.actions) {
37099
+ actions.add(action);
37100
+ }
37101
+ }
37102
+ return Array.from(actions);
37103
+ }
37104
+ function supportsInlineMessageButtons(actions) {
37105
+ return actions.some((action) => action === "send" || action === "reply" || action === "thread-reply" || action === "edit");
37106
+ }
37107
+ function describeInlineMessageTool({
37108
+ cfg
37109
+ }) {
37110
+ const actions = listEnabledInlineActions(cfg);
37111
+ if (actions.length === 0) {
37112
+ return {
37113
+ actions: [],
37114
+ capabilities: [],
37115
+ schema: null
37116
+ };
37117
+ }
37118
+ const buttonsEnabled = supportsInlineMessageButtons(actions);
37119
+ const capabilities = buttonsEnabled ? ["interactive", "buttons"] : [];
37120
+ const schema = buttonsEnabled ? [
37121
+ {
37122
+ properties: {
37123
+ buttons: createMessageToolButtonsSchemaCompat()
37124
+ }
37125
+ }
37126
+ ] : [];
37127
+ return {
37128
+ actions,
37129
+ capabilities,
37130
+ schema
37131
+ };
37132
+ }
36578
37133
  function isActionEnabled(params) {
36579
37134
  const key = ACTION_TO_GATE_KEY.get(params.action);
36580
37135
  if (!key)
@@ -36590,21 +37145,10 @@ function isActionEnabled(params) {
36590
37145
  return gate(key, group.defaultEnabled);
36591
37146
  }
36592
37147
  var inlineMessageActions = {
36593
- listActions: ({ cfg }) => {
36594
- const account = resolveInlineAccount({ cfg, accountId: null });
36595
- if (!account.enabled || !account.configured)
36596
- return [];
36597
- const gate = createActionGate(account.config.actions ?? {});
36598
- const actions = new Set;
36599
- for (const group of ACTION_GROUPS) {
36600
- if (!gate(group.key, group.defaultEnabled))
36601
- continue;
36602
- for (const action of group.actions) {
36603
- actions.add(action);
36604
- }
36605
- }
36606
- return Array.from(actions);
36607
- },
37148
+ describeMessageTool: describeInlineMessageTool,
37149
+ listActions: ({ cfg }) => listEnabledInlineActions(cfg),
37150
+ supportsButtons: ({ cfg }) => supportsInlineMessageButtons(listEnabledInlineActions(cfg)),
37151
+ supportsCards: () => false,
36608
37152
  supportsAction: ({ action }) => SUPPORTED_ACTIONS.includes(action),
36609
37153
  extractToolSend: ({ args }) => {
36610
37154
  const action = typeof args.action === "string" ? args.action.trim() : "";
@@ -37809,7 +38353,7 @@ var inlineChannelPlugin = {
37809
38353
  },
37810
38354
  security: {
37811
38355
  resolveDmPolicy: ({ cfg, accountId, account }) => {
37812
- const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID2;
38356
+ const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
37813
38357
  const useAccountPath = Boolean(cfg.channels?.inline?.accounts?.[resolvedAccountId]);
37814
38358
  const basePath = useAccountPath ? `channels.inline.accounts.${resolvedAccountId}.` : "channels.inline.";
37815
38359
  return {
@@ -38074,7 +38618,7 @@ var inlineChannelPlugin = {
38074
38618
  },
38075
38619
  status: {
38076
38620
  defaultRuntime: {
38077
- accountId: DEFAULT_ACCOUNT_ID2,
38621
+ accountId: DEFAULT_ACCOUNT_ID,
38078
38622
  running: false,
38079
38623
  lastStartAt: null,
38080
38624
  lastStopAt: null,
@@ -38159,9 +38703,6 @@ var inlineChannelPlugin = {
38159
38703
  };
38160
38704
 
38161
38705
  // src/inline/message-tools.ts
38162
- import {
38163
- jsonResult as jsonResult2
38164
- } from "openclaw/plugin-sdk";
38165
38706
  var InlineNudgeToolParameters = {
38166
38707
  type: "object",
38167
38708
  additionalProperties: false,
@@ -38473,7 +39014,7 @@ function createInlineNudgeTool(ctx) {
38473
39014
  }
38474
39015
  });
38475
39016
  const messageId = result.oneofKind === "sendMessage" ? extractFirstMessageId2(result.sendMessage.updates) : null;
38476
- return jsonResult2({
39017
+ return jsonResult({
38477
39018
  ok: true,
38478
39019
  accountId: resolvedAccountId,
38479
39020
  nudged: true,
@@ -38527,7 +39068,7 @@ function createInlineForwardTool(ctx) {
38527
39068
  }
38528
39069
  });
38529
39070
  const forwardedMessageId = result.oneofKind === "forwardMessages" ? extractFirstMessageId2(result.forwardMessages.updates) : null;
38530
- return jsonResult2({
39071
+ return jsonResult({
38531
39072
  ok: true,
38532
39073
  accountId: resolvedAccountId,
38533
39074
  from: source.normalized,
@@ -38613,7 +39154,7 @@ function filterSpaceMembers(params) {
38613
39154
  target: `user:${member.userId}`
38614
39155
  }));
38615
39156
  }
38616
- function jsonResult3(payload) {
39157
+ function jsonResult2(payload) {
38617
39158
  return {
38618
39159
  content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
38619
39160
  details: payload
@@ -38664,7 +39205,7 @@ function createInlineMembersTool(ctx) {
38664
39205
  userId,
38665
39206
  limit
38666
39207
  });
38667
- return jsonResult3({
39208
+ return jsonResult2({
38668
39209
  ok: true,
38669
39210
  accountId: resolvedAccountId,
38670
39211
  spaceId: String(spaceId),
@@ -38680,10 +39221,6 @@ function createInlineMembersTool(ctx) {
38680
39221
  }
38681
39222
 
38682
39223
  // src/inline/profile-tool.ts
38683
- import {
38684
- detectMime as detectMime2,
38685
- loadWebMedia as loadWebMedia2
38686
- } from "openclaw/plugin-sdk";
38687
39224
  var InlineProfileToolParameters = {
38688
39225
  type: "object",
38689
39226
  additionalProperties: false,
@@ -38710,7 +39247,7 @@ var InlineProfileToolParameters = {
38710
39247
  }
38711
39248
  }
38712
39249
  };
38713
- function jsonResult4(payload) {
39250
+ function jsonResult3(payload) {
38714
39251
  return {
38715
39252
  content: [
38716
39253
  {
@@ -38747,9 +39284,24 @@ function readTrimmedString(value) {
38747
39284
  function resolvePhotoSource(args) {
38748
39285
  return readTrimmedString(args.photoPath) ?? readTrimmedString(args.photoUrl);
38749
39286
  }
39287
+ function looksLikeLocalMediaSource2(mediaUrl) {
39288
+ return !/^https?:\/\//i.test(mediaUrl.trim());
39289
+ }
38750
39290
  async function uploadProfilePhoto(client, rawSource) {
38751
- const loaded = await loadWebMedia2(rawSource);
38752
- const contentType = loaded.contentType ?? await detectMime2({
39291
+ const runtimeMedia = getInlineRuntime().media;
39292
+ const loadWebMediaCompat = runtimeMedia.loadWebMedia;
39293
+ let loaded;
39294
+ try {
39295
+ loaded = await runtimeMedia.loadWebMedia(rawSource);
39296
+ } catch (error48) {
39297
+ const message = String(error48);
39298
+ const deniedLocalPath = /not under an allowed directory/i.test(message);
39299
+ if (!deniedLocalPath || !looksLikeLocalMediaSource2(rawSource)) {
39300
+ throw error48;
39301
+ }
39302
+ loaded = await loadWebMediaCompat(rawSource, undefined, { localRoots: "any" });
39303
+ }
39304
+ const contentType = loaded.contentType ?? await runtimeMedia.detectMime({
38753
39305
  buffer: loaded.buffer,
38754
39306
  ...loaded.fileName ? { filePath: loaded.fileName } : {}
38755
39307
  }) ?? undefined;
@@ -38799,7 +39351,7 @@ function createInlineProfileTool(ctx) {
38799
39351
  if (result.oneofKind !== "updateBotProfile") {
38800
39352
  throw new Error(`inline_update_profile: expected updateBotProfile result, got ${String(result.oneofKind)}`);
38801
39353
  }
38802
- return jsonResult4({
39354
+ return jsonResult3({
38803
39355
  ok: true,
38804
39356
  accountId: resolvedAccountId,
38805
39357
  botUserId: String(me.userId),
@@ -38815,9 +39367,6 @@ function createInlineProfileTool(ctx) {
38815
39367
  };
38816
39368
  }
38817
39369
 
38818
- // src/inline/bot-commands-tool.ts
38819
- import { jsonResult as jsonResult5 } from "openclaw/plugin-sdk";
38820
-
38821
39370
  // src/inline/bot-commands-api.ts
38822
39371
  function normalizeInlineBotBaseUrl(baseUrl) {
38823
39372
  return baseUrl.replace(/\/+$/, "");
@@ -38988,7 +39537,7 @@ function createInlineBotCommandsTool(ctx) {
38988
39537
  method: "GET"
38989
39538
  });
38990
39539
  const commands = Array.isArray(result.commands) ? result.commands : [];
38991
- return jsonResult5({
39540
+ return jsonResult({
38992
39541
  ok: true,
38993
39542
  action,
38994
39543
  accountId: account.accountId,
@@ -39005,7 +39554,7 @@ function createInlineBotCommandsTool(ctx) {
39005
39554
  method: "POST",
39006
39555
  body: { commands }
39007
39556
  });
39008
- return jsonResult5({
39557
+ return jsonResult({
39009
39558
  ok: true,
39010
39559
  action,
39011
39560
  accountId: account.accountId,
@@ -39019,7 +39568,7 @@ function createInlineBotCommandsTool(ctx) {
39019
39568
  methodName: "deleteMyCommands",
39020
39569
  method: "POST"
39021
39570
  });
39022
- return jsonResult5({
39571
+ return jsonResult({
39023
39572
  ok: true,
39024
39573
  action,
39025
39574
  accountId: account.accountId
@@ -39029,7 +39578,6 @@ function createInlineBotCommandsTool(ctx) {
39029
39578
  }
39030
39579
 
39031
39580
  // src/inline/bot-commands-sync.ts
39032
- import * as pluginSdk from "openclaw/plugin-sdk";
39033
39581
  var INLINE_BASE_NATIVE_COMMANDS = [
39034
39582
  { command: "help", description: "Show available commands." },
39035
39583
  { command: "commands", description: "List all slash commands." },
@@ -39059,12 +39607,15 @@ var INLINE_BASE_NATIVE_COMMANDS = [
39059
39607
  ];
39060
39608
  var INLINE_COMMAND_NAME_RE = /^[a-z0-9_]{1,32}$/;
39061
39609
  var INLINE_COMMAND_LIMIT = 100;
39062
- function getPluginSdkFunction(name) {
39063
- const raw = pluginSdk[name];
39064
- if (typeof raw !== "function")
39065
- return null;
39066
- return raw;
39067
- }
39610
+ var FALLBACK_NATIVE_COMMAND_HELPERS = {
39611
+ available: false,
39612
+ listNativeCommandSpecsForConfig: () => [],
39613
+ listSkillCommandsForAgents: () => []
39614
+ };
39615
+ var FALLBACK_PLUGIN_COMMAND_SPECS = {
39616
+ available: false,
39617
+ specs: []
39618
+ };
39068
39619
  function normalizeDynamicCommandName(raw) {
39069
39620
  const trimmed = raw.trim().toLowerCase();
39070
39621
  const withoutSlash = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
@@ -39090,41 +39641,42 @@ function shouldSyncInlineNativeSkills(cfg) {
39090
39641
  const effective = inlineNativeSkillsSetting ?? cfg.commands?.nativeSkills ?? "auto";
39091
39642
  return effective !== false;
39092
39643
  }
39093
- function buildInlineNativeCommandsForConfig(cfg) {
39094
- const listNativeCommandSpecsForConfig = getPluginSdkFunction("listNativeCommandSpecsForConfig");
39095
- const listSkillCommandsForAgents = getPluginSdkFunction("listSkillCommandsForAgents");
39096
- const getPluginCommandSpecs = getPluginSdkFunction("getPluginCommandSpecs");
39097
- if (!listNativeCommandSpecsForConfig) {
39098
- const commands2 = [...INLINE_BASE_NATIVE_COMMANDS];
39099
- if (cfg.commands?.config === true) {
39100
- commands2.push({ command: "config", description: "Show or set config values." });
39101
- }
39102
- if (cfg.commands?.debug === true) {
39103
- commands2.push({ command: "debug", description: "Set runtime debug overrides." });
39104
- }
39105
- return commands2;
39644
+ async function buildInlineNativeCommandsForConfig(params) {
39645
+ const commands = [...INLINE_BASE_NATIVE_COMMANDS];
39646
+ if (params.cfg.commands?.config === true) {
39647
+ commands.push({ command: "config", description: "Show or set config values." });
39648
+ }
39649
+ if (params.cfg.commands?.debug === true) {
39650
+ commands.push({ command: "debug", description: "Set runtime debug overrides." });
39106
39651
  }
39107
- const skillCommands = shouldSyncInlineNativeSkills(cfg) && listSkillCommandsForAgents ? listSkillCommandsForAgents({ cfg }) : [];
39108
- const nativeSpecs = listNativeCommandSpecsForConfig(cfg, { skillCommands });
39109
- const pluginSpecs = getPluginCommandSpecs?.() ?? [];
39110
- const commands = [];
39652
+ const { listNativeCommandSpecsForConfig, listSkillCommandsForAgents } = params.nativeHelpers;
39653
+ const skillCommands = shouldSyncInlineNativeSkills(params.cfg) ? listSkillCommandsForAgents({ cfg: params.cfg }) : [];
39654
+ const nativeSpecs = listNativeCommandSpecsForConfig(params.cfg, { skillCommands });
39655
+ const { specs: pluginSpecs } = params.pluginSpecs;
39111
39656
  const seen = new Set;
39657
+ const resolved = [];
39658
+ for (const base of commands) {
39659
+ appendUniqueCommand(resolved, seen, base.command, base.description);
39660
+ }
39112
39661
  for (const spec of nativeSpecs) {
39113
- appendUniqueCommand(commands, seen, spec.name, spec.description);
39662
+ appendUniqueCommand(resolved, seen, spec.name, spec.description);
39114
39663
  }
39115
39664
  for (const spec of pluginSpecs) {
39116
- appendUniqueCommand(commands, seen, spec.name, spec.description);
39665
+ appendUniqueCommand(resolved, seen, spec.name, spec.description);
39117
39666
  }
39118
- return commands;
39119
- }
39120
- function isSdkNativeCommandSourceAvailable() {
39121
- return Boolean(getPluginSdkFunction("listNativeCommandSpecsForConfig"));
39667
+ return resolved;
39122
39668
  }
39123
39669
  async function syncInlineNativeCommands(params) {
39124
39670
  const accountIds = listInlineAccountIds(params.cfg);
39125
39671
  const nativeEnabled = shouldSyncInlineNativeCommands(params.cfg);
39126
- const usingSdkSource = isSdkNativeCommandSourceAvailable();
39127
- const allCommands = nativeEnabled ? buildInlineNativeCommandsForConfig(params.cfg) : [];
39672
+ const nativeHelpers = nativeEnabled ? await loadNativeCommandHelpersCompat() : FALLBACK_NATIVE_COMMAND_HELPERS;
39673
+ const pluginSpecs = nativeEnabled ? await loadPluginCommandSpecsCompat("inline") : FALLBACK_PLUGIN_COMMAND_SPECS;
39674
+ const usingSdkSource = nativeHelpers.available || pluginSpecs.available;
39675
+ const allCommands = nativeEnabled ? await buildInlineNativeCommandsForConfig({
39676
+ cfg: params.cfg,
39677
+ nativeHelpers,
39678
+ pluginSpecs
39679
+ }) : [];
39128
39680
  const commands = allCommands.slice(0, INLINE_COMMAND_LIMIT);
39129
39681
  if (allCommands.length > INLINE_COMMAND_LIMIT) {
39130
39682
  params.logger?.warn?.(`[inline] native command sync truncating ${allCommands.length} commands to ${INLINE_COMMAND_LIMIT}`);
@@ -39215,5 +39767,5 @@ export {
39215
39767
  src_default as default
39216
39768
  };
39217
39769
 
39218
- //# debugId=ECFAEB3746DF293B64756E2164756E21
39770
+ //# debugId=7535F56BE481336764756E2164756E21
39219
39771
  //# sourceMappingURL=index.js.map