newmark-agent 0.5.14 → 0.6.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/conversation-utility-host.bundle.cjs +4565 -2998
- package/dist/conversation-utility-host.js +1 -1
- package/dist/core/agent.d.ts +108 -16
- package/dist/core/agent.js +698 -195
- package/dist/core/agentKernel/agent.d.ts +1 -0
- package/dist/core/agentKernel/agent.js +9 -0
- package/dist/core/agentKernelDiagnostics.d.ts +4 -6
- package/dist/core/agentKernelDiagnostics.js +12 -9
- package/dist/core/agentKernelRunner.d.ts +5 -0
- package/dist/core/agentKernelRunner.js +250 -107
- package/dist/core/autoRouter.js +17 -27
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.js +7 -1
- package/dist/core/conversationCommandState.d.ts +17 -0
- package/dist/core/conversationCommandState.js +140 -0
- package/dist/core/conversationKernel.d.ts +25 -4
- package/dist/core/conversationKernel.js +360 -89
- package/dist/core/conversationListEvent.d.ts +6 -0
- package/dist/core/conversationListEvent.js +14 -0
- package/dist/core/electronUtilityAgentClient.d.ts +4 -1
- package/dist/core/electronUtilityAgentClient.js +4 -4
- package/dist/core/electronUtilityRuntimePool.d.ts +8 -2
- package/dist/core/electronUtilityRuntimePool.js +11 -5
- package/dist/core/installUpdate.js +41 -29
- package/dist/core/modelResponseHealth.d.ts +17 -0
- package/dist/core/modelResponseHealth.js +193 -0
- package/dist/core/providerUsageAccounting.d.ts +47 -0
- package/dist/core/providerUsageAccounting.js +71 -0
- package/dist/core/requestContextEstimate.d.ts +18 -0
- package/dist/core/requestContextEstimate.js +54 -0
- package/dist/core/subagent.d.ts +89 -5
- package/dist/core/subagent.js +264 -41
- package/dist/core/subagentCommunication.d.ts +43 -0
- package/dist/core/subagentCommunication.js +167 -0
- package/dist/core/types.d.ts +34 -1
- package/dist/core/utilityAgentProtocol.d.ts +4 -0
- package/dist/core/workEventCoalescer.js +4 -1
- package/dist/core/wslAgentClient.d.ts +18 -5
- package/dist/core/wslAgentClient.js +79 -27
- package/dist/core/wslAgentProtocol.d.ts +7 -0
- package/dist/core/wslAgentRuntimePool.d.ts +8 -2
- package/dist/core/wslAgentRuntimePool.js +19 -6
- package/dist/core/wslRuntimeProcessTree.d.ts +10 -0
- package/dist/core/wslRuntimeProcessTree.js +104 -0
- package/dist/llm/provider.d.ts +5 -12
- package/dist/llm/provider.js +150 -269
- package/dist/main.js +582 -356
- package/dist/preload.js +3 -3
- package/dist/providers/chat-completions.adapter.d.ts +2 -0
- package/dist/providers/chat-completions.adapter.js +84 -36
- package/dist/providers/provider-adapter.d.ts +2 -0
- package/dist/providers/provider-events.d.ts +23 -14
- package/dist/providers/provider-events.js +148 -43
- package/dist/providers/provider-headers.d.ts +7 -3
- package/dist/providers/provider-headers.js +109 -39
- package/dist/providers/provider-request-compat.d.ts +6 -0
- package/dist/providers/provider-request-compat.js +37 -0
- package/dist/providers/responses.adapter.d.ts +2 -0
- package/dist/providers/responses.adapter.js +192 -126
- package/dist/server.d.ts +9 -2
- package/dist/server.js +100 -24
- package/dist/tools/index.js +17 -1
- package/dist/ui/index.html +2515 -693
- package/dist/ui/lucide-sprite.svg +7 -0
- package/dist/ui/startup.html +6 -6
- package/dist/wsl-agent-host.bundle.cjs +4575 -3006
- package/dist/wsl-agent-host.js +9 -4
- package/package.json +23 -4
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { ProviderResponseMetadata } from './provider-adapter';
|
|
2
|
-
|
|
3
|
-
export
|
|
2
|
+
/** Native, cross-realm and custom transport Headers share the same get shape. */
|
|
3
|
+
export type ProviderHeaderInput = Headers | Record<string, string> | {
|
|
4
|
+
get(name: string): string | null;
|
|
5
|
+
};
|
|
6
|
+
export declare function headerGet(headers: ProviderHeaderInput, name: string): string | null;
|
|
7
|
+
export declare function normalizeProviderHeaders(headers: ProviderHeaderInput): ProviderResponseMetadata;
|
|
4
8
|
/**
|
|
5
9
|
* Filter a header record for request-side diagnostics: only explicitly allowed
|
|
6
10
|
* non-sensitive fields are retained. Never returns cookies or credentials.
|
|
7
11
|
*/
|
|
8
|
-
export declare function filterRequestHeadersForDiagnostics(headers:
|
|
12
|
+
export declare function filterRequestHeadersForDiagnostics(headers: ProviderHeaderInput): Record<string, string>;
|
|
9
13
|
//# sourceMappingURL=provider-headers.d.ts.map
|
|
@@ -11,17 +11,29 @@ exports.filterRequestHeadersForDiagnostics = filterRequestHeadersForDiagnostics;
|
|
|
11
11
|
const ALLOWED_HEADERS = new Set([
|
|
12
12
|
'x-request-id',
|
|
13
13
|
'request-id',
|
|
14
|
-
'x-request-id',
|
|
15
14
|
'x-correlation-id',
|
|
16
15
|
'x-amzn-requestid',
|
|
17
16
|
'x-amzn-trace-id',
|
|
18
17
|
'x-ratelimit-limit',
|
|
19
18
|
'x-ratelimit-remaining',
|
|
20
19
|
'x-ratelimit-reset',
|
|
20
|
+
'x-ratelimit-limit-requests',
|
|
21
|
+
'x-ratelimit-remaining-requests',
|
|
22
|
+
'x-ratelimit-reset-requests',
|
|
23
|
+
'x-ratelimit-limit-tokens',
|
|
24
|
+
'x-ratelimit-remaining-tokens',
|
|
25
|
+
'x-ratelimit-reset-tokens',
|
|
26
|
+
'anthropic-ratelimit-requests-limit',
|
|
27
|
+
'anthropic-ratelimit-requests-remaining',
|
|
28
|
+
'anthropic-ratelimit-requests-reset',
|
|
29
|
+
'anthropic-ratelimit-tokens-limit',
|
|
30
|
+
'anthropic-ratelimit-tokens-remaining',
|
|
31
|
+
'anthropic-ratelimit-tokens-reset',
|
|
21
32
|
'ratelimit-limit',
|
|
22
33
|
'ratelimit-remaining',
|
|
23
34
|
'ratelimit-reset',
|
|
24
35
|
'retry-after',
|
|
36
|
+
'retry-after-ms',
|
|
25
37
|
'x-cache',
|
|
26
38
|
'x-cache-status',
|
|
27
39
|
'cf-cache-status',
|
|
@@ -38,15 +50,80 @@ const FORBIDDEN_HEADERS = new Set([
|
|
|
38
50
|
'x-github-token',
|
|
39
51
|
]);
|
|
40
52
|
function headerGet(headers, name) {
|
|
41
|
-
if (typeof
|
|
42
|
-
return
|
|
53
|
+
if (!headers || typeof headers !== 'object')
|
|
54
|
+
return null;
|
|
55
|
+
const getter = headers.get;
|
|
56
|
+
if (typeof getter === 'function') {
|
|
57
|
+
try {
|
|
58
|
+
const value = getter.call(headers, name.toLowerCase());
|
|
59
|
+
if (typeof value === 'string')
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
catch { /* A malformed custom container can still expose a plain record. */ }
|
|
43
63
|
}
|
|
44
64
|
const record = headers;
|
|
45
65
|
const key = Object.keys(record).find(k => k.toLowerCase() === name.toLowerCase());
|
|
46
|
-
return key === undefined ? null : record[key];
|
|
66
|
+
return key === undefined || typeof record[key] !== 'string' ? null : record[key];
|
|
67
|
+
}
|
|
68
|
+
function nonNegativeNumber(value) {
|
|
69
|
+
if (value === null || !/^\d+(?:\.\d+)?$/.test(value.trim()))
|
|
70
|
+
return undefined;
|
|
71
|
+
const numeric = Number(value.trim());
|
|
72
|
+
return Number.isFinite(numeric) && numeric <= Number.MAX_SAFE_INTEGER ? numeric : undefined;
|
|
73
|
+
}
|
|
74
|
+
function validIso(milliseconds) {
|
|
75
|
+
if (!Number.isFinite(milliseconds))
|
|
76
|
+
return '';
|
|
77
|
+
const date = new Date(milliseconds);
|
|
78
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : '';
|
|
79
|
+
}
|
|
80
|
+
function durationMilliseconds(value) {
|
|
81
|
+
const text = value.trim().toLowerCase();
|
|
82
|
+
if (!/^(?:\d+(?:\.\d+)?(?:ms|s|m|h|d))+$/.test(text))
|
|
83
|
+
return undefined;
|
|
84
|
+
const units = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
85
|
+
let duration = 0;
|
|
86
|
+
for (const match of text.matchAll(/(\d+(?:\.\d+)?)(ms|s|m|h|d)/g))
|
|
87
|
+
duration += Number(match[1]) * units[match[2]];
|
|
88
|
+
return Number.isFinite(duration) && duration <= Number.MAX_SAFE_INTEGER ? duration : undefined;
|
|
89
|
+
}
|
|
90
|
+
function resetTime(value, kind, now) {
|
|
91
|
+
if (value === null || !value.trim())
|
|
92
|
+
return '';
|
|
93
|
+
const numeric = nonNegativeNumber(value);
|
|
94
|
+
if (kind === 'duration') {
|
|
95
|
+
const duration = durationMilliseconds(value) ?? (numeric === undefined ? undefined : numeric * 1000);
|
|
96
|
+
return duration === undefined ? '' : validIso(now + duration);
|
|
97
|
+
}
|
|
98
|
+
if (kind === 'epoch' && numeric !== undefined) {
|
|
99
|
+
// GitHub's x-ratelimit-reset is epoch seconds. Some compatible gateways
|
|
100
|
+
// publish epoch milliseconds; neither format is a relative duration.
|
|
101
|
+
return validIso(numeric >= 1e12 ? numeric : numeric * 1000);
|
|
102
|
+
}
|
|
103
|
+
if (numeric !== undefined || !/[A-Za-z]|\d[Tt]\d/.test(value))
|
|
104
|
+
return '';
|
|
105
|
+
return validIso(Date.parse(value));
|
|
106
|
+
}
|
|
107
|
+
function retryAfterSeconds(headers, now) {
|
|
108
|
+
// Matches the official OpenAI SDK's precedence for the nonstandard precise
|
|
109
|
+
// millisecond extension. A real zero remains authoritative.
|
|
110
|
+
const milliseconds = nonNegativeNumber(headerGet(headers, 'retry-after-ms'));
|
|
111
|
+
if (milliseconds !== undefined)
|
|
112
|
+
return milliseconds / 1000;
|
|
113
|
+
const raw = headerGet(headers, 'retry-after');
|
|
114
|
+
const seconds = nonNegativeNumber(raw);
|
|
115
|
+
if (seconds !== undefined)
|
|
116
|
+
return seconds;
|
|
117
|
+
// Reject malformed numeric values instead of letting Date.parse interpret
|
|
118
|
+
// values such as "-1" as an unrelated calendar date.
|
|
119
|
+
if (!raw || !/[A-Za-z]/.test(raw))
|
|
120
|
+
return undefined;
|
|
121
|
+
const parsed = Date.parse(raw);
|
|
122
|
+
return Number.isFinite(parsed) ? Math.max(0, Math.ceil((parsed - now) / 1000)) : undefined;
|
|
47
123
|
}
|
|
48
124
|
function normalizeProviderHeaders(headers) {
|
|
49
125
|
const result = {};
|
|
126
|
+
const now = Date.now();
|
|
50
127
|
const requestId = headerGet(headers, 'x-request-id') ||
|
|
51
128
|
headerGet(headers, 'request-id') ||
|
|
52
129
|
headerGet(headers, 'x-correlation-id') ||
|
|
@@ -56,46 +133,30 @@ function normalizeProviderHeaders(headers) {
|
|
|
56
133
|
const traceId = headerGet(headers, 'x-amzn-trace-id');
|
|
57
134
|
if (traceId)
|
|
58
135
|
result.traceId = traceId;
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
else {
|
|
73
|
-
const parsed = Date.parse(resetRaw);
|
|
74
|
-
if (Number.isFinite(parsed))
|
|
75
|
-
resetAt = new Date(parsed).toISOString();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (Number.isFinite(limit) && Number.isFinite(remaining)) {
|
|
79
|
-
result.rateLimit = { limit, remaining, resetAt };
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const retryAfter = headerGet(headers, 'retry-after');
|
|
83
|
-
if (retryAfter) {
|
|
84
|
-
if (/^\d+(?:\.\d+)?$/.test(retryAfter)) {
|
|
85
|
-
result.retryAfterSeconds = Number(retryAfter);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const parsed = Date.parse(retryAfter);
|
|
89
|
-
if (Number.isFinite(parsed)) {
|
|
90
|
-
result.retryAfterSeconds = Math.max(0, Math.ceil((parsed - Date.now()) / 1000));
|
|
91
|
-
}
|
|
92
|
-
}
|
|
136
|
+
const families = [
|
|
137
|
+
['x-ratelimit-limit-requests', 'x-ratelimit-remaining-requests', 'x-ratelimit-reset-requests', 'duration'],
|
|
138
|
+
['anthropic-ratelimit-requests-limit', 'anthropic-ratelimit-requests-remaining', 'anthropic-ratelimit-requests-reset', 'date'],
|
|
139
|
+
['x-ratelimit-limit', 'x-ratelimit-remaining', 'x-ratelimit-reset', 'epoch'],
|
|
140
|
+
['ratelimit-limit', 'ratelimit-remaining', 'ratelimit-reset', 'duration'],
|
|
141
|
+
];
|
|
142
|
+
for (const [limitName, remainingName, resetName, resetKind] of families) {
|
|
143
|
+
const limit = nonNegativeNumber(headerGet(headers, limitName));
|
|
144
|
+
const remaining = nonNegativeNumber(headerGet(headers, remainingName));
|
|
145
|
+
if (limit === undefined || remaining === undefined || !Number.isInteger(limit) || !Number.isInteger(remaining))
|
|
146
|
+
continue;
|
|
147
|
+
result.rateLimit = { limit, remaining, resetAt: resetTime(headerGet(headers, resetName), resetKind, now) };
|
|
148
|
+
break;
|
|
93
149
|
}
|
|
150
|
+
const retryAfter = retryAfterSeconds(headers, now);
|
|
151
|
+
if (retryAfter !== undefined)
|
|
152
|
+
result.retryAfterSeconds = retryAfter;
|
|
94
153
|
const cacheStateRaw = headerGet(headers, 'x-cache-status') ||
|
|
95
154
|
headerGet(headers, 'cf-cache-status') ||
|
|
96
155
|
headerGet(headers, 'x-cache') ||
|
|
97
156
|
headerGet(headers, 'x-vercel-cache');
|
|
98
157
|
if (cacheStateRaw) {
|
|
158
|
+
// This is HTTP/CDN cache metadata only. It cannot establish model token
|
|
159
|
+
// cache usage or a prompt-cache hit ratio; those require response usage.
|
|
99
160
|
const lower = cacheStateRaw.toLowerCase();
|
|
100
161
|
result.cacheState = lower.includes('hit') ? 'hit' : lower.includes('miss') ? 'miss' : 'unknown';
|
|
101
162
|
}
|
|
@@ -107,13 +168,22 @@ function normalizeProviderHeaders(headers) {
|
|
|
107
168
|
*/
|
|
108
169
|
function filterRequestHeadersForDiagnostics(headers) {
|
|
109
170
|
const out = {};
|
|
171
|
+
if (headers && typeof headers.get === 'function') {
|
|
172
|
+
for (const key of ALLOWED_HEADERS) {
|
|
173
|
+
const value = headerGet(headers, key);
|
|
174
|
+
if (value !== null)
|
|
175
|
+
out[key] = value;
|
|
176
|
+
}
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
110
179
|
for (const [key, value] of Object.entries(headers || {})) {
|
|
111
180
|
const lower = key.toLowerCase();
|
|
112
181
|
if (FORBIDDEN_HEADERS.has(lower))
|
|
113
182
|
continue;
|
|
114
183
|
if (!ALLOWED_HEADERS.has(lower))
|
|
115
184
|
continue;
|
|
116
|
-
|
|
185
|
+
if (typeof value === 'string')
|
|
186
|
+
out[key] = value;
|
|
117
187
|
}
|
|
118
188
|
return out;
|
|
119
189
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Request construction shared by Chat, Responses and native protocol paths. */
|
|
2
|
+
export type RequestProtocol = 'openai' | 'anthropic' | 'github_models';
|
|
3
|
+
export declare function providerRequestHeaders(protocol: RequestProtocol, apiKey: string, stream?: boolean): Record<string, string>;
|
|
4
|
+
/** Preserve custom gateway prefixes and queries; replace only known endpoints. */
|
|
5
|
+
export declare function providerEndpoint(baseUrl: string, endpoint: string): string;
|
|
6
|
+
//# sourceMappingURL=provider-request-compat.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.providerRequestHeaders = providerRequestHeaders;
|
|
4
|
+
exports.providerEndpoint = providerEndpoint;
|
|
5
|
+
function providerRequestHeaders(protocol, apiKey, stream = false) {
|
|
6
|
+
const headers = {
|
|
7
|
+
'Content-Type': 'application/json',
|
|
8
|
+
Accept: stream ? 'text/event-stream' : protocol === 'github_models' ? 'application/vnd.github+json' : 'application/json',
|
|
9
|
+
};
|
|
10
|
+
// Local compatible servers may intentionally have no authentication. Never
|
|
11
|
+
// substitute a fake key or send an empty Bearer credential to such servers.
|
|
12
|
+
if (apiKey)
|
|
13
|
+
headers[protocol === 'anthropic' ? 'x-api-key' : 'Authorization'] = protocol === 'anthropic' ? apiKey : `Bearer ${apiKey}`;
|
|
14
|
+
if (protocol === 'anthropic')
|
|
15
|
+
headers['anthropic-version'] = '2023-06-01';
|
|
16
|
+
if (protocol === 'github_models')
|
|
17
|
+
headers['X-GitHub-Api-Version'] = '2022-11-28';
|
|
18
|
+
return headers;
|
|
19
|
+
}
|
|
20
|
+
/** Preserve custom gateway prefixes and queries; replace only known endpoints. */
|
|
21
|
+
function providerEndpoint(baseUrl, endpoint) {
|
|
22
|
+
const url = new URL(baseUrl.trim());
|
|
23
|
+
const suffix = '/' + endpoint.replace(/^\/+/, '');
|
|
24
|
+
let base = url.pathname.replace(/\/+$/, '');
|
|
25
|
+
if (/^\/(?:inference|catalog)\//.test(suffix)) {
|
|
26
|
+
base = base.replace(/\/(?:inference\/chat\/completions|catalog\/models|inference)$/i, '');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
base = base.replace(/\/(?:chat\/completions|responses|messages|models)$/i, '');
|
|
30
|
+
}
|
|
31
|
+
if (!base && /^(?:api\.openai\.com|api\.anthropic\.com)$/i.test(url.hostname))
|
|
32
|
+
base = '/v1';
|
|
33
|
+
url.pathname = base + suffix;
|
|
34
|
+
url.hash = '';
|
|
35
|
+
return url.toString();
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=provider-request-compat.js.map
|
|
@@ -16,6 +16,8 @@ export declare class ResponsesAdapter implements ModelProviderAdapter {
|
|
|
16
16
|
execute(request: SerializedProviderRequest, signal: AbortSignal, transport?: typeof defaultProviderTransport): AsyncIterable<NormalizedProviderEvent>;
|
|
17
17
|
private emitNonStreaming;
|
|
18
18
|
normalizeUsage(value: unknown): ActualApiUsage | null;
|
|
19
|
+
private completionError;
|
|
20
|
+
private validToolArguments;
|
|
19
21
|
normalizeHeaders(headers: Headers | Record<string, string>): ProviderResponseMetadata;
|
|
20
22
|
private extractResponsesText;
|
|
21
23
|
private extractChatCompletionText;
|