@silbercue/chrome 0.2.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/LICENSE +21 -0
- package/README.md +229 -0
- package/build/cache/a11y-tree.d.ts +252 -0
- package/build/cache/a11y-tree.js +1956 -0
- package/build/cache/index.d.ts +8 -0
- package/build/cache/index.js +4 -0
- package/build/cache/selector-cache.d.ts +47 -0
- package/build/cache/selector-cache.js +119 -0
- package/build/cache/session-defaults.d.ts +27 -0
- package/build/cache/session-defaults.js +130 -0
- package/build/cache/tab-state-cache.d.ts +39 -0
- package/build/cache/tab-state-cache.js +171 -0
- package/build/cdp/cdp-client.d.ts +25 -0
- package/build/cdp/cdp-client.js +146 -0
- package/build/cdp/chrome-launcher.d.ts +85 -0
- package/build/cdp/chrome-launcher.js +502 -0
- package/build/cdp/console-collector.d.ts +53 -0
- package/build/cdp/console-collector.js +147 -0
- package/build/cdp/debug.d.ts +1 -0
- package/build/cdp/debug.js +6 -0
- package/build/cdp/dialog-handler.d.ts +54 -0
- package/build/cdp/dialog-handler.js +129 -0
- package/build/cdp/dom-watcher.d.ts +45 -0
- package/build/cdp/dom-watcher.js +195 -0
- package/build/cdp/emulation.d.ts +12 -0
- package/build/cdp/emulation.js +17 -0
- package/build/cdp/index.d.ts +11 -0
- package/build/cdp/index.js +6 -0
- package/build/cdp/network-collector.d.ts +77 -0
- package/build/cdp/network-collector.js +257 -0
- package/build/cdp/protocol.d.ts +20 -0
- package/build/cdp/protocol.js +1 -0
- package/build/cdp/session-manager.d.ts +62 -0
- package/build/cdp/session-manager.js +205 -0
- package/build/cdp/settle.d.ts +16 -0
- package/build/cdp/settle.js +71 -0
- package/build/cli/license-commands.d.ts +19 -0
- package/build/cli/license-commands.js +199 -0
- package/build/cli/top-level-commands.d.ts +49 -0
- package/build/cli/top-level-commands.js +222 -0
- package/build/hooks/index.d.ts +2 -0
- package/build/hooks/index.js +1 -0
- package/build/hooks/pro-hooks.d.ts +126 -0
- package/build/hooks/pro-hooks.js +17 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +86 -0
- package/build/license/free-tier-config.d.ts +14 -0
- package/build/license/free-tier-config.js +18 -0
- package/build/license/index.d.ts +4 -0
- package/build/license/index.js +2 -0
- package/build/license/license-status.d.ts +15 -0
- package/build/license/license-status.js +9 -0
- package/build/overlay/session-overlay.d.ts +22 -0
- package/build/overlay/session-overlay.js +372 -0
- package/build/plan/index.d.ts +7 -0
- package/build/plan/index.js +4 -0
- package/build/plan/plan-conditions.d.ts +12 -0
- package/build/plan/plan-conditions.js +242 -0
- package/build/plan/plan-executor.d.ts +49 -0
- package/build/plan/plan-executor.js +259 -0
- package/build/plan/plan-state-store.d.ts +24 -0
- package/build/plan/plan-state-store.js +43 -0
- package/build/plan/plan-variables.d.ts +16 -0
- package/build/plan/plan-variables.js +71 -0
- package/build/registry.d.ts +124 -0
- package/build/registry.js +884 -0
- package/build/server.d.ts +1 -0
- package/build/server.js +245 -0
- package/build/tools/click.d.ts +34 -0
- package/build/tools/click.js +293 -0
- package/build/tools/configure-session.d.ts +15 -0
- package/build/tools/configure-session.js +45 -0
- package/build/tools/console-logs.d.ts +18 -0
- package/build/tools/console-logs.js +44 -0
- package/build/tools/dom-snapshot.d.ts +13 -0
- package/build/tools/dom-snapshot.js +259 -0
- package/build/tools/element-utils.d.ts +23 -0
- package/build/tools/element-utils.js +133 -0
- package/build/tools/error-utils.d.ts +8 -0
- package/build/tools/error-utils.js +27 -0
- package/build/tools/evaluate.d.ts +34 -0
- package/build/tools/evaluate.js +217 -0
- package/build/tools/file-upload.d.ts +20 -0
- package/build/tools/file-upload.js +174 -0
- package/build/tools/fill-form.d.ts +39 -0
- package/build/tools/fill-form.js +256 -0
- package/build/tools/handle-dialog.d.ts +15 -0
- package/build/tools/handle-dialog.js +48 -0
- package/build/tools/index.d.ts +35 -0
- package/build/tools/index.js +18 -0
- package/build/tools/navigate.d.ts +18 -0
- package/build/tools/navigate.js +111 -0
- package/build/tools/network-monitor.d.ts +18 -0
- package/build/tools/network-monitor.js +66 -0
- package/build/tools/observe.d.ts +44 -0
- package/build/tools/observe.js +339 -0
- package/build/tools/press-key.d.ts +33 -0
- package/build/tools/press-key.js +155 -0
- package/build/tools/read-page.d.ts +22 -0
- package/build/tools/read-page.js +100 -0
- package/build/tools/run-plan.d.ts +205 -0
- package/build/tools/run-plan.js +215 -0
- package/build/tools/screenshot.d.ts +16 -0
- package/build/tools/screenshot.js +283 -0
- package/build/tools/scroll.d.ts +28 -0
- package/build/tools/scroll.js +143 -0
- package/build/tools/switch-tab.d.ts +26 -0
- package/build/tools/switch-tab.js +355 -0
- package/build/tools/tab-status.d.ts +7 -0
- package/build/tools/tab-status.js +50 -0
- package/build/tools/type.d.ts +31 -0
- package/build/tools/type.js +247 -0
- package/build/tools/virtual-desk.d.ts +7 -0
- package/build/tools/virtual-desk.js +108 -0
- package/build/tools/visual-constants.d.ts +3 -0
- package/build/tools/visual-constants.js +10 -0
- package/build/tools/wait-for.d.ts +26 -0
- package/build/tools/wait-for.js +323 -0
- package/build/transport/index.d.ts +3 -0
- package/build/transport/index.js +2 -0
- package/build/transport/pipe-transport.d.ts +18 -0
- package/build/transport/pipe-transport.js +63 -0
- package/build/transport/transport.d.ts +8 -0
- package/build/transport/transport.js +1 -0
- package/build/transport/websocket-transport.d.ts +22 -0
- package/build/transport/websocket-transport.js +200 -0
- package/build/types.d.ts +21 -0
- package/build/types.js +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolResponse } from "../types.js";
|
|
3
|
+
import type { ToolRegistry } from "../registry.js";
|
|
4
|
+
import type { CdpClient } from "../cdp/cdp-client.js";
|
|
5
|
+
import type { SessionManager } from "../cdp/session-manager.js";
|
|
6
|
+
import type { SuspendedPlanResponse } from "../plan/plan-executor.js";
|
|
7
|
+
import type { PlanStateStore } from "../plan/plan-state-store.js";
|
|
8
|
+
import type { LicenseStatus } from "../license/license-status.js";
|
|
9
|
+
import type { FreeTierConfig } from "../license/free-tier-config.js";
|
|
10
|
+
export declare const runPlanSchema: z.ZodObject<{
|
|
11
|
+
steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
12
|
+
tool: z.ZodString;
|
|
13
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
14
|
+
saveAs: z.ZodOptional<z.ZodString>;
|
|
15
|
+
if: z.ZodOptional<z.ZodString>;
|
|
16
|
+
suspend: z.ZodOptional<z.ZodObject<{
|
|
17
|
+
question: z.ZodOptional<z.ZodString>;
|
|
18
|
+
context: z.ZodOptional<z.ZodEnum<["screenshot"]>>;
|
|
19
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
question?: string | undefined;
|
|
22
|
+
condition?: string | undefined;
|
|
23
|
+
context?: "screenshot" | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
question?: string | undefined;
|
|
26
|
+
condition?: string | undefined;
|
|
27
|
+
context?: "screenshot" | undefined;
|
|
28
|
+
}>>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
tool: string;
|
|
31
|
+
params?: Record<string, unknown> | undefined;
|
|
32
|
+
saveAs?: string | undefined;
|
|
33
|
+
if?: string | undefined;
|
|
34
|
+
suspend?: {
|
|
35
|
+
question?: string | undefined;
|
|
36
|
+
condition?: string | undefined;
|
|
37
|
+
context?: "screenshot" | undefined;
|
|
38
|
+
} | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
tool: string;
|
|
41
|
+
params?: Record<string, unknown> | undefined;
|
|
42
|
+
saveAs?: string | undefined;
|
|
43
|
+
if?: string | undefined;
|
|
44
|
+
suspend?: {
|
|
45
|
+
question?: string | undefined;
|
|
46
|
+
condition?: string | undefined;
|
|
47
|
+
context?: "screenshot" | undefined;
|
|
48
|
+
} | undefined;
|
|
49
|
+
}>, "many">>;
|
|
50
|
+
parallel: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
51
|
+
tab: z.ZodString;
|
|
52
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
53
|
+
tool: z.ZodString;
|
|
54
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
55
|
+
saveAs: z.ZodOptional<z.ZodString>;
|
|
56
|
+
if: z.ZodOptional<z.ZodString>;
|
|
57
|
+
suspend: z.ZodOptional<z.ZodObject<{
|
|
58
|
+
question: z.ZodOptional<z.ZodString>;
|
|
59
|
+
context: z.ZodOptional<z.ZodEnum<["screenshot"]>>;
|
|
60
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
question?: string | undefined;
|
|
63
|
+
condition?: string | undefined;
|
|
64
|
+
context?: "screenshot" | undefined;
|
|
65
|
+
}, {
|
|
66
|
+
question?: string | undefined;
|
|
67
|
+
condition?: string | undefined;
|
|
68
|
+
context?: "screenshot" | undefined;
|
|
69
|
+
}>>;
|
|
70
|
+
}, "strip", z.ZodTypeAny, {
|
|
71
|
+
tool: string;
|
|
72
|
+
params?: Record<string, unknown> | undefined;
|
|
73
|
+
saveAs?: string | undefined;
|
|
74
|
+
if?: string | undefined;
|
|
75
|
+
suspend?: {
|
|
76
|
+
question?: string | undefined;
|
|
77
|
+
condition?: string | undefined;
|
|
78
|
+
context?: "screenshot" | undefined;
|
|
79
|
+
} | undefined;
|
|
80
|
+
}, {
|
|
81
|
+
tool: string;
|
|
82
|
+
params?: Record<string, unknown> | undefined;
|
|
83
|
+
saveAs?: string | undefined;
|
|
84
|
+
if?: string | undefined;
|
|
85
|
+
suspend?: {
|
|
86
|
+
question?: string | undefined;
|
|
87
|
+
condition?: string | undefined;
|
|
88
|
+
context?: "screenshot" | undefined;
|
|
89
|
+
} | undefined;
|
|
90
|
+
}>, "many">;
|
|
91
|
+
}, "strip", z.ZodTypeAny, {
|
|
92
|
+
steps: {
|
|
93
|
+
tool: string;
|
|
94
|
+
params?: Record<string, unknown> | undefined;
|
|
95
|
+
saveAs?: string | undefined;
|
|
96
|
+
if?: string | undefined;
|
|
97
|
+
suspend?: {
|
|
98
|
+
question?: string | undefined;
|
|
99
|
+
condition?: string | undefined;
|
|
100
|
+
context?: "screenshot" | undefined;
|
|
101
|
+
} | undefined;
|
|
102
|
+
}[];
|
|
103
|
+
tab: string;
|
|
104
|
+
}, {
|
|
105
|
+
steps: {
|
|
106
|
+
tool: string;
|
|
107
|
+
params?: Record<string, unknown> | undefined;
|
|
108
|
+
saveAs?: string | undefined;
|
|
109
|
+
if?: string | undefined;
|
|
110
|
+
suspend?: {
|
|
111
|
+
question?: string | undefined;
|
|
112
|
+
condition?: string | undefined;
|
|
113
|
+
context?: "screenshot" | undefined;
|
|
114
|
+
} | undefined;
|
|
115
|
+
}[];
|
|
116
|
+
tab: string;
|
|
117
|
+
}>, "many">>;
|
|
118
|
+
vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
119
|
+
errorStrategy: z.ZodDefault<z.ZodOptional<z.ZodEnum<["abort", "continue", "screenshot"]>>>;
|
|
120
|
+
use_operator: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
121
|
+
resume: z.ZodOptional<z.ZodObject<{
|
|
122
|
+
planId: z.ZodString;
|
|
123
|
+
answer: z.ZodString;
|
|
124
|
+
}, "strip", z.ZodTypeAny, {
|
|
125
|
+
planId: string;
|
|
126
|
+
answer: string;
|
|
127
|
+
}, {
|
|
128
|
+
planId: string;
|
|
129
|
+
answer: string;
|
|
130
|
+
}>>;
|
|
131
|
+
}, "strip", z.ZodTypeAny, {
|
|
132
|
+
errorStrategy: "abort" | "continue" | "screenshot";
|
|
133
|
+
use_operator: boolean;
|
|
134
|
+
resume?: {
|
|
135
|
+
planId: string;
|
|
136
|
+
answer: string;
|
|
137
|
+
} | undefined;
|
|
138
|
+
steps?: {
|
|
139
|
+
tool: string;
|
|
140
|
+
params?: Record<string, unknown> | undefined;
|
|
141
|
+
saveAs?: string | undefined;
|
|
142
|
+
if?: string | undefined;
|
|
143
|
+
suspend?: {
|
|
144
|
+
question?: string | undefined;
|
|
145
|
+
condition?: string | undefined;
|
|
146
|
+
context?: "screenshot" | undefined;
|
|
147
|
+
} | undefined;
|
|
148
|
+
}[] | undefined;
|
|
149
|
+
vars?: Record<string, unknown> | undefined;
|
|
150
|
+
parallel?: {
|
|
151
|
+
steps: {
|
|
152
|
+
tool: string;
|
|
153
|
+
params?: Record<string, unknown> | undefined;
|
|
154
|
+
saveAs?: string | undefined;
|
|
155
|
+
if?: string | undefined;
|
|
156
|
+
suspend?: {
|
|
157
|
+
question?: string | undefined;
|
|
158
|
+
condition?: string | undefined;
|
|
159
|
+
context?: "screenshot" | undefined;
|
|
160
|
+
} | undefined;
|
|
161
|
+
}[];
|
|
162
|
+
tab: string;
|
|
163
|
+
}[] | undefined;
|
|
164
|
+
}, {
|
|
165
|
+
resume?: {
|
|
166
|
+
planId: string;
|
|
167
|
+
answer: string;
|
|
168
|
+
} | undefined;
|
|
169
|
+
steps?: {
|
|
170
|
+
tool: string;
|
|
171
|
+
params?: Record<string, unknown> | undefined;
|
|
172
|
+
saveAs?: string | undefined;
|
|
173
|
+
if?: string | undefined;
|
|
174
|
+
suspend?: {
|
|
175
|
+
question?: string | undefined;
|
|
176
|
+
condition?: string | undefined;
|
|
177
|
+
context?: "screenshot" | undefined;
|
|
178
|
+
} | undefined;
|
|
179
|
+
}[] | undefined;
|
|
180
|
+
vars?: Record<string, unknown> | undefined;
|
|
181
|
+
errorStrategy?: "abort" | "continue" | "screenshot" | undefined;
|
|
182
|
+
parallel?: {
|
|
183
|
+
steps: {
|
|
184
|
+
tool: string;
|
|
185
|
+
params?: Record<string, unknown> | undefined;
|
|
186
|
+
saveAs?: string | undefined;
|
|
187
|
+
if?: string | undefined;
|
|
188
|
+
suspend?: {
|
|
189
|
+
question?: string | undefined;
|
|
190
|
+
condition?: string | undefined;
|
|
191
|
+
context?: "screenshot" | undefined;
|
|
192
|
+
} | undefined;
|
|
193
|
+
}[];
|
|
194
|
+
tab: string;
|
|
195
|
+
}[] | undefined;
|
|
196
|
+
use_operator?: boolean | undefined;
|
|
197
|
+
}>;
|
|
198
|
+
export type RunPlanParams = z.infer<typeof runPlanSchema>;
|
|
199
|
+
/** Dependencies injected by the registry */
|
|
200
|
+
export interface RunPlanDeps {
|
|
201
|
+
cdpClient: CdpClient;
|
|
202
|
+
sessionId: string;
|
|
203
|
+
sessionManager?: SessionManager;
|
|
204
|
+
}
|
|
205
|
+
export declare function runPlanHandler(params: RunPlanParams, registry: ToolRegistry, deps?: RunPlanDeps, stateStore?: PlanStateStore, license?: LicenseStatus, freeTierConfig?: FreeTierConfig): Promise<ToolResponse | SuspendedPlanResponse>;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { executePlan } from "../plan/plan-executor.js";
|
|
3
|
+
import { getProHooks, proFeatureError } from "../hooks/pro-hooks.js";
|
|
4
|
+
import { FreeTierLicenseStatus } from "../license/license-status.js";
|
|
5
|
+
import { DEFAULT_FREE_TIER_CONFIG } from "../license/free-tier-config.js";
|
|
6
|
+
const suspendSchema = z.object({
|
|
7
|
+
question: z.string().optional().describe("Question to ask the agent when suspending"),
|
|
8
|
+
context: z.enum(["screenshot"]).optional().describe("Context to include: 'screenshot' captures the page"),
|
|
9
|
+
condition: z.string().optional().describe("Condition expression — suspend AFTER step if true. Uses $varName syntax."),
|
|
10
|
+
});
|
|
11
|
+
const stepSchema = z.object({
|
|
12
|
+
tool: z.string().describe("Tool name to execute (e.g. 'navigate', 'click', 'type')"),
|
|
13
|
+
params: z.record(z.unknown()).optional().describe("Parameters for the tool. Use $varName for variable substitution."),
|
|
14
|
+
saveAs: z.string().optional().describe("Save step result as variable (accessible via $name in later steps)"),
|
|
15
|
+
if: z.string().optional().describe("Condition expression — step runs only if true. Use $varName for variables. Example: \"$pageTitle === 'Login'\""),
|
|
16
|
+
suspend: suspendSchema.optional().describe("Suspend plan at this step to ask the agent a question"),
|
|
17
|
+
});
|
|
18
|
+
const resumeSchema = z.object({
|
|
19
|
+
planId: z.string().describe("ID of the suspended plan to resume"),
|
|
20
|
+
answer: z.string().describe("Agent's answer to the suspend question"),
|
|
21
|
+
});
|
|
22
|
+
// Story 7.6: Schema for parallel tab groups
|
|
23
|
+
const parallelGroupSchema = z.object({
|
|
24
|
+
tab: z.string().describe("Tab ID (targetId) to execute steps on"),
|
|
25
|
+
steps: z.array(stepSchema).describe("Steps to execute on this tab"),
|
|
26
|
+
});
|
|
27
|
+
export const runPlanSchema = z.object({
|
|
28
|
+
steps: z
|
|
29
|
+
.array(stepSchema)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Array of tool steps to execute sequentially."),
|
|
32
|
+
parallel: z
|
|
33
|
+
.array(parallelGroupSchema)
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Array of tab groups to execute in parallel. Pro-Feature — requires Pro license."),
|
|
36
|
+
vars: z
|
|
37
|
+
.record(z.unknown())
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Initial variables for the plan. Accessible via $varName in step params and conditions."),
|
|
40
|
+
errorStrategy: z
|
|
41
|
+
.enum(["abort", "continue", "screenshot"])
|
|
42
|
+
.optional()
|
|
43
|
+
.default("abort")
|
|
44
|
+
.describe("Error handling: 'abort' (default) stops on first error, 'continue' runs all steps, 'screenshot' captures page on error then aborts."),
|
|
45
|
+
use_operator: z.boolean().optional().default(false).describe("Pro-Feature: Operator mode (rule engine + Micro-LLM). Returns pro-feature error in Free tier."),
|
|
46
|
+
resume: resumeSchema.optional().describe("Resume a previously suspended plan."),
|
|
47
|
+
});
|
|
48
|
+
export async function runPlanHandler(params, registry, deps, stateStore, license, freeTierConfig) {
|
|
49
|
+
// Story 15.1: use_operator is a Pro-Feature — return pro-feature error
|
|
50
|
+
// BEFORE any mode validation so users get a clear pro-feature hint even
|
|
51
|
+
// when steps/parallel/resume is missing.
|
|
52
|
+
if (params.use_operator) {
|
|
53
|
+
return proFeatureError("use_operator");
|
|
54
|
+
}
|
|
55
|
+
// --- Validation: steps, parallel, and resume are mutually exclusive ---
|
|
56
|
+
const modeCount = [params.steps, params.parallel, params.resume].filter(Boolean).length;
|
|
57
|
+
if (modeCount > 1) {
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: "text", text: "Nur eines von 'steps', 'parallel' oder 'resume' angeben" }],
|
|
60
|
+
isError: true,
|
|
61
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (modeCount === 0) {
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text", text: "Eines von 'steps', 'parallel' oder 'resume' muss angegeben werden" }],
|
|
67
|
+
isError: true,
|
|
68
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// --- Story 9.1: Resolve step limit from license status ---
|
|
72
|
+
const resolvedLicense = license ?? new FreeTierLicenseStatus();
|
|
73
|
+
const resolvedConfig = freeTierConfig ?? DEFAULT_FREE_TIER_CONFIG;
|
|
74
|
+
const stepLimit = resolvedLicense.isPro() ? undefined : resolvedConfig.runPlanLimit;
|
|
75
|
+
// --- Story 7.6 / 15.4: Parallel path ---
|
|
76
|
+
// Multi-Tab-Parallel-Engine lebt im Pro-Repo und wird via executeParallel-Hook injiziert.
|
|
77
|
+
if (params.parallel) {
|
|
78
|
+
// Pro-Feature-Gate: parallel requires Pro license
|
|
79
|
+
// H1-Fix (Code-Review 15.6): zentralen proFeatureError-Helper nutzen statt
|
|
80
|
+
// Inline-String, damit der Wortlaut nicht gegen den Helper-Vertrag driftet.
|
|
81
|
+
if (!resolvedLicense.isPro()) {
|
|
82
|
+
return proFeatureError("parallel");
|
|
83
|
+
}
|
|
84
|
+
if (params.parallel.length === 0) {
|
|
85
|
+
return {
|
|
86
|
+
content: [{ type: "text", text: "parallel darf nicht leer sein" }],
|
|
87
|
+
isError: true,
|
|
88
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (!deps) {
|
|
92
|
+
return {
|
|
93
|
+
content: [{ type: "text", text: "Parallel-Ausfuehrung benoetigt CDP-Verbindung" }],
|
|
94
|
+
isError: true,
|
|
95
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Safety-Net: Pro-Lizenz vorhanden, aber Pro-Repo hat den Hook nicht registriert
|
|
99
|
+
// (z.B. jemand benutzt das Free-npm-Paket ohne Pro-Add-on). Sauberer Pro-Feature-Error
|
|
100
|
+
// statt undefined.executeParallel(...)-Crash.
|
|
101
|
+
const hooks = getProHooks();
|
|
102
|
+
if (!hooks.executeParallel) {
|
|
103
|
+
return proFeatureError("parallel");
|
|
104
|
+
}
|
|
105
|
+
// Inline tab-scope: attach + Runtime/Accessibility enable + sessionId-Override.
|
|
106
|
+
// Standard-CDP-Plumbing, keine Pro-Logik — bleibt im Free-Repo. Der Pro-Hook ist
|
|
107
|
+
// die reine Orchestrierungs-Engine (Semaphore, Promise.allSettled, Group-Aggregation).
|
|
108
|
+
//
|
|
109
|
+
// H2-Fix (Code-Review 15.4): attachte Sessions werden in `attachedSessions`
|
|
110
|
+
// getrackt und nach dem Hook-Aufruf via `Target.detachFromTarget` aufgeraeumt,
|
|
111
|
+
// damit wiederholte parallel-Laeufe keine Session-Leaks verursachen.
|
|
112
|
+
const cdpClient = deps.cdpClient;
|
|
113
|
+
const attachedSessions = [];
|
|
114
|
+
const registryFactory = async (tabTargetId) => {
|
|
115
|
+
const { sessionId: tabSessionId } = await cdpClient.send("Target.attachToTarget", { targetId: tabTargetId, flatten: true });
|
|
116
|
+
attachedSessions.push({ targetId: tabTargetId, sessionId: tabSessionId });
|
|
117
|
+
await cdpClient.send("Runtime.enable", {}, tabSessionId);
|
|
118
|
+
await cdpClient.send("Accessibility.enable", {}, tabSessionId);
|
|
119
|
+
return {
|
|
120
|
+
executeTool: (name, toolParams) => registry.executeTool(name, toolParams, tabSessionId),
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
// H1-Fix (Code-Review 15.4): Hook-Exceptions in MCP-konforme isError-Response
|
|
124
|
+
// wandeln statt nach oben durchzulassen.
|
|
125
|
+
try {
|
|
126
|
+
return await hooks.executeParallel(params.parallel, registryFactory, {
|
|
127
|
+
vars: params.vars,
|
|
128
|
+
errorStrategy: params.errorStrategy,
|
|
129
|
+
concurrencyLimit: 5,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
content: [{
|
|
135
|
+
type: "text",
|
|
136
|
+
text: `parallel execution failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
137
|
+
}],
|
|
138
|
+
isError: true,
|
|
139
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
// H2-Fix: Cleanup aller attachten Sessions, auch im Fehlerfall.
|
|
144
|
+
// Best-effort: Detach-Fehler werden geschluckt, damit ein einzelner
|
|
145
|
+
// bereits geschlossener Tab nicht den ganzen Cleanup blockiert.
|
|
146
|
+
for (const { sessionId: tabSessionId } of attachedSessions) {
|
|
147
|
+
try {
|
|
148
|
+
await cdpClient.send("Target.detachFromTarget", { sessionId: tabSessionId });
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Tab ggf. bereits geschlossen — ignorieren
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// --- Resume path ---
|
|
157
|
+
if (params.resume) {
|
|
158
|
+
if (!stateStore) {
|
|
159
|
+
return {
|
|
160
|
+
content: [{ type: "text", text: "Resume nicht verfuegbar: kein PlanStateStore konfiguriert" }],
|
|
161
|
+
isError: true,
|
|
162
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const suspended = stateStore.resume(params.resume.planId);
|
|
166
|
+
if (!suspended) {
|
|
167
|
+
return {
|
|
168
|
+
content: [{ type: "text", text: "Plan abgelaufen oder nicht gefunden" }],
|
|
169
|
+
isError: true,
|
|
170
|
+
_meta: { elapsedMs: 0, method: "run_plan" },
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const resumeOptions = {
|
|
174
|
+
vars: suspended.vars,
|
|
175
|
+
errorStrategy: suspended.errorStrategy,
|
|
176
|
+
resumeState: {
|
|
177
|
+
suspendedAtIndex: suspended.suspendedAtIndex,
|
|
178
|
+
completedResults: suspended.completedResults,
|
|
179
|
+
vars: suspended.vars,
|
|
180
|
+
answer: params.resume.answer,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
return executePlan(suspended.steps, registry, resumeOptions, stateStore);
|
|
184
|
+
}
|
|
185
|
+
const planOptions = {
|
|
186
|
+
vars: params.vars,
|
|
187
|
+
errorStrategy: params.errorStrategy,
|
|
188
|
+
};
|
|
189
|
+
// Story 9.1: Apply step limit to steps array before execution
|
|
190
|
+
const allSteps = params.steps;
|
|
191
|
+
let steps = allSteps;
|
|
192
|
+
const total = allSteps.length;
|
|
193
|
+
const truncated = stepLimit !== undefined && allSteps.length > stepLimit;
|
|
194
|
+
if (truncated) {
|
|
195
|
+
steps = allSteps.slice(0, stepLimit);
|
|
196
|
+
}
|
|
197
|
+
// Default: plain sequential execution
|
|
198
|
+
const result = await executePlan(steps, registry, planOptions, stateStore);
|
|
199
|
+
// Story 9.1 + BUG-008: Inject truncation info into _meta AND visible output
|
|
200
|
+
if (truncated && result._meta) {
|
|
201
|
+
result._meta.truncated = true;
|
|
202
|
+
result._meta.limit = stepLimit;
|
|
203
|
+
result._meta.total = total;
|
|
204
|
+
injectTruncationWarning(result, total, stepLimit, allSteps);
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
/** BUG-008: Inject visible truncation warning into response content */
|
|
209
|
+
function injectTruncationWarning(result, total, limit, allSteps) {
|
|
210
|
+
const skippedTools = allSteps.slice(limit).map((s, i) => `[${limit + i + 1}] ${s.tool}`).join(", ");
|
|
211
|
+
result.content.unshift({
|
|
212
|
+
type: "text",
|
|
213
|
+
text: `Plan truncated from ${total} to ${limit} steps (Free Tier limit). Skipped: ${skippedTools}. Upgrade to Pro for unlimited steps.`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { CdpClient } from "../cdp/cdp-client.js";
|
|
3
|
+
import type { SessionManager } from "../cdp/session-manager.js";
|
|
4
|
+
import type { ToolResponse } from "../types.js";
|
|
5
|
+
export declare const screenshotSchema: z.ZodObject<{
|
|
6
|
+
full_page: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
7
|
+
som: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
full_page: boolean;
|
|
10
|
+
som: boolean;
|
|
11
|
+
}, {
|
|
12
|
+
full_page?: boolean | undefined;
|
|
13
|
+
som?: boolean | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
export type ScreenshotParams = z.infer<typeof screenshotSchema>;
|
|
16
|
+
export declare function screenshotHandler(params: ScreenshotParams, cdpClient: CdpClient, sessionId?: string, sessionManager?: SessionManager): Promise<ToolResponse>;
|