specrails-desktop 2.46.0 → 2.47.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 (94) hide show
  1. package/client/dist/assets/{ActivityFeedPage-CsHQPpvl.js → ActivityFeedPage-DSCpSOGV.js} +1 -1
  2. package/client/dist/assets/{AgentBrowserCapture-BVcCK7x0.js → AgentBrowserCapture-mc1c5pgS.js} +1 -1
  3. package/client/dist/assets/{AgentModeAnalyticsPane-C5F3m29G.js → AgentModeAnalyticsPane--UkamBTm.js} +2 -2
  4. package/client/dist/assets/{AgentModeCodePane-C5QuKsu0.js → AgentModeCodePane-DJCswsvU.js} +2 -2
  5. package/client/dist/assets/{AgentModeJobsPane-rnD-EPMd.js → AgentModeJobsPane-Dw3DNFkh.js} +1 -1
  6. package/client/dist/assets/{AgentsPage-DiyJWZcU.js → AgentsPage-ChElPUL9.js} +1 -1
  7. package/client/dist/assets/{AnalyticsPage-Dkmb0dnd.js → AnalyticsPage-BGtkFHBp.js} +1 -1
  8. package/client/dist/assets/{CodePage-C0dH99-t.js → CodePage-BBnw3VGn.js} +1 -1
  9. package/client/dist/assets/{DesktopAnalyticsPage-DuTjr2n8.js → DesktopAnalyticsPage-B85tNScc.js} +1 -1
  10. package/client/dist/assets/{DocsDialog-BVZJZHVR.js → DocsDialog-D4cXrOMl.js} +1 -1
  11. package/client/dist/assets/{DocsPage-D6KHTv8V.js → DocsPage-BCAbC6qy.js} +1 -1
  12. package/client/dist/assets/{ExportDropdown-pWZGYCv3.js → ExportDropdown-BwuvqS2Y.js} +1 -1
  13. package/client/dist/assets/{InteractiveJobComposer-Ck3PQxjN.js → InteractiveJobComposer-Coq-Zhk0.js} +2 -2
  14. package/client/dist/assets/{JobDetailModal-DkoMH3ie.js → JobDetailModal--Mjam0Nc.js} +1 -1
  15. package/client/dist/assets/{JobDetailPage-CBVivcl2.js → JobDetailPage-B6ShWSBh.js} +1 -1
  16. package/client/dist/assets/{JobsPage-CzxEeca9.js → JobsPage-DHU_ep_B.js} +1 -1
  17. package/client/dist/assets/{LoopBuilderPage-CtmOE4-b.js → LoopBuilderPage-Byvq8Oqx.js} +1 -1
  18. package/client/dist/assets/{LoopPreviewModal-BYeLjQbr.js → LoopPreviewModal-BMC9Mgj1.js} +1 -1
  19. package/client/dist/assets/{LoopsPage-6iW7g25k.js → LoopsPage-CFGl-Nw8.js} +1 -1
  20. package/client/dist/assets/{MinimizedChatsContext-B6wVevPq.js → MinimizedChatsContext-DHjHBYqa.js} +1 -1
  21. package/client/dist/assets/{PluginsPage-Bf1z3WPF.js → PluginsPage-BHygRnW6.js} +1 -1
  22. package/client/dist/assets/{ProjectSettingsDialog-DsCRIc4v.js → ProjectSettingsDialog-nspqxH-M.js} +1 -1
  23. package/client/dist/assets/{RepositoryDeliveries-BQm_3TO8.js → RepositoryDeliveries-Dq9NJOWi.js} +1 -1
  24. package/client/dist/assets/{RepositoryScopeSelector-DnAFtjTz.js → RepositoryScopeSelector-C3jKG2z0.js} +1 -1
  25. package/client/dist/assets/{ReviewPacketPage-CaXAwtR7.js → ReviewPacketPage-C9mqhi65.js} +1 -1
  26. package/client/dist/assets/{TemplatePreviewModal-9aRFpJ_J.js → TemplatePreviewModal-BmwoAjOr.js} +1 -1
  27. package/client/dist/assets/{TicketDetailModalContext-B1X5glzV.js → TicketDetailModalContext-lYmoONrd.js} +1 -1
  28. package/client/dist/assets/{Trans-BwLgX6n7.js → Trans-C0KyPo2O.js} +1 -1
  29. package/client/dist/assets/agentRuntime-62GWdc26.js +1 -0
  30. package/client/dist/assets/agentRuntime-BN1mKAuY.js +1 -0
  31. package/client/dist/assets/agentRuntime-BNBCzQLM.js +1 -0
  32. package/client/dist/assets/agentRuntime-BQE_K1GG.js +1 -0
  33. package/client/dist/assets/agentRuntime-CCU3HCtS.js +1 -0
  34. package/client/dist/assets/agentRuntime-DT72Bpdv.js +1 -0
  35. package/client/dist/assets/agentRuntime-ZfMPeeiP.js +1 -0
  36. package/client/dist/assets/agentRuntime-g3W8Ry4d.js +1 -0
  37. package/client/dist/assets/{agents-IUOgqT5t.js → agents-BIT1UdTy.js} +1 -1
  38. package/client/dist/assets/{agents-DaYcxAr1.js → agents-C7fKfvm8.js} +1 -1
  39. package/client/dist/assets/{agents-ms7TwG16.js → agents-CST-lpYX.js} +1 -1
  40. package/client/dist/assets/{agents-Bvyi3y6R.js → agents-Cm2JYrAa.js} +1 -1
  41. package/client/dist/assets/{agents-BHp0_FQt.js → agents-DsgGMGwU.js} +1 -1
  42. package/client/dist/assets/{agents-45GbINfh.js → agents-DyI4rbHa.js} +1 -1
  43. package/client/dist/assets/{agents-rzPnqoBR.js → agents-H6tVQUNP.js} +1 -1
  44. package/client/dist/assets/{agents-DMKFStHL.js → agents-_5mJMkAE.js} +1 -1
  45. package/client/dist/assets/{formatDistanceToNow-CeZv93iR.js → formatDistanceToNow-D44phX1J.js} +1 -1
  46. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DxAkjvJb.js → getTimezoneOffsetInMilliseconds-EAh9LFSx.js} +1 -1
  47. package/client/dist/assets/{index-DYoyDWim.js → index-DgMBighL.js} +9 -9
  48. package/client/dist/assets/{jira-api-ChjVGJx_.js → jira-api-BQR6G0YY.js} +1 -1
  49. package/client/dist/assets/{narration-D-e9ssxA.js → narration-B1uGfofH.js} +1 -1
  50. package/client/dist/assets/{narration-DnrKC3mF.js → narration-BKcL4Srl.js} +1 -1
  51. package/client/dist/assets/{narration-CvQdWdR5.js → narration-BtjKyHVM.js} +1 -1
  52. package/client/dist/assets/{narration-BPMOQPFe.js → narration-CqNvgRi9.js} +1 -1
  53. package/client/dist/assets/{narration-DKLjXIFI.js → narration-DiPyj06T.js} +1 -1
  54. package/client/dist/assets/{narration-4OSg0b5-.js → narration-DrBAf8uv.js} +1 -1
  55. package/client/dist/assets/{narration-Dypjxeel.js → narration-OyujFouL.js} +1 -1
  56. package/client/dist/assets/{narration-BSldQfjd.js → narration-UWi_xIZ-.js} +1 -1
  57. package/client/dist/assets/{project-repositories-BvBj9XH9.js → project-repositories-GRYdjlKB.js} +1 -1
  58. package/client/dist/assets/{spending-DNM6NAoA.js → spending-CN9PHM65.js} +1 -1
  59. package/client/dist/assets/{useDesktop-mxHVQOdx.js → useDesktop-iius_s5d.js} +1 -1
  60. package/client/dist/assets/{useSharedWebSocket-DnxHj8jP.js → useSharedWebSocket-D7hkZ3Ka.js} +2 -2
  61. package/client/dist/index.html +16 -16
  62. package/docs/plans/implementation-efficiency-artifact.json +18 -0
  63. package/docs/plans/implementation-efficiency-evaluation.json +1817 -0
  64. package/docs/plans/implementation-efficiency-evaluation.md +41 -0
  65. package/docs/plans/implementation-efficiency-progress.md +48 -0
  66. package/docs/plans/implementation-efficiency-release.md +41 -0
  67. package/docs/plans/implementation-efficiency.md +124 -0
  68. package/package.json +1 -1
  69. package/server/dist/agent-runtime-bridge.js +29 -25
  70. package/server/dist/agent-runtime-controls-router.js +8 -0
  71. package/server/dist/agent-runtime-controls.js +57 -10
  72. package/server/dist/agent-runtime-effective-config.js +32 -0
  73. package/server/dist/agent-runtime-events.js +46 -0
  74. package/server/dist/agent-runtime-history.js +47 -0
  75. package/server/dist/agent-runtime-loader.js +84 -5
  76. package/server/dist/agent-runtime-metrics.js +76 -0
  77. package/server/dist/agent-runtime-package.js +205 -0
  78. package/server/dist/agent-runtime-settings-router.js +25 -4
  79. package/server/dist/agent-runtime-settings.js +26 -0
  80. package/server/dist/loop-executors.js +2 -2
  81. package/server/dist/loop-run-manager.js +10 -2
  82. package/server/dist/mcp/tools/rails.js +1 -0
  83. package/server/dist/rail-isolated-launch.js +1 -0
  84. package/server/dist/rails-router.js +26 -0
  85. package/server/dist/schemas/agent-runtime.schema.json +18 -1
  86. package/server/dist/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
  87. package/client/dist/assets/agentRuntime-BUagD2I_.js +0 -1
  88. package/client/dist/assets/agentRuntime-BkL70WtX.js +0 -1
  89. package/client/dist/assets/agentRuntime-CWXVqgqE.js +0 -1
  90. package/client/dist/assets/agentRuntime-CvNBdUAe.js +0 -1
  91. package/client/dist/assets/agentRuntime-D4RmeuNY.js +0 -1
  92. package/client/dist/assets/agentRuntime-DTidBWKg.js +0 -1
  93. package/client/dist/assets/agentRuntime-DhKYfyaU.js +0 -1
  94. package/client/dist/assets/agentRuntime-LL8_GLx9.js +0 -1
