thumbgate 1.14.1 → 1.16.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 (150) hide show
  1. package/.claude-plugin/marketplace.json +6 -6
  2. package/.claude-plugin/plugin.json +3 -3
  3. package/.well-known/llms.txt +5 -5
  4. package/.well-known/mcp/server-card.json +1 -1
  5. package/README.md +60 -35
  6. package/adapters/chatgpt/openapi.yaml +118 -2
  7. package/adapters/claude/.mcp.json +2 -2
  8. package/adapters/mcp/server-stdio.js +217 -84
  9. package/adapters/opencode/opencode.json +1 -1
  10. package/bench/prompt-eval-suite.json +5 -1
  11. package/bin/cli.js +211 -8
  12. package/config/enforcement.json +59 -7
  13. package/config/evals/agent-safety-eval.json +338 -22
  14. package/config/gates/default.json +33 -0
  15. package/config/gates/routine.json +43 -0
  16. package/config/github-about.json +3 -3
  17. package/config/mcp-allowlists.json +4 -0
  18. package/config/merge-quality-checks.json +2 -1
  19. package/config/model-candidates.json +131 -0
  20. package/openapi/openapi.yaml +118 -2
  21. package/package.json +70 -51
  22. package/public/blog.html +7 -7
  23. package/public/codex-plugin.html +13 -7
  24. package/public/compare.html +29 -23
  25. package/public/dashboard.html +105 -12
  26. package/public/guide.html +28 -28
  27. package/public/index.html +233 -97
  28. package/public/learn.html +87 -20
  29. package/public/lessons.html +26 -2
  30. package/public/numbers.html +271 -0
  31. package/public/pro.html +89 -19
  32. package/scripts/agent-audit-trace.js +55 -0
  33. package/scripts/agent-memory-lifecycle.js +96 -0
  34. package/scripts/agent-readiness-plan.js +118 -0
  35. package/scripts/agentic-data-pipeline.js +21 -1
  36. package/scripts/agents-sdk-sandbox-plan.js +57 -0
  37. package/scripts/ai-org-governance.js +98 -0
  38. package/scripts/ai-search-distribution.js +43 -0
  39. package/scripts/artifact-agent-plan.js +81 -0
  40. package/scripts/billing.js +27 -8
  41. package/scripts/cli-feedback.js +2 -1
  42. package/scripts/cli-schema.js +60 -5
  43. package/scripts/code-mode-mcp-plan.js +71 -0
  44. package/scripts/commercial-offer.js +1 -1
  45. package/scripts/context-engine.js +1 -2
  46. package/scripts/context-manager.js +4 -1
  47. package/scripts/contextfs.js +214 -32
  48. package/scripts/dashboard-render-spec.js +1 -1
  49. package/scripts/dashboard.js +275 -9
  50. package/scripts/decision-journal.js +13 -3
  51. package/scripts/document-workflow-governance.js +62 -0
  52. package/scripts/enterprise-agent-rollout.js +34 -0
  53. package/scripts/experience-replay-governance.js +69 -0
  54. package/scripts/export-hf-dataset.js +1 -1
  55. package/scripts/feedback-loop.js +141 -9
  56. package/scripts/feedback-to-rules.js +17 -23
  57. package/scripts/gates-engine.js +4 -6
  58. package/scripts/growth-campaigns.js +49 -0
  59. package/scripts/harness-selector.js +145 -1
  60. package/scripts/hybrid-supervisor-agent.js +64 -0
  61. package/scripts/inference-cache-policy.js +72 -0
  62. package/scripts/inference-economics.js +53 -0
  63. package/scripts/internal-agent-bootstrap.js +12 -2
  64. package/scripts/knowledge-layer-plan.js +108 -0
  65. package/scripts/lesson-canonical.js +181 -0
  66. package/scripts/lesson-db.js +71 -10
  67. package/scripts/lesson-inference.js +183 -44
  68. package/scripts/lesson-search.js +4 -1
  69. package/scripts/lesson-synthesis.js +23 -2
  70. package/scripts/llm-client.js +157 -26
  71. package/scripts/mailer/resend-mailer.js +112 -1
  72. package/scripts/mcp-transport-strategy.js +66 -0
  73. package/scripts/memory-store-governance.js +60 -0
  74. package/scripts/meta-agent-loop.js +7 -13
  75. package/scripts/model-access-eligibility.js +38 -0
  76. package/scripts/model-migration-readiness.js +55 -0
  77. package/scripts/native-messaging-audit.js +514 -0
  78. package/scripts/operational-integrity.js +96 -3
  79. package/scripts/otel-declarative-config.js +56 -0
  80. package/scripts/perplexity-client.js +1 -1
  81. package/scripts/post-training-governance.js +34 -0
  82. package/scripts/pr-manager.js +47 -7
  83. package/scripts/private-core-boundary.js +72 -0
  84. package/scripts/production-agent-readiness.js +40 -0
  85. package/scripts/profile-router.js +16 -1
  86. package/scripts/prompt-eval.js +564 -32
  87. package/scripts/prompt-programs.js +93 -0
  88. package/scripts/provider-action-normalizer.js +585 -0
  89. package/scripts/rule-validator.js +285 -0
  90. package/scripts/scaling-law-claims.js +60 -0
  91. package/scripts/security-scanner.js +1 -1
  92. package/scripts/self-distill-agent.js +7 -32
  93. package/scripts/seo-gsd.js +400 -43
  94. package/scripts/skill-rag-router.js +53 -0
  95. package/scripts/spec-gate.js +1 -1
  96. package/scripts/student-consistent-training.js +73 -0
  97. package/scripts/synthetic-data-provenance.js +98 -0
  98. package/scripts/task-context-result.js +81 -0
  99. package/scripts/telemetry-analytics.js +149 -0
  100. package/scripts/thompson-sampling.js +2 -2
  101. package/scripts/token-savings.js +7 -6
  102. package/scripts/token-tco.js +46 -0
  103. package/scripts/tool-registry.js +75 -3
  104. package/scripts/verification-loop.js +10 -1
  105. package/scripts/verifier-scoring.js +71 -0
  106. package/scripts/workflow-sentinel.js +284 -28
  107. package/scripts/workspace-agent-routines.js +118 -0
  108. package/skills/thumbgate/SKILL.md +1 -1
  109. package/src/api/server.js +434 -120
  110. package/.claude-plugin/README.md +0 -170
  111. package/adapters/README.md +0 -12
  112. package/scripts/analytics-report.js +0 -328
  113. package/scripts/autonomous-workflow.js +0 -377
  114. package/scripts/billing-setup.js +0 -109
  115. package/scripts/creator-campaigns.js +0 -239
  116. package/scripts/cross-encoder-reranker.js +0 -235
  117. package/scripts/daemon-manager.js +0 -108
  118. package/scripts/decision-trace.js +0 -354
  119. package/scripts/delegation-runtime.js +0 -896
  120. package/scripts/dispatch-brief.js +0 -159
  121. package/scripts/distribution-surfaces.js +0 -110
  122. package/scripts/feedback-history-distiller.js +0 -382
  123. package/scripts/funnel-analytics.js +0 -35
  124. package/scripts/history-distiller.js +0 -200
  125. package/scripts/hosted-job-launcher.js +0 -256
  126. package/scripts/intent-router.js +0 -392
  127. package/scripts/lesson-reranker.js +0 -263
  128. package/scripts/lesson-retrieval.js +0 -148
  129. package/scripts/managed-lesson-agent.js +0 -183
  130. package/scripts/operational-dashboard.js +0 -103
  131. package/scripts/operational-summary.js +0 -129
  132. package/scripts/operator-artifacts.js +0 -608
  133. package/scripts/optimize-context.js +0 -17
  134. package/scripts/org-dashboard.js +0 -206
  135. package/scripts/partner-orchestration.js +0 -146
  136. package/scripts/predictive-insights.js +0 -356
  137. package/scripts/pulse.js +0 -80
  138. package/scripts/reflector-agent.js +0 -221
  139. package/scripts/sales-pipeline.js +0 -681
  140. package/scripts/session-episode-store.js +0 -329
  141. package/scripts/session-health-sensor.js +0 -242
  142. package/scripts/session-report.js +0 -120
  143. package/scripts/swarm-coordinator.js +0 -81
  144. package/scripts/tool-kpi-tracker.js +0 -12
  145. package/scripts/webhook-delivery.js +0 -62
  146. package/scripts/workflow-sprint-intake.js +0 -475
  147. package/skills/agent-memory/SKILL.md +0 -97
  148. package/skills/solve-architecture-autonomy/SKILL.md +0 -17
  149. package/skills/solve-architecture-autonomy/tool.js +0 -33
  150. package/skills/thumbgate-feedback/SKILL.md +0 -49
