

























@@ -29,6 +29,13 @@ function fakeCtx(overrides: Partial<OpenClawPluginToolContext> = {}): OpenClawPl
2929};
3030}
313132+function requireRecord(value: unknown, label: string): Record<string, unknown> {
33+if (value === null || typeof value !== "object" || Array.isArray(value)) {
34+throw new Error(`expected ${label} to be a record`);
35+}
36+return value as Record<string, unknown>;
37+}
38+3239describe("lobster plugin tool", () => {
3340it("returns the Lobster envelope in details", async () => {
3441const runner = {
@@ -54,12 +61,11 @@ describe("lobster plugin tool", () => {
5461timeoutMs: 1000,
5562maxStdoutBytes: 512_000,
5663});
57-expect(res.details).toMatchObject({
58-ok: true,
59-status: "ok",
60-output: [{ hello: "world" }],
61-requiresApproval: null,
62-});
64+const details = requireRecord(res.details, "lobster tool details");
65+expect(details.ok).toBe(true);
66+expect(details.status).toBe("ok");
67+expect(details.output).toEqual([{ hello: "world" }]);
68+expect(details.requiresApproval).toBeNull();
6369});
64706571it("supports approval envelopes without changing the tool contract", async () => {
@@ -94,15 +100,13 @@ describe("lobster plugin tool", () => {
94100timeoutMs: 1500,
95101maxStdoutBytes: 4096,
96102});
97-expect(res.details).toMatchObject({
98-ok: true,
99-status: "needs_approval",
100-requiresApproval: {
101-type: "approval_request",
102-prompt: "Send these alerts?",
103-resumeToken: "resume-token-1",
104-},
105-});
103+const details = requireRecord(res.details, "approval lobster tool details");
104+expect(details.ok).toBe(true);
105+expect(details.status).toBe("needs_approval");
106+const approval = requireRecord(details.requiresApproval, "approval request");
107+expect(approval.type).toBe("approval_request");
108+expect(approval.prompt).toBe("Send these alerts?");
109+expect(approval.resumeToken).toBe("resume-token-1");
106110});
107111108112it("throws when the runner returns an error envelope", async () => {
@@ -172,16 +176,13 @@ describe("lobster plugin tool", () => {
172176approvalId: "approval-1",
173177},
174178});
175-expect(res.details).toMatchObject({
176-ok: true,
177-status: "needs_approval",
178-flow: {
179-flowId: "flow-1",
180-},
181-mutation: {
182-applied: true,
183-},
184-});
179+const details = requireRecord(res.details, "managed run lobster tool details");
180+expect(details.ok).toBe(true);
181+expect(details.status).toBe("needs_approval");
182+const flow = requireRecord(details.flow, "managed run flow details");
183+expect(flow.flowId).toBe("flow-1");
184+const mutation = requireRecord(details.mutation, "managed run mutation details");
185+expect(mutation.applied).toBe(true);
185186});
186187187188it("rejects managed TaskFlow params when no bound taskFlow runtime is available", async () => {
@@ -251,13 +252,11 @@ describe("lobster plugin tool", () => {
251252timeoutMs: 20_000,
252253maxStdoutBytes: 512_000,
253254});
254-expect(res.details).toMatchObject({
255-ok: true,
256-status: "ok",
257-mutation: {
258-applied: true,
259-},
260-});
255+const details = requireRecord(res.details, "managed resume lobster tool details");
256+expect(details.ok).toBe(true);
257+expect(details.status).toBe("ok");
258+const mutation = requireRecord(details.mutation, "managed resume mutation details");
259+expect(mutation.applied).toBe(true);
261260});
262261263262it("rejects managed TaskFlow resume mode without a token or approvalId", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。