newmark-agent 0.4.8 → 0.5.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 +238 -29
- package/dist/core/agent.d.ts +1 -0
- package/dist/core/agent.js +102 -10
- package/dist/core/agentKernelRunner.js +1 -1
- package/dist/core/autoRouter.d.ts +1 -1
- package/dist/core/autoRouter.js +16 -7
- package/dist/core/conversationKernel.d.ts +13 -8
- package/dist/core/conversationKernel.js +111 -10
- package/dist/core/electronUtilityAgentClient.d.ts +2 -8
- package/dist/core/electronUtilityRuntimePool.d.ts +3 -15
- package/dist/core/utilityAgentProtocol.d.ts +2 -8
- package/dist/core/workEventCoalescer.d.ts +16 -0
- package/dist/core/workEventCoalescer.js +52 -0
- package/dist/core/wslAgentClient.d.ts +2 -8
- package/dist/core/wslAgentProtocol.d.ts +2 -8
- package/dist/core/wslAgentRuntimePool.d.ts +3 -15
- package/dist/llm/provider.d.ts +5 -0
- package/dist/llm/provider.js +63 -1
- package/dist/main.js +221 -175
- package/dist/preload.js +2 -0
- package/dist/server.d.ts +17 -1
- package/dist/server.js +331 -9
- package/dist/ui/index.html +295 -51
- package/dist/wsl-agent-host.bundle.cjs +238 -29
- package/package.json +10 -5
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WorkEventCoalescer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Bounds cross-process traffic for high-rate streaming text without changing
|
|
6
|
+
* durable work-run events. Non-text events always flush pending text first.
|
|
7
|
+
*/
|
|
8
|
+
class WorkEventCoalescer {
|
|
9
|
+
emit;
|
|
10
|
+
windowMs;
|
|
11
|
+
pending = new Map();
|
|
12
|
+
constructor(emit, windowMs = 16) {
|
|
13
|
+
this.emit = emit;
|
|
14
|
+
this.windowMs = windowMs;
|
|
15
|
+
}
|
|
16
|
+
push(event) {
|
|
17
|
+
if (event.type !== 'text') {
|
|
18
|
+
this.flushAll();
|
|
19
|
+
this.emit(event);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const key = `${event.workspaceId || ''}::${event.conversationId}::${event.runtimeKey || ''}::${event.runId || ''}`;
|
|
23
|
+
const current = this.pending.get(key);
|
|
24
|
+
if (current) {
|
|
25
|
+
current.content += event.content;
|
|
26
|
+
current.event = event;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const entry = {
|
|
30
|
+
event,
|
|
31
|
+
content: event.content,
|
|
32
|
+
timer: setTimeout(() => this.flush(key), this.windowMs),
|
|
33
|
+
};
|
|
34
|
+
this.pending.set(key, entry);
|
|
35
|
+
}
|
|
36
|
+
flush(key) {
|
|
37
|
+
const entry = this.pending.get(key);
|
|
38
|
+
if (!entry)
|
|
39
|
+
return;
|
|
40
|
+
this.pending.delete(key);
|
|
41
|
+
clearTimeout(entry.timer);
|
|
42
|
+
if (entry.content)
|
|
43
|
+
this.emit({ ...entry.event, content: entry.content });
|
|
44
|
+
}
|
|
45
|
+
flushAll() {
|
|
46
|
+
for (const key of [...this.pending.keys()])
|
|
47
|
+
this.flush(key);
|
|
48
|
+
}
|
|
49
|
+
pendingCount() { return this.pending.size; }
|
|
50
|
+
}
|
|
51
|
+
exports.WorkEventCoalescer = WorkEventCoalescer;
|
|
52
|
+
//# sourceMappingURL=workEventCoalescer.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
|
|
2
|
-
import { ConversationQueueAction } from './conversationKernel';
|
|
2
|
+
import { ConversationQueueAction, ConversationQueueActionInput } from './conversationKernel';
|
|
3
3
|
import { TerminalTakeoverEvent, TerminalTakeoverOwnerFilter, TerminalTakeoverState } from '../tools/terminalTakeover';
|
|
4
4
|
import { WslAgentPromptRequest, WslAgentPromptResult, WslAutoRouteRatingResult, WslAgentWorkspace, WslAgentStopResult, WslConversationRewindResult, WslHostToolRequest } from './wslAgentProtocol';
|
|
5
5
|
import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
|
|
@@ -72,13 +72,7 @@ export declare class WslAgentClient {
|
|
|
72
72
|
snapshotTarget(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
|
|
73
73
|
rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
|
|
74
74
|
enqueueGuide(target: ConversationRuntimeTarget, envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
|
|
75
|
-
queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?:
|
|
76
|
-
id?: string;
|
|
77
|
-
text?: string;
|
|
78
|
-
requestedMode?: string;
|
|
79
|
-
goalObjective?: string;
|
|
80
|
-
createdAt?: string;
|
|
81
|
-
}): Promise<Record<string, unknown>>;
|
|
75
|
+
queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
|
|
82
76
|
checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
|
|
83
77
|
contextCompress(target: ConversationRuntimeTarget, options?: {
|
|
84
78
|
keepRecent?: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
|
|
2
|
-
import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueMode, ConversationStopResult } from './conversationKernel';
|
|
2
|
+
import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueActionInput, ConversationQueueMode, ConversationStopResult } from './conversationKernel';
|
|
3
3
|
import { ConversationRuntimeTarget } from './conversationTarget';
|
|
4
4
|
import { TerminalTakeoverEvent, TerminalTakeoverOwnerFilter, TerminalTakeoverState } from '../tools/terminalTakeover';
|
|
5
5
|
import { BrowserUseRequest } from './browserUse';
|
|
@@ -117,13 +117,7 @@ export type WslAgentRequest = {
|
|
|
117
117
|
params: {
|
|
118
118
|
target: ConversationRuntimeTarget;
|
|
119
119
|
action: ConversationQueueAction;
|
|
120
|
-
input?:
|
|
121
|
-
id?: string;
|
|
122
|
-
text?: string;
|
|
123
|
-
requestedMode?: string;
|
|
124
|
-
goalObjective?: string;
|
|
125
|
-
createdAt?: string;
|
|
126
|
-
};
|
|
120
|
+
input?: ConversationQueueActionInput;
|
|
127
121
|
};
|
|
128
122
|
} | {
|
|
129
123
|
id: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
|
|
2
|
-
import { ConversationQueueAction } from './conversationKernel';
|
|
2
|
+
import { ConversationQueueAction, ConversationQueueActionInput } from './conversationKernel';
|
|
3
3
|
import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
|
|
4
4
|
import { WslHostToolHandler } from './wslAgentClient';
|
|
5
5
|
import { WslAgentPromptRequest, WslAgentPromptResult, WslAutoRouteRatingResult, WslAgentStopResult, WslConversationRewindResult } from './wslAgentProtocol';
|
|
@@ -11,13 +11,7 @@ export interface WslTargetRuntimeClient {
|
|
|
11
11
|
rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
|
|
12
12
|
requestStop(target: ConversationRuntimeTarget, runId?: string): Promise<WslAgentStopResult>;
|
|
13
13
|
enqueueGuide(target: ConversationRuntimeTarget, envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
|
|
14
|
-
queueAction?(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?:
|
|
15
|
-
id?: string;
|
|
16
|
-
text?: string;
|
|
17
|
-
requestedMode?: string;
|
|
18
|
-
goalObjective?: string;
|
|
19
|
-
createdAt?: string;
|
|
20
|
-
}): Promise<Record<string, unknown>>;
|
|
14
|
+
queueAction?(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
|
|
21
15
|
checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
|
|
22
16
|
contextCompress?(target: ConversationRuntimeTarget, options?: {
|
|
23
17
|
keepRecent?: number;
|
|
@@ -81,13 +75,7 @@ export declare class WslAgentRuntimePool {
|
|
|
81
75
|
rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
|
|
82
76
|
requestStop(target: ConversationRuntimeTarget, runId?: string): Promise<WslPoolStopResult>;
|
|
83
77
|
enqueueGuide(envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
|
|
84
|
-
queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?:
|
|
85
|
-
id?: string;
|
|
86
|
-
text?: string;
|
|
87
|
-
requestedMode?: string;
|
|
88
|
-
goalObjective?: string;
|
|
89
|
-
createdAt?: string;
|
|
90
|
-
}): Promise<Record<string, unknown>>;
|
|
78
|
+
queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
|
|
91
79
|
checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
|
|
92
80
|
contextCompress(target: ConversationRuntimeTarget, options?: {
|
|
93
81
|
keepRecent?: number;
|
package/dist/llm/provider.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export declare class LLMProvider {
|
|
|
33
33
|
thinkingTierMaps?: Record<string, Record<string, string>> | undefined;
|
|
34
34
|
static nodeHttpTransport: ((method: 'GET' | 'POST', url: string, headers: Record<string, string>, body?: string) => Promise<NodeHttpResult>) | null;
|
|
35
35
|
static powershellTransport: ((method: 'GET' | 'POST', url: string, headers: Record<string, string>, body?: string) => Promise<NodeHttpResult>) | null;
|
|
36
|
+
private readonly temperatureUnsupported;
|
|
36
37
|
constructor(name: string, baseUrl: string, apiKey: string, explicitProtocol?: ProviderProtocol | undefined, openAIMode?: OpenAITransportMode | boolean, useProviderAdaptersV2?: boolean, requestTimeoutMs?: number,
|
|
37
38
|
/** dev-0.4.3 模型原生思考强度档位映射(模型名 → { 模型原生档位: Newmark 档位 })。 */
|
|
38
39
|
thinkingTierMaps?: Record<string, Record<string, string>> | undefined);
|
|
@@ -60,7 +61,11 @@ export declare class LLMProvider {
|
|
|
60
61
|
private isPlainHttpLoopback;
|
|
61
62
|
private transportDiagnostic;
|
|
62
63
|
private githubModelsHeaders;
|
|
64
|
+
private temperatureCapabilityKey;
|
|
65
|
+
private unsupportedTemperatureError;
|
|
66
|
+
private requestBodyForTemperatureCapability;
|
|
63
67
|
private postJsonWithFetchFallback;
|
|
68
|
+
private postJsonOnce;
|
|
64
69
|
private getJsonWithFetchFallback;
|
|
65
70
|
private shouldUseNodeHttpFallback;
|
|
66
71
|
private nodeHttpJson;
|
package/dist/llm/provider.js
CHANGED
|
@@ -101,6 +101,7 @@ class LLMProvider {
|
|
|
101
101
|
thinkingTierMaps;
|
|
102
102
|
static nodeHttpTransport = null;
|
|
103
103
|
static powershellTransport = null;
|
|
104
|
+
temperatureUnsupported = new Set();
|
|
104
105
|
constructor(name, baseUrl, apiKey, explicitProtocol, openAIMode = 'chat_stream', useProviderAdaptersV2 = false, requestTimeoutMs = DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS,
|
|
105
106
|
/** dev-0.4.3 模型原生思考强度档位映射(模型名 → { 模型原生档位: Newmark 档位 })。 */
|
|
106
107
|
thinkingTierMaps) {
|
|
@@ -286,7 +287,52 @@ class LLMProvider {
|
|
|
286
287
|
'X-GitHub-Api-Version': '2022-11-28',
|
|
287
288
|
};
|
|
288
289
|
}
|
|
290
|
+
temperatureCapabilityKey(url, body) {
|
|
291
|
+
return `${url}|${String(body.model || '')}`;
|
|
292
|
+
}
|
|
293
|
+
unsupportedTemperatureError(status, raw) {
|
|
294
|
+
if (status !== 400)
|
|
295
|
+
return false;
|
|
296
|
+
try {
|
|
297
|
+
const parsed = JSON.parse(String(raw || ''));
|
|
298
|
+
if (String(parsed?.error?.param || '').toLowerCase() === 'temperature')
|
|
299
|
+
return true;
|
|
300
|
+
return /unsupported parameter[^\n]*temperature|temperature[^\n]*not supported/i.test(String(parsed?.error?.message || ''));
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return /unsupported parameter[^\n]*temperature|temperature[^\n]*not supported/i.test(String(raw || ''));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
requestBodyForTemperatureCapability(url, body) {
|
|
307
|
+
const prepared = { ...body };
|
|
308
|
+
if (this.temperatureUnsupported.has(this.temperatureCapabilityKey(url, body)))
|
|
309
|
+
delete prepared.temperature;
|
|
310
|
+
return prepared;
|
|
311
|
+
}
|
|
289
312
|
async postJsonWithFetchFallback(url, headers, body, timeoutMs = 120000, signal) {
|
|
313
|
+
const prepared = this.requestBodyForTemperatureCapability(url, body);
|
|
314
|
+
const response = await this.postJsonOnce(url, headers, prepared, timeoutMs, signal);
|
|
315
|
+
if (prepared.temperature === undefined || response.status !== 400)
|
|
316
|
+
return response;
|
|
317
|
+
const cloneable = typeof response.clone === 'function';
|
|
318
|
+
const errorText = await (cloneable ? response.clone() : response).text();
|
|
319
|
+
if (!this.unsupportedTemperatureError(response.status, errorText)) {
|
|
320
|
+
if (cloneable)
|
|
321
|
+
return response;
|
|
322
|
+
return {
|
|
323
|
+
ok: response.ok,
|
|
324
|
+
status: response.status,
|
|
325
|
+
headers: response.headers,
|
|
326
|
+
text: async () => errorText,
|
|
327
|
+
json: async () => JSON.parse(errorText || '{}'),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
this.temperatureUnsupported.add(this.temperatureCapabilityKey(url, body));
|
|
331
|
+
const retryBody = { ...body };
|
|
332
|
+
delete retryBody.temperature;
|
|
333
|
+
return this.postJsonOnce(url, headers, retryBody, timeoutMs, signal);
|
|
334
|
+
}
|
|
335
|
+
async postJsonOnce(url, headers, body, timeoutMs = 120000, signal) {
|
|
290
336
|
const effectiveTimeout = this.effectiveRequestTimeout(timeoutMs);
|
|
291
337
|
// Electron utility processes can leave an undici response body pending when
|
|
292
338
|
// several isolated workers concurrently call a plain-HTTP local provider.
|
|
@@ -1024,6 +1070,7 @@ class LLMProvider {
|
|
|
1024
1070
|
*/
|
|
1025
1071
|
buildProviderAdapterTransport() {
|
|
1026
1072
|
return async (request, signal) => {
|
|
1073
|
+
request.body = this.requestBodyForTemperatureCapability(request.url, request.body);
|
|
1027
1074
|
if (request.body?.stream === true) {
|
|
1028
1075
|
const abort = new AbortController();
|
|
1029
1076
|
const forwardAbort = () => abort.abort(signal?.reason);
|
|
@@ -1035,12 +1082,27 @@ class LLMProvider {
|
|
|
1035
1082
|
const timer = setTimeout(() => abort.abort(providerTimeoutError(effectiveTimeout)), effectiveTimeout);
|
|
1036
1083
|
try {
|
|
1037
1084
|
try {
|
|
1038
|
-
|
|
1085
|
+
let response = await fetch(request.url, {
|
|
1039
1086
|
method: 'POST',
|
|
1040
1087
|
headers: request.headers,
|
|
1041
1088
|
body: JSON.stringify(request.body),
|
|
1042
1089
|
signal: abort.signal,
|
|
1043
1090
|
});
|
|
1091
|
+
if (request.body.temperature !== undefined && response.status === 400) {
|
|
1092
|
+
const errorText = await response.clone().text();
|
|
1093
|
+
if (this.unsupportedTemperatureError(response.status, errorText)) {
|
|
1094
|
+
this.temperatureUnsupported.add(this.temperatureCapabilityKey(request.url, request.body));
|
|
1095
|
+
const retryBody = { ...request.body };
|
|
1096
|
+
delete retryBody.temperature;
|
|
1097
|
+
response = await fetch(request.url, {
|
|
1098
|
+
method: 'POST',
|
|
1099
|
+
headers: request.headers,
|
|
1100
|
+
body: JSON.stringify(retryBody),
|
|
1101
|
+
signal: abort.signal,
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
return response;
|
|
1044
1106
|
}
|
|
1045
1107
|
catch (error) {
|
|
1046
1108
|
if (signal?.aborted)
|