nemoris 0.1.0 → 0.1.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.
- package/.env.example +49 -49
- package/LICENSE +21 -21
- package/README.md +209 -209
- package/SECURITY.md +59 -119
- package/bin/nemoris +46 -46
- package/config/agents/agent.toml.example +28 -28
- package/config/agents/content.toml +23 -0
- package/config/agents/default.toml +22 -22
- package/config/agents/heartbeat.toml +35 -0
- package/config/agents/iris.toml +23 -0
- package/config/agents/lab.toml +23 -0
- package/config/agents/main.toml +45 -0
- package/config/agents/nemo.toml +21 -0
- package/config/agents/ops.toml +38 -0
- package/config/agents/orchestrator.toml +18 -18
- package/config/agents/revenue.toml +23 -0
- package/config/agents/testyboo.toml +19 -0
- package/config/delivery.toml +73 -73
- package/config/embeddings.toml +5 -5
- package/config/identity/content-purpose.md +11 -0
- package/config/identity/content-soul.md +45 -0
- package/config/identity/default-purpose.md +1 -1
- package/config/identity/default-soul.md +3 -3
- package/config/identity/heartbeat-purpose.md +9 -0
- package/config/identity/heartbeat-soul.md +16 -0
- package/config/identity/iris-purpose.md +17 -0
- package/config/identity/iris-soul.md +68 -0
- package/config/identity/lab-purpose.md +10 -0
- package/config/identity/lab-soul.md +38 -0
- package/config/identity/main-purpose.md +17 -0
- package/config/identity/main-soul.md +66 -0
- package/config/identity/main-user.md +22 -0
- package/config/identity/ops-purpose.md +9 -0
- package/config/identity/ops-soul.md +16 -0
- package/config/identity/orchestrator-purpose.md +1 -1
- package/config/identity/orchestrator-soul.md +1 -1
- package/config/identity/revenue-purpose.md +9 -0
- package/config/identity/revenue-soul.md +41 -0
- package/config/identity/testyboo-purpose.md +13 -0
- package/config/identity/testyboo-soul.md +20 -0
- package/config/improvement-targets.toml +15 -15
- package/config/jobs/heartbeat-check.toml +30 -30
- package/config/jobs/memory-rollup.toml +46 -46
- package/config/jobs/workspace-health.toml +63 -63
- package/config/mcp.toml +16 -16
- package/config/output-contracts.toml +17 -17
- package/config/peers.toml +32 -32
- package/config/peers.toml.example +32 -32
- package/config/policies/memory-default.toml +10 -10
- package/config/policies/memory-heartbeat.toml +5 -5
- package/config/policies/memory-ops.toml +10 -10
- package/config/policies/tools-heartbeat-minimal.toml +8 -8
- package/config/policies/tools-interactive-safe.toml +8 -8
- package/config/policies/tools-ops-bounded.toml +8 -8
- package/config/policies/tools-orchestrator.toml +7 -7
- package/config/providers/anthropic.toml +15 -15
- package/config/providers/ollama.toml +5 -5
- package/config/providers/openai-codex.toml +9 -9
- package/config/providers/openrouter.toml +5 -5
- package/config/router.toml +22 -22
- package/config/runtime.toml +114 -114
- package/config/skills/self-improvement.toml +15 -15
- package/config/skills/telegram-onboarding-spec.md +240 -240
- package/config/skills/workspace-monitor.toml +15 -15
- package/config/task-router.toml +42 -42
- package/install.sh +50 -50
- package/package.json +91 -90
- package/src/auth/auth-profiles.js +169 -169
- package/src/auth/openai-codex-oauth.js +285 -285
- package/src/battle.js +449 -449
- package/src/cli/help.js +265 -265
- package/src/cli/output-filter.js +49 -49
- package/src/cli/runtime-control.js +704 -704
- package/src/cli-main.js +2763 -2763
- package/src/cli.js +78 -78
- package/src/config/loader.js +332 -332
- package/src/config/schema-validator.js +214 -214
- package/src/config/toml-lite.js +8 -8
- package/src/daemon/action-handlers.js +71 -71
- package/src/daemon/healing-tick.js +87 -87
- package/src/daemon/health-probes.js +90 -90
- package/src/daemon/notifier.js +57 -57
- package/src/daemon/nurse.js +218 -218
- package/src/daemon/repair-log.js +106 -106
- package/src/daemon/rule-staging.js +90 -90
- package/src/daemon/rules.js +29 -29
- package/src/daemon/telegram-commands.js +54 -54
- package/src/daemon/updater.js +85 -85
- package/src/jobs/job-runner.js +78 -78
- package/src/mcp/consumer.js +129 -129
- package/src/memory/active-recall.js +171 -171
- package/src/memory/backend-manager.js +97 -97
- package/src/memory/backends/file-backend.js +38 -38
- package/src/memory/backends/qmd-backend.js +219 -219
- package/src/memory/embedding-guards.js +24 -24
- package/src/memory/embedding-index.js +118 -118
- package/src/memory/embedding-service.js +179 -179
- package/src/memory/file-index.js +177 -177
- package/src/memory/memory-signature.js +5 -5
- package/src/memory/memory-store.js +648 -648
- package/src/memory/retrieval-planner.js +66 -66
- package/src/memory/scoring.js +145 -145
- package/src/memory/simhash.js +78 -78
- package/src/memory/sqlite-active-store.js +824 -824
- package/src/memory/write-policy.js +36 -36
- package/src/onboarding/aliases.js +33 -33
- package/src/onboarding/auth/api-key.js +224 -224
- package/src/onboarding/auth/ollama-detect.js +42 -42
- package/src/onboarding/clack-prompter.js +77 -77
- package/src/onboarding/doctor.js +530 -530
- package/src/onboarding/lock.js +42 -42
- package/src/onboarding/model-catalog.js +344 -344
- package/src/onboarding/phases/auth.js +576 -589
- package/src/onboarding/phases/build.js +130 -130
- package/src/onboarding/phases/choose.js +82 -82
- package/src/onboarding/phases/detect.js +98 -98
- package/src/onboarding/phases/hatch.js +216 -216
- package/src/onboarding/phases/identity.js +79 -79
- package/src/onboarding/phases/ollama.js +345 -345
- package/src/onboarding/phases/scaffold.js +99 -99
- package/src/onboarding/phases/telegram.js +377 -377
- package/src/onboarding/phases/validate.js +204 -204
- package/src/onboarding/phases/verify.js +206 -206
- package/src/onboarding/platform.js +482 -482
- package/src/onboarding/status-bar.js +95 -95
- package/src/onboarding/templates.js +794 -794
- package/src/onboarding/toml-writer.js +38 -38
- package/src/onboarding/tui.js +250 -250
- package/src/onboarding/uninstall.js +153 -153
- package/src/onboarding/wizard.js +516 -499
- package/src/providers/anthropic.js +168 -168
- package/src/providers/base.js +247 -247
- package/src/providers/circuit-breaker.js +136 -136
- package/src/providers/ollama.js +163 -163
- package/src/providers/openai-codex.js +149 -149
- package/src/providers/openrouter.js +136 -136
- package/src/providers/registry.js +36 -36
- package/src/providers/router.js +16 -16
- package/src/runtime/bootstrap-cache.js +47 -47
- package/src/runtime/capabilities-prompt.js +25 -25
- package/src/runtime/completion-ping.js +99 -99
- package/src/runtime/config-validator.js +121 -121
- package/src/runtime/context-ledger.js +360 -360
- package/src/runtime/cutover-readiness.js +42 -42
- package/src/runtime/daemon.js +729 -729
- package/src/runtime/delivery-ack.js +195 -195
- package/src/runtime/delivery-adapters/local-file.js +41 -41
- package/src/runtime/delivery-adapters/openclaw-cli.js +94 -94
- package/src/runtime/delivery-adapters/openclaw-peer.js +98 -98
- package/src/runtime/delivery-adapters/shadow.js +13 -13
- package/src/runtime/delivery-adapters/standalone-http.js +98 -98
- package/src/runtime/delivery-adapters/telegram.js +104 -104
- package/src/runtime/delivery-adapters/tui.js +128 -128
- package/src/runtime/delivery-manager.js +807 -807
- package/src/runtime/delivery-store.js +168 -168
- package/src/runtime/dependency-health.js +118 -118
- package/src/runtime/envelope.js +114 -114
- package/src/runtime/evaluation.js +1089 -1089
- package/src/runtime/exec-approvals.js +216 -216
- package/src/runtime/executor.js +500 -500
- package/src/runtime/failure-ping.js +67 -67
- package/src/runtime/flows.js +83 -83
- package/src/runtime/guards.js +45 -45
- package/src/runtime/handoff.js +51 -51
- package/src/runtime/identity-cache.js +28 -28
- package/src/runtime/improvement-engine.js +109 -109
- package/src/runtime/improvement-harness.js +581 -581
- package/src/runtime/input-sanitiser.js +72 -72
- package/src/runtime/interaction-contract.js +347 -347
- package/src/runtime/lane-readiness.js +226 -226
- package/src/runtime/migration.js +323 -323
- package/src/runtime/model-resolution.js +78 -78
- package/src/runtime/network.js +64 -64
- package/src/runtime/notification-store.js +97 -97
- package/src/runtime/notifier.js +256 -256
- package/src/runtime/orchestrator.js +53 -53
- package/src/runtime/orphan-reaper.js +41 -41
- package/src/runtime/output-contract-schema.js +139 -139
- package/src/runtime/output-contract-validator.js +439 -439
- package/src/runtime/peer-readiness.js +69 -69
- package/src/runtime/peer-registry.js +133 -133
- package/src/runtime/pilot-status.js +108 -108
- package/src/runtime/prompt-builder.js +261 -261
- package/src/runtime/provider-attempt.js +582 -582
- package/src/runtime/report-fallback.js +71 -71
- package/src/runtime/result-normalizer.js +183 -183
- package/src/runtime/retention.js +74 -74
- package/src/runtime/review.js +244 -244
- package/src/runtime/route-job.js +15 -15
- package/src/runtime/run-store.js +38 -38
- package/src/runtime/schedule.js +88 -88
- package/src/runtime/scheduler-state.js +434 -434
- package/src/runtime/scheduler.js +656 -656
- package/src/runtime/session-compactor.js +182 -182
- package/src/runtime/session-search.js +155 -155
- package/src/runtime/slack-inbound.js +249 -249
- package/src/runtime/ssrf.js +102 -102
- package/src/runtime/status-aggregator.js +330 -330
- package/src/runtime/task-contract.js +140 -140
- package/src/runtime/task-packet.js +107 -107
- package/src/runtime/task-router.js +140 -140
- package/src/runtime/telegram-inbound.js +1565 -1565
- package/src/runtime/token-counter.js +134 -134
- package/src/runtime/token-estimator.js +59 -59
- package/src/runtime/tool-loop.js +200 -200
- package/src/runtime/transport-server.js +311 -311
- package/src/runtime/tui-server.js +411 -411
- package/src/runtime/ulid.js +44 -44
- package/src/security/ssrf-check.js +197 -197
- package/src/setup.js +369 -369
- package/src/shadow/bridge.js +303 -303
- package/src/skills/loader.js +84 -84
- package/src/tools/catalog.json +49 -49
- package/src/tools/cli-delegate.js +44 -44
- package/src/tools/mcp-client.js +106 -106
- package/src/tools/micro/cancel-task.js +6 -6
- package/src/tools/micro/complete-task.js +6 -6
- package/src/tools/micro/fail-task.js +6 -6
- package/src/tools/micro/http-fetch.js +74 -74
- package/src/tools/micro/index.js +36 -36
- package/src/tools/micro/lcm-recall.js +60 -60
- package/src/tools/micro/list-dir.js +17 -17
- package/src/tools/micro/list-skills.js +46 -46
- package/src/tools/micro/load-skill.js +38 -38
- package/src/tools/micro/memory-search.js +45 -45
- package/src/tools/micro/read-file.js +11 -11
- package/src/tools/micro/session-search.js +54 -54
- package/src/tools/micro/shell-exec.js +43 -43
- package/src/tools/micro/trigger-job.js +79 -79
- package/src/tools/micro/web-search.js +58 -58
- package/src/tools/micro/workspace-paths.js +39 -39
- package/src/tools/micro/write-file.js +14 -14
- package/src/tools/micro/write-memory.js +41 -41
- package/src/tools/registry.js +348 -348
- package/src/tools/tool-result-contract.js +36 -36
- package/src/tui/chat.js +835 -835
- package/src/tui/renderer.js +175 -175
- package/src/tui/socket-client.js +217 -217
- package/src/utils/canonical-json.js +29 -29
- package/src/utils/compaction.js +30 -30
- package/src/utils/env-loader.js +5 -5
- package/src/utils/errors.js +80 -80
- package/src/utils/fs.js +101 -101
- package/src/utils/ids.js +5 -5
- package/src/utils/model-context-limits.js +30 -30
- package/src/utils/token-budget.js +74 -74
- package/src/utils/usage-cost.js +25 -25
- package/src/utils/usage-metrics.js +14 -14
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
const ORPHAN_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* On startup: mark stuck running jobs as failed.
|
|
5
|
-
* Jobs running for < 5 min are left alone (daemon may have just restarted briefly).
|
|
6
|
-
* Uses created_at as a proxy for when the job became running.
|
|
7
|
-
*
|
|
8
|
-
* @param {import('./scheduler-state.js').SchedulerStateStore} stateStore
|
|
9
|
-
* @returns {{ job_id: string }[]} reaped job rows
|
|
10
|
-
*/
|
|
11
|
-
export function reapOrphanedJobs(stateStore) {
|
|
12
|
-
// Ensure columns exist for result and completed_at tracking
|
|
13
|
-
_addColumnIfMissing(stateStore.db, "interactive_jobs", "result", "TEXT");
|
|
14
|
-
_addColumnIfMissing(stateStore.db, "interactive_jobs", "completed_at", "TEXT");
|
|
15
|
-
_addColumnIfMissing(stateStore.db, "interactive_jobs", "started_at", "TEXT");
|
|
16
|
-
|
|
17
|
-
const cutoff = new Date(Date.now() - ORPHAN_THRESHOLD_MS).toISOString();
|
|
18
|
-
const now = new Date().toISOString();
|
|
19
|
-
|
|
20
|
-
const reaped = stateStore.db.prepare(`
|
|
21
|
-
UPDATE interactive_jobs
|
|
22
|
-
SET status = 'failed',
|
|
23
|
-
result = json_object('error', 'Daemon restarted before job completed'),
|
|
24
|
-
completed_at = ?
|
|
25
|
-
WHERE status = 'running'
|
|
26
|
-
AND COALESCE(started_at, created_at) < ?
|
|
27
|
-
RETURNING job_id
|
|
28
|
-
`).all(now, cutoff);
|
|
29
|
-
|
|
30
|
-
if (reaped.length > 0) {
|
|
31
|
-
console.log(`[startup] reaped ${reaped.length} orphaned job(s)`);
|
|
32
|
-
}
|
|
33
|
-
return reaped;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function _addColumnIfMissing(db, table, column, type) {
|
|
37
|
-
const cols = db.prepare(`pragma table_info(${table})`).all();
|
|
38
|
-
if (!cols.some((c) => c.name === column)) {
|
|
39
|
-
db.exec(`alter table ${table} add column ${column} ${type}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
1
|
+
const ORPHAN_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* On startup: mark stuck running jobs as failed.
|
|
5
|
+
* Jobs running for < 5 min are left alone (daemon may have just restarted briefly).
|
|
6
|
+
* Uses created_at as a proxy for when the job became running.
|
|
7
|
+
*
|
|
8
|
+
* @param {import('./scheduler-state.js').SchedulerStateStore} stateStore
|
|
9
|
+
* @returns {{ job_id: string }[]} reaped job rows
|
|
10
|
+
*/
|
|
11
|
+
export function reapOrphanedJobs(stateStore) {
|
|
12
|
+
// Ensure columns exist for result and completed_at tracking
|
|
13
|
+
_addColumnIfMissing(stateStore.db, "interactive_jobs", "result", "TEXT");
|
|
14
|
+
_addColumnIfMissing(stateStore.db, "interactive_jobs", "completed_at", "TEXT");
|
|
15
|
+
_addColumnIfMissing(stateStore.db, "interactive_jobs", "started_at", "TEXT");
|
|
16
|
+
|
|
17
|
+
const cutoff = new Date(Date.now() - ORPHAN_THRESHOLD_MS).toISOString();
|
|
18
|
+
const now = new Date().toISOString();
|
|
19
|
+
|
|
20
|
+
const reaped = stateStore.db.prepare(`
|
|
21
|
+
UPDATE interactive_jobs
|
|
22
|
+
SET status = 'failed',
|
|
23
|
+
result = json_object('error', 'Daemon restarted before job completed'),
|
|
24
|
+
completed_at = ?
|
|
25
|
+
WHERE status = 'running'
|
|
26
|
+
AND COALESCE(started_at, created_at) < ?
|
|
27
|
+
RETURNING job_id
|
|
28
|
+
`).all(now, cutoff);
|
|
29
|
+
|
|
30
|
+
if (reaped.length > 0) {
|
|
31
|
+
console.log(`[startup] reaped ${reaped.length} orphaned job(s)`);
|
|
32
|
+
}
|
|
33
|
+
return reaped;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function _addColumnIfMissing(db, table, column, type) {
|
|
37
|
+
const cols = db.prepare(`pragma table_info(${table})`).all();
|
|
38
|
+
if (!cols.some((c) => c.name === column)) {
|
|
39
|
+
db.exec(`alter table ${table} add column ${column} ${type}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
function titleCase(value) {
|
|
2
|
-
return String(value || "")
|
|
3
|
-
.split(/[_\-\s]+/)
|
|
4
|
-
.filter(Boolean)
|
|
5
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
6
|
-
.join("");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function buildBulletedBriefingOutputSchema(contract) {
|
|
10
|
-
const properties = {};
|
|
11
|
-
const required = [];
|
|
12
|
-
|
|
13
|
-
if (contract.profile?.requireStatus) {
|
|
14
|
-
properties.status = {
|
|
15
|
-
type: "string",
|
|
16
|
-
description: "One-line overall status."
|
|
17
|
-
};
|
|
18
|
-
required.push("status");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
for (const section of contract.requiredSections || []) {
|
|
22
|
-
properties[section] = {
|
|
23
|
-
type: "string",
|
|
24
|
-
description: `${titleCase(section)} update. Use 'None' if there is no concrete data.`
|
|
25
|
-
};
|
|
26
|
-
required.push(section);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
type: "object",
|
|
31
|
-
additionalProperties: false,
|
|
32
|
-
properties,
|
|
33
|
-
required
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function buildStructuredRollupOutputSchema(contract) {
|
|
38
|
-
const properties = {};
|
|
39
|
-
const required = [];
|
|
40
|
-
|
|
41
|
-
for (const section of contract.requiredSections || []) {
|
|
42
|
-
properties[section] = {
|
|
43
|
-
type: "array",
|
|
44
|
-
description: `${titleCase(section)} bullets. Use ['None'] if there is no concrete data.`,
|
|
45
|
-
minItems: contract.profile?.requireSectionItems ? 1 : 0,
|
|
46
|
-
items: {
|
|
47
|
-
type: "string"
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
required.push(section);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
type: "object",
|
|
55
|
-
additionalProperties: false,
|
|
56
|
-
properties,
|
|
57
|
-
required
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function buildGenericOutputSchema(contract) {
|
|
62
|
-
const properties = {};
|
|
63
|
-
const required = [];
|
|
64
|
-
|
|
65
|
-
for (const section of contract.requiredSections || []) {
|
|
66
|
-
properties[section] = {
|
|
67
|
-
type: "string",
|
|
68
|
-
description: `${titleCase(section)} section content.`
|
|
69
|
-
};
|
|
70
|
-
required.push(section);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
type: "object",
|
|
75
|
-
additionalProperties: false,
|
|
76
|
-
properties,
|
|
77
|
-
required
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function buildContractOutputSchema(contract) {
|
|
82
|
-
if (!contract) {
|
|
83
|
-
return {
|
|
84
|
-
type: "string"
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (contract.format === "bulleted_briefing") {
|
|
89
|
-
return buildBulletedBriefingOutputSchema(contract);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (contract.format === "structured_rollup") {
|
|
93
|
-
return buildStructuredRollupOutputSchema(contract);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return buildGenericOutputSchema(contract);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function compileOutputContractSchema(contract, options = {}) {
|
|
100
|
-
if (!contract) return null;
|
|
101
|
-
const thoughtFirst = options.thoughtFirst ?? false;
|
|
102
|
-
|
|
103
|
-
const properties = {};
|
|
104
|
-
const required = [];
|
|
105
|
-
|
|
106
|
-
if (thoughtFirst) {
|
|
107
|
-
properties.analysis = {
|
|
108
|
-
type: "string",
|
|
109
|
-
description: "Compact reasoning about the task before finalizing the structured result."
|
|
110
|
-
};
|
|
111
|
-
required.push("analysis");
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
properties.summary = {
|
|
115
|
-
type: "string",
|
|
116
|
-
description: "Short summary suitable for a completion pingback."
|
|
117
|
-
};
|
|
118
|
-
properties.output = buildContractOutputSchema(contract);
|
|
119
|
-
properties.nextActions = {
|
|
120
|
-
type: "array",
|
|
121
|
-
description: "Concrete next actions after the job result.",
|
|
122
|
-
items: {
|
|
123
|
-
type: "string"
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
required.push("summary", "output", "nextActions");
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
name: contract.schemaName || `${String(contract.format || "bounded_output").replace(/[^a-z0-9]+/gi, "_").toLowerCase()}_response`,
|
|
130
|
-
thoughtFirst,
|
|
131
|
-
reasoningField: thoughtFirst ? "analysis" : null,
|
|
132
|
-
schema: {
|
|
133
|
-
type: "object",
|
|
134
|
-
additionalProperties: false,
|
|
135
|
-
properties,
|
|
136
|
-
required
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
}
|
|
1
|
+
function titleCase(value) {
|
|
2
|
+
return String(value || "")
|
|
3
|
+
.split(/[_\-\s]+/)
|
|
4
|
+
.filter(Boolean)
|
|
5
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
6
|
+
.join("");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function buildBulletedBriefingOutputSchema(contract) {
|
|
10
|
+
const properties = {};
|
|
11
|
+
const required = [];
|
|
12
|
+
|
|
13
|
+
if (contract.profile?.requireStatus) {
|
|
14
|
+
properties.status = {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "One-line overall status."
|
|
17
|
+
};
|
|
18
|
+
required.push("status");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const section of contract.requiredSections || []) {
|
|
22
|
+
properties[section] = {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: `${titleCase(section)} update. Use 'None' if there is no concrete data.`
|
|
25
|
+
};
|
|
26
|
+
required.push(section);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
type: "object",
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
properties,
|
|
33
|
+
required
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildStructuredRollupOutputSchema(contract) {
|
|
38
|
+
const properties = {};
|
|
39
|
+
const required = [];
|
|
40
|
+
|
|
41
|
+
for (const section of contract.requiredSections || []) {
|
|
42
|
+
properties[section] = {
|
|
43
|
+
type: "array",
|
|
44
|
+
description: `${titleCase(section)} bullets. Use ['None'] if there is no concrete data.`,
|
|
45
|
+
minItems: contract.profile?.requireSectionItems ? 1 : 0,
|
|
46
|
+
items: {
|
|
47
|
+
type: "string"
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
required.push(section);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
type: "object",
|
|
55
|
+
additionalProperties: false,
|
|
56
|
+
properties,
|
|
57
|
+
required
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildGenericOutputSchema(contract) {
|
|
62
|
+
const properties = {};
|
|
63
|
+
const required = [];
|
|
64
|
+
|
|
65
|
+
for (const section of contract.requiredSections || []) {
|
|
66
|
+
properties[section] = {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: `${titleCase(section)} section content.`
|
|
69
|
+
};
|
|
70
|
+
required.push(section);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
type: "object",
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
properties,
|
|
77
|
+
required
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function buildContractOutputSchema(contract) {
|
|
82
|
+
if (!contract) {
|
|
83
|
+
return {
|
|
84
|
+
type: "string"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (contract.format === "bulleted_briefing") {
|
|
89
|
+
return buildBulletedBriefingOutputSchema(contract);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (contract.format === "structured_rollup") {
|
|
93
|
+
return buildStructuredRollupOutputSchema(contract);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return buildGenericOutputSchema(contract);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function compileOutputContractSchema(contract, options = {}) {
|
|
100
|
+
if (!contract) return null;
|
|
101
|
+
const thoughtFirst = options.thoughtFirst ?? false;
|
|
102
|
+
|
|
103
|
+
const properties = {};
|
|
104
|
+
const required = [];
|
|
105
|
+
|
|
106
|
+
if (thoughtFirst) {
|
|
107
|
+
properties.analysis = {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "Compact reasoning about the task before finalizing the structured result."
|
|
110
|
+
};
|
|
111
|
+
required.push("analysis");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
properties.summary = {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "Short summary suitable for a completion pingback."
|
|
117
|
+
};
|
|
118
|
+
properties.output = buildContractOutputSchema(contract);
|
|
119
|
+
properties.nextActions = {
|
|
120
|
+
type: "array",
|
|
121
|
+
description: "Concrete next actions after the job result.",
|
|
122
|
+
items: {
|
|
123
|
+
type: "string"
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
required.push("summary", "output", "nextActions");
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
name: contract.schemaName || `${String(contract.format || "bounded_output").replace(/[^a-z0-9]+/gi, "_").toLowerCase()}_response`,
|
|
130
|
+
thoughtFirst,
|
|
131
|
+
reasoningField: thoughtFirst ? "analysis" : null,
|
|
132
|
+
schema: {
|
|
133
|
+
type: "object",
|
|
134
|
+
additionalProperties: false,
|
|
135
|
+
properties,
|
|
136
|
+
required
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|