newmark-agent 0.6.2 → 0.6.4

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.
@@ -2,6 +2,10 @@
2
2
  export interface RequestContextEstimate {
3
3
  requestId: string;
4
4
  runId: string;
5
+ /** Immutable runtime branch that owned this model request. */
6
+ branchId: string;
7
+ /** Content hash of the actual submitted system/messages/tools payload. */
8
+ contextHash: string;
5
9
  model: string;
6
10
  at: string;
7
11
  estimatedTokens: number;
@@ -14,5 +18,5 @@ export interface RequestContextEstimate {
14
18
  inputTokens?: number;
15
19
  cacheReadTokens?: number;
16
20
  }
17
- export declare function estimateSubmittedContext(messages: Array<Record<string, unknown>>, systemPrompt: string, tools: unknown[], buildBlockStart: number): Omit<RequestContextEstimate, 'requestId' | 'runId' | 'model' | 'at'>;
21
+ export declare function estimateSubmittedContext(messages: Array<Record<string, unknown>>, systemPrompt: string, tools: unknown[], buildBlockStart: number): Omit<RequestContextEstimate, 'requestId' | 'runId' | 'model' | 'at' | 'branchId' | 'contextHash'>;
18
22
  //# sourceMappingURL=requestContextEstimate.d.ts.map
@@ -1311,12 +1311,19 @@ class LLMProvider {
1311
1311
  async *chatStreamWithTools(model, messages, systemPrompt, temperature, maxTokens, tools, signal, reasoningTier, sessionId) {
1312
1312
  if (signal?.aborted)
1313
1313
  throw abortFailure(signal);
1314
+ // A non-positive value means "provider owns the output limit". Protocols
1315
+ // whose wire format requires a positive max_tokens (Anthropic, GitHub
1316
+ // Models) fall back to the selected reasoning tier's budget; OpenAI-style
1317
+ // adapters omit the field entirely so the endpoint decides.
1318
+ const requiredMaxTokens = maxTokens > 0
1319
+ ? maxTokens
1320
+ : this.intelligenceConfig(reasoningTier || 'medium').maxTokens;
1314
1321
  if (this.protocol() === 'anthropic') {
1315
- yield* this.anthropicChatWithTools(model, messages, systemPrompt, temperature, maxTokens, tools, signal);
1322
+ yield* this.anthropicChatWithTools(model, messages, systemPrompt, temperature, requiredMaxTokens, tools, signal);
1316
1323
  return;
1317
1324
  }
1318
1325
  if (this.protocol() === 'github_models') {
1319
- yield* this.githubModelsChatStreamWithTools(model, messages, systemPrompt, temperature, maxTokens, tools, signal);
1326
+ yield* this.githubModelsChatStreamWithTools(model, messages, systemPrompt, temperature, requiredMaxTokens, tools, signal);
1320
1327
  return;
1321
1328
  }
1322
1329
  if (this.useProviderAdaptersV2) {
package/dist/main.js CHANGED
@@ -3123,7 +3123,7 @@ else {
3123
3123
  };
3124
3124
  const mutateConversationQueue = async (target, rawAction, input = {}) => {
3125
3125
  const action = rawAction.replace(/^queue_/, '');
3126
- if (!['enqueue', 'update', 'delete', 'reorder', 'toggle_pause', 'set_pause', 'guide'].includes(action))
3126
+ if (!['enqueue', 'update', 'delete', 'reorder', 'toggle_pause', 'set_pause', 'repair_blocked', 'guide'].includes(action))
3127
3127
  throw new Error('Unknown queue action');
3128
3128
  const key = activeFlowStateKey(target);
3129
3129
  const flow = activeFlowStateFor(target);
@@ -3292,6 +3292,10 @@ else {
3292
3292
  // Other conversations' paused Flows are never touched by this send.
3293
3293
  const flow = activeFlowStateFor(target);
3294
3294
  const snapshot = await runtimeSnapshotForTarget(target);
3295
+ // The renderer's visible composer selection is authoritative for this
3296
+ // send. It is provider-qualified (deployment:providerId:modelId), so it
3297
+ // can never fall back to a same-named model on another provider.
3298
+ const requestedModelSelection = String(requested.model || '').trim();
3295
3299
  const structured = typeof message === 'string' ? { text: message } : { ...message };
3296
3300
  const requestedMode = String(requested.requestedMode || structured.visibleMode || snapshot.mode || 'build');
3297
3301
  const inputMode = String(requested.inputMode || snapshot.inputMode || 'guide') === 'next' ? 'next' : 'guide';
@@ -3319,9 +3323,18 @@ else {
3319
3323
  });
3320
3324
  return { ok: receipt.status !== 'rejected', accepted: receipt.status !== 'rejected', receipt, ...await runtimeSnapshotForTarget(target) };
3321
3325
  }
3326
+ const requestedBranchPath = Array.isArray(structured.branchPath)
3327
+ ? (structured.branchPath || []).map(id => String(id || '')).filter(Boolean)
3328
+ : String(structured.branchPath || '').split('>').map(id => id.trim()).filter(Boolean);
3329
+ const requestedBranchNodeId = String(structured.branchNodeId
3330
+ || requestedBranchPath[requestedBranchPath.length - 1]
3331
+ || '');
3322
3332
  return await applyConversationAction(target, 'queue_enqueue', '', {
3323
3333
  id, text: structured.visibleUserInput || structured.text, requestedMode: requestedMode === 'flow' ? 'build' : requestedMode,
3324
3334
  goalObjective: objective, images: structured.images, createdAt: new Date().toISOString(),
3335
+ branchNodeId: requestedBranchNodeId || undefined,
3336
+ branchPath: requestedBranchPath.length ? requestedBranchPath : undefined,
3337
+ modelSelection: requestedModelSelection || undefined,
3325
3338
  });
3326
3339
  }
3327
3340
  await selectConversationMode(target, requestedMode);
@@ -3335,10 +3348,10 @@ else {
3335
3348
  // 发送命令时锁定输入框选择的模型:接受命令后的整个运行过程都以该
3336
3349
  // 模型为准(唯一例外是显式的不可用回退,且回退会以结构化事件同步
3337
3350
  // 到前端输入框下方的选择区,而不是隐藏的参数回退)。
3338
- const requestedModel = String(snapshot.model || agent.model);
3351
+ const requestedModel = String(requestedModelSelection || snapshot.model || agent.model);
3339
3352
  const options = {
3340
3353
  mode: requestedMode === 'goal' ? 'goal' : requestedMode,
3341
- model: String(snapshot.model || agent.ensureUsableModelSelection()),
3354
+ model: String(requestedModelSelection || snapshot.model || agent.ensureUsableModelSelection()),
3342
3355
  intelligence: String(snapshot.intelligence || agent.intelligence),
3343
3356
  inputMode: inputMode,
3344
3357
  engine: agent.engine,
@@ -3460,6 +3473,16 @@ else {
3460
3473
  settlement: new Promise(resolve => { resolvePendingSettlement = resolve; }),
3461
3474
  };
3462
3475
  pendingFlowStarts.set(flowKey, pending);
3476
+ // Admit the Flow build at command-acceptance time. It may wait behind a
3477
+ // running Build, but its queue position fixes the parent of every later
3478
+ // Next item; the actual Flow start only claims this existing build.
3479
+ const flowCommandId = `flow-${flowKey}-${(0, crypto_1.randomUUID)()}`;
3480
+ const flowBuildId = ensureConversationKernel(root).admitExternalBuild(flowTarget, {
3481
+ commandId: flowCommandId,
3482
+ text: String(input || ''),
3483
+ requestedMode: 'flow',
3484
+ modelSelection: agent.modelSelectionValue(),
3485
+ });
3463
3486
  let previousQueuePaused = false;
3464
3487
  try {
3465
3488
  let state = await runtimeSnapshotForTarget(flowTarget);
@@ -3485,7 +3508,13 @@ else {
3485
3508
  }
3486
3509
  const flowAgent = ensureConversationKernel(root).beginExternalRun(flowTarget, {
3487
3510
  mode: 'flow', model: agent.model, intelligence: agent.intelligence, inputMode: agent.inputMode, engine: agent.engine,
3488
- }, () => isolatedConversationAgent(flowTarget), previousQueuePaused);
3511
+ }, () => isolatedConversationAgent(flowTarget), previousQueuePaused, {
3512
+ commandId: flowCommandId,
3513
+ text: String(input || ''),
3514
+ requestedMode: 'flow',
3515
+ modelSelection: agent.modelSelectionValue(),
3516
+ existingBuildId: flowBuildId || undefined,
3517
+ });
3489
3518
  mainConversationOwners.add(flowKey);
3490
3519
  conversationSelections.set(flowKey, { ...conversationSelections.get(flowKey), mode: 'flow' });
3491
3520
  const previousMode = flowAgent.mode;
@@ -3655,7 +3684,13 @@ else {
3655
3684
  const flowAgent = ensureConversationKernel(root).beginExternalRun(flowTarget, {
3656
3685
  mode: 'flow', model: suspension.flowAgent?.model || agent.model, intelligence: suspension.flowAgent?.intelligence || agent.intelligence,
3657
3686
  inputMode: suspension.flowAgent?.inputMode || agent.inputMode, engine: agent.engine,
3658
- }, () => suspension.flowAgent || isolatedConversationAgent(flowTarget), suspension.queueWasPaused ?? true);
3687
+ }, () => suspension.flowAgent || isolatedConversationAgent(flowTarget), suspension.queueWasPaused ?? true, {
3688
+ commandId: `flow-resume-${flowKey}-${(0, crypto_1.randomUUID)()}`,
3689
+ text: String(response || ''),
3690
+ requestedMode: 'flow',
3691
+ modelSelection: agent.modelSelectionValue(),
3692
+ resume: true,
3693
+ });
3659
3694
  mainConversationOwners.add(flowKey);
3660
3695
  suspension.flowAgent = flowAgent;
3661
3696
  // A previous Flow may have been interrupted just before its isolated
@@ -44,8 +44,13 @@ class ChatCompletionsAdapter {
44
44
  model: request.model,
45
45
  messages,
46
46
  temperature: request.temperature,
47
- max_tokens: request.maxOutputTokens,
48
47
  };
48
+ // Omit the cap entirely for provider-owned output. Only auxiliary
49
+ // requests that explicitly need a bounded completion send a positive
50
+ // max_tokens value.
51
+ if (Number.isFinite(request.maxOutputTokens) && request.maxOutputTokens > 0) {
52
+ body.max_tokens = request.maxOutputTokens;
53
+ }
49
54
  if (tools.length) {
50
55
  body.tools = tools;
51
56
  body.tool_choice = 'auto';
@@ -69,8 +69,11 @@ class ResponsesAdapter {
69
69
  model: request.model,
70
70
  input: input.length ? input : [{ role: 'user', content: '' }],
71
71
  temperature: request.temperature,
72
- max_output_tokens: request.maxOutputTokens,
73
72
  };
73
+ // Omit the cap entirely for provider-owned output.
74
+ if (Number.isFinite(request.maxOutputTokens) && request.maxOutputTokens > 0) {
75
+ body.max_output_tokens = request.maxOutputTokens;
76
+ }
74
77
  if (request.reasoningEffort)
75
78
  body.reasoning = { effort: request.reasoningEffort, summary: 'auto' };
76
79
  if (request.systemPrompt)
package/dist/server.d.ts CHANGED
@@ -32,6 +32,7 @@ export interface HostedMobileServerOptions {
32
32
  clientMessageId?: string;
33
33
  flowName?: string;
34
34
  flowStart?: number;
35
+ model?: string;
35
36
  }) => Promise<Record<string, unknown>>;
36
37
  }
37
38
  export interface HostedMobileServerStatus {
package/dist/server.js CHANGED
@@ -153,6 +153,7 @@ function hostedCommandOptions(params) {
153
153
  clientMessageId: String(params.clientMessageId || ''),
154
154
  flowName: String(params.flowName || params.defaultFlow || ''),
155
155
  flowStart: typeof params.flowStart === 'number' && Number.isFinite(params.flowStart) ? params.flowStart : undefined,
156
+ model: String(params.model || ''),
156
157
  };
157
158
  }
158
159
  const MOBILE_EDITABLE_EXTENSIONS = new Set([