newmark-agent 0.5.0 → 0.5.2

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.
@@ -329201,7 +329201,10 @@ var ResponsesAdapter = class {
329201
329201
  if (eventType === "response.reasoning_summary_text.delta") {
329202
329202
  const key3 = `${String(payload.item_id || "")}:${String(payload.summary_index || 0)}`;
329203
329203
  const delta = this.extractText(payload.delta);
329204
- if (delta) reasoningSummaries.set(key3, (reasoningSummaries.get(key3) || "") + delta);
329204
+ if (delta) {
329205
+ reasoningSummaries.set(key3, (reasoningSummaries.get(key3) || "") + delta);
329206
+ yield { type: "reasoning.summary.delta", delta };
329207
+ }
329205
329208
  continue;
329206
329209
  }
329207
329210
  if (eventType === "response.reasoning_summary_text.done") {
@@ -330195,16 +330198,12 @@ ${responsePath}
330195
330198
  const transport = this.buildProviderAdapterTransport();
330196
330199
  const streaming = mode === "chat_stream";
330197
330200
  const reasoningState = { current: "" };
330198
- let reasoningStatusEmitted = false;
330199
330201
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
330200
330202
  if (event.type === "response.started" || event.type === "response.completed") continue;
330201
330203
  if (event.type === "tool_call.started" || event.type === "tool_call.arguments.delta") continue;
330202
330204
  if (event.type === "reasoning.summary.delta") {
330203
330205
  reasoningState.current += event.delta;
330204
- if (!streaming && !reasoningStatusEmitted) {
330205
- reasoningStatusEmitted = true;
330206
- yield { type: "status", text: "", reasoningContent: reasoningState.current };
330207
- }
330206
+ yield { type: "status", text: "", reasoningContent: reasoningState.current };
330208
330207
  continue;
330209
330208
  }
330210
330209
  if (event.type === "text.delta") {
@@ -330256,11 +330255,20 @@ ${responsePath}
330256
330255
  serialized.headers["Accept"] = "text/event-stream";
330257
330256
  const execSignal = signal ?? new AbortController().signal;
330258
330257
  const transport = this.buildProviderAdapterTransport();
330258
+ let reasoningSummary = "";
330259
330259
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
330260
330260
  if (event.type === "response.started" || event.type === "response.completed") continue;
330261
330261
  if (event.type === "tool_call.started" || event.type === "tool_call.arguments.delta") continue;
330262
+ if (event.type === "reasoning.summary.delta") {
330263
+ reasoningSummary += event.delta;
330264
+ yield { type: "status", text: "", reasoningContent: reasoningSummary };
330265
+ continue;
330266
+ }
330262
330267
  if (event.type === "reasoning.summary.done") {
330263
- if (event.summary) yield { type: "status", text: event.summary };
330268
+ if (event.summary && event.summary !== reasoningSummary) {
330269
+ reasoningSummary = event.summary;
330270
+ yield { type: "status", text: "", reasoningContent: reasoningSummary };
330271
+ }
330264
330272
  continue;
330265
330273
  }
330266
330274
  if (event.type === "text.delta") {
@@ -330509,6 +330517,7 @@ ${responsePath}
330509
330517
  if (!delta) continue;
330510
330518
  if (delta.reasoning_content) {
330511
330519
  currentReasoningContent += delta.reasoning_content;
330520
+ yield { type: "status", text: "", reasoningContent: currentReasoningContent };
330512
330521
  }
330513
330522
  const deltaText = this.extractTextValue(delta.content);
330514
330523
  if (deltaText) {
@@ -340962,6 +340971,7 @@ async function runAgentKernel(agent) {
340962
340971
  currentAgent.emitWorkEvent({ type: "thought", content: "" });
340963
340972
  }
340964
340973
  if (delta) {
340974
+ currentAgent.emitWorkEvent({ type: "thought_delta", content: delta });
340965
340975
  stream2.push({ type: "thinking_delta", contentIndex, delta, partial: assistantMessage2(model, thinking ? [{ type: "text", text }] : [], "stop") });
340966
340976
  }
340967
340977
  }
@@ -346693,7 +346703,7 @@ ${String(event.toolArgs || "")}`;
346693
346703
  id: `${Date.now()}-${Math.random().toString(16).slice(2)}`,
346694
346704
  conversationId: input.conversationId || this.activeConversationId || "default",
346695
346705
  type: publishedType,
346696
- content: isToolEvent ? this.publicToolEventContent(publishedType, toolName) : input.type === "text" ? this.sanitizeAssistantStreamingOutput(input.content || "") : this.sanitizePublicWorkContent(input.content || ""),
346706
+ content: isToolEvent ? this.publicToolEventContent(publishedType, toolName) : input.type === "text" || input.type === "thought_delta" ? this.sanitizeAssistantStreamingOutput(input.content || "") : this.sanitizePublicWorkContent(input.content || ""),
346697
346707
  mode: input.mode || this.modeName(),
346698
346708
  model: input.model || this.model,
346699
346709
  timestamp: input.timestamp || this.nowLabel(),
@@ -2280,7 +2280,7 @@ class Agent {
2280
2280
  type: publishedType,
2281
2281
  content: isToolEvent
2282
2282
  ? this.publicToolEventContent(publishedType, toolName)
2283
- : input.type === 'text'
2283
+ : input.type === 'text' || input.type === 'thought_delta'
2284
2284
  ? this.sanitizeAssistantStreamingOutput(input.content || '')
2285
2285
  : this.sanitizePublicWorkContent(input.content || ''),
2286
2286
  mode: input.mode || this.modeName(),
@@ -576,6 +576,7 @@ async function runAgentKernel(agent) {
576
576
  currentAgent.emitWorkEvent({ type: 'thought', content: '' });
577
577
  }
578
578
  if (delta) {
579
+ currentAgent.emitWorkEvent({ type: 'thought_delta', content: delta });
579
580
  stream.push({ type: 'thinking_delta', contentIndex, delta, partial: assistantMessage(model, thinking ? [{ type: 'text', text }] : [], 'stop') });
580
581
  }
581
582
  }
@@ -100,7 +100,7 @@ export interface ChatMessage {
100
100
  export interface AgentWorkEvent {
101
101
  id: string;
102
102
  conversationId: string;
103
- type: 'start' | 'text' | 'response' | 'final_response' | 'tool_call' | 'tool_result' | 'thought' | 'thought_result' | 'status' | 'done' | 'error' | 'queue_update' | 'guide';
103
+ type: 'start' | 'text' | 'response' | 'final_response' | 'tool_call' | 'tool_result' | 'thought' | 'thought_delta' | 'thought_result' | 'status' | 'done' | 'error' | 'queue_update' | 'guide';
104
104
  content: string;
105
105
  mode: string;
106
106
  model: string;
@@ -1,7 +1,7 @@
1
1
  import type { AgentWorkEvent } from './types';
2
2
  /**
3
- * Bounds cross-process traffic for high-rate streaming text without changing
4
- * durable work-run events. Non-text events always flush pending text first.
3
+ * Bounds cross-process traffic for high-rate response and thought deltas
4
+ * without changing durable work-run events. Lifecycle events flush deltas first.
5
5
  */
6
6
  export declare class WorkEventCoalescer {
7
7
  private readonly emit;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WorkEventCoalescer = void 0;
4
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.
5
+ * Bounds cross-process traffic for high-rate response and thought deltas
6
+ * without changing durable work-run events. Lifecycle events flush deltas first.
7
7
  */
8
8
  class WorkEventCoalescer {
9
9
  emit;
@@ -14,12 +14,12 @@ class WorkEventCoalescer {
14
14
  this.windowMs = windowMs;
15
15
  }
16
16
  push(event) {
17
- if (event.type !== 'text') {
17
+ if (event.type !== 'text' && event.type !== 'thought_delta') {
18
18
  this.flushAll();
19
19
  this.emit(event);
20
20
  return;
21
21
  }
22
- const key = `${event.workspaceId || ''}::${event.conversationId}::${event.runtimeKey || ''}::${event.runId || ''}`;
22
+ const key = `${event.type}::${event.workspaceId || ''}::${event.conversationId}::${event.runtimeKey || ''}::${event.runId || ''}`;
23
23
  const current = this.pending.get(key);
24
24
  if (current) {
25
25
  current.content += event.content;
@@ -956,7 +956,6 @@ class LLMProvider {
956
956
  const transport = this.buildProviderAdapterTransport();
957
957
  const streaming = mode === 'chat_stream';
958
958
  const reasoningState = { current: '' };
959
- let reasoningStatusEmitted = false;
960
959
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
961
960
  if (event.type === 'response.started' || event.type === 'response.completed')
962
961
  continue;
@@ -964,10 +963,7 @@ class LLMProvider {
964
963
  continue;
965
964
  if (event.type === 'reasoning.summary.delta') {
966
965
  reasoningState.current += event.delta;
967
- if (!streaming && !reasoningStatusEmitted) {
968
- reasoningStatusEmitted = true;
969
- yield { type: 'status', text: '', reasoningContent: reasoningState.current };
970
- }
966
+ yield { type: 'status', text: '', reasoningContent: reasoningState.current };
971
967
  continue;
972
968
  }
973
969
  if (event.type === 'text.delta') {
@@ -1020,14 +1016,22 @@ class LLMProvider {
1020
1016
  serialized.headers['Accept'] = 'text/event-stream';
1021
1017
  const execSignal = signal ?? new AbortController().signal;
1022
1018
  const transport = this.buildProviderAdapterTransport();
1019
+ let reasoningSummary = '';
1023
1020
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
1024
1021
  if (event.type === 'response.started' || event.type === 'response.completed')
1025
1022
  continue;
1026
1023
  if (event.type === 'tool_call.started' || event.type === 'tool_call.arguments.delta')
1027
1024
  continue;
1025
+ if (event.type === 'reasoning.summary.delta') {
1026
+ reasoningSummary += event.delta;
1027
+ yield { type: 'status', text: '', reasoningContent: reasoningSummary };
1028
+ continue;
1029
+ }
1028
1030
  if (event.type === 'reasoning.summary.done') {
1029
- if (event.summary)
1030
- yield { type: 'status', text: event.summary };
1031
+ if (event.summary && event.summary !== reasoningSummary) {
1032
+ reasoningSummary = event.summary;
1033
+ yield { type: 'status', text: '', reasoningContent: reasoningSummary };
1034
+ }
1031
1035
  continue;
1032
1036
  }
1033
1037
  if (event.type === 'text.delta') {
@@ -1293,6 +1297,7 @@ class LLMProvider {
1293
1297
  continue;
1294
1298
  if (delta.reasoning_content) {
1295
1299
  currentReasoningContent += delta.reasoning_content;
1300
+ yield { type: 'status', text: '', reasoningContent: currentReasoningContent };
1296
1301
  }
1297
1302
  const deltaText = this.extractTextValue(delta.content);
1298
1303
  if (deltaText) {
package/dist/main.js CHANGED
@@ -314,9 +314,9 @@ const workEventCoalescer = new workEventCoalescer_1.WorkEventCoalescer(event =>
314
314
  const workEventNoMobileCoalescer = new workEventCoalescer_1.WorkEventCoalescer(event => dispatchAgentWorkEvent(event, false));
315
315
  function broadcastAgentWorkEvent(event, mirrorToMobile = true) {
316
316
  const workEvent = event;
317
- // Text deltas are the only high-frequency event. They are coalesced at the
318
- // IPC/SSE boundary; all lifecycle/tool events retain immediate ordering.
319
- if (workEvent.type === 'text') {
317
+ // Response and thought deltas are coalesced at the IPC/SSE boundary; all
318
+ // lifecycle/tool events retain immediate ordering.
319
+ if (workEvent.type === 'text' || workEvent.type === 'thought_delta') {
320
320
  (mirrorToMobile ? workEventCoalescer : workEventNoMobileCoalescer).push(workEvent);
321
321
  return;
322
322
  }
@@ -154,8 +154,10 @@ class ResponsesAdapter {
154
154
  if (eventType === 'response.reasoning_summary_text.delta') {
155
155
  const key = `${String(payload.item_id || '')}:${String(payload.summary_index || 0)}`;
156
156
  const delta = this.extractText(payload.delta);
157
- if (delta)
157
+ if (delta) {
158
158
  reasoningSummaries.set(key, (reasoningSummaries.get(key) || '') + delta);
159
+ yield { type: 'reasoning.summary.delta', delta };
160
+ }
159
161
  continue;
160
162
  }
161
163
  if (eventType === 'response.reasoning_summary_text.done') {
package/dist/server.js CHANGED
@@ -1092,6 +1092,18 @@ async function handleApi(req, res, body) {
1092
1092
  mobileJson(res, { workspace: { id: ws.id, name: ws.name, path: ws.path, isInternal: ws.isInternal }, conversations });
1093
1093
  return;
1094
1094
  }
1095
+ case '/api/mobile/provider-catalog-export': {
1096
+ if (req.method !== 'POST') {
1097
+ mobileJson(res, { error: 'Method not allowed' }, 405);
1098
+ return;
1099
+ }
1100
+ // This is intentionally separate from mobile state: normal remote UI
1101
+ // projection stays redacted, while an explicit paired-device import
1102
+ // can migrate a usable local provider configuration.
1103
+ res.setHeader('Cache-Control', 'no-store');
1104
+ mobileJson(res, { providers: agent.config.providers() });
1105
+ return;
1106
+ }
1095
1107
  case '/api/mobile/right-sidebar-state': {
1096
1108
  const workspaceId = url.searchParams.get('workspaceId') || '';
1097
1109
  const conversationId = url.searchParams.get('conversationId') || '';
@@ -9896,7 +9896,7 @@ function publicWorkEvent(event) {
9896
9896
  var content = String(event && event.content || '');
9897
9897
  var toolArgs = String(event && event.toolArgs || '');
9898
9898
  if (/<think(?:\s|>)/i.test(content) || /<\/think>/i.test(content) || /<\/?think\b|(?:reasoning_content|thinking_delta)\s*[::]/i.test(toolArgs)) return false;
9899
- return ['start', 'text', 'response', 'final_response', 'status', 'tool_call', 'tool_result', 'thought', 'thought_result', 'guide', 'guide_accepted', 'guide_applied', 'guide_deferred', 'guide_rejected', 'done', 'error', 'interrupted', 'force_interrupted'].indexOf(type) >= 0;
9899
+ return ['start', 'text', 'response', 'final_response', 'status', 'tool_call', 'tool_result', 'thought', 'thought_delta', 'thought_result', 'guide', 'guide_accepted', 'guide_applied', 'guide_deferred', 'guide_rejected', 'done', 'error', 'interrupted', 'force_interrupted'].indexOf(type) >= 0;
9900
9900
  }
9901
9901
 
9902
9902
  function publicToolNameForUi(value) {
@@ -10568,6 +10568,16 @@ function renderWorkRunEvents(run, includeGuides) {
10568
10568
  }
10569
10569
  if (!rawEvent) continue;
10570
10570
  }
10571
+ if (rawType === 'thought_delta') {
10572
+ for (var thoughtDeltaIndex = events.length - 1; thoughtDeltaIndex >= 0; thoughtDeltaIndex--) {
10573
+ var liveThought = events[thoughtDeltaIndex];
10574
+ if (String(liveThought && liveThought.type || '').toLowerCase() !== 'thought' || liveThought.completed) continue;
10575
+ events[thoughtDeltaIndex] = Object.assign({}, liveThought, { content: String(liveThought.content || '') + String(rawEvent.content || '') });
10576
+ rawEvent = null;
10577
+ break;
10578
+ }
10579
+ if (!rawEvent) continue;
10580
+ }
10571
10581
  events.push(rawEvent);
10572
10582
  }
10573
10583
  flushPublicText();
@@ -10786,6 +10796,16 @@ function applyAgentWorkEventToRun(event) {
10786
10796
  recordGuideUiMessage(event, target);
10787
10797
  }
10788
10798
  if (publicWorkEvent(event) && type !== 'start') {
10799
+ if (type === 'thought_delta') {
10800
+ for (var liveThoughtIndex = run.events.length - 1; liveThoughtIndex >= 0; liveThoughtIndex--) {
10801
+ var liveThoughtEvent = run.events[liveThoughtIndex];
10802
+ if (String(liveThoughtEvent.type || '').toLowerCase() !== 'thought' || liveThoughtEvent.completed) continue;
10803
+ run.events[liveThoughtIndex] = Object.assign({}, liveThoughtEvent, {
10804
+ content: String(liveThoughtEvent.content || '') + String(event.content || '')
10805
+ });
10806
+ break;
10807
+ }
10808
+ } else {
10789
10809
  var incomingGuideKey = guideWorkEventKey(event);
10790
10810
  if (incomingGuideKey) {
10791
10811
  for (var guideEventIndex = run.events.length - 1; guideEventIndex >= 0; guideEventIndex--) {
@@ -10805,6 +10825,7 @@ function applyAgentWorkEventToRun(event) {
10805
10825
  var eventId = String(event.id || [event.sequence || '', type, event.timestamp || '', event.content || ''].join('|'));
10806
10826
  if (!run.events.some(function(item) { return String(item.id || '') === eventId; })) run.events.push(Object.assign({}, event, { id: eventId }));
10807
10827
  run.events.sort(compareConversationWorkEvents);
10828
+ }
10808
10829
  }
10809
10830
  run.sequence = Math.max(Number(run.sequence || 0), Number(event.sequence || 0));
10810
10831
  if (type === 'done') { run.status = 'completed'; run.endedAt = event.endedAt || event.timestampIso || new Date().toISOString(); if (run.userToggled !== true) run.expanded = false; }
@@ -11366,7 +11387,13 @@ function cacheAgentWorkEvent(event) {
11366
11387
  var id = eventRuntimeKey(event);
11367
11388
  if (!state.agentWorkEventsByConversation) state.agentWorkEventsByConversation = {};
11368
11389
  if (!state.agentWorkEventsByConversation[id]) state.agentWorkEventsByConversation[id] = [];
11369
- state.agentWorkEventsByConversation[id].push(event);
11390
+ var cached = state.agentWorkEventsByConversation[id];
11391
+ var previous = cached.length ? cached[cached.length - 1] : null;
11392
+ if (event.type === 'thought_delta' && previous && previous.type === 'thought_delta' && String(previous.runId || '') === String(event.runId || '')) {
11393
+ previous.content = String(previous.content || '') + String(event.content || '');
11394
+ } else {
11395
+ cached.push(event);
11396
+ }
11370
11397
  var limit = Number(state.agentWorkEventLimit || 240);
11371
11398
  if (state.agentWorkEventsByConversation[id].length > limit) {
11372
11399
  state.agentWorkEventsByConversation[id] = state.agentWorkEventsByConversation[id].slice(-limit);
@@ -329205,7 +329205,10 @@ var ResponsesAdapter = class {
329205
329205
  if (eventType === "response.reasoning_summary_text.delta") {
329206
329206
  const key3 = `${String(payload.item_id || "")}:${String(payload.summary_index || 0)}`;
329207
329207
  const delta = this.extractText(payload.delta);
329208
- if (delta) reasoningSummaries.set(key3, (reasoningSummaries.get(key3) || "") + delta);
329208
+ if (delta) {
329209
+ reasoningSummaries.set(key3, (reasoningSummaries.get(key3) || "") + delta);
329210
+ yield { type: "reasoning.summary.delta", delta };
329211
+ }
329209
329212
  continue;
329210
329213
  }
329211
329214
  if (eventType === "response.reasoning_summary_text.done") {
@@ -330199,16 +330202,12 @@ ${responsePath}
330199
330202
  const transport = this.buildProviderAdapterTransport();
330200
330203
  const streaming = mode === "chat_stream";
330201
330204
  const reasoningState = { current: "" };
330202
- let reasoningStatusEmitted = false;
330203
330205
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
330204
330206
  if (event.type === "response.started" || event.type === "response.completed") continue;
330205
330207
  if (event.type === "tool_call.started" || event.type === "tool_call.arguments.delta") continue;
330206
330208
  if (event.type === "reasoning.summary.delta") {
330207
330209
  reasoningState.current += event.delta;
330208
- if (!streaming && !reasoningStatusEmitted) {
330209
- reasoningStatusEmitted = true;
330210
- yield { type: "status", text: "", reasoningContent: reasoningState.current };
330211
- }
330210
+ yield { type: "status", text: "", reasoningContent: reasoningState.current };
330212
330211
  continue;
330213
330212
  }
330214
330213
  if (event.type === "text.delta") {
@@ -330260,11 +330259,20 @@ ${responsePath}
330260
330259
  serialized.headers["Accept"] = "text/event-stream";
330261
330260
  const execSignal = signal ?? new AbortController().signal;
330262
330261
  const transport = this.buildProviderAdapterTransport();
330262
+ let reasoningSummary = "";
330263
330263
  for await (const event of adapter.execute(serialized, execSignal, transport)) {
330264
330264
  if (event.type === "response.started" || event.type === "response.completed") continue;
330265
330265
  if (event.type === "tool_call.started" || event.type === "tool_call.arguments.delta") continue;
330266
+ if (event.type === "reasoning.summary.delta") {
330267
+ reasoningSummary += event.delta;
330268
+ yield { type: "status", text: "", reasoningContent: reasoningSummary };
330269
+ continue;
330270
+ }
330266
330271
  if (event.type === "reasoning.summary.done") {
330267
- if (event.summary) yield { type: "status", text: event.summary };
330272
+ if (event.summary && event.summary !== reasoningSummary) {
330273
+ reasoningSummary = event.summary;
330274
+ yield { type: "status", text: "", reasoningContent: reasoningSummary };
330275
+ }
330268
330276
  continue;
330269
330277
  }
330270
330278
  if (event.type === "text.delta") {
@@ -330513,6 +330521,7 @@ ${responsePath}
330513
330521
  if (!delta) continue;
330514
330522
  if (delta.reasoning_content) {
330515
330523
  currentReasoningContent += delta.reasoning_content;
330524
+ yield { type: "status", text: "", reasoningContent: currentReasoningContent };
330516
330525
  }
330517
330526
  const deltaText = this.extractTextValue(delta.content);
330518
330527
  if (deltaText) {
@@ -340966,6 +340975,7 @@ async function runAgentKernel(agent) {
340966
340975
  currentAgent.emitWorkEvent({ type: "thought", content: "" });
340967
340976
  }
340968
340977
  if (delta) {
340978
+ currentAgent.emitWorkEvent({ type: "thought_delta", content: delta });
340969
340979
  stream2.push({ type: "thinking_delta", contentIndex, delta, partial: assistantMessage2(model, thinking ? [{ type: "text", text }] : [], "stop") });
340970
340980
  }
340971
340981
  }
@@ -346697,7 +346707,7 @@ ${String(event.toolArgs || "")}`;
346697
346707
  id: `${Date.now()}-${Math.random().toString(16).slice(2)}`,
346698
346708
  conversationId: input2.conversationId || this.activeConversationId || "default",
346699
346709
  type: publishedType,
346700
- content: isToolEvent ? this.publicToolEventContent(publishedType, toolName) : input2.type === "text" ? this.sanitizeAssistantStreamingOutput(input2.content || "") : this.sanitizePublicWorkContent(input2.content || ""),
346710
+ content: isToolEvent ? this.publicToolEventContent(publishedType, toolName) : input2.type === "text" || input2.type === "thought_delta" ? this.sanitizeAssistantStreamingOutput(input2.content || "") : this.sanitizePublicWorkContent(input2.content || ""),
346701
346711
  mode: input2.mode || this.modeName(),
346702
346712
  model: input2.model || this.model,
346703
346713
  timestamp: input2.timestamp || this.nowLabel(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "newmark-agent",
3
3
  "productName": "Newmark Agent",
4
- "version": "0.5.0",
4
+ "version": "0.5.2",
5
5
  "description": "Newmark Agent — Portable AI coding agent with rich GUI and CLI (TypeScript)",
6
6
  "homepage": "https://github.com/positer/Newmark-Agent",
7
7
  "repository": {