dsh-lark-bot 0.7.0 → 0.8.0
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 +206 -6
- package/SECURITY.md +15 -0
- package/dist/cli.js +1376 -17
- package/dist/cli.js.map +1 -1
- package/dist/plugin.d.ts +17 -0
- package/dist/plugin.js +77 -3
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/plugin.d.ts
CHANGED
|
@@ -113,6 +113,23 @@ interface RuntimeEnv {
|
|
|
113
113
|
archiveMaxAgeDays: number;
|
|
114
114
|
accessDefaultDeny: boolean;
|
|
115
115
|
eventFreshnessMs: number;
|
|
116
|
+
/** Bridge engine heartbeat interval (guardian liveness signal), default 5000. */
|
|
117
|
+
heartbeatMs: number;
|
|
118
|
+
/** Guardian disabled switch (DSH_LARK_GUARDIAN_DISABLED=1 keeps it stopped). */
|
|
119
|
+
guardianDisabled: boolean;
|
|
120
|
+
/** dsh profile the guardian watches / relaunches (default `dsh-lark`). */
|
|
121
|
+
guardianProfile: string;
|
|
122
|
+
/** Bridge state profile providing Feishu credentials (default `default`). */
|
|
123
|
+
guardianBridgeProfile: string;
|
|
124
|
+
/** Guardian watchdog poll interval, default 2000. */
|
|
125
|
+
guardianPollMs: number;
|
|
126
|
+
/** Heartbeat staleness threshold before takeover, default 15000. */
|
|
127
|
+
guardianStaleMs: number;
|
|
128
|
+
/**
|
|
129
|
+
* When a dsh process is alive but the bridge heartbeat has been stale for
|
|
130
|
+
* longer than this, treat the engine as dead and take over (default 120000).
|
|
131
|
+
*/
|
|
132
|
+
guardianEngineDeadMs: number;
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
interface ActiveRunHandle {
|
package/dist/plugin.js
CHANGED
|
@@ -64,7 +64,7 @@ var init_dsh_compat = __esm({
|
|
|
64
64
|
sdkServer: "0.1.0-rc.6",
|
|
65
65
|
acp: "0.1.0-rc.6",
|
|
66
66
|
node: ">=22.19.0",
|
|
67
|
-
verifiedAt: "2026-08-
|
|
67
|
+
verifiedAt: "2026-08-15"
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
});
|
|
@@ -4449,7 +4449,13 @@ var DEFAULTS = {
|
|
|
4449
4449
|
scopeConcurrency: 2,
|
|
4450
4450
|
retentionMsgs: 40,
|
|
4451
4451
|
archiveMax: 50,
|
|
4452
|
-
archiveMaxAgeDays: 90
|
|
4452
|
+
archiveMaxAgeDays: 90,
|
|
4453
|
+
heartbeatMs: 5e3,
|
|
4454
|
+
guardianPollMs: 2e3,
|
|
4455
|
+
guardianStaleMs: 15e3,
|
|
4456
|
+
guardianEngineDeadMs: 12e4,
|
|
4457
|
+
guardianProfile: "dsh-lark",
|
|
4458
|
+
guardianBridgeProfile: "default"
|
|
4453
4459
|
};
|
|
4454
4460
|
function nonEmpty(value) {
|
|
4455
4461
|
const trimmed = value?.trim();
|
|
@@ -4535,6 +4541,15 @@ function parseMinOneInt(value, fallback, name2) {
|
|
|
4535
4541
|
}
|
|
4536
4542
|
return parsed;
|
|
4537
4543
|
}
|
|
4544
|
+
function parsePositiveIntMin(value, fallback, name2) {
|
|
4545
|
+
const raw = value?.trim();
|
|
4546
|
+
if (!raw) return fallback;
|
|
4547
|
+
const parsed = Number(raw);
|
|
4548
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
4549
|
+
throw new Error(`${name2} must be a positive integer, got "${raw}"`);
|
|
4550
|
+
}
|
|
4551
|
+
return parsed;
|
|
4552
|
+
}
|
|
4538
4553
|
function loadRuntimeEnv(source = process.env) {
|
|
4539
4554
|
const homeOverride = nonEmpty(source.DSH_LARK_HOME);
|
|
4540
4555
|
const workspace = nonEmpty(source.DSH_LARK_WORKSPACE);
|
|
@@ -4585,7 +4600,30 @@ function loadRuntimeEnv(source = process.env) {
|
|
|
4585
4600
|
"DSH_LARK_ARCHIVE_MAX_AGE_DAYS"
|
|
4586
4601
|
),
|
|
4587
4602
|
accessDefaultDeny: parseBoolean(source.DSH_LARK_ACCESS_DEFAULT_DENY, false),
|
|
4588
|
-
eventFreshnessMs: parseFreshness(source.DSH_LARK_EVENT_FRESHNESS_MS)
|
|
4603
|
+
eventFreshnessMs: parseFreshness(source.DSH_LARK_EVENT_FRESHNESS_MS),
|
|
4604
|
+
heartbeatMs: parsePositiveIntMin(
|
|
4605
|
+
source.DSH_LARK_HEARTBEAT_MS,
|
|
4606
|
+
DEFAULTS.heartbeatMs,
|
|
4607
|
+
"DSH_LARK_HEARTBEAT_MS"
|
|
4608
|
+
),
|
|
4609
|
+
guardianDisabled: parseBoolean(source.DSH_LARK_GUARDIAN_DISABLED, false),
|
|
4610
|
+
guardianProfile: nonEmpty(source.DSH_LARK_GUARDIAN_PROFILE) ?? DEFAULTS.guardianProfile,
|
|
4611
|
+
guardianBridgeProfile: nonEmpty(source.DSH_LARK_GUARDIAN_BRIDGE_PROFILE) ?? DEFAULTS.guardianBridgeProfile,
|
|
4612
|
+
guardianPollMs: parsePositiveIntMin(
|
|
4613
|
+
source.DSH_LARK_GUARDIAN_POLL_MS,
|
|
4614
|
+
DEFAULTS.guardianPollMs,
|
|
4615
|
+
"DSH_LARK_GUARDIAN_POLL_MS"
|
|
4616
|
+
),
|
|
4617
|
+
guardianStaleMs: parsePositiveIntMin(
|
|
4618
|
+
source.DSH_LARK_GUARDIAN_STALE_MS,
|
|
4619
|
+
DEFAULTS.guardianStaleMs,
|
|
4620
|
+
"DSH_LARK_GUARDIAN_STALE_MS"
|
|
4621
|
+
),
|
|
4622
|
+
guardianEngineDeadMs: parsePositiveIntMin(
|
|
4623
|
+
source.DSH_LARK_GUARDIAN_ENGINE_DEAD_MS,
|
|
4624
|
+
DEFAULTS.guardianEngineDeadMs,
|
|
4625
|
+
"DSH_LARK_GUARDIAN_ENGINE_DEAD_MS"
|
|
4626
|
+
)
|
|
4589
4627
|
};
|
|
4590
4628
|
}
|
|
4591
4629
|
|
|
@@ -5315,6 +5353,36 @@ var WorkspaceStore = class {
|
|
|
5315
5353
|
}
|
|
5316
5354
|
};
|
|
5317
5355
|
|
|
5356
|
+
// src/guardian/heartbeat.ts
|
|
5357
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
5358
|
+
var DEFAULT_HEARTBEAT_INTERVAL_MS = 5e3;
|
|
5359
|
+
function startHeartbeat(file, pid, intervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS) {
|
|
5360
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5361
|
+
let stopped = false;
|
|
5362
|
+
const beat = async () => {
|
|
5363
|
+
if (stopped) return;
|
|
5364
|
+
const payload = { pid, startedAt, ts: Date.now() };
|
|
5365
|
+
try {
|
|
5366
|
+
await writeFileAtomic(file, `${JSON.stringify(payload)}
|
|
5367
|
+
`, {
|
|
5368
|
+
mode: 384
|
|
5369
|
+
});
|
|
5370
|
+
} catch {
|
|
5371
|
+
}
|
|
5372
|
+
};
|
|
5373
|
+
void beat();
|
|
5374
|
+
const timer = setInterval(() => {
|
|
5375
|
+
void beat();
|
|
5376
|
+
}, intervalMs);
|
|
5377
|
+
timer.unref?.();
|
|
5378
|
+
return {
|
|
5379
|
+
stop() {
|
|
5380
|
+
stopped = true;
|
|
5381
|
+
clearInterval(timer);
|
|
5382
|
+
}
|
|
5383
|
+
};
|
|
5384
|
+
}
|
|
5385
|
+
|
|
5318
5386
|
// src/cli/commands/run.ts
|
|
5319
5387
|
var DEBOUNCE_MS = 600;
|
|
5320
5388
|
async function ensureBotProfile(store, options) {
|
|
@@ -5520,6 +5588,11 @@ async function startBridgeEngine(options) {
|
|
|
5520
5588
|
larkChannel = bridge.channel;
|
|
5521
5589
|
await notifyServer.start();
|
|
5522
5590
|
process.env.DSH_LARK_NOTIFY_URL = notifyServer.url ?? "";
|
|
5591
|
+
const heartbeat = startHeartbeat(
|
|
5592
|
+
paths.profilePath(profileName, "guardian", "heartbeat.json"),
|
|
5593
|
+
process.pid,
|
|
5594
|
+
env.heartbeatMs
|
|
5595
|
+
);
|
|
5523
5596
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5524
5597
|
log.info("cli", "started", {
|
|
5525
5598
|
profile: profileName,
|
|
@@ -5544,6 +5617,7 @@ async function startBridgeEngine(options) {
|
|
|
5544
5617
|
stop: async () => {
|
|
5545
5618
|
if (stopped) return;
|
|
5546
5619
|
stopped = true;
|
|
5620
|
+
heartbeat.stop();
|
|
5547
5621
|
await notifyServer.stop();
|
|
5548
5622
|
await bridge.disconnect();
|
|
5549
5623
|
await adapter.dispose?.();
|