@@ -222,7 +222,7 @@ function createLoopExecutors(opts = {}) {
222
222
  return null;
223
223
  }
224
224
  },
225
- async runAiStep({ coreRun, prompt, sessionId, provider, model, effort, profileName, cwd, repoDir, executionManifest, onLine, onRawLine, onSpawn, aiStepTimeoutMs, idleTimeoutMs }) {
225
+ async runAiStep({ runtimeProviderOverride, coreRun, prompt, sessionId, provider, model, effort, profileName, cwd, repoDir, executionManifest, onLine, onRawLine, onSpawn, aiStepTimeoutMs, idleTimeoutMs }) {
226
226
  const adapter = (0, providers_1.getAdapter)(provider);
227
227
  // First iteration spawns headless (rail-job); subsequent iterations resume
228
228
  // the session so the agent keeps prior context across iterations.
@@ -246,7 +246,7 @@ function createLoopExecutors(opts = {}) {
246
246
  return (0, agent_runtime_bridge_1.runAgentRuntimeInvocation)({
247
247
  contextPath: core.contextPath, cwd, env: { ...programmaticStepEnv(resolveEnv(), repoDir, executionManifest), SPECRAILS_EXECUTION_CONTEXT: core.contextPath }, configPath: runtimeConfigPath(cwd),
248
248
  change: (0, agent_runtime_bridge_1.runtimeChangeName)(coreRun.runId), resume: admitted,
249
- defaultProvider: provider, selectedModel: model,
249
+ defaultProvider: provider, providerOverride: runtimeProviderOverride,
250
250
  onLine, onRawLine, onSpawn, timeoutMs: aiStepTimeoutMs,
251
251
  });
252
252
  }
@@ -5,6 +5,8 @@ exports.truncate = truncate;
5
5
  exports.resolveRunVars = resolveRunVars;
6
6
  exports.extractChangeId = extractChangeId;
7
7
  exports.recoverOrphanLoopStepAccounting = recoverOrphanLoopStepAccounting;
8
+ const agent_runtime_events_1 = require("./agent-runtime-events");
9
+ const agent_runtime_settings_1 = require("./agent-runtime-settings");
8
10
  const multi_repo_execution_store_1 = require("./multi-repo-execution-store");
9
11
  const win_spawn_1 = require("./util/win-spawn");
10
12
  const db_1 = require("./db");
@@ -561,7 +563,7 @@ class LoopRunManager {
561
563
  async run(req) {
562
564
  // Later fresh steps must verify the admitted spec, even if its caller or
563
565
  // backlog changes while the implementation is running.
564
- req = { ...req, graph: structuredClone(req.graph) };
566
+ req = { ...req, runtimeProviderOverride: (0, agent_runtime_settings_1.validateRuntimeProviderOverride)(req.runtimeProviderOverride), graph: structuredClone(req.graph) };
565
567
  if (req.spec)
566
568
  req = { ...req, spec: structuredClone(req.spec) };
567
569
  if (req.executionManifest)
@@ -752,6 +754,12 @@ class LoopRunManager {
752
754
  logLine(line);
753
755
  return;
754
756
  }
757
+ if (eventType === 'runtime-efficiency-event') {
758
+ const validated = (0, agent_runtime_events_1.runtimeEfficiencyEventLine)(line, runId);
759
+ if (!validated || (0, agent_runtime_events_1.isRecordedRuntimeEfficiencyEvent)(this.db, runId, validated))
760
+ return;
761
+ line = validated;
762
+ }
755
763
  const s = takeSeq();
756
764
  try {
757
765
  (0, db_1.appendEvent)(this.db, runId, s, { event_type: eventType, source: 'stdout', payload: line });
@@ -1145,7 +1153,7 @@ class LoopRunManager {
1145
1153
  nextEventSeq: takeSeq,
1146
1154
  recoveryStepKey: aiRecoveryKey,
1147
1155
  })
1148
- : this.executors.runAiStep({ coreRun, prompt, sessionId, provider: nodeProvider, model: nodeModel, effort: nodeEffort, profileName: req.profileName, cwd: req.cwd, repoDir: req.repoDir, executionManifest: req.executionManifest, onLine: logLine, onRawLine, onSpawn: (c) => this._activeChild.set(runId, c), aiStepTimeoutMs: effectiveTimeoutMs, idleTimeoutMs });
1156
+ : this.executors.runAiStep({ runtimeProviderOverride: req.runtimeProviderOverride, coreRun, prompt, sessionId, provider: nodeProvider, model: nodeModel, effort: nodeEffort, profileName: req.profileName, cwd: req.cwd, repoDir: req.repoDir, executionManifest: req.executionManifest, onLine: logLine, onRawLine, onSpawn: (c) => this._activeChild.set(runId, c), aiStepTimeoutMs: effectiveTimeoutMs, idleTimeoutMs });
1149
1157
  };
1150
1158
  let res = await runAttempt(aiSessionId);
1151
1159
  if (this._disposed)
@@ -47,6 +47,7 @@ function railsTools() {
47
47
  'stop (destructive — kills all active jobs and loop runs for the rail). ' +
48
48
  'For on_review tickets with an already-open GitHub PR (including a published pr_ready delivery), launch automatically tries to continue that PR head branch; Jira-linked in_progress tickets can do the same when the PR match is explicit; fresh tickets still start from the project integration branch. ' +
49
49
  'When launched from the in-app agent chat without an explicit aiEngine, the engine defaults to your conversation\'s provider. On that same provider, an omitted model inherits the conversation model; an explicit model wins (pass aiEngine to override; launch_all always uses each rail\'s stored engine). ' +
50
+ 'For Implement and Batch Implement, the selected launch provider applies to ALL runtime roles (architect, developer, reviewer); an explicit launch model/effort also applies to each role. Resuming an existing execution keeps its original frozen role configuration; start a new launch to change providers. ' +
50
51
  'User-facing naming: call the free-form autonomous mode "Freestyle"; use "freestyle" as the canonical API enum value for that same capability. ' +
51
52
  'For small OpenSpec-governed work, recommend "SDD Quick (OpenSpec)" and launch with mode "loop" plus loopId "factory:sdd-quick-openspec"; keep Freestyle for ticket-local implementation-only work. ' +
52
53
  'NAMING: railIndex is the 0-BASED internal identity; the dashboard shows rails 1-based ("Rail N" = railIndex N-1). When talking to the user, ALWAYS say "Rail <railIndex + 1>" (or the rail\'s custom name) — results include railLabel with the correct user-facing label.',
@@ -1187,6 +1187,7 @@ async function launchIsolatedRail(input, io = {}) {
1187
1187
  });
1188
1188
  const spec = ctx.getTicketSpec(a.ticketId);
1189
1189
  const enginePromise = ctx.loopRunManager.run({
1190
+ runtimeProviderOverride: input.runtimeProviderOverride,
1190
1191
  runId: a.runId, loopId, loopName, graph: loopGraph, projectId: ctx.project.id,
1191
1192
  cwd: a.handle.worktreePath, repoDir: a.handle.worktreePath,
1192
1193
  repositoryId: singleRepositoryId,
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prDeliveryRevisionAllowed = prDeliveryRevisionAllowed;
4
4
  exports.createRailsRouter = createRailsRouter;
5
+ const agent_runtime_settings_1 = require("./agent-runtime-settings");
5
6
  const express_1 = require("express");
6
7
  const rails_store_1 = require("./rails-store");
7
8
  const queue_manager_1 = require("./queue-manager");
@@ -432,6 +433,14 @@ function createRailsRouter() {
432
433
  res.status(400).json({ error: 'Invalid rail index' });
433
434
  return;
434
435
  }
436
+ let runtimeProviderOverride;
437
+ try {
438
+ runtimeProviderOverride = (0, agent_runtime_settings_1.validateRuntimeProviderOverride)(req.body?.runtimeProviderOverride);
439
+ }
440
+ catch {
441
+ res.status(400).json({ error: 'invalid_runtime_provider_override' });
442
+ return;
443
+ }
435
444
  let { mode = 'implement' } = req.body ?? {};
436
445
  const { repositoryIds: rawRepositoryIds, baseDeliveryIds, profileName, aiEngine, model, loopId: rawLoopId, reasoning_effort, originConversationId, originSurface, targetPrNumber, revisionOfDeliveryId, revisionNote, baseBranch: rawBaseBranch } = req.body ?? {};
437
446
  // Revision launch (nontech-review-experience Wave 3): the user asked for a
@@ -635,6 +644,21 @@ function createRailsRouter() {
635
644
  // Only pass a provider override when one was actually requested (keeps
636
645
  // single-provider rails on the legacy code path).
637
646
  const railProvider = requestedEngine ? engineCheck.provider : undefined;
647
+ // Mission/MCP and Launch-all submit aiEngine or use the saved rail engine.
648
+ // Resolve this at the shared boundary, not only in the Dashboard payload.
649
+ if (!runtimeProviderOverride && requestedEngine) {
650
+ try {
651
+ runtimeProviderOverride = (0, agent_runtime_settings_1.validateRuntimeProviderOverride)({ provider: engineCheck.provider, ...(model ? { model } : {}), ...(reasoning_effort ? { effort: reasoning_effort } : {}) });
652
+ }
653
+ catch {
654
+ res.status(400).json({ error: 'invalid_runtime_provider_override' });
655
+ return;
656
+ }
657
+ }
658
+ if (runtimeProviderOverride && runtimeProviderOverride.provider !== engineCheck.provider) {
659
+ res.status(400).json({ error: 'runtime_provider_mismatch' });
660
+ return;
661
+ }
638
662
  // Freestyle bypasses the OpenSpec pipeline and hands the raw spec to a
639
663
  // provider that explicitly advertises autonomous freestyle support.
640
664
  if (mode === 'freestyle' && (0, providers_1.getAdapter)(engineCheck.provider).capabilities.freestyle !== true) {
@@ -907,6 +931,7 @@ function createRailsRouter() {
907
931
  }
908
932
  try {
909
933
  const ids = await (0, rail_isolated_launch_1.launchIsolatedRail)({
934
+ runtimeProviderOverride,
910
935
  ctx: c, railIndex, ticketIds: [...rail.ticketIds], repositoryIds, ...repositoryBases, loopId, loopName, loopGraph,
911
936
  provider: loopProvider, model: loopModel, effort, scope,
912
937
  profileName: resolvedProfile,
@@ -1015,6 +1040,7 @@ function createRailsRouter() {
1015
1040
  };
1016
1041
  const runPromise = c.loopRunManager
1017
1042
  .run({
1043
+ runtimeProviderOverride,
1018
1044
  runId,
1019
1045
  loopId,
1020
1046
  loopName,
@@ -7,6 +7,11 @@
7
7
  "required": ["schemaVersion", "providers", "agents", "verification"],
8
8
  "properties": {
9
9
  "schemaVersion": { "const": 1 },
10
+ "efficiency": { "type": "object", "additionalProperties": false, "required": ["schemaVersion"], "properties": {
11
+ "schemaVersion": { "const": 1 }, "contextMode": { "enum": ["full", "incremental"] }, "reviewMode": { "enum": ["full", "incremental"] },
12
+ "planning": { "enum": ["full", "proportional"] }, "acceptDeveloperChecks": { "type": "boolean" },
13
+ "verification": { "type": "object", "additionalProperties": false, "properties": { "maxConcurrency": { "type": "integer", "minimum": 1, "maximum": 4 } } }
14
+ } },
10
15
  "rolePrompts": { "type": "object", "additionalProperties": false, "properties": {
11
16
  "architect": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" },
12
17
  "developer": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" },
@@ -31,6 +36,7 @@
31
36
  "maxCostUsd": { "type": "number", "exclusiveMinimum": 0 }, "timeoutMs": { "$ref": "#/definitions/positiveInteger" }
32
37
  } },
33
38
  "verification": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["repositoryId", "command", "args"], "properties": {
39
+ "key": { "$ref": "#/definitions/id" }, "label": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "\\S" }, "policy": { "$ref": "#/definitions/checkPolicy" },
34
40
  "repositoryId": { "$ref": "#/definitions/id" }, "command": { "type": "string", "minLength": 1 },
35
41
  "args": { "type": "array", "items": { "type": "string" } }, "cwd": { "type": "string", "minLength": 1 },
36
42
  "env": { "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "additionalProperties": { "type": "string" } },
@@ -49,10 +55,21 @@
49
55
  } }
50
56
  },
51
57
  "definitions": {
58
+ "effort": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{0,31}$" },
59
+ "inputList": { "type": "array", "maxItems": 256, "items": { "type": "string", "minLength": 1, "maxLength": 4096, "pattern": "\\S" } },
60
+ "checkPolicy": { "type": "object", "additionalProperties": false, "properties": {
61
+ "reuse": { "enum": ["never", "snapshot-local"] }, "inputs": { "$ref": "#/definitions/inputList" },
62
+ "toolchainInputs": { "$ref": "#/definitions/inputList" }, "resources": { "$ref": "#/definitions/inputList" },
63
+ "deterministic": { "type": "boolean" }, "readOnly": { "type": "boolean" }, "independentGroup": { "$ref": "#/definitions/id" }
64
+ } },
52
65
  "id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$" },
53
66
  "positiveInteger": { "type": "integer", "minimum": 1 },
54
67
  "score": { "type": "number", "minimum": 0, "maximum": 100 },
55
- "agent": { "type": "object", "additionalProperties": false, "required": ["provider"], "properties": {
68
+ "agent": { "type": "object", "additionalProperties": false, "required": ["provider"], "dependencies": { "escalation": ["model"] }, "properties": {
69
+ "effort": { "$ref": "#/definitions/effort" },
70
+ "escalation": { "type": "object", "additionalProperties": false, "required": ["model"], "properties": {
71
+ "model": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^-\\r\\n\\u0000][^\\r\\n\\u0000]*$" }, "effort": { "$ref": "#/definitions/effort" }
72
+ } },
56
73
  "provider": { "$ref": "#/definitions/id" }, "model": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^-\\r\\n\\u0000][^\\r\\n\\u0000]*$" },
57
74
  "maxTurns": { "$ref": "#/definitions/positiveInteger" }
58
75
  } }