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.
Files changed (68) hide show
  1. package/dist/conversation-utility-host.bundle.cjs +4565 -2998
  2. package/dist/conversation-utility-host.js +1 -1
  3. package/dist/core/agent.d.ts +108 -16
  4. package/dist/core/agent.js +698 -195
  5. package/dist/core/agentKernel/agent.d.ts +1 -0
  6. package/dist/core/agentKernel/agent.js +9 -0
  7. package/dist/core/agentKernelDiagnostics.d.ts +4 -6
  8. package/dist/core/agentKernelDiagnostics.js +12 -9
  9. package/dist/core/agentKernelRunner.d.ts +5 -0
  10. package/dist/core/agentKernelRunner.js +250 -107
  11. package/dist/core/autoRouter.js +17 -27
  12. package/dist/core/config.d.ts +2 -0
  13. package/dist/core/config.js +7 -1
  14. package/dist/core/conversationCommandState.d.ts +17 -0
  15. package/dist/core/conversationCommandState.js +140 -0
  16. package/dist/core/conversationKernel.d.ts +25 -4
  17. package/dist/core/conversationKernel.js +360 -89
  18. package/dist/core/conversationListEvent.d.ts +6 -0
  19. package/dist/core/conversationListEvent.js +14 -0
  20. package/dist/core/electronUtilityAgentClient.d.ts +4 -1
  21. package/dist/core/electronUtilityAgentClient.js +4 -4
  22. package/dist/core/electronUtilityRuntimePool.d.ts +8 -2
  23. package/dist/core/electronUtilityRuntimePool.js +11 -5
  24. package/dist/core/installUpdate.js +41 -29
  25. package/dist/core/modelResponseHealth.d.ts +17 -0
  26. package/dist/core/modelResponseHealth.js +193 -0
  27. package/dist/core/providerUsageAccounting.d.ts +47 -0
  28. package/dist/core/providerUsageAccounting.js +71 -0
  29. package/dist/core/requestContextEstimate.d.ts +18 -0
  30. package/dist/core/requestContextEstimate.js +54 -0
  31. package/dist/core/subagent.d.ts +89 -5
  32. package/dist/core/subagent.js +264 -41
  33. package/dist/core/subagentCommunication.d.ts +43 -0
  34. package/dist/core/subagentCommunication.js +167 -0
  35. package/dist/core/types.d.ts +34 -1
  36. package/dist/core/utilityAgentProtocol.d.ts +4 -0
  37. package/dist/core/workEventCoalescer.js +4 -1
  38. package/dist/core/wslAgentClient.d.ts +18 -5
  39. package/dist/core/wslAgentClient.js +79 -27
  40. package/dist/core/wslAgentProtocol.d.ts +7 -0
  41. package/dist/core/wslAgentRuntimePool.d.ts +8 -2
  42. package/dist/core/wslAgentRuntimePool.js +19 -6
  43. package/dist/core/wslRuntimeProcessTree.d.ts +10 -0
  44. package/dist/core/wslRuntimeProcessTree.js +104 -0
  45. package/dist/llm/provider.d.ts +5 -12
  46. package/dist/llm/provider.js +150 -269
  47. package/dist/main.js +582 -356
  48. package/dist/preload.js +3 -3
  49. package/dist/providers/chat-completions.adapter.d.ts +2 -0
  50. package/dist/providers/chat-completions.adapter.js +84 -36
  51. package/dist/providers/provider-adapter.d.ts +2 -0
  52. package/dist/providers/provider-events.d.ts +23 -14
  53. package/dist/providers/provider-events.js +148 -43
  54. package/dist/providers/provider-headers.d.ts +7 -3
  55. package/dist/providers/provider-headers.js +109 -39
  56. package/dist/providers/provider-request-compat.d.ts +6 -0
  57. package/dist/providers/provider-request-compat.js +37 -0
  58. package/dist/providers/responses.adapter.d.ts +2 -0
  59. package/dist/providers/responses.adapter.js +192 -126
  60. package/dist/server.d.ts +9 -2
  61. package/dist/server.js +100 -24
  62. package/dist/tools/index.js +17 -1
  63. package/dist/ui/index.html +2515 -693
  64. package/dist/ui/lucide-sprite.svg +7 -0
  65. package/dist/ui/startup.html +6 -6
  66. package/dist/wsl-agent-host.bundle.cjs +4575 -3006
  67. package/dist/wsl-agent-host.js +9 -4
  68. package/package.json +23 -4
@@ -1,9 +1,13 @@
1
1
  import { ProviderResponseMetadata } from './provider-adapter';
2
- export declare function headerGet(headers: Headers | Record<string, string>, name: string): string | null;
3
- export declare function normalizeProviderHeaders(headers: Headers | Record<string, string>): ProviderResponseMetadata;
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: Record<string, string>): Record<string, string>;
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 Headers !== 'undefined' && headers instanceof Headers) {
42
- return headers.get(name);
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 limitRaw = headerGet(headers, 'x-ratelimit-limit');
60
- const remainingRaw = headerGet(headers, 'x-ratelimit-remaining');
61
- const resetRaw = headerGet(headers, 'x-ratelimit-reset');
62
- if (limitRaw && remainingRaw) {
63
- const limit = Number(limitRaw);
64
- const remaining = Number(remainingRaw);
65
- let resetAt = '';
66
- if (resetRaw) {
67
- const numeric = Number(resetRaw);
68
- if (Number.isFinite(numeric) && numeric > 1e10)
69
- resetAt = new Date(numeric).toISOString();
70
- else if (Number.isFinite(numeric))
71
- resetAt = new Date(Date.now() + numeric * 1000).toISOString();
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
- out[key] = value;
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;