@stagewhisper/stagewhisper 0.51.0 → 0.53.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/src/reasoning.ts DELETED
@@ -1,210 +0,0 @@
1
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
2
- import {
3
- callOpenResponses,
4
- OpenResponsesError,
5
- type OpenResponsesCreateResponseRequestBody,
6
- type OpenResponsesResponseResource,
7
- } from "./openresponses.js";
8
-
9
- export type ProbeResult = {
10
- ok: boolean;
11
- model: string | null;
12
- error: string | null;
13
- };
14
-
15
- export async function probeOpenResponses(
16
- api: OpenClawPluginApi,
17
- ): Promise<ProbeResult> {
18
- const body: OpenResponsesCreateResponseRequestBody = {
19
- model: "openclaw/default",
20
- input: "Reply with exactly: OK",
21
- max_output_tokens: 16,
22
- };
23
-
24
- const controller = new AbortController();
25
- const timer = setTimeout(() => controller.abort(), 15_000);
26
-
27
- try {
28
- const result = await callOpenResponses(api, body, controller.signal, undefined);
29
- const model = (result as Record<string, unknown>).model as string ?? null;
30
- return { ok: true, model, error: null };
31
- } catch (err) {
32
- return {
33
- ok: false,
34
- model: null,
35
- error: err instanceof Error ? err.message : String(err),
36
- };
37
- } finally {
38
- clearTimeout(timer);
39
- }
40
- }
41
-
42
- export type ReasoningJobEnvelope = {
43
- event_type: "reasoning_job";
44
- job_id: string;
45
- purpose: string;
46
- deadline_at: string;
47
- idempotency_key: string;
48
- schema_version: number;
49
- response_schema: Record<string, unknown>;
50
- payload: Record<string, unknown>;
51
- model?: string;
52
- correlation_id?: string;
53
- };
54
-
55
- export type ReasoningJobResult = {
56
- job_id: string;
57
- status: "completed" | "failed" | "timed_out";
58
- provider_run_id: string | null;
59
- model_ref: string | null;
60
- usage: { input_tokens: number; output_tokens: number } | null;
61
- output: Record<string, unknown> | null;
62
- error_code: string | null;
63
- error_message: string | null;
64
- };
65
-
66
- function extractTextOutput(result: OpenResponsesResponseResource): string | null {
67
- const output = result.output;
68
- if (!Array.isArray(output)) return null;
69
- for (const item of output) {
70
- if (item.type !== "message") continue;
71
- const content = (item as Record<string, unknown>).content;
72
- if (!Array.isArray(content)) continue;
73
- for (const part of content) {
74
- const p = part as Record<string, unknown>;
75
- if (p.type === "output_text" && typeof p.text === "string") {
76
- return p.text;
77
- }
78
- }
79
- }
80
- return null;
81
- }
82
-
83
- function buildSchemaInstruction(schema: Record<string, unknown>, purpose: string, systemInstruction?: string): string {
84
- const parts: string[] = [];
85
- if (systemInstruction) {
86
- parts.push(systemInstruction);
87
- parts.push("");
88
- }
89
- parts.push(
90
- `You are a structured reasoning engine for the "${purpose}" task.`,
91
- "You MUST respond with a JSON object conforming to this schema.",
92
- "Output ONLY valid JSON. No markdown fences, no explanation, no extra text.",
93
- "",
94
- "JSON Schema:",
95
- JSON.stringify(schema, null, 2),
96
- );
97
- return parts.join("\n");
98
- }
99
-
100
- export async function executeReasoningJob(
101
- api: OpenClawPluginApi,
102
- job: ReasoningJobEnvelope,
103
- displayModel: string | null,
104
- ): Promise<ReasoningJobResult> {
105
- const parsedDeadline = new Date(job.deadline_at).getTime();
106
- const deadlineMs = Number.isFinite(parsedDeadline)
107
- ? parsedDeadline - Date.now()
108
- : -1;
109
- if (deadlineMs <= 0) {
110
- return {
111
- job_id: job.job_id,
112
- status: "timed_out",
113
- provider_run_id: null,
114
- model_ref: displayModel,
115
- usage: null,
116
- output: null,
117
- error_code: "deadline_expired_before_start",
118
- error_message: "Job deadline had already passed when execution began",
119
- };
120
- }
121
-
122
- const model = job.model ?? displayModel ?? "openclaw/default";
123
- const correlationId = job.correlation_id;
124
-
125
- const requestBody: OpenResponsesCreateResponseRequestBody = {
126
- model,
127
- input: JSON.stringify(job.payload),
128
- instructions: buildSchemaInstruction(
129
- job.response_schema,
130
- job.purpose,
131
- (job.payload.system_instruction as string) ?? undefined,
132
- ),
133
- max_output_tokens: 4096,
134
- };
135
-
136
- const controller = new AbortController();
137
- const timer = setTimeout(() => controller.abort(), deadlineMs);
138
-
139
- try {
140
- const result = await callOpenResponses(api, requestBody, controller.signal, correlationId);
141
- const textOutput = extractTextOutput(result);
142
-
143
- let parsed: Record<string, unknown> | null = null;
144
- if (textOutput) {
145
- const cleaned = textOutput.replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/, "").trim();
146
- try {
147
- parsed = JSON.parse(cleaned) as Record<string, unknown>;
148
- } catch {
149
- return {
150
- job_id: job.job_id,
151
- status: "failed",
152
- provider_run_id: result.id,
153
- model_ref: (result as Record<string, unknown>).model as string ?? model,
154
- usage: result.usage
155
- ? {
156
- input_tokens: result.usage.input_tokens ?? 0,
157
- output_tokens: result.usage.output_tokens ?? 0,
158
- }
159
- : null,
160
- output: null,
161
- error_code: "response_parse_error",
162
- error_message: "Response text is not valid JSON",
163
- };
164
- }
165
- }
166
-
167
- return {
168
- job_id: job.job_id,
169
- status: "completed",
170
- provider_run_id: result.id,
171
- model_ref: (result as Record<string, unknown>).model as string ?? model,
172
- usage: result.usage
173
- ? {
174
- input_tokens: result.usage.input_tokens ?? 0,
175
- output_tokens: result.usage.output_tokens ?? 0,
176
- }
177
- : null,
178
- output: parsed,
179
- error_code: null,
180
- error_message: null,
181
- };
182
- } catch (err) {
183
- if (controller.signal.aborted) {
184
- return {
185
- job_id: job.job_id,
186
- status: "timed_out",
187
- provider_run_id: null,
188
- model_ref: model,
189
- usage: null,
190
- output: null,
191
- error_code: "deadline_exceeded",
192
- error_message: `Reasoning execution exceeded deadline of ${deadlineMs}ms`,
193
- };
194
- }
195
-
196
- const isRetryable = err instanceof OpenResponsesError && err.retryable;
197
- return {
198
- job_id: job.job_id,
199
- status: "failed",
200
- provider_run_id: null,
201
- model_ref: model,
202
- usage: null,
203
- output: null,
204
- error_code: isRetryable ? "retryable_error" : "execution_error",
205
- error_message: err instanceof Error ? err.message : String(err),
206
- };
207
- } finally {
208
- clearTimeout(timer);
209
- }
210
- }
package/src/runtime.ts DELETED
@@ -1,6 +0,0 @@
1
- import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
2
- import type { PluginRuntime } from "openclaw/plugin-sdk/core";
3
-
4
- export const { setRuntime, getRuntime } = createPluginRuntimeStore<PluginRuntime>(
5
- "StageWhisper plugin runtime not initialized",
6
- );