@inline-openclaw/inline 0.0.3
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/README.md +116 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/inline/accounts.d.ts +20 -0
- package/dist/inline/accounts.d.ts.map +1 -0
- package/dist/inline/accounts.js +72 -0
- package/dist/inline/accounts.js.map +1 -0
- package/dist/inline/channel.d.ts +4 -0
- package/dist/inline/channel.d.ts.map +1 -0
- package/dist/inline/channel.js +288 -0
- package/dist/inline/channel.js.map +1 -0
- package/dist/inline/config-schema.d.ts +166 -0
- package/dist/inline/config-schema.d.ts.map +1 -0
- package/dist/inline/config-schema.js +43 -0
- package/dist/inline/config-schema.js.map +1 -0
- package/dist/inline/monitor.d.ts +25 -0
- package/dist/inline/monitor.d.ts.map +1 -0
- package/dist/inline/monitor.js +401 -0
- package/dist/inline/monitor.js.map +1 -0
- package/dist/inline/normalize.d.ts +3 -0
- package/dist/inline/normalize.d.ts.map +1 -0
- package/dist/inline/normalize.js +19 -0
- package/dist/inline/normalize.js.map +1 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +11 -0
- package/dist/runtime.js.map +1 -0
- package/openclaw.plugin.json +11 -0
- package/package.json +67 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const InlineAccountSchemaBase: z.ZodObject<{
|
|
3
|
+
name: z.ZodOptional<z.ZodString>;
|
|
4
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
5
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
6
|
+
token: z.ZodOptional<z.ZodString>;
|
|
7
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
8
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
9
|
+
open: "open";
|
|
10
|
+
disabled: "disabled";
|
|
11
|
+
allowlist: "allowlist";
|
|
12
|
+
pairing: "pairing";
|
|
13
|
+
}>>>;
|
|
14
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
open: "open";
|
|
18
|
+
disabled: "disabled";
|
|
19
|
+
allowlist: "allowlist";
|
|
20
|
+
}>>>;
|
|
21
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
22
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
export declare const InlineRuntimeAccountSchema: z.ZodObject<{
|
|
26
|
+
name: z.ZodOptional<z.ZodString>;
|
|
27
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
28
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
29
|
+
token: z.ZodOptional<z.ZodString>;
|
|
30
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
31
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
open: "open";
|
|
33
|
+
disabled: "disabled";
|
|
34
|
+
allowlist: "allowlist";
|
|
35
|
+
pairing: "pairing";
|
|
36
|
+
}>>>;
|
|
37
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
39
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
40
|
+
open: "open";
|
|
41
|
+
disabled: "disabled";
|
|
42
|
+
allowlist: "allowlist";
|
|
43
|
+
}>>>;
|
|
44
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
45
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
47
|
+
}, z.core.$loose>;
|
|
48
|
+
export declare const InlineAccountSchema: z.ZodObject<{
|
|
49
|
+
name: z.ZodOptional<z.ZodString>;
|
|
50
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
52
|
+
token: z.ZodOptional<z.ZodString>;
|
|
53
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
54
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
55
|
+
open: "open";
|
|
56
|
+
disabled: "disabled";
|
|
57
|
+
allowlist: "allowlist";
|
|
58
|
+
pairing: "pairing";
|
|
59
|
+
}>>>;
|
|
60
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
61
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
62
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
63
|
+
open: "open";
|
|
64
|
+
disabled: "disabled";
|
|
65
|
+
allowlist: "allowlist";
|
|
66
|
+
}>>>;
|
|
67
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
68
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
69
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
70
|
+
}, z.core.$strict>;
|
|
71
|
+
export declare const InlineRuntimeConfigSchema: z.ZodObject<{
|
|
72
|
+
name: z.ZodOptional<z.ZodString>;
|
|
73
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
74
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
75
|
+
token: z.ZodOptional<z.ZodString>;
|
|
76
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
77
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
78
|
+
open: "open";
|
|
79
|
+
disabled: "disabled";
|
|
80
|
+
allowlist: "allowlist";
|
|
81
|
+
pairing: "pairing";
|
|
82
|
+
}>>>;
|
|
83
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
84
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
85
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
86
|
+
open: "open";
|
|
87
|
+
disabled: "disabled";
|
|
88
|
+
allowlist: "allowlist";
|
|
89
|
+
}>>>;
|
|
90
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
91
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
92
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodObject<{
|
|
94
|
+
name: z.ZodOptional<z.ZodString>;
|
|
95
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
96
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
97
|
+
token: z.ZodOptional<z.ZodString>;
|
|
98
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
99
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
100
|
+
open: "open";
|
|
101
|
+
disabled: "disabled";
|
|
102
|
+
allowlist: "allowlist";
|
|
103
|
+
pairing: "pairing";
|
|
104
|
+
}>>>;
|
|
105
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
106
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
107
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
108
|
+
open: "open";
|
|
109
|
+
disabled: "disabled";
|
|
110
|
+
allowlist: "allowlist";
|
|
111
|
+
}>>>;
|
|
112
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
113
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
114
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
115
|
+
}, z.core.$loose>>>>;
|
|
116
|
+
}, z.core.$loose>;
|
|
117
|
+
export declare const InlineConfigSchema: z.ZodObject<{
|
|
118
|
+
name: z.ZodOptional<z.ZodString>;
|
|
119
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
120
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
121
|
+
token: z.ZodOptional<z.ZodString>;
|
|
122
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
123
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
124
|
+
open: "open";
|
|
125
|
+
disabled: "disabled";
|
|
126
|
+
allowlist: "allowlist";
|
|
127
|
+
pairing: "pairing";
|
|
128
|
+
}>>>;
|
|
129
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
130
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
131
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
132
|
+
open: "open";
|
|
133
|
+
disabled: "disabled";
|
|
134
|
+
allowlist: "allowlist";
|
|
135
|
+
}>>>;
|
|
136
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
137
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
138
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
139
|
+
accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodObject<{
|
|
140
|
+
name: z.ZodOptional<z.ZodString>;
|
|
141
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
142
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
143
|
+
token: z.ZodOptional<z.ZodString>;
|
|
144
|
+
tokenFile: z.ZodOptional<z.ZodString>;
|
|
145
|
+
dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
146
|
+
open: "open";
|
|
147
|
+
disabled: "disabled";
|
|
148
|
+
allowlist: "allowlist";
|
|
149
|
+
pairing: "pairing";
|
|
150
|
+
}>>>;
|
|
151
|
+
allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
152
|
+
groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
153
|
+
groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
154
|
+
open: "open";
|
|
155
|
+
disabled: "disabled";
|
|
156
|
+
allowlist: "allowlist";
|
|
157
|
+
}>>>;
|
|
158
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
159
|
+
parseMarkdown: z.ZodOptional<z.ZodBoolean>;
|
|
160
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
161
|
+
}, z.core.$strict>>>>;
|
|
162
|
+
}, z.core.$strict>;
|
|
163
|
+
export type InlineConfig = z.infer<typeof InlineConfigSchema>;
|
|
164
|
+
export type InlineAccountConfig = z.infer<typeof InlineAccountSchema>;
|
|
165
|
+
export type InlineRuntimeConfig = z.infer<typeof InlineRuntimeConfigSchema>;
|
|
166
|
+
//# sourceMappingURL=config-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/inline/config-schema.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;kBAezB,CAAA;AAEX,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;iBAAwC,CAAA;AAE/E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;kBAS9B,CAAA;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEtB,CAAA;AAEhB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAW7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAC7D,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AACrE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DmPolicySchema, GroupPolicySchema, requireOpenAllowFrom, } from "openclaw/plugin-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export const InlineAccountSchemaBase = z
|
|
4
|
+
.object({
|
|
5
|
+
name: z.string().optional(),
|
|
6
|
+
enabled: z.boolean().optional(),
|
|
7
|
+
baseUrl: z.string().optional(),
|
|
8
|
+
token: z.string().optional(),
|
|
9
|
+
tokenFile: z.string().optional(),
|
|
10
|
+
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
|
11
|
+
allowFrom: z.array(z.string()).optional(),
|
|
12
|
+
groupAllowFrom: z.array(z.string()).optional(),
|
|
13
|
+
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
|
14
|
+
requireMention: z.boolean().optional(),
|
|
15
|
+
parseMarkdown: z.boolean().optional(),
|
|
16
|
+
textChunkLimit: z.number().int().positive().optional(),
|
|
17
|
+
})
|
|
18
|
+
.strict();
|
|
19
|
+
export const InlineRuntimeAccountSchema = InlineAccountSchemaBase.passthrough();
|
|
20
|
+
export const InlineAccountSchema = InlineAccountSchemaBase.superRefine((value, ctx) => {
|
|
21
|
+
requireOpenAllowFrom({
|
|
22
|
+
policy: value.dmPolicy,
|
|
23
|
+
...(value.allowFrom ? { allowFrom: value.allowFrom } : {}),
|
|
24
|
+
ctx,
|
|
25
|
+
path: ["allowFrom"],
|
|
26
|
+
message: 'channels.inline.dmPolicy="open" requires channels.inline.allowFrom to include "*"',
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
export const InlineRuntimeConfigSchema = InlineRuntimeAccountSchema.extend({
|
|
30
|
+
accounts: z.record(z.string(), InlineRuntimeAccountSchema.optional()).optional(),
|
|
31
|
+
}).passthrough();
|
|
32
|
+
export const InlineConfigSchema = InlineAccountSchemaBase.extend({
|
|
33
|
+
accounts: z.record(z.string(), InlineAccountSchema.optional()).optional(),
|
|
34
|
+
}).superRefine((value, ctx) => {
|
|
35
|
+
requireOpenAllowFrom({
|
|
36
|
+
policy: value.dmPolicy,
|
|
37
|
+
...(value.allowFrom ? { allowFrom: value.allowFrom } : {}),
|
|
38
|
+
ctx,
|
|
39
|
+
path: ["allowFrom"],
|
|
40
|
+
message: 'channels.inline.dmPolicy="open" requires channels.inline.allowFrom to include "*"',
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=config-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/inline/config-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC;KACrC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,QAAQ,EAAE,cAAc,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACtD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACzC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC9C,WAAW,EAAE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IAC9D,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACtC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACvD,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,0BAA0B,GAAG,uBAAuB,CAAC,WAAW,EAAE,CAAA;AAE/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACpF,oBAAoB,CAAC;QACnB,MAAM,EAAE,KAAK,CAAC,QAAQ;QACtB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG;QACH,IAAI,EAAE,CAAC,WAAW,CAAC;QACnB,OAAO,EACL,mFAAmF;KACtF,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,0BAA0B,CAAC,MAAM,CAAC;IACzE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;CACjF,CAAC,CAAC,WAAW,EAAE,CAAA;AAEhB,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC,MAAM,CAAC;IAC/D,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC1E,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC5B,oBAAoB,CAAC;QACnB,MAAM,EAAE,KAAK,CAAC,QAAQ;QACtB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG;QACH,IAAI,EAAE,CAAC,WAAW,CAAC;QACnB,OAAO,EACL,mFAAmF;KACtF,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type OpenClawConfig, type RuntimeEnv } from "openclaw/plugin-sdk";
|
|
2
|
+
import { type ResolvedInlineAccount } from "./accounts.js";
|
|
3
|
+
type InlineMonitorHandle = {
|
|
4
|
+
stop: () => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
type StatusSink = (patch: {
|
|
7
|
+
lastInboundAt?: number;
|
|
8
|
+
lastOutboundAt?: number;
|
|
9
|
+
lastError?: string;
|
|
10
|
+
}) => void;
|
|
11
|
+
export declare function monitorInlineProvider(params: {
|
|
12
|
+
cfg: OpenClawConfig;
|
|
13
|
+
account: ResolvedInlineAccount;
|
|
14
|
+
runtime: RuntimeEnv;
|
|
15
|
+
abortSignal: AbortSignal;
|
|
16
|
+
log?: {
|
|
17
|
+
info: (msg: string) => void;
|
|
18
|
+
warn: (msg: string) => void;
|
|
19
|
+
error: (msg: string) => void;
|
|
20
|
+
debug?: (msg: string) => void;
|
|
21
|
+
};
|
|
22
|
+
statusSink?: StatusSink;
|
|
23
|
+
}): Promise<InlineMonitorHandle>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/inline/monitor.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAK9E,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B,CAAA;AAED,KAAK,UAAU,GAAG,CAAC,KAAK,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAA;AAwE1G,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,GAAG,EAAE,cAAc,CAAA;IACnB,OAAO,EAAE,qBAAqB,CAAA;IAC9B,OAAO,EAAE,UAAU,CAAA;IACnB,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAA;IAC/H,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuX/B"}
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createReplyPrefixOptions, createTypingCallbacks, logInboundDrop, resolveControlCommandGate, resolveMentionGatingWithBypass, } from "openclaw/plugin-sdk";
|
|
4
|
+
import { InlineSdkClient, JsonFileStateStore, Method } from "@inline-chat/realtime-sdk";
|
|
5
|
+
import { resolveInlineToken } from "./accounts.js";
|
|
6
|
+
import { getInlineRuntime } from "../runtime.js";
|
|
7
|
+
const CHANNEL_ID = "inline";
|
|
8
|
+
function normalizeAllowEntry(raw) {
|
|
9
|
+
return raw.trim().replace(/^inline:/i, "").replace(/^user:/i, "");
|
|
10
|
+
}
|
|
11
|
+
function normalizeAllowlist(entries) {
|
|
12
|
+
return (entries ?? [])
|
|
13
|
+
.map((entry) => normalizeAllowEntry(String(entry)))
|
|
14
|
+
.map((entry) => entry.trim())
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
function allowlistMatch(params) {
|
|
18
|
+
if (params.allowFrom.some((entry) => entry === "*"))
|
|
19
|
+
return true;
|
|
20
|
+
return params.allowFrom.some((entry) => entry === params.senderId);
|
|
21
|
+
}
|
|
22
|
+
async function resolveChatInfo(client, cache, chatId) {
|
|
23
|
+
const existing = cache.get(chatId);
|
|
24
|
+
if (existing)
|
|
25
|
+
return existing;
|
|
26
|
+
const result = await client.getChat({ chatId });
|
|
27
|
+
const peerKind = result.peer?.type.oneofKind;
|
|
28
|
+
const kind = peerKind === "user" ? "direct" : "group";
|
|
29
|
+
const title = result.title?.trim() || null;
|
|
30
|
+
const info = { kind, title };
|
|
31
|
+
cache.set(chatId, info);
|
|
32
|
+
return info;
|
|
33
|
+
}
|
|
34
|
+
function messageText(message) {
|
|
35
|
+
return (message.message ?? "").trim();
|
|
36
|
+
}
|
|
37
|
+
function normalizeInlineUsername(raw) {
|
|
38
|
+
const trimmed = raw?.trim();
|
|
39
|
+
if (!trimmed)
|
|
40
|
+
return undefined;
|
|
41
|
+
return trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
|
|
42
|
+
}
|
|
43
|
+
function buildInlineSenderName(params) {
|
|
44
|
+
const name = [params.firstName, params.lastName].filter(Boolean).join(" ").trim();
|
|
45
|
+
return name || undefined;
|
|
46
|
+
}
|
|
47
|
+
function rewriteNumericMentionsToUsernames(text, senderProfilesById) {
|
|
48
|
+
if (!text.includes("@"))
|
|
49
|
+
return text;
|
|
50
|
+
return text.replace(/(^|[^\w])@([0-9]+)\b/g, (full, prefix, userId) => {
|
|
51
|
+
const username = senderProfilesById.get(userId)?.username;
|
|
52
|
+
if (!username)
|
|
53
|
+
return full;
|
|
54
|
+
return `${prefix}@${username}`;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export async function monitorInlineProvider(params) {
|
|
58
|
+
const { cfg, account, runtime, abortSignal, log, statusSink } = params;
|
|
59
|
+
const core = getInlineRuntime();
|
|
60
|
+
if (!account.configured || !account.baseUrl) {
|
|
61
|
+
throw new Error(`Inline not configured for account "${account.accountId}" (missing baseUrl or token)`);
|
|
62
|
+
}
|
|
63
|
+
const token = await resolveInlineToken(account);
|
|
64
|
+
const stateDir = core.state.resolveStateDir();
|
|
65
|
+
const statePath = path.join(stateDir, "channels", "inline", `${account.accountId}.json`);
|
|
66
|
+
await mkdir(path.dirname(statePath), { recursive: true });
|
|
67
|
+
const sdkLog = {
|
|
68
|
+
debug: (msg) => log?.debug?.(msg),
|
|
69
|
+
info: (msg) => log?.info(msg),
|
|
70
|
+
warn: (msg) => log?.warn(msg),
|
|
71
|
+
error: (msg) => log?.error(msg),
|
|
72
|
+
};
|
|
73
|
+
const client = new InlineSdkClient({
|
|
74
|
+
baseUrl: account.baseUrl,
|
|
75
|
+
token,
|
|
76
|
+
logger: sdkLog,
|
|
77
|
+
state: new JsonFileStateStore(statePath),
|
|
78
|
+
});
|
|
79
|
+
await client.connect(abortSignal);
|
|
80
|
+
const me = await client.getMe();
|
|
81
|
+
log?.info(`[${account.accountId}] inline connected (me=${String(me.userId)})`);
|
|
82
|
+
const chatCache = new Map();
|
|
83
|
+
const senderProfilesById = new Map();
|
|
84
|
+
const hydratedParticipantChats = new Set();
|
|
85
|
+
const participantFetches = new Map();
|
|
86
|
+
const hydrateChatParticipants = async (chatId) => {
|
|
87
|
+
const chatKey = String(chatId);
|
|
88
|
+
if (hydratedParticipantChats.has(chatKey))
|
|
89
|
+
return;
|
|
90
|
+
const existing = participantFetches.get(chatKey);
|
|
91
|
+
if (existing)
|
|
92
|
+
return existing;
|
|
93
|
+
const run = (async () => {
|
|
94
|
+
const result = await client.invokeRaw(Method.GET_CHAT_PARTICIPANTS, {
|
|
95
|
+
oneofKind: "getChatParticipants",
|
|
96
|
+
getChatParticipants: { chatId },
|
|
97
|
+
});
|
|
98
|
+
if (result.oneofKind !== "getChatParticipants")
|
|
99
|
+
return;
|
|
100
|
+
for (const user of result.getChatParticipants.users ?? []) {
|
|
101
|
+
const userId = String(user.id);
|
|
102
|
+
if (!userId)
|
|
103
|
+
continue;
|
|
104
|
+
const nextName = buildInlineSenderName({ firstName: user.firstName, lastName: user.lastName });
|
|
105
|
+
const nextUsername = normalizeInlineUsername(user.username);
|
|
106
|
+
const previous = senderProfilesById.get(userId);
|
|
107
|
+
const mergedName = nextName ?? previous?.name;
|
|
108
|
+
const mergedUsername = nextUsername ?? previous?.username;
|
|
109
|
+
senderProfilesById.set(userId, {
|
|
110
|
+
...(mergedName ? { name: mergedName } : {}),
|
|
111
|
+
...(mergedUsername ? { username: mergedUsername } : {}),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
hydratedParticipantChats.add(chatKey);
|
|
115
|
+
})()
|
|
116
|
+
.catch((err) => {
|
|
117
|
+
statusSink?.({ lastError: `getChatParticipants failed: ${String(err)}` });
|
|
118
|
+
})
|
|
119
|
+
.finally(() => {
|
|
120
|
+
participantFetches.delete(chatKey);
|
|
121
|
+
});
|
|
122
|
+
participantFetches.set(chatKey, run);
|
|
123
|
+
await run;
|
|
124
|
+
};
|
|
125
|
+
const loop = (async () => {
|
|
126
|
+
try {
|
|
127
|
+
for await (const event of client.events()) {
|
|
128
|
+
if (abortSignal.aborted)
|
|
129
|
+
break;
|
|
130
|
+
if (event.kind !== "message.new")
|
|
131
|
+
continue;
|
|
132
|
+
const msg = event.message;
|
|
133
|
+
const rawBody = messageText(msg);
|
|
134
|
+
if (!rawBody)
|
|
135
|
+
continue;
|
|
136
|
+
// Ignore echoes / our own outbound messages.
|
|
137
|
+
if (msg.out || msg.fromId === me.userId)
|
|
138
|
+
continue;
|
|
139
|
+
const chatId = event.chatId;
|
|
140
|
+
statusSink?.({ lastInboundAt: Date.now() });
|
|
141
|
+
let chatInfo;
|
|
142
|
+
try {
|
|
143
|
+
chatInfo = await resolveChatInfo(client, chatCache, chatId);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
// Default conservative behavior if metadata fetch fails.
|
|
147
|
+
chatInfo = { kind: "group", title: null };
|
|
148
|
+
statusSink?.({ lastError: `getChat failed: ${String(err)}` });
|
|
149
|
+
}
|
|
150
|
+
const isGroup = chatInfo.kind !== "direct";
|
|
151
|
+
const senderId = String(msg.fromId);
|
|
152
|
+
await hydrateChatParticipants(chatId);
|
|
153
|
+
const senderProfile = senderProfilesById.get(senderId);
|
|
154
|
+
const senderUsername = senderProfile?.username;
|
|
155
|
+
const senderName = senderProfile?.name ?? (!isGroup ? chatInfo.title ?? undefined : undefined);
|
|
156
|
+
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
|
157
|
+
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
|
|
158
|
+
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
|
|
159
|
+
const configAllowFrom = normalizeAllowlist(account.config.allowFrom);
|
|
160
|
+
const configGroupAllowFrom = normalizeAllowlist(account.config.groupAllowFrom);
|
|
161
|
+
const storeAllowFrom = await core.channel.pairing.readAllowFromStore(CHANNEL_ID).catch(() => []);
|
|
162
|
+
const storeAllowList = normalizeAllowlist(storeAllowFrom);
|
|
163
|
+
const effectiveAllowFrom = [...configAllowFrom, ...storeAllowList].filter(Boolean);
|
|
164
|
+
const effectiveGroupAllowFrom = [
|
|
165
|
+
...(configGroupAllowFrom.length > 0 ? configGroupAllowFrom : configAllowFrom),
|
|
166
|
+
...storeAllowList,
|
|
167
|
+
].filter(Boolean);
|
|
168
|
+
const allowTextCommands = core.channel.commands.shouldHandleTextCommands({
|
|
169
|
+
cfg,
|
|
170
|
+
surface: CHANNEL_ID,
|
|
171
|
+
});
|
|
172
|
+
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
|
|
173
|
+
const allowForCommands = isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom;
|
|
174
|
+
const senderAllowedForCommands = allowlistMatch({ allowFrom: allowForCommands, senderId });
|
|
175
|
+
const hasControlCommand = core.channel.text.hasControlCommand(rawBody, cfg);
|
|
176
|
+
const commandGate = resolveControlCommandGate({
|
|
177
|
+
useAccessGroups,
|
|
178
|
+
authorizers: [{ configured: allowForCommands.length > 0, allowed: senderAllowedForCommands }],
|
|
179
|
+
allowTextCommands,
|
|
180
|
+
hasControlCommand,
|
|
181
|
+
});
|
|
182
|
+
const commandAuthorized = commandGate.commandAuthorized;
|
|
183
|
+
if (isGroup) {
|
|
184
|
+
if (groupPolicy === "disabled") {
|
|
185
|
+
log?.info(`[${account.accountId}] inline: drop group chat=${String(chatId)} (groupPolicy=disabled)`);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (groupPolicy === "allowlist") {
|
|
189
|
+
const allowed = allowlistMatch({ allowFrom: effectiveGroupAllowFrom, senderId });
|
|
190
|
+
if (!allowed) {
|
|
191
|
+
log?.info(`[${account.accountId}] inline: drop group sender=${senderId} (groupPolicy=allowlist)`);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
if (dmPolicy === "disabled") {
|
|
198
|
+
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=disabled)`);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (dmPolicy !== "open") {
|
|
202
|
+
const allowed = allowlistMatch({ allowFrom: effectiveAllowFrom, senderId });
|
|
203
|
+
if (!allowed) {
|
|
204
|
+
if (dmPolicy === "pairing") {
|
|
205
|
+
const { code, created } = await core.channel.pairing.upsertPairingRequest({
|
|
206
|
+
channel: CHANNEL_ID,
|
|
207
|
+
id: senderId,
|
|
208
|
+
meta: {},
|
|
209
|
+
// Pass adapter explicitly to avoid relying on registry lookup for plugin channels.
|
|
210
|
+
pairingAdapter: { idLabel: "inlineUserId", normalizeAllowEntry },
|
|
211
|
+
});
|
|
212
|
+
if (created) {
|
|
213
|
+
try {
|
|
214
|
+
await client.sendMessage({
|
|
215
|
+
chatId,
|
|
216
|
+
text: core.channel.pairing.buildPairingReply({
|
|
217
|
+
channel: CHANNEL_ID,
|
|
218
|
+
idLine: `Your Inline user id: ${senderId}`,
|
|
219
|
+
code,
|
|
220
|
+
}),
|
|
221
|
+
});
|
|
222
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
runtime.error?.(`inline: pairing reply failed for ${senderId}: ${String(err)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
log?.info(`[${account.accountId}] inline: drop DM sender=${senderId} (dmPolicy=${dmPolicy})`);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (commandGate.shouldBlock) {
|
|
235
|
+
logInboundDrop({
|
|
236
|
+
log: (m) => runtime.log?.(m),
|
|
237
|
+
channel: CHANNEL_ID,
|
|
238
|
+
reason: "control command (unauthorized)",
|
|
239
|
+
target: senderId,
|
|
240
|
+
});
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
244
|
+
cfg,
|
|
245
|
+
channel: CHANNEL_ID,
|
|
246
|
+
accountId: account.accountId,
|
|
247
|
+
peer: {
|
|
248
|
+
kind: isGroup ? "group" : "direct",
|
|
249
|
+
// DM sessions should be stable per sender. Group sessions should be stable per chat.
|
|
250
|
+
id: isGroup ? String(chatId) : senderId,
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
const mentionRegexes = core.channel.mentions.buildMentionRegexes(cfg, route.agentId);
|
|
254
|
+
const wasMentioned = typeof msg.mentioned === "boolean"
|
|
255
|
+
? msg.mentioned
|
|
256
|
+
: mentionRegexes.length
|
|
257
|
+
? core.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes)
|
|
258
|
+
: false;
|
|
259
|
+
const requireMention = isGroup ? (account.config.requireMention ?? true) : false;
|
|
260
|
+
const mentionGate = resolveMentionGatingWithBypass({
|
|
261
|
+
isGroup,
|
|
262
|
+
requireMention,
|
|
263
|
+
canDetectMention: typeof msg.mentioned === "boolean" || mentionRegexes.length > 0,
|
|
264
|
+
wasMentioned,
|
|
265
|
+
allowTextCommands,
|
|
266
|
+
hasControlCommand,
|
|
267
|
+
commandAuthorized,
|
|
268
|
+
});
|
|
269
|
+
if (isGroup && mentionGate.shouldSkip) {
|
|
270
|
+
runtime.log?.(`inline: drop group chat ${String(chatId)} (no mention)`);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const timestamp = Number(msg.date) * 1000;
|
|
274
|
+
const fromLabel = isGroup ? `chat:${chatInfo.title ?? String(chatId)}` : `user:${senderId}`;
|
|
275
|
+
const storePath = core.channel.session.resolveStorePath(cfg.session?.store, { agentId: route.agentId });
|
|
276
|
+
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
277
|
+
const previousTimestamp = core.channel.session.readSessionUpdatedAt({ storePath, sessionKey: route.sessionKey });
|
|
278
|
+
const body = core.channel.reply.formatAgentEnvelope({
|
|
279
|
+
channel: "Inline",
|
|
280
|
+
from: fromLabel,
|
|
281
|
+
timestamp,
|
|
282
|
+
...(previousTimestamp != null ? { previousTimestamp } : {}),
|
|
283
|
+
envelope: envelopeOptions,
|
|
284
|
+
body: rawBody,
|
|
285
|
+
});
|
|
286
|
+
const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
287
|
+
Body: body,
|
|
288
|
+
RawBody: rawBody,
|
|
289
|
+
CommandBody: rawBody,
|
|
290
|
+
From: isGroup ? `inline:chat:${String(chatId)}` : `inline:${senderId}`,
|
|
291
|
+
To: `inline:${String(chatId)}`,
|
|
292
|
+
SessionKey: route.sessionKey,
|
|
293
|
+
AccountId: route.accountId,
|
|
294
|
+
ChatType: isGroup ? "group" : "direct",
|
|
295
|
+
ConversationLabel: fromLabel,
|
|
296
|
+
...(isGroup ? { GroupSubject: chatInfo.title ?? String(chatId) } : {}),
|
|
297
|
+
SenderId: senderId,
|
|
298
|
+
...(senderName ? { SenderName: senderName } : {}),
|
|
299
|
+
...(senderUsername ? { SenderUsername: senderUsername } : {}),
|
|
300
|
+
Provider: CHANNEL_ID,
|
|
301
|
+
Surface: CHANNEL_ID,
|
|
302
|
+
MessageSid: String(msg.id),
|
|
303
|
+
...(msg.replyToMsgId != null ? { ReplyToId: String(msg.replyToMsgId) } : {}),
|
|
304
|
+
Timestamp: timestamp || Date.now(),
|
|
305
|
+
WasMentioned: mentionGate.effectiveWasMentioned,
|
|
306
|
+
CommandAuthorized: commandAuthorized,
|
|
307
|
+
OriginatingChannel: CHANNEL_ID,
|
|
308
|
+
OriginatingTo: `inline:${String(chatId)}`,
|
|
309
|
+
});
|
|
310
|
+
await core.channel.session.recordInboundSession({
|
|
311
|
+
storePath,
|
|
312
|
+
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
|
313
|
+
ctx: ctxPayload,
|
|
314
|
+
...(!isGroup
|
|
315
|
+
? {
|
|
316
|
+
updateLastRoute: {
|
|
317
|
+
sessionKey: route.mainSessionKey,
|
|
318
|
+
channel: CHANNEL_ID,
|
|
319
|
+
to: `inline:${String(chatId)}`,
|
|
320
|
+
accountId: route.accountId,
|
|
321
|
+
},
|
|
322
|
+
}
|
|
323
|
+
: {}),
|
|
324
|
+
onRecordError: (err) => runtime.error?.(`inline: failed updating session meta: ${String(err)}`),
|
|
325
|
+
});
|
|
326
|
+
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
|
327
|
+
cfg,
|
|
328
|
+
agentId: route.agentId,
|
|
329
|
+
channel: CHANNEL_ID,
|
|
330
|
+
accountId: account.accountId,
|
|
331
|
+
});
|
|
332
|
+
const typingCallbacks = createTypingCallbacks({
|
|
333
|
+
start: () => client.sendTyping({ chatId, typing: true }),
|
|
334
|
+
stop: () => client.sendTyping({ chatId, typing: false }),
|
|
335
|
+
onStartError: (err) => runtime.error?.(`inline typing start failed: ${String(err)}`),
|
|
336
|
+
onStopError: (err) => runtime.error?.(`inline typing stop failed: ${String(err)}`),
|
|
337
|
+
});
|
|
338
|
+
const parseMarkdown = account.config.parseMarkdown ?? true;
|
|
339
|
+
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
340
|
+
ctx: ctxPayload,
|
|
341
|
+
cfg,
|
|
342
|
+
dispatcherOptions: {
|
|
343
|
+
...prefixOptions,
|
|
344
|
+
...typingCallbacks,
|
|
345
|
+
deliver: async (payload) => {
|
|
346
|
+
const text = (payload.text ?? "").trim();
|
|
347
|
+
const mediaList = payload.mediaUrls?.length
|
|
348
|
+
? payload.mediaUrls
|
|
349
|
+
: payload.mediaUrl
|
|
350
|
+
? [payload.mediaUrl]
|
|
351
|
+
: [];
|
|
352
|
+
const mediaBlock = mediaList.length ? mediaList.map((url) => `Attachment: ${url}`).join("\n") : "";
|
|
353
|
+
const combined = text
|
|
354
|
+
? mediaBlock
|
|
355
|
+
? `${text}\n\n${mediaBlock}`
|
|
356
|
+
: text
|
|
357
|
+
: mediaBlock;
|
|
358
|
+
if (!combined.trim())
|
|
359
|
+
return;
|
|
360
|
+
const outboundText = rewriteNumericMentionsToUsernames(combined, senderProfilesById);
|
|
361
|
+
let replyToMsgId;
|
|
362
|
+
if (payload.replyToId != null) {
|
|
363
|
+
try {
|
|
364
|
+
replyToMsgId = BigInt(payload.replyToId);
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// ignore
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
await client.sendMessage({
|
|
371
|
+
chatId,
|
|
372
|
+
text: outboundText,
|
|
373
|
+
...(replyToMsgId != null ? { replyToMsgId } : {}),
|
|
374
|
+
parseMarkdown,
|
|
375
|
+
});
|
|
376
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
377
|
+
},
|
|
378
|
+
onError: (err, info) => runtime.error?.(`inline ${info.kind} reply failed: ${String(err)}`),
|
|
379
|
+
},
|
|
380
|
+
replyOptions: {
|
|
381
|
+
onModelSelected,
|
|
382
|
+
blockReplyTimeoutMs: 25_000,
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (err) {
|
|
388
|
+
statusSink?.({ lastError: String(err) });
|
|
389
|
+
runtime.error?.(`inline monitor loop crashed: ${String(err)}`);
|
|
390
|
+
}
|
|
391
|
+
})();
|
|
392
|
+
const stop = async () => {
|
|
393
|
+
await client.close().catch(() => { });
|
|
394
|
+
await loop.catch(() => { });
|
|
395
|
+
};
|
|
396
|
+
abortSignal.addEventListener("abort", () => {
|
|
397
|
+
void stop();
|
|
398
|
+
}, { once: true });
|
|
399
|
+
return { stop };
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=monitor.js.map
|