@reactive-skills/runtime 0.4.0 โ 0.4.1
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/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/core/projection-engine.d.ts +1 -0
- package/dist/core/projection-engine.js +1 -0
- package/dist/mcp/server.js +104 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
## [0.4.1] - 2026-09-14
|
|
3
|
+
|
|
4
|
+
- feat(runtime,axi): add mcp job tools, template jobId context, and flexible jobs cli arguments (2b31451)
|
|
5
|
+
- feat(mcp): add reactive_switch_job and reactive_archive_job tools with active job indicators
|
|
6
|
+
- feat(projections): expose jobId directly in ProjectionContext for Handlebars templates
|
|
7
|
+
- feat(axi): support bidirectional argument ordering in jobs command (jobs list <skill> and jobs <skill> list)
|
|
8
|
+
- docs: introduce PERFORMANCE-STANDARDS.md for P0-P3 latency budgets, caching tiers, and CRAP score limits
|
|
9
|
+
|
|
2
10
|
## [0.4.0] - 2026-09-14
|
|
3
11
|
|
|
4
12
|
- feat(axi): implement native validate command for skill manifest and statechart verification (3b75a21)
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Reactive Skills Architecture (RSA) core runtime โ FSM engine, event store, guard evaluator, projection engine, job manager, and MCP server.
|
|
4
4
|
|
|
5
|
-
> ๐ **What's New in v0.4.
|
|
5
|
+
> ๐ **What's New in v0.4.1:** MCP job management tools (`reactive_switch_job`, `reactive_archive_job`), template-level `jobId` context, and `PERFORMANCE-STANDARDS.md`. [Read Full Release Notes โ](https://github.com/Reactive-Skills/reactive-skills/releases/tag/v0.4.1) ยท [View Changelog](https://github.com/Reactive-Skills/reactive-skills/blob/main/CHANGELOG.md)
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
package/dist/mcp/server.js
CHANGED
|
@@ -455,7 +455,10 @@ export function createReactiveMcpServer(options = {}) {
|
|
|
455
455
|
const targetSkill = skill || defaultSkill;
|
|
456
456
|
const jobManager = new JobManager(workspaceDir);
|
|
457
457
|
const activeJobId = jobManager.getActiveJobId(targetSkill);
|
|
458
|
-
const jobs = jobManager.listJobs(targetSkill)
|
|
458
|
+
const jobs = jobManager.listJobs(targetSkill).map(j => ({
|
|
459
|
+
...j,
|
|
460
|
+
isActive: j.id === activeJobId,
|
|
461
|
+
}));
|
|
459
462
|
return {
|
|
460
463
|
content: [
|
|
461
464
|
{
|
|
@@ -476,6 +479,106 @@ export function createReactiveMcpServer(options = {}) {
|
|
|
476
479
|
};
|
|
477
480
|
}
|
|
478
481
|
});
|
|
482
|
+
// 10. TOOL: reactive_switch_job
|
|
483
|
+
server.tool('reactive_switch_job', 'Switch the active execution job pointer for a reactive skill and synchronize deliverables', {
|
|
484
|
+
skill: z.string().optional().describe('Name of the reactive skill (defaults to active skill)'),
|
|
485
|
+
job_id: z.string().describe('Target job ID to set as active'),
|
|
486
|
+
}, async ({ skill, job_id }) => {
|
|
487
|
+
try {
|
|
488
|
+
const skillName = skill || defaultSkill;
|
|
489
|
+
const jobManager = new JobManager(workspaceDir);
|
|
490
|
+
const job = jobManager.getJob(skillName, job_id);
|
|
491
|
+
if (!job) {
|
|
492
|
+
return {
|
|
493
|
+
content: [{ type: 'text', text: JSON.stringify({ error: `Job '${job_id}' not found for skill '${skillName}'` }) }],
|
|
494
|
+
isError: true,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
jobManager.setActiveJobId(skillName, job_id);
|
|
498
|
+
// Re-mirror deliverables: copy archive deliverables to root if they exist
|
|
499
|
+
const docsDir = path.join(workspaceDir, '.docs', skillName);
|
|
500
|
+
const archiveDir = path.join(docsDir, 'jobs', job_id);
|
|
501
|
+
let mirroredCount = 0;
|
|
502
|
+
if (fs.existsSync(archiveDir)) {
|
|
503
|
+
const files = fs.readdirSync(archiveDir);
|
|
504
|
+
for (const file of files) {
|
|
505
|
+
const src = path.join(archiveDir, file);
|
|
506
|
+
if (fs.statSync(src).isFile()) {
|
|
507
|
+
const dest = path.join(docsDir, file);
|
|
508
|
+
fs.copyFileSync(src, dest);
|
|
509
|
+
mirroredCount++;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
content: [
|
|
515
|
+
{
|
|
516
|
+
type: 'text',
|
|
517
|
+
text: JSON.stringify({
|
|
518
|
+
skill: skillName,
|
|
519
|
+
activeJobId: job_id,
|
|
520
|
+
status: job.status,
|
|
521
|
+
currentState: job.currentState,
|
|
522
|
+
mirroredDeliverables: mirroredCount,
|
|
523
|
+
}, null, 2),
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
return {
|
|
530
|
+
content: [{ type: 'text', text: JSON.stringify({ error: err.message }) }],
|
|
531
|
+
isError: true,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
// 11. TOOL: reactive_archive_job
|
|
536
|
+
server.tool('reactive_archive_job', 'Archive an execution job for a reactive skill and rotate active pointer if archived was active', {
|
|
537
|
+
skill: z.string().optional().describe('Name of the reactive skill (defaults to active skill)'),
|
|
538
|
+
job_id: z.string().optional().describe('Job ID to archive (defaults to active job)'),
|
|
539
|
+
}, async ({ skill, job_id }) => {
|
|
540
|
+
try {
|
|
541
|
+
const skillName = skill || defaultSkill;
|
|
542
|
+
const jobManager = new JobManager(workspaceDir);
|
|
543
|
+
const targetId = job_id || jobManager.getActiveJobId(skillName);
|
|
544
|
+
const currentActive = jobManager.getActiveJobId(skillName);
|
|
545
|
+
const job = jobManager.getJob(skillName, targetId);
|
|
546
|
+
if (!job) {
|
|
547
|
+
return {
|
|
548
|
+
content: [{ type: 'text', text: JSON.stringify({ error: `Job '${targetId}' not found for skill '${skillName}'` }) }],
|
|
549
|
+
isError: true,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
jobManager.updateJob(skillName, targetId, {
|
|
553
|
+
status: 'archived',
|
|
554
|
+
completedAt: new Date().toISOString(),
|
|
555
|
+
});
|
|
556
|
+
let freshJobId = currentActive;
|
|
557
|
+
if (currentActive === targetId) {
|
|
558
|
+
const freshJob = jobManager.createJob(skillName, { setActive: true });
|
|
559
|
+
freshJobId = freshJob.id;
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
content: [
|
|
563
|
+
{
|
|
564
|
+
type: 'text',
|
|
565
|
+
text: JSON.stringify({
|
|
566
|
+
skill: skillName,
|
|
567
|
+
archivedJobId: targetId,
|
|
568
|
+
status: 'archived',
|
|
569
|
+
activeJobId: freshJobId,
|
|
570
|
+
}, null, 2),
|
|
571
|
+
},
|
|
572
|
+
],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
catch (err) {
|
|
576
|
+
return {
|
|
577
|
+
content: [{ type: 'text', text: JSON.stringify({ error: err.message }) }],
|
|
578
|
+
isError: true,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
});
|
|
479
582
|
// RESOURCE 1: reactive://events
|
|
480
583
|
server.resource('reactive-events', 'reactive://events', async (uri) => {
|
|
481
584
|
const store = new EventStore({ enableSqlite: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactive-skills/runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Reactive Skills Architecture (RSA) core runtime โ FSM engine, event store, guard evaluator, projection engine, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|