@wingman-ai/gateway 0.2.1 → 0.2.3
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/.wingman/agents/README.md +1 -0
- package/.wingman/agents/coding/agent.md +179 -112
- package/.wingman/agents/coding/implementor.md +50 -3
- package/.wingman/agents/main/agent.md +4 -0
- package/README.md +1 -0
- package/dist/agent/config/agentConfig.cjs +30 -1
- package/dist/agent/config/agentConfig.js +30 -1
- package/dist/agent/config/modelFactory.cjs +22 -2
- package/dist/agent/config/modelFactory.d.ts +2 -0
- package/dist/agent/config/modelFactory.js +22 -2
- package/dist/agent/tests/agentConfig.test.cjs +39 -0
- package/dist/agent/tests/agentConfig.test.js +39 -0
- package/dist/agent/tests/modelFactory.test.cjs +12 -5
- package/dist/agent/tests/modelFactory.test.js +12 -5
- package/dist/cli/commands/init.cjs +7 -6
- package/dist/cli/commands/init.js +7 -6
- package/dist/cli/commands/provider.cjs +17 -3
- package/dist/cli/commands/provider.js +17 -3
- package/dist/cli/config/loader.cjs +27 -0
- package/dist/cli/config/loader.js +27 -0
- package/dist/cli/config/schema.cjs +80 -2
- package/dist/cli/config/schema.d.ts +88 -0
- package/dist/cli/config/schema.js +67 -1
- package/dist/cli/core/agentInvoker.cjs +242 -17
- package/dist/cli/core/agentInvoker.d.ts +46 -4
- package/dist/cli/core/agentInvoker.js +214 -13
- package/dist/cli/core/sessionManager.cjs +32 -5
- package/dist/cli/core/sessionManager.js +32 -5
- package/dist/cli/index.cjs +6 -5
- package/dist/cli/index.js +6 -5
- package/dist/cli/types.d.ts +32 -0
- package/dist/gateway/http/sessions.cjs +7 -7
- package/dist/gateway/http/sessions.js +7 -7
- package/dist/gateway/server.cjs +230 -28
- package/dist/gateway/server.d.ts +11 -1
- package/dist/gateway/server.js +230 -28
- package/dist/gateway/types.d.ts +5 -1
- package/dist/gateway/validation.cjs +1 -0
- package/dist/gateway/validation.d.ts +2 -0
- package/dist/gateway/validation.js +1 -0
- package/dist/providers/codex.cjs +167 -0
- package/dist/providers/codex.d.ts +15 -0
- package/dist/providers/codex.js +127 -0
- package/dist/providers/credentials.cjs +8 -0
- package/dist/providers/credentials.js +8 -0
- package/dist/providers/registry.cjs +11 -0
- package/dist/providers/registry.d.ts +1 -1
- package/dist/providers/registry.js +11 -0
- package/dist/tests/agentInvokerSummarization.test.cjs +296 -0
- package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
- package/dist/tests/agentInvokerSummarization.test.js +290 -0
- package/dist/tests/cli-config-loader.test.cjs +88 -0
- package/dist/tests/cli-config-loader.test.js +88 -0
- package/dist/tests/codex-credentials-precedence.test.cjs +94 -0
- package/dist/tests/codex-credentials-precedence.test.d.ts +1 -0
- package/dist/tests/codex-credentials-precedence.test.js +88 -0
- package/dist/tests/codex-provider.test.cjs +186 -0
- package/dist/tests/codex-provider.test.d.ts +1 -0
- package/dist/tests/codex-provider.test.js +180 -0
- package/dist/tests/gateway.test.cjs +173 -1
- package/dist/tests/gateway.test.js +173 -1
- package/dist/tests/provider-command-codex.test.cjs +57 -0
- package/dist/tests/provider-command-codex.test.d.ts +1 -0
- package/dist/tests/provider-command-codex.test.js +51 -0
- package/dist/tests/sessionStateMessages.test.cjs +38 -0
- package/dist/tests/sessionStateMessages.test.js +38 -0
- package/dist/webui/assets/index-BVMavpud.css +11 -0
- package/dist/webui/assets/index-DCB2aVVf.js +182 -0
- package/dist/webui/index.html +2 -2
- package/package.json +3 -1
- package/dist/webui/assets/index-BytPznA_.css +0 -1
- package/dist/webui/assets/index-u_5qlVip.js +0 -176
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createLogger } from "../logger.js";
|
|
5
|
+
const CODEX_HOME_ENV = "CODEX_HOME";
|
|
6
|
+
const CODEX_AUTH_FILE = "auth.json";
|
|
7
|
+
const DEFAULT_CODEX_INSTRUCTIONS = "You are Wingman, a coding assistant. Follow the user's request exactly and keep tool usage focused.";
|
|
8
|
+
const logger = createLogger();
|
|
9
|
+
function getCodexAuthPath() {
|
|
10
|
+
const codexHome = process.env[CODEX_HOME_ENV]?.trim();
|
|
11
|
+
if (codexHome) return join(codexHome, CODEX_AUTH_FILE);
|
|
12
|
+
return join(homedir(), ".codex", CODEX_AUTH_FILE);
|
|
13
|
+
}
|
|
14
|
+
function resolveCodexAuthFromFile() {
|
|
15
|
+
const authPath = getCodexAuthPath();
|
|
16
|
+
if (!existsSync(authPath)) return {
|
|
17
|
+
authPath
|
|
18
|
+
};
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
21
|
+
if (!parsed || "object" != typeof parsed) return {
|
|
22
|
+
authPath
|
|
23
|
+
};
|
|
24
|
+
const root = parsed;
|
|
25
|
+
const tokens = root.tokens && "object" == typeof root.tokens ? root.tokens : void 0;
|
|
26
|
+
const accessToken = firstNonEmptyString([
|
|
27
|
+
tokens?.access_token,
|
|
28
|
+
root.access_token
|
|
29
|
+
]);
|
|
30
|
+
const accountId = firstNonEmptyString([
|
|
31
|
+
tokens?.account_id,
|
|
32
|
+
root.account_id
|
|
33
|
+
]);
|
|
34
|
+
return {
|
|
35
|
+
accessToken,
|
|
36
|
+
accountId,
|
|
37
|
+
authPath
|
|
38
|
+
};
|
|
39
|
+
} catch {
|
|
40
|
+
return {
|
|
41
|
+
authPath
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function createCodexFetch(options = {}) {
|
|
46
|
+
const baseFetch = options.baseFetch || globalThis.fetch.bind(globalThis);
|
|
47
|
+
return async (input, init)=>{
|
|
48
|
+
const codexAuth = resolveCodexAuthFromFile();
|
|
49
|
+
const accessToken = codexAuth.accessToken || options.fallbackToken;
|
|
50
|
+
const accountId = codexAuth.accountId || options.fallbackAccountId;
|
|
51
|
+
if (!accessToken) throw new Error("Codex credentials missing. Run `codex login` or set CODEX_ACCESS_TOKEN.");
|
|
52
|
+
const headers = new Headers(init?.headers || {});
|
|
53
|
+
headers.delete("authorization");
|
|
54
|
+
headers.delete("x-api-key");
|
|
55
|
+
headers.set("Authorization", `Bearer ${accessToken}`);
|
|
56
|
+
if (accountId) headers.set("ChatGPT-Account-ID", accountId);
|
|
57
|
+
const body = withCodexRequestDefaults(init?.body);
|
|
58
|
+
const response = await baseFetch(input, {
|
|
59
|
+
...init,
|
|
60
|
+
headers,
|
|
61
|
+
body
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
let responseBody = "";
|
|
65
|
+
try {
|
|
66
|
+
responseBody = await response.clone().text();
|
|
67
|
+
} catch {}
|
|
68
|
+
const preview = responseBody.trim().slice(0, 1200);
|
|
69
|
+
logger.warn(`Codex request failed (${response.status} ${response.statusText || ""})`, {
|
|
70
|
+
url: "string" == typeof input ? input : input instanceof URL ? input.toString() : input.url,
|
|
71
|
+
bodyPresent: preview.length > 0,
|
|
72
|
+
bodyPreview: preview || null
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return response;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function withCodexRequestDefaults(body) {
|
|
79
|
+
if ("string" != typeof body || !body.trim()) return body;
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(body);
|
|
82
|
+
if (!parsed || "object" != typeof parsed || Array.isArray(parsed)) return body;
|
|
83
|
+
const root = stripUnsupportedCodexParams(parsed);
|
|
84
|
+
const instructions = "string" == typeof root.instructions && root.instructions.trim() ? root.instructions.trim() : extractInstructionsFromInput(root.input) || DEFAULT_CODEX_INSTRUCTIONS;
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
...root,
|
|
87
|
+
store: false,
|
|
88
|
+
instructions
|
|
89
|
+
});
|
|
90
|
+
} catch {
|
|
91
|
+
return body;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function stripUnsupportedCodexParams(payload) {
|
|
95
|
+
const next = {
|
|
96
|
+
...payload
|
|
97
|
+
};
|
|
98
|
+
delete next.temperature;
|
|
99
|
+
return next;
|
|
100
|
+
}
|
|
101
|
+
function extractInstructionsFromInput(input) {
|
|
102
|
+
if (!Array.isArray(input)) return;
|
|
103
|
+
for (const item of input){
|
|
104
|
+
if (!item || "object" != typeof item || Array.isArray(item)) continue;
|
|
105
|
+
const message = item;
|
|
106
|
+
const role = "string" == typeof message.role ? message.role : "";
|
|
107
|
+
if ("system" !== role && "developer" !== role) continue;
|
|
108
|
+
const text = extractTextContent(message.content);
|
|
109
|
+
if (text) return text;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function extractTextContent(content) {
|
|
113
|
+
if ("string" == typeof content && content.trim()) return content.trim();
|
|
114
|
+
if (!Array.isArray(content)) return;
|
|
115
|
+
for (const part of content){
|
|
116
|
+
if (!part || "object" != typeof part || Array.isArray(part)) continue;
|
|
117
|
+
const block = part;
|
|
118
|
+
const text = "string" == typeof block.text ? block.text : "string" == typeof block.content ? block.content : void 0;
|
|
119
|
+
if (!text || !text.trim()) continue;
|
|
120
|
+
const type = "string" == typeof block.type ? block.type : "";
|
|
121
|
+
if (!type || type.includes("text")) return text.trim();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function firstNonEmptyString(values) {
|
|
125
|
+
for (const value of values)if ("string" == typeof value && value.trim()) return value.trim();
|
|
126
|
+
}
|
|
127
|
+
export { createCodexFetch, getCodexAuthPath, resolveCodexAuthFromFile };
|
|
@@ -36,6 +36,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
36
36
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
37
37
|
const external_node_os_namespaceObject = require("node:os");
|
|
38
38
|
const external_node_path_namespaceObject = require("node:path");
|
|
39
|
+
const external_codex_cjs_namespaceObject = require("./codex.cjs");
|
|
39
40
|
const external_registry_cjs_namespaceObject = require("./registry.cjs");
|
|
40
41
|
const CREDENTIALS_VERSION = 1;
|
|
41
42
|
const CREDENTIALS_DIR = (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.homedir)(), ".wingman");
|
|
@@ -121,6 +122,13 @@ function resolveProviderToken(providerName) {
|
|
|
121
122
|
envVar
|
|
122
123
|
};
|
|
123
124
|
}
|
|
125
|
+
if ("codex" === provider.name) {
|
|
126
|
+
const codexAuth = (0, external_codex_cjs_namespaceObject.resolveCodexAuthFromFile)();
|
|
127
|
+
if (codexAuth.accessToken) return {
|
|
128
|
+
token: codexAuth.accessToken,
|
|
129
|
+
source: "credentials"
|
|
130
|
+
};
|
|
131
|
+
}
|
|
124
132
|
const credentials = getProviderCredentials(provider.name);
|
|
125
133
|
const token = credentials?.accessToken ?? credentials?.apiKey ?? credentials?.refreshToken;
|
|
126
134
|
if (token && token.trim()) return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { resolveCodexAuthFromFile } from "./codex.js";
|
|
4
5
|
import { getProviderSpec } from "./registry.js";
|
|
5
6
|
const CREDENTIALS_VERSION = 1;
|
|
6
7
|
const CREDENTIALS_DIR = join(homedir(), ".wingman");
|
|
@@ -86,6 +87,13 @@ function resolveProviderToken(providerName) {
|
|
|
86
87
|
envVar
|
|
87
88
|
};
|
|
88
89
|
}
|
|
90
|
+
if ("codex" === provider.name) {
|
|
91
|
+
const codexAuth = resolveCodexAuthFromFile();
|
|
92
|
+
if (codexAuth.accessToken) return {
|
|
93
|
+
token: codexAuth.accessToken,
|
|
94
|
+
source: "credentials"
|
|
95
|
+
};
|
|
96
|
+
}
|
|
89
97
|
const credentials = getProviderCredentials(provider.name);
|
|
90
98
|
const token = credentials?.accessToken ?? credentials?.apiKey ?? credentials?.refreshToken;
|
|
91
99
|
if (token && token.trim()) return {
|
|
@@ -47,6 +47,17 @@ const PROVIDERS = {
|
|
|
47
47
|
],
|
|
48
48
|
category: "model"
|
|
49
49
|
},
|
|
50
|
+
codex: {
|
|
51
|
+
name: "codex",
|
|
52
|
+
label: "OpenAI Codex",
|
|
53
|
+
type: "api-key",
|
|
54
|
+
envVars: [
|
|
55
|
+
"CODEX_ACCESS_TOKEN",
|
|
56
|
+
"CHATGPT_ACCESS_TOKEN"
|
|
57
|
+
],
|
|
58
|
+
baseURL: "https://chatgpt.com/backend-api/codex",
|
|
59
|
+
category: "model"
|
|
60
|
+
},
|
|
50
61
|
openrouter: {
|
|
51
62
|
name: "openrouter",
|
|
52
63
|
label: "OpenRouter",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type ProviderAuthType = "api-key" | "oauth";
|
|
2
2
|
export type ProviderCategory = "model" | "voice";
|
|
3
|
-
export type ProviderName = "anthropic" | "openai" | "openrouter" | "copilot" | "xai" | "lmstudio" | "ollama" | "elevenlabs";
|
|
3
|
+
export type ProviderName = "anthropic" | "openai" | "codex" | "openrouter" | "copilot" | "xai" | "lmstudio" | "ollama" | "elevenlabs";
|
|
4
4
|
export interface ProviderOAuthConfig {
|
|
5
5
|
authorizationUrl: string;
|
|
6
6
|
tokenUrl: string;
|
|
@@ -17,6 +17,17 @@ const PROVIDERS = {
|
|
|
17
17
|
],
|
|
18
18
|
category: "model"
|
|
19
19
|
},
|
|
20
|
+
codex: {
|
|
21
|
+
name: "codex",
|
|
22
|
+
label: "OpenAI Codex",
|
|
23
|
+
type: "api-key",
|
|
24
|
+
envVars: [
|
|
25
|
+
"CODEX_ACCESS_TOKEN",
|
|
26
|
+
"CHATGPT_ACCESS_TOKEN"
|
|
27
|
+
],
|
|
28
|
+
baseURL: "https://chatgpt.com/backend-api/codex",
|
|
29
|
+
category: "model"
|
|
30
|
+
},
|
|
20
31
|
openrouter: {
|
|
21
32
|
name: "openrouter",
|
|
22
33
|
label: "OpenRouter",
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_exports__ = {};
|
|
3
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
4
|
+
const schema_cjs_namespaceObject = require("../cli/config/schema.cjs");
|
|
5
|
+
const agentInvoker_cjs_namespaceObject = require("../cli/core/agentInvoker.cjs");
|
|
6
|
+
const parseConfig = (input)=>{
|
|
7
|
+
const result = (0, schema_cjs_namespaceObject.validateConfig)(input);
|
|
8
|
+
if (!result.success || !result.data) throw new Error(result.error || "Expected config validation to succeed");
|
|
9
|
+
return result.data;
|
|
10
|
+
};
|
|
11
|
+
(0, external_vitest_namespaceObject.describe)("resolveSummarizationMiddlewareSettings", ()=>{
|
|
12
|
+
(0, external_vitest_namespaceObject.it)("returns default summarization settings from config defaults", ()=>{
|
|
13
|
+
const config = parseConfig({});
|
|
14
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveSummarizationMiddlewareSettings)(config)).toEqual({
|
|
15
|
+
maxTokensBeforeSummary: 12000,
|
|
16
|
+
messagesToKeep: 8
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
(0, external_vitest_namespaceObject.it)("returns null when summarization is disabled", ()=>{
|
|
20
|
+
const config = parseConfig({
|
|
21
|
+
summarization: {
|
|
22
|
+
enabled: false
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveSummarizationMiddlewareSettings)(config)).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
(0, external_vitest_namespaceObject.it)("returns custom summarization settings when configured", ()=>{
|
|
28
|
+
const config = parseConfig({
|
|
29
|
+
summarization: {
|
|
30
|
+
enabled: true,
|
|
31
|
+
maxTokensBeforeSummary: 20000,
|
|
32
|
+
messagesToKeep: 10
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveSummarizationMiddlewareSettings)(config)).toEqual({
|
|
36
|
+
maxTokensBeforeSummary: 20000,
|
|
37
|
+
messagesToKeep: 10
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
(0, external_vitest_namespaceObject.describe)("configureDeepAgentSummarizationMiddleware", ()=>{
|
|
42
|
+
(0, external_vitest_namespaceObject.it)("replaces built-in summarization middleware with configured settings", ()=>{
|
|
43
|
+
const agent = {
|
|
44
|
+
options: {
|
|
45
|
+
middleware: [
|
|
46
|
+
{
|
|
47
|
+
name: "todoListMiddleware"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "SummarizationMiddleware",
|
|
51
|
+
marker: "old"
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
(0, agentInvoker_cjs_namespaceObject.configureDeepAgentSummarizationMiddleware)(agent, {
|
|
57
|
+
maxTokensBeforeSummary: 9000,
|
|
58
|
+
messagesToKeep: 5
|
|
59
|
+
}, "openai:gpt-4o-mini");
|
|
60
|
+
(0, external_vitest_namespaceObject.expect)(agent.options.middleware).toHaveLength(2);
|
|
61
|
+
(0, external_vitest_namespaceObject.expect)(agent.options.middleware[1]?.name).toBe("SummarizationMiddleware");
|
|
62
|
+
(0, external_vitest_namespaceObject.expect)(agent.options.middleware[1]?.marker).toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
(0, external_vitest_namespaceObject.it)("removes built-in summarization middleware when disabled", ()=>{
|
|
65
|
+
const agent = {
|
|
66
|
+
options: {
|
|
67
|
+
middleware: [
|
|
68
|
+
{
|
|
69
|
+
name: "todoListMiddleware"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "SummarizationMiddleware"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "patchToolCallsMiddleware"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
(0, agentInvoker_cjs_namespaceObject.configureDeepAgentSummarizationMiddleware)(agent, null);
|
|
81
|
+
(0, external_vitest_namespaceObject.expect)(agent.options.middleware.map((m)=>m.name)).toEqual([
|
|
82
|
+
"todoListMiddleware",
|
|
83
|
+
"patchToolCallsMiddleware"
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
(0, external_vitest_namespaceObject.describe)("resolveModelRetryMiddlewareSettings", ()=>{
|
|
88
|
+
(0, external_vitest_namespaceObject.it)("returns default retry settings when config defaults are used", ()=>{
|
|
89
|
+
const config = parseConfig({});
|
|
90
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveModelRetryMiddlewareSettings)(config)).toEqual({
|
|
91
|
+
maxRetries: 2,
|
|
92
|
+
backoffFactor: 2,
|
|
93
|
+
initialDelayMs: 1000,
|
|
94
|
+
maxDelayMs: 60000,
|
|
95
|
+
jitter: true,
|
|
96
|
+
onFailure: "continue"
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
(0, external_vitest_namespaceObject.it)("returns configured retry settings when enabled", ()=>{
|
|
100
|
+
const config = parseConfig({
|
|
101
|
+
modelRetry: {
|
|
102
|
+
enabled: true,
|
|
103
|
+
maxRetries: 3,
|
|
104
|
+
backoffFactor: 1.5,
|
|
105
|
+
initialDelayMs: 250,
|
|
106
|
+
maxDelayMs: 5000,
|
|
107
|
+
jitter: false,
|
|
108
|
+
onFailure: "error"
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveModelRetryMiddlewareSettings)(config)).toEqual({
|
|
112
|
+
maxRetries: 3,
|
|
113
|
+
backoffFactor: 1.5,
|
|
114
|
+
initialDelayMs: 250,
|
|
115
|
+
maxDelayMs: 5000,
|
|
116
|
+
jitter: false,
|
|
117
|
+
onFailure: "error"
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
(0, external_vitest_namespaceObject.describe)("resolveToolRetryMiddlewareSettings", ()=>{
|
|
122
|
+
(0, external_vitest_namespaceObject.it)("returns null by default", ()=>{
|
|
123
|
+
const config = parseConfig({});
|
|
124
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveToolRetryMiddlewareSettings)(config)).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
(0, external_vitest_namespaceObject.it)("returns configured retry settings and tool filter when enabled", ()=>{
|
|
127
|
+
const config = parseConfig({
|
|
128
|
+
toolRetry: {
|
|
129
|
+
enabled: true,
|
|
130
|
+
maxRetries: 4,
|
|
131
|
+
backoffFactor: 2,
|
|
132
|
+
initialDelayMs: 500,
|
|
133
|
+
maxDelayMs: 10000,
|
|
134
|
+
jitter: true,
|
|
135
|
+
onFailure: "continue",
|
|
136
|
+
tools: [
|
|
137
|
+
"internet_search",
|
|
138
|
+
"web_crawler"
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveToolRetryMiddlewareSettings)(config)).toEqual({
|
|
143
|
+
maxRetries: 4,
|
|
144
|
+
backoffFactor: 2,
|
|
145
|
+
initialDelayMs: 500,
|
|
146
|
+
maxDelayMs: 10000,
|
|
147
|
+
jitter: true,
|
|
148
|
+
onFailure: "continue",
|
|
149
|
+
tools: [
|
|
150
|
+
"internet_search",
|
|
151
|
+
"web_crawler"
|
|
152
|
+
]
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
(0, external_vitest_namespaceObject.describe)("resolveHumanInTheLoopSettings", ()=>{
|
|
157
|
+
(0, external_vitest_namespaceObject.it)("returns null by default", ()=>{
|
|
158
|
+
const config = parseConfig({});
|
|
159
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveHumanInTheLoopSettings)(config)).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
(0, external_vitest_namespaceObject.it)("returns null when enabled but no tool policy is defined", ()=>{
|
|
162
|
+
const config = parseConfig({
|
|
163
|
+
humanInTheLoop: {
|
|
164
|
+
enabled: true,
|
|
165
|
+
interruptOn: {}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveHumanInTheLoopSettings)(config)).toBeNull();
|
|
169
|
+
});
|
|
170
|
+
(0, external_vitest_namespaceObject.it)("returns interrupt map when enabled with tool policies", ()=>{
|
|
171
|
+
const config = parseConfig({
|
|
172
|
+
humanInTheLoop: {
|
|
173
|
+
enabled: true,
|
|
174
|
+
interruptOn: {
|
|
175
|
+
command_execute: {
|
|
176
|
+
allowedDecisions: [
|
|
177
|
+
"approve",
|
|
178
|
+
"reject"
|
|
179
|
+
],
|
|
180
|
+
description: "Command execution requires approval"
|
|
181
|
+
},
|
|
182
|
+
internet_search: false
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.resolveHumanInTheLoopSettings)(config)).toEqual({
|
|
187
|
+
interruptOn: {
|
|
188
|
+
command_execute: {
|
|
189
|
+
allowedDecisions: [
|
|
190
|
+
"approve",
|
|
191
|
+
"reject"
|
|
192
|
+
],
|
|
193
|
+
description: "Command execution requires approval"
|
|
194
|
+
},
|
|
195
|
+
internet_search: false
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
(0, external_vitest_namespaceObject.describe)("detectToolEventContext", ()=>{
|
|
201
|
+
(0, external_vitest_namespaceObject.it)("extracts tool context for tool start events", ()=>{
|
|
202
|
+
const detected = (0, agentInvoker_cjs_namespaceObject.detectToolEventContext)({
|
|
203
|
+
event: "on_tool_start",
|
|
204
|
+
name: "glob"
|
|
205
|
+
});
|
|
206
|
+
(0, external_vitest_namespaceObject.expect)(detected).toEqual({
|
|
207
|
+
event: "on_tool_start",
|
|
208
|
+
toolName: "glob"
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
(0, external_vitest_namespaceObject.it)("returns null for non-tool events", ()=>{
|
|
212
|
+
const detected = (0, agentInvoker_cjs_namespaceObject.detectToolEventContext)({
|
|
213
|
+
event: "on_chat_model_stream",
|
|
214
|
+
data: {
|
|
215
|
+
chunk: {
|
|
216
|
+
text: "hello"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
(0, external_vitest_namespaceObject.expect)(detected).toBeNull();
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
(0, external_vitest_namespaceObject.describe)("chunkHasAssistantText", ()=>{
|
|
224
|
+
(0, external_vitest_namespaceObject.it)("detects text in on_chat_model_stream chunks", ()=>{
|
|
225
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.chunkHasAssistantText)({
|
|
226
|
+
event: "on_chat_model_stream",
|
|
227
|
+
data: {
|
|
228
|
+
chunk: {
|
|
229
|
+
content: [
|
|
230
|
+
{
|
|
231
|
+
type: "text",
|
|
232
|
+
text: "hello"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
})).toBe(true);
|
|
238
|
+
});
|
|
239
|
+
(0, external_vitest_namespaceObject.it)("detects text in on_llm_stream chunks", ()=>{
|
|
240
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.chunkHasAssistantText)({
|
|
241
|
+
event: "on_llm_stream",
|
|
242
|
+
data: {
|
|
243
|
+
chunk: {
|
|
244
|
+
text: "delta"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
})).toBe(true);
|
|
248
|
+
});
|
|
249
|
+
(0, external_vitest_namespaceObject.it)("returns false when chunk has no assistant text", ()=>{
|
|
250
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.chunkHasAssistantText)({
|
|
251
|
+
event: "on_tool_start",
|
|
252
|
+
name: "glob"
|
|
253
|
+
})).toBe(false);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
(0, external_vitest_namespaceObject.describe)("selectStreamingFallbackText", ()=>{
|
|
257
|
+
(0, external_vitest_namespaceObject.it)("returns the most recent assistant message in the same invocation window", ()=>{
|
|
258
|
+
const selected = (0, agentInvoker_cjs_namespaceObject.selectStreamingFallbackText)([
|
|
259
|
+
{
|
|
260
|
+
role: "assistant",
|
|
261
|
+
createdAt: 1000,
|
|
262
|
+
content: "stale message"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
role: "assistant",
|
|
266
|
+
createdAt: 4500,
|
|
267
|
+
content: "fresh fallback"
|
|
268
|
+
}
|
|
269
|
+
], 4000);
|
|
270
|
+
(0, external_vitest_namespaceObject.expect)(selected).toBe("fresh fallback");
|
|
271
|
+
});
|
|
272
|
+
(0, external_vitest_namespaceObject.it)("ignores stale, user-role, and empty-content messages", ()=>{
|
|
273
|
+
const selected = (0, agentInvoker_cjs_namespaceObject.selectStreamingFallbackText)([
|
|
274
|
+
{
|
|
275
|
+
role: "assistant",
|
|
276
|
+
createdAt: 1000,
|
|
277
|
+
content: "too old"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
role: "user",
|
|
281
|
+
createdAt: 4900,
|
|
282
|
+
content: "not assistant"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
role: "assistant",
|
|
286
|
+
createdAt: 5000,
|
|
287
|
+
content: " "
|
|
288
|
+
}
|
|
289
|
+
], 5000);
|
|
290
|
+
(0, external_vitest_namespaceObject.expect)(selected).toBeUndefined();
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
294
|
+
Object.defineProperty(exports, '__esModule', {
|
|
295
|
+
value: true
|
|
296
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|