Merge pull request #177 from PR0M3TH3AN/feat/nostr-platform-model-info-17811919130475421613

Add platform and model support to Nostr lock events
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-15 17:41:27 -05:00
commit 07ce4ed4b4
9 files changed
+1481 -22

No files matched your search

+8 -1
View File
@@ -437,6 +437,7 @@
status: content.status ?? 'unknown',
date: content.date ?? dTag.split('/')[3] ?? todayStr(),
platform: content.platform ?? 'unknown',
model: content.model ?? null,
};
}
@@ -585,8 +586,14 @@
left.appendChild(meta);
header.appendChild(left);
const right = createElement('div', 'flex flex-col items-end gap-1');
const badge = createElement('span', `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${ps.bg} ${ps.text}`, ps.label);
header.appendChild(badge);
right.appendChild(badge);
if (lock.model && lock.model !== 'unknown') {
right.appendChild(createElement('span', 'text-xs text-muted mono opacity-75', lock.model));
}
header.appendChild(right);
card.appendChild(header);
// Grid
+1
View File
@@ -143,6 +143,7 @@ a { color: inherit; }
.w-full { width: 100%; }
.shrink-0 { flex-shrink: 0; }
.opacity-60 { opacity: 0.6; }
.opacity-75 { opacity: 0.75; }
.text-center { text-align: center; }
.text-xs { font-size: 0.75rem; line-height: 1rem; }
+19 -9
View File
@@ -18,7 +18,7 @@ const FAILURE_CATEGORY = {
const LOCK_INCIDENT_LINK = 'docs/agent-handoffs/learnings/2026-02-15-relay-health-preflight-job.md';
function parseArgs(argv) {
const args = { cadence: null, platform: process.env.AGENT_PLATFORM || 'codex' };
const args = { cadence: null, platform: process.env.AGENT_PLATFORM || 'codex', model: process.env.AGENT_MODEL || null };
for (let i = 0; i < argv.length; i += 1) {
const value = argv[i];
if (!value.startsWith('--') && !args.cadence) {
@@ -34,6 +34,10 @@ function parseArgs(argv) {
args.platform = argv[i + 1] || args.platform;
i += 1;
}
if (value === '--model') {
args.model = argv[i + 1] || args.model;
i += 1;
}
}
return args;
}
@@ -540,8 +544,11 @@ function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function acquireLockWithRetry({ selectedAgent, cadence, platform, lockRetry, idempotencyKey }) {
async function acquireLockWithRetry({ selectedAgent, cadence, platform, model, lockRetry, idempotencyKey }) {
const lockCommandArgs = ['run', 'lock:lock', '--', '--agent', selectedAgent, '--cadence', cadence];
if (model) {
lockCommandArgs.push('--model', model);
}
const backoffScheduleMs = [];
let attempts = 0;
const correlationId = idempotencyKey || `${cadence}:${selectedAgent}:${getRunDateKey()}`;
@@ -551,6 +558,7 @@ async function acquireLockWithRetry({ selectedAgent, cadence, platform, lockRetr
const result = await runCommand('npm', lockCommandArgs, {
env: {
AGENT_PLATFORM: platform,
...(model ? { AGENT_MODEL: model } : {}),
...(idempotencyKey ? { SCHEDULER_LOCK_IDEMPOTENCY_KEY: idempotencyKey } : {}),
SCHEDULER_LOCK_CORRELATION_ID: correlationId,
SCHEDULER_LOCK_ATTEMPT_ID: String(attempts),
@@ -664,7 +672,7 @@ async function writeLog({ cadence, agent, status, reason, detail, platform, meta
}
async function main() {
const { cadence, platform } = parseArgs(process.argv.slice(2));
const { cadence, platform, model } = parseArgs(process.argv.slice(2));
if (!VALID_CADENCES.has(cadence)) {
console.error('Usage: node scripts/agent/run-scheduler-cycle.mjs <daily|weekly>');
process.exit(1);
@@ -772,6 +780,7 @@ async function main() {
selectedAgent,
cadence,
platform,
model,
lockRetry: schedulerConfig.lockRetry,
idempotencyKey: deferralForAgent?.idempotency_key,
});
@@ -785,7 +794,8 @@ async function main() {
const combinedLockOutput = `${lockResult.stderr}\n${lockResult.stdout}`;
const diagnosticsSummary = summarizeLockFailureReasons(combinedLockOutput);
const backendCategory = lockAttempt.finalBackendCategory || classifyLockBackendError(combinedLockOutput);
const lockCommand = `AGENT_PLATFORM=${platform} npm run lock:lock -- --agent ${selectedAgent} --cadence ${cadence}`;
const modelPart = model ? ` --model ${model}` : '';
const lockCommand = `AGENT_PLATFORM=${platform} npm run lock:lock -- --agent ${selectedAgent} --cadence ${cadence}${modelPart}`;
const stderrExcerpt = excerptText(lockResult.stderr);
const stdoutExcerpt = excerptText(lockResult.stdout);
const backoffSchedule = lockAttempt.backoffScheduleMs.join(', ');
@@ -892,7 +902,7 @@ async function main() {
if (schedulerConfig.memoryPolicy.retrieveCommand) {
const retrieveResult = await runCommand('bash', ['-lc', schedulerConfig.memoryPolicy.retrieveCommand], {
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
env: { AGENT_PLATFORM: platform, ...(model ? { AGENT_MODEL: model } : {}), SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
});
outputChunks.push(retrieveResult.stdout, retrieveResult.stderr);
if (retrieveResult.code !== 0) {
@@ -911,7 +921,7 @@ async function main() {
if (schedulerConfig.handoffCommand) {
const handoff = await runCommand('bash', ['-lc', schedulerConfig.handoffCommand], {
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
env: { AGENT_PLATFORM: platform, ...(model ? { AGENT_MODEL: model } : {}), SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
});
outputChunks.push(handoff.stdout, handoff.stderr);
if (handoff.code !== 0) {
@@ -944,7 +954,7 @@ async function main() {
if (schedulerConfig.memoryPolicy.storeCommand) {
const storeResult = await runCommand('bash', ['-lc', schedulerConfig.memoryPolicy.storeCommand], {
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
env: { AGENT_PLATFORM: platform, ...(model ? { AGENT_MODEL: model } : {}), SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
});
outputChunks.push(storeResult.stdout, storeResult.stderr);
if (storeResult.code !== 0) {
@@ -1043,8 +1053,8 @@ async function main() {
const completeResult = await runCommand(
'npm',
['run', 'lock:complete', '--', '--agent', selectedAgent, '--cadence', cadence],
{ env: { AGENT_PLATFORM: platform } },
['run', 'lock:complete', '--', '--agent', selectedAgent, '--cadence', cadence, ...(model ? ['--model', model] : [])],
{ env: { AGENT_PLATFORM: platform, ...(model ? { AGENT_MODEL: model } : {}) } },
);
if (completeResult.code !== 0) {
+1 -1
View File
@@ -43,7 +43,7 @@ const invariants = [
],
},
schedulerSnippets: [
"runCommand('npm', ['run', `lock:check:${cadence}`])",
"runCommand('npm', ['run', `lock:check:${cadence}`",
'checkPayload.excluded',
'checkPayload.locked',
'checkPayload.paused',
+10 -3
View File
@@ -31,7 +31,8 @@ export function parseArgs(argv) {
allRelaysDownMinutes: null,
minSuccessRate: null,
windowMinutes: null,
full: false,
platform: null,
model: null,
};
let i = 0;
@@ -118,8 +119,14 @@ export function parseArgs(argv) {
args.windowMinutes = parseInt(argv[++i], 10);
} else if (arg.startsWith('--window-minutes=')) {
args.windowMinutes = parseInt(arg.split('=')[1], 10);
} else if (arg === '--full') {
args.full = true;
} else if (arg === '--platform') {
args.platform = argv[++i];
} else if (arg.startsWith('--platform=')) {
args.platform = arg.split('=')[1];
} else if (arg === '--model') {
args.model = argv[++i];
} else if (arg.startsWith('--model=')) {
args.model = arg.split('=')[1];
}
}
+23 -7
View File
@@ -33,7 +33,7 @@ import {
unpinMemory,
} from './services/memory/index.js';
import { ExitError } from './errors.mjs';
import { todayDateStr, nowUnix, getIsoWeekStr } from './utils.mjs';
import { todayDateStr, nowUnix, getIsoWeekStr, detectPlatform } from './utils.mjs';
import { runRelayHealthCheck } from './relay-health.mjs';
import fs from 'node:fs/promises';
import path from 'node:path';
@@ -204,7 +204,10 @@ export async function cmdCheck(cadence, deps = {}) {
* @returns {Promise<{status: string, eventId: string}>}
* @throws {ExitError} If lock is denied (already locked, completed, or race lost)
*/
export async function cmdLock(agent, cadence, dryRun = false, deps = {}) {
export async function cmdLock(agent, cadence, optionsOrDryRun = false, deps = {}) {
const options = typeof optionsOrDryRun === 'object' ? optionsOrDryRun : { dryRun: !!optionsOrDryRun };
const { dryRun = false, platform = null, model = null } = options;
const {
getRelays = _getRelays,
getNamespace = _getNamespace,
@@ -290,7 +293,8 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) {
status: 'started',
namespace,
date: dateStr,
platform: process.env.AGENT_PLATFORM || 'unknown',
platform: platform || process.env.AGENT_PLATFORM || detectPlatform() || 'unknown',
model: model || process.env.AGENT_MODEL || 'unknown',
lockedAt: new Date(now * 1000).toISOString(),
expiresAt: new Date(expiresAt * 1000).toISOString(),
}),
@@ -436,7 +440,10 @@ export async function cmdList(cadence, deps = {}) {
* @returns {Promise<{status: string, eventId: string}>}
* @throws {ExitError} If no active lock exists for the agent
*/
export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) {
export async function cmdComplete(agent, cadence, optionsOrDryRun = false, deps = {}) {
const options = typeof optionsOrDryRun === 'object' ? optionsOrDryRun : { dryRun: !!optionsOrDryRun };
const { dryRun = false, platform = null, model = null } = options;
const {
getRelays = _getRelays,
getNamespace = _getNamespace,
@@ -500,7 +507,8 @@ export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) {
status: 'completed',
namespace,
date: dateStr,
platform: process.env.AGENT_PLATFORM || 'unknown',
platform: platform || process.env.AGENT_PLATFORM || detectPlatform() || 'unknown',
model: model || process.env.AGENT_MODEL || 'unknown',
startedAt: startedAtIso,
completedAt: new Date(now * 1000).toISOString(),
}),
@@ -614,7 +622,11 @@ export async function main(argv) {
console.error(`ERROR: --cadence <${[...VALID_CADENCES].join('|')}> is required for lock`);
throw new ExitError(1, 'Missing cadence');
}
await cmdLock(args.agent, args.cadence, args.dryRun);
await cmdLock(args.agent, args.cadence, {
dryRun: args.dryRun,
platform: args.platform,
model: args.model
});
break;
}
@@ -627,7 +639,11 @@ export async function main(argv) {
console.error(`ERROR: --cadence <${[...VALID_CADENCES].join('|')}> is required for complete`);
throw new ExitError(1, 'Missing cadence');
}
await cmdComplete(args.agent, args.cadence, args.dryRun);
await cmdComplete(args.agent, args.cadence, {
dryRun: args.dryRun,
platform: args.platform,
model: args.model
});
break;
}
+7
View File
@@ -27,3 +27,10 @@ export function getIsoWeekStr(dateInput) {
return `${date.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;
}
export function detectPlatform() {
if (process.env.JULES_API_KEY || process.env.JULES_SESSION_ID) return 'jules';
if (process.env.CODEX_API_KEY || process.env.CODEX_SESSION_ID) return 'codex';
if (process.env.GOOSE_API_KEY || process.env.GOOSE_SESSION_ID) return 'goose';
return null;
}
+1 -1
View File
@@ -129,7 +129,7 @@ describe('Scheduler cycle ordering guarantees', () => {
const order = [
"const preflight = await runLockHealthPreflight({ cadence, platform });",
"const checkResult = await runCommand('npm', ['run', `lock:check:${cadence}`]);",
"const checkResult = await runCommand('npm', ['run', `lock:check:${cadence}`",
"const lockAttempt = await acquireLockWithRetry({",
"if (schedulerConfig.handoffCommand)",
"const artifactCheck = await runCommand('node', [",
+1411
View File
File diff suppressed because it is too large. Load diff