@pcamarajr/scout 0.6.0 → 0.7.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/dist/cli.js +121 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/credentials.d.ts +73 -0
- package/dist/credentials.js +196 -0
- package/dist/credentials.js.map +1 -0
- package/dist/engine.js +5 -8
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runner/agent-tools.d.ts +45 -0
- package/dist/runner/agent-tools.js +151 -0
- package/dist/runner/agent-tools.js.map +1 -0
- package/dist/runner/ai-runner.d.ts +11 -35
- package/dist/runner/ai-runner.js +36 -229
- package/dist/runner/ai-runner.js.map +1 -1
- package/dist/runner/engines/ai-sdk.d.ts +58 -0
- package/dist/runner/engines/ai-sdk.js +144 -0
- package/dist/runner/engines/ai-sdk.js.map +1 -0
- package/dist/runner/engines/claude-agent-sdk.d.ts +11 -0
- package/dist/runner/engines/claude-agent-sdk.js +117 -0
- package/dist/runner/engines/claude-agent-sdk.js.map +1 -0
- package/dist/runner/engines/index.d.ts +20 -0
- package/dist/runner/engines/index.js +28 -0
- package/dist/runner/engines/index.js.map +1 -0
- package/dist/runner/engines/types.d.ts +68 -0
- package/dist/runner/engines/types.js +37 -0
- package/dist/runner/engines/types.js.map +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { anthropic } from "@ai-sdk/anthropic";
|
|
2
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
3
|
+
import { createVertex } from "@ai-sdk/google-vertex";
|
|
4
|
+
import { openai } from "@ai-sdk/openai";
|
|
5
|
+
import { generateText, stepCountIs, tool, } from "ai";
|
|
6
|
+
import { detectAiCredentials } from "../../credentials.js";
|
|
7
|
+
/**
|
|
8
|
+
* Maps a provider + model id onto the matching AI SDK `LanguageModel`.
|
|
9
|
+
*
|
|
10
|
+
* anthropic → @ai-sdk/anthropic
|
|
11
|
+
* openai → @ai-sdk/openai
|
|
12
|
+
* google → @ai-sdk/google when a Gemini/Generative-AI API key is present;
|
|
13
|
+
* otherwise @ai-sdk/google-vertex (keyless, via Application Default
|
|
14
|
+
* Credentials). The split is driven by the same credential ladder
|
|
15
|
+
* `detectAiCredentials("google")` reports, so the engine and
|
|
16
|
+
* `scout doctor` agree on which sub-provider runs.
|
|
17
|
+
*
|
|
18
|
+
* For Vertex we pass `project` from GOOGLE_CLOUD_PROJECT when set (the provider
|
|
19
|
+
* otherwise reads GOOGLE_VERTEX_PROJECT) and default `location` to
|
|
20
|
+
* GOOGLE_VERTEX_LOCATION or "us-central1" — the Vertex provider requires a
|
|
21
|
+
* location eagerly at model construction, so we supply a sensible default to
|
|
22
|
+
* keep the keyless path zero-config. ADC itself comes from google-auth-library.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveModel(provider, modelId) {
|
|
25
|
+
switch (provider) {
|
|
26
|
+
case "anthropic":
|
|
27
|
+
return anthropic(modelId);
|
|
28
|
+
case "openai":
|
|
29
|
+
return openai(modelId);
|
|
30
|
+
case "google": {
|
|
31
|
+
const status = detectAiCredentials("google");
|
|
32
|
+
const usesApiKey = status.ok && status.source !== undefined && /API_KEY$/.test(status.source);
|
|
33
|
+
if (usesApiKey)
|
|
34
|
+
return createGoogleGenerativeAI()(modelId);
|
|
35
|
+
const project = process.env.GOOGLE_CLOUD_PROJECT?.trim();
|
|
36
|
+
const location = process.env.GOOGLE_VERTEX_LOCATION?.trim() || "us-central1";
|
|
37
|
+
return createVertex({ location, ...(project ? { project } : {}) })(modelId);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Second engine, built on the Vercel AI SDK. It runs the SAME engine-neutral
|
|
43
|
+
* ScoutTool set through `generateText`'s tool-calling loop, against Anthropic,
|
|
44
|
+
* Google (Gemini API key or Vertex ADC) or OpenAI — selected per the spec's
|
|
45
|
+
* provider via {@link resolveModel}. The shared orchestrator owns prompts,
|
|
46
|
+
* verdict capture and the forced-verdict rescue — this class only drives the SDK
|
|
47
|
+
* loop and maps the SDK's `finishReason` into the QueryEndInfo vocabulary the
|
|
48
|
+
* rescue understands.
|
|
49
|
+
*/
|
|
50
|
+
export class AiSdkEngine {
|
|
51
|
+
opts;
|
|
52
|
+
constructor(opts = {}) {
|
|
53
|
+
this.opts = opts;
|
|
54
|
+
}
|
|
55
|
+
async run(spec) {
|
|
56
|
+
const model = this.opts.model ?? resolveModel(spec.provider, spec.model);
|
|
57
|
+
const tools = buildAiSdkTools(spec.tools);
|
|
58
|
+
const transcript = [];
|
|
59
|
+
// Running conversation so resume() can append the rescue prompt and
|
|
60
|
+
// continue from where the agent left off.
|
|
61
|
+
const messages = [{ role: "user", content: spec.userPrompt }];
|
|
62
|
+
const abortController = new AbortController();
|
|
63
|
+
const step = async (maxTurns) => {
|
|
64
|
+
try {
|
|
65
|
+
const result = await generateText({
|
|
66
|
+
model,
|
|
67
|
+
system: spec.systemPrompt,
|
|
68
|
+
messages,
|
|
69
|
+
tools,
|
|
70
|
+
stopWhen: stepCountIs(maxTurns),
|
|
71
|
+
abortSignal: abortController.signal,
|
|
72
|
+
});
|
|
73
|
+
// Collect assistant text across every step in order.
|
|
74
|
+
for (const s of result.steps) {
|
|
75
|
+
if (s.text && s.text.trim())
|
|
76
|
+
transcript.push(s.text.trim());
|
|
77
|
+
}
|
|
78
|
+
// Persist the full assistant/tool exchange so the next step continues it.
|
|
79
|
+
messages.push(...result.response.messages);
|
|
80
|
+
return toEndInfo(result.finishReason, result.steps.length);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
subtype: "error_during_execution",
|
|
85
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const end = await step(spec.maxTurns);
|
|
90
|
+
const resume = async (prompt, maxTurns) => {
|
|
91
|
+
const before = transcript.length;
|
|
92
|
+
messages.push({ role: "user", content: prompt });
|
|
93
|
+
const resumeEnd = await step(maxTurns);
|
|
94
|
+
return { end: resumeEnd, transcript: transcript.slice(before) };
|
|
95
|
+
};
|
|
96
|
+
return { end, transcript, resume };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Maps the AI SDK `finishReason` onto the QueryEndInfo.subtype vocabulary that
|
|
101
|
+
* {@link describeNoVerdict} and the forced-verdict rescue already speak.
|
|
102
|
+
*
|
|
103
|
+
* tool-calls / length → "error_max_turns" (hit the step budget mid-flight)
|
|
104
|
+
* stop → "success" (model ended its turn cleanly)
|
|
105
|
+
* error / content-filter / other → "error_during_execution"
|
|
106
|
+
*
|
|
107
|
+
* Rationale: when the loop stops on `tool-calls` it means `stopWhen` cut it off
|
|
108
|
+
* with a tool call still pending — i.e. it would have kept going, the budget ran
|
|
109
|
+
* out (exactly the Agent SDK's `error_max_turns`). `length` is the token-budget
|
|
110
|
+
* analog. Only a clean `stop` means the model chose to end its turn.
|
|
111
|
+
*/
|
|
112
|
+
export function toEndInfo(finishReason, numTurns) {
|
|
113
|
+
switch (finishReason) {
|
|
114
|
+
case "tool-calls":
|
|
115
|
+
case "length":
|
|
116
|
+
return { subtype: "error_max_turns", numTurns };
|
|
117
|
+
case "stop":
|
|
118
|
+
return { subtype: "success", numTurns };
|
|
119
|
+
default:
|
|
120
|
+
return { subtype: "error_during_execution", numTurns, errors: [`finishReason=${finishReason}`] };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Adapts the engine-neutral ScoutTool set into AI SDK tools. `execute` returns
|
|
125
|
+
* the tool text; on a tool error we return the error string (prefixed "ERRO:",
|
|
126
|
+
* same as the handler produces) rather than throwing. Returning a string keeps
|
|
127
|
+
* the model in the loop with the failure visible — the same recovery affordance
|
|
128
|
+
* the Agent SDK gives via an isError tool result — instead of aborting the run.
|
|
129
|
+
*/
|
|
130
|
+
function buildAiSdkTools(scoutTools) {
|
|
131
|
+
const entries = scoutTools.map((scoutTool) => [
|
|
132
|
+
scoutTool.name,
|
|
133
|
+
tool({
|
|
134
|
+
description: scoutTool.description,
|
|
135
|
+
inputSchema: scoutTool.schema,
|
|
136
|
+
execute: async (args) => {
|
|
137
|
+
const result = await scoutTool.handler(args);
|
|
138
|
+
return result.text;
|
|
139
|
+
},
|
|
140
|
+
}),
|
|
141
|
+
]);
|
|
142
|
+
return Object.fromEntries(entries);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=ai-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-sdk.js","sourceRoot":"","sources":["../../../src/runner/engines/ai-sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentEngine, EngineRunSpec, EngineSession } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The original, trusted engine: runs the verification through the
|
|
4
|
+
* `@anthropic-ai/claude-agent-sdk` subprocess. Behavior here is intentionally
|
|
5
|
+
* IDENTICAL to the pre-refactor ai-runner: bypassPermissions, empty
|
|
6
|
+
* settingSources, allowedTools scoped to the in-process MCP browser server, the
|
|
7
|
+
* query()+drain() loop, and an abort-in-finally so no subprocess outlives a run.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClaudeAgentSdkEngine implements AgentEngine {
|
|
10
|
+
run(spec: EngineRunSpec): Promise<EngineSession>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createSdkMcpServer, query, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* The original, trusted engine: runs the verification through the
|
|
4
|
+
* `@anthropic-ai/claude-agent-sdk` subprocess. Behavior here is intentionally
|
|
5
|
+
* IDENTICAL to the pre-refactor ai-runner: bypassPermissions, empty
|
|
6
|
+
* settingSources, allowedTools scoped to the in-process MCP browser server, the
|
|
7
|
+
* query()+drain() loop, and an abort-in-finally so no subprocess outlives a run.
|
|
8
|
+
*/
|
|
9
|
+
export class ClaudeAgentSdkEngine {
|
|
10
|
+
async run(spec) {
|
|
11
|
+
const browserServer = createSdkMcpServer({
|
|
12
|
+
name: "browser",
|
|
13
|
+
version: "1.0.0",
|
|
14
|
+
tools: spec.tools.map(toAgentSdkTool),
|
|
15
|
+
});
|
|
16
|
+
const baseOptions = {
|
|
17
|
+
model: spec.model,
|
|
18
|
+
systemPrompt: spec.systemPrompt,
|
|
19
|
+
mcpServers: { browser: browserServer },
|
|
20
|
+
allowedTools: ["mcp__browser__*"],
|
|
21
|
+
tools: [],
|
|
22
|
+
settingSources: [],
|
|
23
|
+
permissionMode: "bypassPermissions",
|
|
24
|
+
};
|
|
25
|
+
const transcript = [];
|
|
26
|
+
let sessionId;
|
|
27
|
+
let endInfo;
|
|
28
|
+
// Drains a query, collecting transcript/session/end info. Always aborts at
|
|
29
|
+
// the end so no claude-agent-sdk subprocess outlives the run.
|
|
30
|
+
const drain = async (q, controller) => {
|
|
31
|
+
try {
|
|
32
|
+
for await (const message of q) {
|
|
33
|
+
if ("session_id" in message && message.session_id)
|
|
34
|
+
sessionId = message.session_id;
|
|
35
|
+
if (message.type === "assistant") {
|
|
36
|
+
for (const block of message.message.content) {
|
|
37
|
+
if (block.type === "text" && block.text.trim())
|
|
38
|
+
transcript.push(block.text.trim());
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (message.type === "result") {
|
|
42
|
+
endInfo = {
|
|
43
|
+
subtype: message.subtype,
|
|
44
|
+
numTurns: message.num_turns,
|
|
45
|
+
errors: "errors" in message ? message.errors : undefined,
|
|
46
|
+
};
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
controller.abort();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const mainController = new AbortController();
|
|
56
|
+
try {
|
|
57
|
+
await drain(query({
|
|
58
|
+
prompt: spec.userPrompt,
|
|
59
|
+
options: { ...baseOptions, maxTurns: spec.maxTurns, abortController: mainController },
|
|
60
|
+
}), mainController);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
endInfo = {
|
|
64
|
+
subtype: "sdk_error",
|
|
65
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const resume = async (prompt, maxTurns) => {
|
|
69
|
+
const resumeTranscript = [];
|
|
70
|
+
let resumeEnd;
|
|
71
|
+
if (!sessionId) {
|
|
72
|
+
return { end: { subtype: "no_session" }, transcript: resumeTranscript };
|
|
73
|
+
}
|
|
74
|
+
const rescueController = new AbortController();
|
|
75
|
+
// Reuse drain() so transcript/session/end semantics stay identical, then
|
|
76
|
+
// split off only what the rescue produced for the resume result.
|
|
77
|
+
const beforeLen = transcript.length;
|
|
78
|
+
try {
|
|
79
|
+
await drain(query({
|
|
80
|
+
prompt,
|
|
81
|
+
options: { ...baseOptions, maxTurns, resume: sessionId, abortController: rescueController },
|
|
82
|
+
}), rescueController);
|
|
83
|
+
resumeEnd = endInfo;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
resumeEnd = {
|
|
87
|
+
subtype: "sdk_error",
|
|
88
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
resumeTranscript.push(...transcript.slice(beforeLen));
|
|
92
|
+
return { end: resumeEnd ?? { subtype: "no_session" }, transcript: resumeTranscript };
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
get end() {
|
|
96
|
+
return endInfo ?? { subtype: "sdk_error" };
|
|
97
|
+
},
|
|
98
|
+
transcript,
|
|
99
|
+
resume,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Adapts an engine-neutral ScoutTool into the Agent SDK `tool()` shape. The
|
|
105
|
+
* Agent SDK's tool() wants a raw Zod shape, so we hand it `schema.shape`, and we
|
|
106
|
+
* map our normalized {text, isError} result back into a CallToolResult.
|
|
107
|
+
*/
|
|
108
|
+
function toAgentSdkTool(scoutTool) {
|
|
109
|
+
return tool(scoutTool.name, scoutTool.description, scoutTool.schema.shape, async (args) => {
|
|
110
|
+
const result = await scoutTool.handler(args);
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text", text: result.text }],
|
|
113
|
+
...(result.isError ? { isError: true } : {}),
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=claude-agent-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-agent-sdk.js","sourceRoot":"","sources":["../../../src/runner/engines/claude-agent-sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AiProvider } from "../../credentials.js";
|
|
2
|
+
import { AiSdkEngine } from "./ai-sdk.js";
|
|
3
|
+
import { ClaudeAgentSdkEngine } from "./claude-agent-sdk.js";
|
|
4
|
+
import type { AgentEngine } from "./types.js";
|
|
5
|
+
/** The two engines Scout can run an AI verification through. */
|
|
6
|
+
export type EngineKind = "agent-sdk" | "ai-sdk";
|
|
7
|
+
/**
|
|
8
|
+
* Resolves which engine to use. Explicit preference (SCOUT_ENGINE / config
|
|
9
|
+
* `engine`) wins. Otherwise the default is forward-looking: the trusted Agent
|
|
10
|
+
* SDK for Anthropic, the AI SDK for non-Anthropic providers (which is the only
|
|
11
|
+
* engine that can reach them — still gated by credential detection until those
|
|
12
|
+
* providers are wired up).
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveEngineKind(provider: AiProvider, enginePref: EngineKind | undefined): EngineKind;
|
|
15
|
+
/** Instantiates the engine for a provider + explicit preference. */
|
|
16
|
+
export declare function selectEngine(provider: AiProvider, enginePref: EngineKind | undefined): AgentEngine;
|
|
17
|
+
/** Parses a raw SCOUT_ENGINE / config value, ignoring unknown strings. */
|
|
18
|
+
export declare function parseEngineKind(value: string | undefined): EngineKind | undefined;
|
|
19
|
+
export { AiSdkEngine, ClaudeAgentSdkEngine };
|
|
20
|
+
export type { AgentEngine };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AiSdkEngine } from "./ai-sdk.js";
|
|
2
|
+
import { ClaudeAgentSdkEngine } from "./claude-agent-sdk.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolves which engine to use. Explicit preference (SCOUT_ENGINE / config
|
|
5
|
+
* `engine`) wins. Otherwise the default is forward-looking: the trusted Agent
|
|
6
|
+
* SDK for Anthropic, the AI SDK for non-Anthropic providers (which is the only
|
|
7
|
+
* engine that can reach them — still gated by credential detection until those
|
|
8
|
+
* providers are wired up).
|
|
9
|
+
*/
|
|
10
|
+
export function resolveEngineKind(provider, enginePref) {
|
|
11
|
+
if (enginePref)
|
|
12
|
+
return enginePref;
|
|
13
|
+
return provider === "anthropic" ? "agent-sdk" : "ai-sdk";
|
|
14
|
+
}
|
|
15
|
+
/** Instantiates the engine for a provider + explicit preference. */
|
|
16
|
+
export function selectEngine(provider, enginePref) {
|
|
17
|
+
return resolveEngineKind(provider, enginePref) === "ai-sdk"
|
|
18
|
+
? new AiSdkEngine()
|
|
19
|
+
: new ClaudeAgentSdkEngine();
|
|
20
|
+
}
|
|
21
|
+
/** Parses a raw SCOUT_ENGINE / config value, ignoring unknown strings. */
|
|
22
|
+
export function parseEngineKind(value) {
|
|
23
|
+
if (value === "agent-sdk" || value === "ai-sdk")
|
|
24
|
+
return value;
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
export { AiSdkEngine, ClaudeAgentSdkEngine };
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runner/engines/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAM7D;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAoB,EACpB,UAAkC;IAElC,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC3D,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAC1B,QAAoB,EACpB,UAAkC;IAElC,OAAO,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,QAAQ;QACzD,CAAC,CAAC,IAAI,WAAW,EAAE;QACnB,CAAC,CAAC,IAAI,oBAAoB,EAAE,CAAC;AACjC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,KAAyB;IACvD,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AiProvider } from "../../credentials.js";
|
|
2
|
+
import type { Step, Verdict } from "../../types.js";
|
|
3
|
+
import type { ScoutTool } from "../agent-tools.js";
|
|
4
|
+
export interface AiRunOutcome {
|
|
5
|
+
verdict: Verdict;
|
|
6
|
+
reason: string;
|
|
7
|
+
steps: Step[];
|
|
8
|
+
transcript: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Set when the runner itself failed to produce a verdict (agent never called
|
|
11
|
+
* scout_verdict) — NOT a UI judgment. Callers may retry and must report it
|
|
12
|
+
* as an infrastructure failure, never as "the scenario is blocked by the UI".
|
|
13
|
+
*/
|
|
14
|
+
runnerFailure?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* How an engine run ended, for no-verdict diagnostics. The Agent SDK fills this
|
|
18
|
+
* from the SDK `result` message; the AI SDK engine maps its `finishReason` into
|
|
19
|
+
* the same `subtype` vocabulary so {@link describeNoVerdict} works unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export interface QueryEndInfo {
|
|
22
|
+
subtype: string;
|
|
23
|
+
numTurns?: number;
|
|
24
|
+
errors?: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Human-readable cause for a run that ended without scout_verdict.
|
|
28
|
+
* Distinguishes runner-infrastructure causes (turn budget, SDK errors) from
|
|
29
|
+
* an agent that simply stopped talking.
|
|
30
|
+
*/
|
|
31
|
+
export declare function describeNoVerdict(end: QueryEndInfo | undefined, maxTurns: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Records navigation relative to the configured baseUrl so cached scripts
|
|
34
|
+
* survive --base-url / SCOUT_BASE_URL pointing at another server. URLs that
|
|
35
|
+
* merely share the prefix (http://localhost:3000x) or live on other hosts
|
|
36
|
+
* stay absolute.
|
|
37
|
+
*/
|
|
38
|
+
export declare function relativizeUrl(url: string, baseUrl: string): string;
|
|
39
|
+
/** Everything an engine needs to drive one agent run. */
|
|
40
|
+
export interface EngineRunSpec {
|
|
41
|
+
/** Inferred from the model id; selects the AI SDK provider in the AI SDK engine. */
|
|
42
|
+
provider: AiProvider;
|
|
43
|
+
model: string;
|
|
44
|
+
systemPrompt: string;
|
|
45
|
+
userPrompt: string;
|
|
46
|
+
tools: ScoutTool[];
|
|
47
|
+
maxTurns: number;
|
|
48
|
+
}
|
|
49
|
+
/** The result of resuming a session (the forced-verdict rescue). */
|
|
50
|
+
export interface EngineResumeResult {
|
|
51
|
+
end: QueryEndInfo;
|
|
52
|
+
transcript: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A live (or just-finished) engine session. The shared orchestrator reads
|
|
56
|
+
* `end`/`transcript`, and — if no verdict was captured — calls `resume()` to
|
|
57
|
+
* run the forced-verdict rescue with a small turn budget.
|
|
58
|
+
*/
|
|
59
|
+
export interface EngineSession {
|
|
60
|
+
end: QueryEndInfo;
|
|
61
|
+
/** Assistant text collected during the run, in order. */
|
|
62
|
+
transcript: string[];
|
|
63
|
+
resume(prompt: string, maxTurns: number): Promise<EngineResumeResult>;
|
|
64
|
+
}
|
|
65
|
+
/** A pluggable agent engine. `run` performs the initial verification pass. */
|
|
66
|
+
export interface AgentEngine {
|
|
67
|
+
run(spec: EngineRunSpec): Promise<EngineSession>;
|
|
68
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable cause for a run that ended without scout_verdict.
|
|
3
|
+
* Distinguishes runner-infrastructure causes (turn budget, SDK errors) from
|
|
4
|
+
* an agent that simply stopped talking.
|
|
5
|
+
*/
|
|
6
|
+
export function describeNoVerdict(end, maxTurns) {
|
|
7
|
+
if (!end)
|
|
8
|
+
return "a sessão do agente terminou sem emitir resultado (subprocesso morreu?)";
|
|
9
|
+
switch (end.subtype) {
|
|
10
|
+
case "error_max_turns":
|
|
11
|
+
return `o agente estourou o limite de ${maxTurns} turns sem chamar scout_verdict`;
|
|
12
|
+
case "error_during_execution":
|
|
13
|
+
return `erro durante a execução do agente${end.errors?.length ? `: ${end.errors.join("; ")}` : ""}`;
|
|
14
|
+
case "success":
|
|
15
|
+
return "o agente encerrou normalmente sem chamar scout_verdict";
|
|
16
|
+
default:
|
|
17
|
+
return `a sessão do agente terminou com "${end.subtype}"${end.errors?.length ? `: ${end.errors.join("; ")}` : ""}`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Records navigation relative to the configured baseUrl so cached scripts
|
|
22
|
+
* survive --base-url / SCOUT_BASE_URL pointing at another server. URLs that
|
|
23
|
+
* merely share the prefix (http://localhost:3000x) or live on other hosts
|
|
24
|
+
* stay absolute.
|
|
25
|
+
*/
|
|
26
|
+
export function relativizeUrl(url, baseUrl) {
|
|
27
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
28
|
+
if (url === base || url === `${base}/`)
|
|
29
|
+
return "/";
|
|
30
|
+
if (url.startsWith(base)) {
|
|
31
|
+
const rest = url.slice(base.length);
|
|
32
|
+
if (rest.startsWith("/") || rest.startsWith("?") || rest.startsWith("#"))
|
|
33
|
+
return rest;
|
|
34
|
+
}
|
|
35
|
+
return url;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/runner/engines/types.ts"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAA6B,EAAE,QAAgB;IAC/E,IAAI,CAAC,GAAG;QAAE,OAAO,wEAAwE,CAAC;IAC1F,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,iBAAiB;YACpB,OAAO,iCAAiC,QAAQ,iCAAiC,CAAC;QACpF,KAAK,wBAAwB;YAC3B,OAAO,oCAAoC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACtG,KAAK,SAAS;YACZ,OAAO,wDAAwD,CAAC;QAClE;YACE,OAAO,oCAAoC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACvH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAe;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACnD,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACxF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pcamarajr/scout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Self-healing browser QA: natural-language scenarios verified by an AI agent, replayed deterministically in CI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,12 +43,18 @@
|
|
|
43
43
|
"dev": "tsx src/cli.ts",
|
|
44
44
|
"typecheck": "tsc --noEmit",
|
|
45
45
|
"test": "node --import tsx --test tests/*.test.ts",
|
|
46
|
+
"smoke": "node scripts/smoke.mjs",
|
|
46
47
|
"prepublishOnly": "npm run build",
|
|
47
48
|
"prepare": "husky"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
51
|
+
"@ai-sdk/anthropic": "^3.0.85",
|
|
52
|
+
"@ai-sdk/google": "^3.0.83",
|
|
53
|
+
"@ai-sdk/google-vertex": "^4.0.147",
|
|
54
|
+
"@ai-sdk/openai": "^3.0.73",
|
|
50
55
|
"@anthropic-ai/claude-agent-sdk": "^0.3.0",
|
|
51
56
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
57
|
+
"ai": "^6.0.208",
|
|
52
58
|
"commander": "^13.1.0",
|
|
53
59
|
"gray-matter": "^4.0.3",
|
|
54
60
|
"playwright": "^1.52.0",
|