@@ -1,200 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * History Distiller — Self-Healing Brain for ThumbGate (Pro feature).
6
- *
7
- * When a user gives thumbs-down, this module:
8
- * 1. Takes the last N conversation messages (chatHistory)
9
- * 2. Identifies the failed tool call and its context
10
- * 3. Auto-proposes a lesson: "I noticed X. I've recorded a rule to NEVER do X. Correct?"
11
- * 4. Creates a prevention rule if the user confirms
12
- *
13
- * This closes the gap from "manual guardrail" to "self-healing brain."
14
- * Strategic value: justifies Pro $19/mo subscription via outcome-based intelligence.
15
- */
16
-
17
- const { createLesson, inferFromSurroundingMessages } = require('./lesson-inference');
18
- const contextfs = require('./contextfs');
19
-
20
- // ---------------------------------------------------------------------------
21
- // Chat History Analysis
22
- // ---------------------------------------------------------------------------
23
-
24
-
25
- const ANTI_PATTERNS = [
26
- { pattern: /\b(?:tailwind|tw-)\b/i, label: 'Tailwind CSS', ruleTemplate: 'NEVER use Tailwind CSS in this project' },
27
- { pattern: /(?:force[- ]?push|push\s*--force|--force)\b/i, label: 'force push', ruleTemplate: 'NEVER force-push to any branch' },
28
- { pattern: /\b(?:rm\s+-rf|delete\s+all)\b/i, label: 'destructive deletion', ruleTemplate: 'NEVER run destructive delete commands without confirmation' },
29
- { pattern: /\bskip\s*(?:test|ci|check)/i, label: 'skipping tests', ruleTemplate: 'NEVER skip tests or CI checks' },
30
- { pattern: /\b(?:mock(?:ed|ing)?|stub(?:bed|bing)?)\b.*\b(?:database|db)\b/i, label: 'mocking database', ruleTemplate: 'NEVER mock the database — use real test instances' },
31
- { pattern: /\b(?:hardcod|hard[- ]cod)/i, label: 'hardcoded values', ruleTemplate: 'NEVER hardcode secrets, URLs, or configuration values' },
32
- { pattern: /\b(?:console\.log|print\s+debug)\b/i, label: 'debug logging', ruleTemplate: 'NEVER leave debug console.log/print statements in production code' },
33
- { pattern: /\b(?:any\b.*type|:\s*any\b)/i, label: 'TypeScript any', ruleTemplate: 'NEVER use the `any` type — use proper type annotations' },
34
- ];
35
-
36
- /**
37
- * Analyze chat history to find the correction pattern.
38
- * Looks for: user corrected the agent about something → agent did it again → user gave thumbs down.
39
- *
40
- * @param {Array} chatHistory - Array of {role, content} messages, most recent last
41
- * @param {Object} failedToolCall - The tool call that triggered the thumbs-down
42
- * @returns {{ correction, antiPattern, proposedRule, confidence, evidence }}
43
- */
44
- function analyzeChatHistory(chatHistory, failedToolCall = null) {
45
- const messages = Array.isArray(chatHistory) ? chatHistory : [];
46
- if (messages.length === 0) return { correction: null, antiPattern: null, proposedRule: null, confidence: 0, evidence: [] };
47
-
48
- const evidence = [];
49
- let bestAntiPattern = null;
50
- let userCorrection = null;
51
-
52
- // Scan for user corrections (messages where user said "don't", "stop", "no", "never", "wrong")
53
- const correctionPatterns = [
54
- /\b(?:don'?t|do not|stop|never|wrong|no,?\s+(?:that|not|I said))\b/i,
55
- /\b(?:I (?:told|said|asked) you|I already|we don'?t)\b/i,
56
- /\b(?:should(?:n'?t| not)|must not|not supposed to)\b/i,
57
- ];
58
-
59
- for (const msg of messages) {
60
- if (msg.role !== 'user') continue;
61
- const text = msg.content || msg.text || '';
62
- for (const cp of correctionPatterns) {
63
- if (cp.test(text)) {
64
- userCorrection = text.slice(0, 200);
65
- evidence.push({ type: 'user_correction', text: userCorrection });
66
- break;
67
- }
68
- }
69
- }
70
-
71
- // Scan assistant messages for anti-patterns
72
- const assistantMessages = messages.filter((m) => m.role === 'assistant').map((m) => m.content || m.text || '');
73
- const allAssistantText = assistantMessages.join('\n');
74
-
75
- // Also check the failed tool call
76
- const toolCallText = failedToolCall
77
- ? `${failedToolCall.tool || ''} ${failedToolCall.input || ''} ${failedToolCall.output || ''}`
78
- : '';
79
- const combinedText = `${allAssistantText}\n${toolCallText}`;
80
-
81
- for (const ap of ANTI_PATTERNS) {
82
- if (ap.pattern.test(combinedText)) {
83
- bestAntiPattern = ap;
84
- evidence.push({ type: 'anti_pattern', label: ap.label });
85
- break;
86
- }
87
- }
88
-
89
- // Build proposed rule
90
- let proposedRule = null;
91
- let confidence = 0;
92
-
93
- if (bestAntiPattern && userCorrection) {
94
- proposedRule = bestAntiPattern.ruleTemplate;
95
- confidence = 90;
96
- } else if (bestAntiPattern) {
97
- proposedRule = bestAntiPattern.ruleTemplate;
98
- confidence = 60;
99
- } else if (userCorrection) {
100
- // Extract the "don't X" part as a rule
101
- const dontMatch = userCorrection.match(/(?:don'?t|never|stop)\s+(.{5,60})/i);
102
- if (dontMatch) {
103
- proposedRule = `NEVER ${dontMatch[1].trim().replace(/[.!?]+$/, '')}`;
104
- confidence = 50;
105
- }
106
- }
107
-
108
- return {
109
- correction: userCorrection,
110
- antiPattern: bestAntiPattern ? bestAntiPattern.label : null,
111
- proposedRule,
112
- confidence,
113
- evidence,
114
- messageCount: messages.length,
115
- };
116
- }
117
-
118
- // ---------------------------------------------------------------------------
119
- // History-Aware Distillation (the main entry point)
120
- // ---------------------------------------------------------------------------
121
-
122
- /**
123
- * Distill a lesson from chat history when thumbs-down is received.
124
- * This is the "Reflector" agent — it takes conversation context and
125
- * auto-proposes what went wrong + a prevention rule.
126
- *
127
- * @param {Object} opts
128
- * @param {Array} opts.chatHistory - Last N messages [{role, content}]
129
- * @param {Object} [opts.failedToolCall] - The tool call that failed
130
- * @param {string} [opts.feedbackContext] - User's feedback context string
131
- * @param {string} [opts.signal] - 'negative' or 'positive'
132
- * @returns {{ lesson, proposedRule, confirmation, autoCreated }}
133
- */
134
- function distillFromHistory({ chatHistory = [], failedToolCall = null, feedbackContext = '', signal = 'negative' } = {}) {
135
- // Step 1: Analyze chat history for corrections and anti-patterns
136
- const analysis = analyzeChatHistory(chatHistory, failedToolCall);
137
-
138
- // Step 2: Infer from surrounding messages (leverage existing module)
139
- const inference = inferFromSurroundingMessages({
140
- priorMessages: chatHistory.slice(-10),
141
- signal,
142
- feedbackContext,
143
- });
144
-
145
- // Step 3: Build the auto-proposed lesson
146
- let proposedWhatWentWrong;
147
- let proposedRule = analysis.proposedRule;
148
-
149
- if (analysis.correction && analysis.antiPattern) {
150
- proposedWhatWentWrong = `I noticed I used ${analysis.antiPattern} despite your earlier correction: "${analysis.correction.slice(0, 100)}". This has been recorded as a mistake.`;
151
- } else if (analysis.antiPattern) {
152
- proposedWhatWentWrong = `I detected a ${analysis.antiPattern} anti-pattern in my output that likely caused the issue.`;
153
- } else if (analysis.correction) {
154
- proposedWhatWentWrong = `You previously corrected me: "${analysis.correction.slice(0, 100)}". I may have repeated the same mistake.`;
155
- } else if (inference.inferredAction) {
156
- proposedWhatWentWrong = `The ${inference.inferredAction.type} action on ${inference.inferredAction.target} did not produce the expected result.`;
157
- } else {
158
- proposedWhatWentWrong = feedbackContext || 'The agent action did not meet expectations.';
159
- }
160
-
161
- // Step 4: Build confirmation message
162
- const confirmation = proposedRule
163
- ? `I've recorded a rule: "${proposedRule}". Correct?`
164
- : `Lesson captured: "${proposedWhatWentWrong.slice(0, 100)}". Any corrections?`;
165
-
166
- // Step 5: Auto-create the lesson
167
- const lesson = createLesson({
168
- signal,
169
- inferredLesson: proposedWhatWentWrong,
170
- triggerMessage: inference.triggerMessage,
171
- priorSummary: inference.priorSummary,
172
- confidence: analysis.confidence || inference.confidence,
173
- tags: analysis.antiPattern ? [analysis.antiPattern] : [],
174
- metadata: { distilled: true, hasCorrection: !!analysis.correction, hasAntiPattern: !!analysis.antiPattern },
175
- });
176
-
177
- // Step 6: If high confidence + anti-pattern, auto-install prevention rule
178
- let ruleInstalled = false;
179
- if (proposedRule && analysis.confidence >= 60) {
180
- try {
181
- contextfs.registerPreventionRules(`# Auto-Distilled Rule\n\n- ${proposedRule}\n\nSource: history-distiller (confidence: ${analysis.confidence}%)`, { source: 'history-distiller', lessonId: lesson.id });
182
- ruleInstalled = true;
183
- } catch { /* non-critical */ }
184
- }
185
-
186
- return {
187
- lesson,
188
- proposedWhatWentWrong,
189
- proposedRule,
190
- confirmation,
191
- ruleInstalled,
192
- analysis,
193
- inference: { action: inference.inferredAction, confidence: inference.confidence },
194
- autoCreated: true,
195
- };
196
- }
197
-
198
- module.exports = {
199
- ANTI_PATTERNS, analyzeChatHistory, distillFromHistory,
200
- };
@@ -1,256 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { spawn } = require('child_process');
6
-
7
- const runner = require('./async-job-runner');
8
- const { buildHarnessJob } = require('./natural-language-harness');
9
- const { ensureDir } = require('./fs-utils');
10
-
11
- const RUNNER_SCRIPT_PATH = path.join(__dirname, 'async-job-runner.js');
12
- const MANAGED_DPO_EXPORT_SCRIPT_PATH = path.join(__dirname, 'managed-dpo-export.js');
13
- const BACKGROUND_LAUNCH_MODE = 'background';
14
- const INLINE_LAUNCH_MODE = 'inline';
15
- const IDLE_JOB_STATUSES = new Set(['queued', 'paused', 'resume_requested']);
16
-
17
- function nowIso() {
18
- return new Date().toISOString();
19
- }
20
-
21
-
22
- function shellQuote(value) {
23
- return `'${String(value).replace(/'/g, `'\\''`)}'`;
24
- }
25
-
26
- function createHostedJobId(prefix = 'job') {
27
- return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
28
- }
29
-
30
- function getStatePath(jobId) {
31
- return runner.getJobRuntimePaths(jobId).statePath;
32
- }
33
-
34
- function writeStateFile(jobId, state) {
35
- const statePath = getStatePath(jobId);
36
- ensureDir(path.dirname(statePath));
37
- fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n', 'utf8');
38
- return state;
39
- }
40
-
41
- function updateIdleJobState(jobId, updater) {
42
- const state = runner.readJobState(jobId);
43
- if (!state) {
44
- const error = new Error(`No persisted state found for job ${jobId}`);
45
- error.statusCode = 404;
46
- throw error;
47
- }
48
-
49
- if (!IDLE_JOB_STATUSES.has(state.status)) {
50
- const error = new Error(`Job ${jobId} is not idle; current status is ${state.status}`);
51
- error.statusCode = 409;
52
- throw error;
53
- }
54
-
55
- return writeStateFile(jobId, updater({ ...state }));
56
- }
57
-
58
- function writeJobFile(jobId, jobSpec) {
59
- const { jobDir } = runner.getJobRuntimePaths(jobId);
60
- ensureDir(jobDir);
61
- const jobFilePath = path.join(jobDir, 'job.json');
62
- fs.writeFileSync(jobFilePath, JSON.stringify(jobSpec, null, 2) + '\n', 'utf8');
63
- return jobFilePath;
64
- }
65
-
66
- function runInlineJob(args) {
67
- if (args.runFile) {
68
- runner.runJobFromFile(args.runFile);
69
- return;
70
- }
71
-
72
- if (args.resumeJobId) {
73
- runner.resumeJob(args.resumeJobId);
74
- return;
75
- }
76
-
77
- throw new Error('Unsupported inline hosted job launch');
78
- }
79
-
80
- function launchRunner(args, options = {}) {
81
- const launchMode = options.launchMode || process.env.THUMBGATE_HOSTED_JOB_LAUNCH_MODE || BACKGROUND_LAUNCH_MODE;
82
- if (launchMode === INLINE_LAUNCH_MODE) {
83
- runInlineJob(args);
84
- return {
85
- launchMode,
86
- pid: process.pid,
87
- };
88
- }
89
-
90
- const runnerArgs = [];
91
- if (args.runFile) {
92
- runnerArgs.push(`--run-file=${args.runFile}`);
93
- } else if (args.resumeJobId) {
94
- runnerArgs.push(`--resume=${args.resumeJobId}`);
95
- } else {
96
- throw new Error('Hosted job launch requires runFile or resumeJobId');
97
- }
98
-
99
- const child = spawn(process.execPath, [RUNNER_SCRIPT_PATH, ...runnerArgs], {
100
- cwd: options.cwd || process.cwd(),
101
- env: process.env,
102
- detached: true,
103
- stdio: 'ignore',
104
- });
105
- child.unref();
106
- return {
107
- launchMode,
108
- pid: child.pid,
109
- };
110
- }
111
-
112
- function prepareManagedJob(jobSpec, options = {}) {
113
- const jobId = options.jobId || jobSpec.id || createHostedJobId(options.jobPrefix || 'job');
114
- const finalSpec = {
115
- ...jobSpec,
116
- id: jobId,
117
- };
118
- const jobFilePath = writeJobFile(jobId, finalSpec);
119
- const queuedState = runner.queueJob({
120
- ...finalSpec,
121
- jobFilePath,
122
- });
123
- return {
124
- jobId,
125
- jobFilePath,
126
- state: queuedState,
127
- jobSpec: {
128
- ...finalSpec,
129
- jobFilePath,
130
- },
131
- };
132
- }
133
-
134
- function launchManagedJob(jobSpec, options = {}) {
135
- const prepared = prepareManagedJob(jobSpec, options);
136
- const launch = launchRunner({ runFile: prepared.jobFilePath }, options);
137
- return {
138
- jobId: prepared.jobId,
139
- jobFilePath: prepared.jobFilePath,
140
- launchMode: launch.launchMode,
141
- pid: launch.pid || null,
142
- state: runner.readJobState(prepared.jobId) || prepared.state,
143
- };
144
- }
145
-
146
- function buildManagedDpoExportJob(params = {}) {
147
- const command = [
148
- shellQuote(process.execPath),
149
- shellQuote(MANAGED_DPO_EXPORT_SCRIPT_PATH),
150
- ];
151
-
152
- if (params.inputPath) {
153
- command.push('--inputPath', shellQuote(params.inputPath));
154
- } else if (params.memoryLogPath) {
155
- command.push('--memoryLogPath', shellQuote(params.memoryLogPath));
156
- }
157
-
158
- if (params.outputPath) {
159
- command.push('--outputPath', shellQuote(params.outputPath));
160
- }
161
-
162
- return {
163
- tags: ['hosted-job', 'dpo-export'],
164
- skill: 'hosted-dpo-export',
165
- autoImprove: false,
166
- verificationMode: 'none',
167
- recordFeedback: false,
168
- stages: [
169
- {
170
- name: 'export_dpo_pairs',
171
- command: command.join(' '),
172
- },
173
- ],
174
- };
175
- }
176
-
177
- function launchDpoExportJob(params = {}, options = {}) {
178
- return launchManagedJob(buildManagedDpoExportJob(params), {
179
- ...options,
180
- jobPrefix: 'dpo_export',
181
- });
182
- }
183
-
184
- function launchHarnessJob(identifier, inputs = {}, options = {}) {
185
- const jobId = options.jobId || createHostedJobId('harness');
186
- const jobSpec = buildHarnessJob(identifier, inputs, {
187
- jobId,
188
- skill: options.skill,
189
- partnerProfile: options.partnerProfile,
190
- autoImprove: options.autoImprove,
191
- });
192
- return launchManagedJob(jobSpec, {
193
- ...options,
194
- jobId,
195
- jobPrefix: 'harness',
196
- });
197
- }
198
-
199
- function resumeHostedJob(jobId, options = {}) {
200
- const state = runner.readJobState(jobId);
201
- if (!state) {
202
- const error = new Error(`No persisted state found for job ${jobId}`);
203
- error.statusCode = 404;
204
- throw error;
205
- }
206
-
207
- if (['completed', 'failed', 'cancelled'].includes(state.status)) {
208
- const error = new Error(`Job ${jobId} is already ${state.status}`);
209
- error.statusCode = 409;
210
- throw error;
211
- }
212
-
213
- const launch = launchRunner({ resumeJobId: jobId }, options);
214
- return {
215
- jobId,
216
- launchMode: launch.launchMode,
217
- pid: launch.pid || null,
218
- state: runner.readJobState(jobId) || state,
219
- };
220
- }
221
-
222
- function pauseQueuedJob(jobId, metadata = {}) {
223
- runner.clearJobControl(jobId);
224
- return updateIdleJobState(jobId, (state) => ({
225
- ...state,
226
- status: 'paused',
227
- updatedAt: nowIso(),
228
- pausedAt: nowIso(),
229
- stopReason: metadata && metadata.reason ? metadata.reason : 'pause_requested',
230
- }));
231
- }
232
-
233
- function cancelQueuedJob(jobId, metadata = {}) {
234
- runner.clearJobControl(jobId);
235
- return updateIdleJobState(jobId, (state) => ({
236
- ...state,
237
- status: 'cancelled',
238
- updatedAt: nowIso(),
239
- endedAt: nowIso(),
240
- stopReason: metadata && metadata.reason ? metadata.reason : 'cancel_requested',
241
- }));
242
- }
243
-
244
- module.exports = {
245
- BACKGROUND_LAUNCH_MODE,
246
- INLINE_LAUNCH_MODE,
247
- buildManagedDpoExportJob,
248
- cancelQueuedJob,
249
- createHostedJobId,
250
- launchDpoExportJob,
251
- launchHarnessJob,
252
- launchManagedJob,
253
- pauseQueuedJob,
254
- prepareManagedJob,
255
- resumeHostedJob,
256
- };