@cleocode/adapters 2026.3.37 → 2026.3.40
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/LICENSE +21 -0
- package/README.md +503 -0
- package/dist/index.js +621 -496
- package/dist/index.js.map +4 -4
- package/package.json +12 -7
- package/src/__tests__/claude-code-adapter.test.d.ts +10 -0
- package/src/__tests__/claude-code-adapter.test.d.ts.map +1 -0
- package/src/__tests__/claude-code-adapter.test.js +192 -0
- package/src/__tests__/claude-code-adapter.test.js.map +1 -0
- package/src/__tests__/claude-code-adapter.test.ts +235 -0
- package/src/__tests__/cursor-adapter.test.d.ts +10 -0
- package/src/__tests__/cursor-adapter.test.d.ts.map +1 -0
- package/src/__tests__/cursor-adapter.test.js +196 -0
- package/src/__tests__/cursor-adapter.test.js.map +1 -0
- package/src/__tests__/cursor-adapter.test.ts +246 -0
- package/src/__tests__/opencode-adapter.test.d.ts +10 -0
- package/src/__tests__/opencode-adapter.test.d.ts.map +1 -0
- package/src/__tests__/opencode-adapter.test.js +204 -0
- package/src/__tests__/opencode-adapter.test.js.map +1 -0
- package/src/__tests__/opencode-adapter.test.ts +250 -0
- package/src/index.d.ts +28 -20
- package/src/index.d.ts.map +1 -1
- package/src/index.js +4 -19
- package/src/index.js.map +1 -1
- package/src/index.ts +25 -25
- package/src/providers/claude-code/__tests__/adapter.test.d.ts +1 -1
- package/src/providers/claude-code/__tests__/adapter.test.d.ts.map +0 -0
- package/src/providers/claude-code/__tests__/adapter.test.js +2 -2
- package/src/providers/claude-code/__tests__/adapter.test.js.map +1 -1
- package/src/providers/claude-code/__tests__/adapter.test.ts +2 -2
- package/src/providers/claude-code/adapter.d.ts +54 -50
- package/src/providers/claude-code/adapter.d.ts.map +0 -0
- package/src/providers/claude-code/adapter.js +1 -1
- package/src/providers/claude-code/adapter.js.map +1 -1
- package/src/providers/claude-code/adapter.ts +1 -1
- package/src/providers/claude-code/context-monitor.d.ts +6 -6
- package/src/providers/claude-code/context-monitor.d.ts.map +0 -0
- package/src/providers/claude-code/context-monitor.js +0 -0
- package/src/providers/claude-code/context-monitor.js.map +0 -0
- package/src/providers/claude-code/context-monitor.ts +0 -0
- package/src/providers/claude-code/hooks.d.ts +36 -36
- package/src/providers/claude-code/hooks.d.ts.map +0 -0
- package/src/providers/claude-code/hooks.js +0 -0
- package/src/providers/claude-code/hooks.js.map +0 -0
- package/src/providers/claude-code/hooks.ts +0 -0
- package/src/providers/claude-code/index.d.ts +6 -2
- package/src/providers/claude-code/index.d.ts.map +1 -1
- package/src/providers/claude-code/index.js +1 -1
- package/src/providers/claude-code/index.js.map +1 -1
- package/src/providers/claude-code/index.ts +2 -2
- package/src/providers/claude-code/install.d.ts +52 -52
- package/src/providers/claude-code/install.d.ts.map +1 -1
- package/src/providers/claude-code/install.js +1 -4
- package/src/providers/claude-code/install.js.map +1 -1
- package/src/providers/claude-code/install.ts +1 -4
- package/src/providers/claude-code/manifest.json +0 -0
- package/src/providers/claude-code/paths.d.ts +5 -5
- package/src/providers/claude-code/paths.d.ts.map +0 -0
- package/src/providers/claude-code/paths.js +0 -0
- package/src/providers/claude-code/paths.js.map +0 -0
- package/src/providers/claude-code/paths.ts +0 -0
- package/src/providers/claude-code/spawn.d.ts +37 -37
- package/src/providers/claude-code/spawn.d.ts.map +1 -1
- package/src/providers/claude-code/spawn.js +4 -0
- package/src/providers/claude-code/spawn.js.map +1 -1
- package/src/providers/claude-code/spawn.ts +5 -0
- package/src/providers/claude-code/statusline.d.ts +1 -2
- package/src/providers/claude-code/statusline.d.ts.map +0 -0
- package/src/providers/claude-code/statusline.js +2 -1
- package/src/providers/claude-code/statusline.js.map +1 -1
- package/src/providers/claude-code/statusline.ts +3 -3
- package/src/providers/claude-code/task-sync.js +1 -3
- package/src/providers/claude-code/task-sync.js.map +1 -1
- package/src/providers/claude-code/task-sync.ts +5 -22
- package/src/providers/claude-code/transport.d.ts +3 -3
- package/src/providers/claude-code/transport.d.ts.map +0 -0
- package/src/providers/claude-code/transport.js +0 -0
- package/src/providers/claude-code/transport.js.map +0 -0
- package/src/providers/claude-code/transport.ts +0 -0
- package/src/providers/cursor/__tests__/adapter.test.d.ts +1 -1
- package/src/providers/cursor/__tests__/adapter.test.d.ts.map +0 -0
- package/src/providers/cursor/__tests__/adapter.test.js +2 -2
- package/src/providers/cursor/__tests__/adapter.test.js.map +1 -1
- package/src/providers/cursor/__tests__/adapter.test.ts +2 -2
- package/src/providers/cursor/adapter.d.ts +44 -40
- package/src/providers/cursor/adapter.d.ts.map +0 -0
- package/src/providers/cursor/adapter.js +0 -0
- package/src/providers/cursor/adapter.js.map +0 -0
- package/src/providers/cursor/adapter.ts +0 -0
- package/src/providers/cursor/hooks.d.ts +29 -29
- package/src/providers/cursor/hooks.d.ts.map +0 -0
- package/src/providers/cursor/hooks.js +0 -0
- package/src/providers/cursor/hooks.js.map +0 -0
- package/src/providers/cursor/hooks.ts +0 -0
- package/src/providers/cursor/index.d.ts +1 -1
- package/src/providers/cursor/index.d.ts.map +0 -0
- package/src/providers/cursor/index.js +0 -0
- package/src/providers/cursor/index.js.map +0 -0
- package/src/providers/cursor/index.ts +0 -0
- package/src/providers/cursor/install.d.ts +67 -67
- package/src/providers/cursor/install.d.ts.map +1 -1
- package/src/providers/cursor/install.js +1 -4
- package/src/providers/cursor/install.js.map +1 -1
- package/src/providers/cursor/install.ts +1 -4
- package/src/providers/cursor/manifest.json +0 -0
- package/src/providers/cursor/spawn.d.ts +31 -31
- package/src/providers/cursor/spawn.d.ts.map +0 -0
- package/src/providers/cursor/spawn.js +0 -0
- package/src/providers/cursor/spawn.js.map +1 -1
- package/src/providers/cursor/spawn.ts +2 -2
- package/src/providers/opencode/__tests__/adapter.test.d.ts +1 -1
- package/src/providers/opencode/__tests__/adapter.test.d.ts.map +0 -0
- package/src/providers/opencode/__tests__/adapter.test.js +2 -2
- package/src/providers/opencode/__tests__/adapter.test.js.map +1 -1
- package/src/providers/opencode/__tests__/adapter.test.ts +2 -2
- package/src/providers/opencode/adapter.d.ts +50 -46
- package/src/providers/opencode/adapter.d.ts.map +0 -0
- package/src/providers/opencode/adapter.js +0 -0
- package/src/providers/opencode/adapter.js.map +0 -0
- package/src/providers/opencode/adapter.ts +0 -0
- package/src/providers/opencode/hooks.d.ts +36 -36
- package/src/providers/opencode/hooks.d.ts.map +0 -0
- package/src/providers/opencode/hooks.js +1 -1
- package/src/providers/opencode/hooks.js.map +1 -1
- package/src/providers/opencode/hooks.ts +1 -1
- package/src/providers/opencode/index.d.ts +2 -2
- package/src/providers/opencode/index.d.ts.map +1 -1
- package/src/providers/opencode/index.js +1 -1
- package/src/providers/opencode/index.js.map +1 -1
- package/src/providers/opencode/index.ts +1 -1
- package/src/providers/opencode/install.d.ts +46 -46
- package/src/providers/opencode/install.d.ts.map +1 -1
- package/src/providers/opencode/install.js +1 -4
- package/src/providers/opencode/install.js.map +1 -1
- package/src/providers/opencode/install.ts +1 -4
- package/src/providers/opencode/manifest.json +0 -0
- package/src/providers/opencode/spawn.d.ts +42 -39
- package/src/providers/opencode/spawn.d.ts.map +1 -1
- package/src/providers/opencode/spawn.js +0 -0
- package/src/providers/opencode/spawn.js.map +1 -1
- package/src/providers/opencode/spawn.ts +2 -7
- package/src/registry.d.ts +12 -12
- package/src/registry.d.ts.map +1 -1
- package/src/registry.js +0 -0
- package/src/registry.js.map +1 -1
- package/src/registry.ts +1 -3
- package/dist/index.d.ts +0 -27
- package/dist/index.d.ts.map +0 -1
- package/dist/providers/claude-code/adapter.d.ts +0 -75
- package/dist/providers/claude-code/adapter.d.ts.map +0 -1
- package/dist/providers/claude-code/adapter.js +0 -154
- package/dist/providers/claude-code/adapter.js.map +0 -1
- package/dist/providers/claude-code/context-monitor.d.ts +0 -24
- package/dist/providers/claude-code/context-monitor.d.ts.map +0 -1
- package/dist/providers/claude-code/context-monitor.js +0 -148
- package/dist/providers/claude-code/context-monitor.js.map +0 -1
- package/dist/providers/claude-code/hooks.d.ts +0 -59
- package/dist/providers/claude-code/hooks.d.ts.map +0 -1
- package/dist/providers/claude-code/hooks.js +0 -77
- package/dist/providers/claude-code/hooks.js.map +0 -1
- package/dist/providers/claude-code/index.d.ts +0 -24
- package/dist/providers/claude-code/index.d.ts.map +0 -1
- package/dist/providers/claude-code/index.js +0 -26
- package/dist/providers/claude-code/index.js.map +0 -1
- package/dist/providers/claude-code/install.d.ts +0 -75
- package/dist/providers/claude-code/install.d.ts.map +0 -1
- package/dist/providers/claude-code/install.js +0 -237
- package/dist/providers/claude-code/install.js.map +0 -1
- package/dist/providers/claude-code/paths.d.ts +0 -24
- package/dist/providers/claude-code/paths.d.ts.map +0 -1
- package/dist/providers/claude-code/paths.js +0 -33
- package/dist/providers/claude-code/paths.js.map +0 -1
- package/dist/providers/claude-code/spawn.d.ts +0 -60
- package/dist/providers/claude-code/spawn.d.ts.map +0 -1
- package/dist/providers/claude-code/spawn.js +0 -160
- package/dist/providers/claude-code/spawn.js.map +0 -1
- package/dist/providers/claude-code/statusline.d.ts +0 -24
- package/dist/providers/claude-code/statusline.d.ts.map +0 -1
- package/dist/providers/claude-code/statusline.js +0 -85
- package/dist/providers/claude-code/statusline.js.map +0 -1
- package/dist/providers/claude-code/task-sync.d.ts +0 -27
- package/dist/providers/claude-code/task-sync.d.ts.map +0 -1
- package/dist/providers/claude-code/task-sync.js +0 -124
- package/dist/providers/claude-code/task-sync.js.map +0 -1
- package/dist/providers/claude-code/transport.d.ts +0 -14
- package/dist/providers/claude-code/transport.d.ts.map +0 -1
- package/dist/providers/claude-code/transport.js +0 -18
- package/dist/providers/claude-code/transport.js.map +0 -1
- package/dist/providers/cursor/adapter.d.ts +0 -62
- package/dist/providers/cursor/adapter.d.ts.map +0 -1
- package/dist/providers/cursor/adapter.js +0 -124
- package/dist/providers/cursor/adapter.js.map +0 -1
- package/dist/providers/cursor/hooks.d.ts +0 -48
- package/dist/providers/cursor/hooks.d.ts.map +0 -1
- package/dist/providers/cursor/hooks.js +0 -55
- package/dist/providers/cursor/hooks.js.map +0 -1
- package/dist/providers/cursor/index.d.ts +0 -19
- package/dist/providers/cursor/index.d.ts.map +0 -1
- package/dist/providers/cursor/index.js +0 -21
- package/dist/providers/cursor/index.js.map +0 -1
- package/dist/providers/cursor/install.d.ts +0 -94
- package/dist/providers/cursor/install.d.ts.map +0 -1
- package/dist/providers/cursor/install.js +0 -241
- package/dist/providers/cursor/install.js.map +0 -1
- package/dist/providers/cursor/spawn.d.ts +0 -50
- package/dist/providers/cursor/spawn.d.ts.map +0 -1
- package/dist/providers/cursor/spawn.js +0 -59
- package/dist/providers/cursor/spawn.js.map +0 -1
- package/dist/providers/opencode/adapter.d.ts +0 -67
- package/dist/providers/opencode/adapter.d.ts.map +0 -1
- package/dist/providers/opencode/adapter.js +0 -144
- package/dist/providers/opencode/adapter.js.map +0 -1
- package/dist/providers/opencode/hooks.d.ts +0 -66
- package/dist/providers/opencode/hooks.d.ts.map +0 -1
- package/dist/providers/opencode/hooks.js +0 -89
- package/dist/providers/opencode/hooks.js.map +0 -1
- package/dist/providers/opencode/index.d.ts +0 -20
- package/dist/providers/opencode/index.d.ts.map +0 -1
- package/dist/providers/opencode/index.js +0 -22
- package/dist/providers/opencode/index.js.map +0 -1
- package/dist/providers/opencode/install.d.ts +0 -65
- package/dist/providers/opencode/install.d.ts.map +0 -1
- package/dist/providers/opencode/install.js +0 -183
- package/dist/providers/opencode/install.js.map +0 -1
- package/dist/providers/opencode/spawn.d.ts +0 -72
- package/dist/providers/opencode/spawn.d.ts.map +0 -1
- package/dist/providers/opencode/spawn.js +0 -219
- package/dist/providers/opencode/spawn.js.map +0 -1
- package/dist/registry.d.ts +0 -36
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -55
- package/dist/registry.js.map +0 -1
- package/src/providers/claude-code/task-sync.d.ts +0 -27
- package/src/providers/claude-code/task-sync.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -231,10 +231,7 @@ var INSTRUCTION_REFERENCES, MCP_SERVER_KEY, ClaudeCodeInstallProvider;
|
|
|
231
231
|
var init_install = __esm({
|
|
232
232
|
"packages/adapters/src/providers/claude-code/install.js"() {
|
|
233
233
|
"use strict";
|
|
234
|
-
INSTRUCTION_REFERENCES = [
|
|
235
|
-
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
236
|
-
"@.cleo/memory-bridge.md"
|
|
237
|
-
];
|
|
234
|
+
INSTRUCTION_REFERENCES = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
|
|
238
235
|
MCP_SERVER_KEY = "cleo";
|
|
239
236
|
ClaudeCodeInstallProvider = class {
|
|
240
237
|
installedProjectDir = null;
|
|
@@ -426,6 +423,152 @@ var init_install = __esm({
|
|
|
426
423
|
}
|
|
427
424
|
});
|
|
428
425
|
|
|
426
|
+
// packages/contracts/src/errors.ts
|
|
427
|
+
function getErrorMessage(error, fallback = "Unknown error") {
|
|
428
|
+
if (error instanceof Error) {
|
|
429
|
+
return error.message;
|
|
430
|
+
}
|
|
431
|
+
if (typeof error === "string") {
|
|
432
|
+
return error;
|
|
433
|
+
}
|
|
434
|
+
if (error !== null && typeof error === "object" && "message" in error && typeof error.message === "string") {
|
|
435
|
+
return error.message;
|
|
436
|
+
}
|
|
437
|
+
return fallback;
|
|
438
|
+
}
|
|
439
|
+
var init_errors = __esm({
|
|
440
|
+
"packages/contracts/src/errors.ts"() {
|
|
441
|
+
"use strict";
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// packages/contracts/src/exit-codes.ts
|
|
446
|
+
var init_exit_codes = __esm({
|
|
447
|
+
"packages/contracts/src/exit-codes.ts"() {
|
|
448
|
+
"use strict";
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// packages/contracts/src/lafs.ts
|
|
453
|
+
var init_lafs = __esm({
|
|
454
|
+
"packages/contracts/src/lafs.ts"() {
|
|
455
|
+
"use strict";
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// packages/contracts/src/operations/issues.ts
|
|
460
|
+
var init_issues = __esm({
|
|
461
|
+
"packages/contracts/src/operations/issues.ts"() {
|
|
462
|
+
"use strict";
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// packages/contracts/src/operations/lifecycle.ts
|
|
467
|
+
var init_lifecycle = __esm({
|
|
468
|
+
"packages/contracts/src/operations/lifecycle.ts"() {
|
|
469
|
+
"use strict";
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// packages/contracts/src/operations/orchestrate.ts
|
|
474
|
+
var init_orchestrate = __esm({
|
|
475
|
+
"packages/contracts/src/operations/orchestrate.ts"() {
|
|
476
|
+
"use strict";
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
// packages/contracts/src/operations/release.ts
|
|
481
|
+
var init_release = __esm({
|
|
482
|
+
"packages/contracts/src/operations/release.ts"() {
|
|
483
|
+
"use strict";
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// packages/contracts/src/operations/research.ts
|
|
488
|
+
var init_research = __esm({
|
|
489
|
+
"packages/contracts/src/operations/research.ts"() {
|
|
490
|
+
"use strict";
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// packages/contracts/src/operations/session.ts
|
|
495
|
+
var init_session = __esm({
|
|
496
|
+
"packages/contracts/src/operations/session.ts"() {
|
|
497
|
+
"use strict";
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// packages/contracts/src/operations/skills.ts
|
|
502
|
+
var init_skills = __esm({
|
|
503
|
+
"packages/contracts/src/operations/skills.ts"() {
|
|
504
|
+
"use strict";
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// packages/contracts/src/operations/system.ts
|
|
509
|
+
var init_system = __esm({
|
|
510
|
+
"packages/contracts/src/operations/system.ts"() {
|
|
511
|
+
"use strict";
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// packages/contracts/src/operations/tasks.ts
|
|
516
|
+
var init_tasks = __esm({
|
|
517
|
+
"packages/contracts/src/operations/tasks.ts"() {
|
|
518
|
+
"use strict";
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// packages/contracts/src/operations/validate.ts
|
|
523
|
+
var init_validate = __esm({
|
|
524
|
+
"packages/contracts/src/operations/validate.ts"() {
|
|
525
|
+
"use strict";
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
// packages/contracts/src/operations/index.ts
|
|
530
|
+
var init_operations = __esm({
|
|
531
|
+
"packages/contracts/src/operations/index.ts"() {
|
|
532
|
+
"use strict";
|
|
533
|
+
init_issues();
|
|
534
|
+
init_lifecycle();
|
|
535
|
+
init_orchestrate();
|
|
536
|
+
init_release();
|
|
537
|
+
init_research();
|
|
538
|
+
init_session();
|
|
539
|
+
init_skills();
|
|
540
|
+
init_system();
|
|
541
|
+
init_tasks();
|
|
542
|
+
init_validate();
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// packages/contracts/src/session.ts
|
|
547
|
+
var init_session2 = __esm({
|
|
548
|
+
"packages/contracts/src/session.ts"() {
|
|
549
|
+
"use strict";
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
// packages/contracts/src/status-registry.ts
|
|
554
|
+
var init_status_registry = __esm({
|
|
555
|
+
"packages/contracts/src/status-registry.ts"() {
|
|
556
|
+
"use strict";
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
// packages/contracts/src/index.ts
|
|
561
|
+
var init_src = __esm({
|
|
562
|
+
"packages/contracts/src/index.ts"() {
|
|
563
|
+
init_errors();
|
|
564
|
+
init_exit_codes();
|
|
565
|
+
init_lafs();
|
|
566
|
+
init_operations();
|
|
567
|
+
init_session2();
|
|
568
|
+
init_status_registry();
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
429
572
|
// packages/adapters/src/providers/claude-code/spawn.js
|
|
430
573
|
import { exec, spawn as nodeSpawn } from "node:child_process";
|
|
431
574
|
import { unlink, writeFile } from "node:fs/promises";
|
|
@@ -434,6 +577,7 @@ var execAsync, ClaudeCodeSpawnProvider;
|
|
|
434
577
|
var init_spawn = __esm({
|
|
435
578
|
"packages/adapters/src/providers/claude-code/spawn.js"() {
|
|
436
579
|
"use strict";
|
|
580
|
+
init_src();
|
|
437
581
|
execAsync = promisify(exec);
|
|
438
582
|
ClaudeCodeSpawnProvider = class {
|
|
439
583
|
/** Map of instance IDs to tracked process info. */
|
|
@@ -500,6 +644,7 @@ var init_spawn = __esm({
|
|
|
500
644
|
startTime
|
|
501
645
|
};
|
|
502
646
|
} catch (error) {
|
|
647
|
+
console.error(`[ClaudeCodeSpawnProvider] Failed to spawn: ${getErrorMessage(error)}`);
|
|
503
648
|
if (tmpFile) {
|
|
504
649
|
try {
|
|
505
650
|
await unlink(tmpFile);
|
|
@@ -512,7 +657,8 @@ var init_spawn = __esm({
|
|
|
512
657
|
providerId: "claude-code",
|
|
513
658
|
status: "failed",
|
|
514
659
|
startTime,
|
|
515
|
-
endTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
660
|
+
endTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
661
|
+
error: getErrorMessage(error)
|
|
516
662
|
};
|
|
517
663
|
}
|
|
518
664
|
}
|
|
@@ -664,8 +810,8 @@ var init_transport = __esm({
|
|
|
664
810
|
// packages/adapters/src/providers/claude-code/adapter.js
|
|
665
811
|
import { exec as exec2 } from "node:child_process";
|
|
666
812
|
import { existsSync as existsSync3 } from "node:fs";
|
|
667
|
-
import { join as join5 } from "node:path";
|
|
668
813
|
import { homedir as homedir4 } from "node:os";
|
|
814
|
+
import { join as join5 } from "node:path";
|
|
669
815
|
import { promisify as promisify2 } from "node:util";
|
|
670
816
|
var execAsync2, ClaudeCodeAdapter;
|
|
671
817
|
var init_adapter = __esm({
|
|
@@ -892,45 +1038,36 @@ var init_claude_code = __esm({
|
|
|
892
1038
|
init_install();
|
|
893
1039
|
init_paths();
|
|
894
1040
|
init_spawn();
|
|
895
|
-
init_transport();
|
|
896
1041
|
init_statusline();
|
|
1042
|
+
init_transport();
|
|
897
1043
|
claude_code_default = ClaudeCodeAdapter;
|
|
898
1044
|
}
|
|
899
1045
|
});
|
|
900
1046
|
|
|
901
|
-
// packages/adapters/src/providers/
|
|
902
|
-
var
|
|
1047
|
+
// packages/adapters/src/providers/cursor/hooks.js
|
|
1048
|
+
var CursorHookProvider;
|
|
903
1049
|
var init_hooks2 = __esm({
|
|
904
|
-
"packages/adapters/src/providers/
|
|
1050
|
+
"packages/adapters/src/providers/cursor/hooks.js"() {
|
|
905
1051
|
"use strict";
|
|
906
|
-
|
|
907
|
-
"session.start": "onSessionStart",
|
|
908
|
-
"session.end": "onSessionEnd",
|
|
909
|
-
"tool.start": "onToolStart",
|
|
910
|
-
"tool.complete": "onToolComplete",
|
|
911
|
-
"error": "onError",
|
|
912
|
-
"prompt.submit": "onPromptSubmit"
|
|
913
|
-
};
|
|
914
|
-
OpenCodeHookProvider = class {
|
|
1052
|
+
CursorHookProvider = class {
|
|
915
1053
|
registered = false;
|
|
916
1054
|
/**
|
|
917
|
-
* Map
|
|
1055
|
+
* Map a provider event name to a CAAMP hook event name.
|
|
918
1056
|
*
|
|
919
|
-
*
|
|
920
|
-
*
|
|
1057
|
+
* Always returns null since Cursor does not emit hook events.
|
|
1058
|
+
*
|
|
1059
|
+
* @param _providerEvent - Ignored; Cursor has no hook events
|
|
1060
|
+
* @returns null (no mapping available)
|
|
921
1061
|
*/
|
|
922
|
-
mapProviderEvent(
|
|
923
|
-
return
|
|
1062
|
+
mapProviderEvent(_providerEvent) {
|
|
1063
|
+
return null;
|
|
924
1064
|
}
|
|
925
1065
|
/**
|
|
926
1066
|
* Register native hooks for a project.
|
|
927
1067
|
*
|
|
928
|
-
*
|
|
929
|
-
* (.opencode/config.json), which is handled by the install provider.
|
|
930
|
-
* This method marks hooks as registered without performing
|
|
931
|
-
* filesystem operations.
|
|
1068
|
+
* No-op for Cursor since it has no hook system.
|
|
932
1069
|
*
|
|
933
|
-
* @param _projectDir -
|
|
1070
|
+
* @param _projectDir - Ignored
|
|
934
1071
|
*/
|
|
935
1072
|
async registerNativeHooks(_projectDir) {
|
|
936
1073
|
this.registered = true;
|
|
@@ -938,45 +1075,34 @@ var init_hooks2 = __esm({
|
|
|
938
1075
|
/**
|
|
939
1076
|
* Unregister native hooks.
|
|
940
1077
|
*
|
|
941
|
-
*
|
|
942
|
-
* the config system. Unregistration happens via the install
|
|
943
|
-
* provider's uninstall method.
|
|
1078
|
+
* No-op for Cursor since it has no hook system.
|
|
944
1079
|
*/
|
|
945
1080
|
async unregisterNativeHooks() {
|
|
946
1081
|
this.registered = false;
|
|
947
1082
|
}
|
|
948
1083
|
/**
|
|
949
|
-
* Check whether hooks have been registered
|
|
1084
|
+
* Check whether hooks have been registered.
|
|
950
1085
|
*/
|
|
951
1086
|
isRegistered() {
|
|
952
1087
|
return this.registered;
|
|
953
1088
|
}
|
|
954
|
-
/**
|
|
955
|
-
* Get the full event mapping for introspection/debugging.
|
|
956
|
-
*/
|
|
957
|
-
getEventMap() {
|
|
958
|
-
return { ...OPENCODE_EVENT_MAP };
|
|
959
|
-
}
|
|
960
1089
|
};
|
|
961
1090
|
}
|
|
962
1091
|
});
|
|
963
1092
|
|
|
964
|
-
// packages/adapters/src/providers/
|
|
1093
|
+
// packages/adapters/src/providers/cursor/install.js
|
|
965
1094
|
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
966
1095
|
import { join as join7 } from "node:path";
|
|
967
|
-
var INSTRUCTION_REFERENCES2, MCP_SERVER_KEY2,
|
|
1096
|
+
var INSTRUCTION_REFERENCES2, MCP_SERVER_KEY2, CursorInstallProvider;
|
|
968
1097
|
var init_install2 = __esm({
|
|
969
|
-
"packages/adapters/src/providers/
|
|
1098
|
+
"packages/adapters/src/providers/cursor/install.js"() {
|
|
970
1099
|
"use strict";
|
|
971
|
-
INSTRUCTION_REFERENCES2 = [
|
|
972
|
-
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
973
|
-
"@.cleo/memory-bridge.md"
|
|
974
|
-
];
|
|
1100
|
+
INSTRUCTION_REFERENCES2 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
|
|
975
1101
|
MCP_SERVER_KEY2 = "cleo";
|
|
976
|
-
|
|
1102
|
+
CursorInstallProvider = class {
|
|
977
1103
|
installedProjectDir = null;
|
|
978
1104
|
/**
|
|
979
|
-
* Install CLEO into
|
|
1105
|
+
* Install CLEO into a Cursor project.
|
|
980
1106
|
*
|
|
981
1107
|
* @param options - Installation options including project directory and MCP server path
|
|
982
1108
|
* @returns Result describing what was installed
|
|
@@ -990,12 +1116,12 @@ var init_install2 = __esm({
|
|
|
990
1116
|
if (mcpServerPath) {
|
|
991
1117
|
mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
|
|
992
1118
|
if (mcpRegistered) {
|
|
993
|
-
details.mcpConfigPath = join7(projectDir, ".
|
|
1119
|
+
details.mcpConfigPath = join7(projectDir, ".cursor", "mcp.json");
|
|
994
1120
|
}
|
|
995
1121
|
}
|
|
996
|
-
instructionFileUpdated = this.
|
|
1122
|
+
instructionFileUpdated = this.updateInstructionFiles(projectDir);
|
|
997
1123
|
if (instructionFileUpdated) {
|
|
998
|
-
details.
|
|
1124
|
+
details.instructionFiles = this.getUpdatedFileList(projectDir);
|
|
999
1125
|
}
|
|
1000
1126
|
this.installedProjectDir = projectDir;
|
|
1001
1127
|
return {
|
|
@@ -1007,23 +1133,23 @@ var init_install2 = __esm({
|
|
|
1007
1133
|
};
|
|
1008
1134
|
}
|
|
1009
1135
|
/**
|
|
1010
|
-
* Uninstall CLEO from the current
|
|
1136
|
+
* Uninstall CLEO from the current Cursor project.
|
|
1011
1137
|
*
|
|
1012
|
-
* Removes the MCP server registration from .
|
|
1013
|
-
* Does not remove
|
|
1138
|
+
* Removes the MCP server registration from .cursor/mcp.json.
|
|
1139
|
+
* Does not remove instruction file references (they are harmless if CLEO is not present).
|
|
1014
1140
|
*/
|
|
1015
1141
|
async uninstall() {
|
|
1016
1142
|
if (!this.installedProjectDir)
|
|
1017
1143
|
return;
|
|
1018
|
-
const
|
|
1019
|
-
if (existsSync5(
|
|
1144
|
+
const mcpPath = join7(this.installedProjectDir, ".cursor", "mcp.json");
|
|
1145
|
+
if (existsSync5(mcpPath)) {
|
|
1020
1146
|
try {
|
|
1021
|
-
const raw = readFileSync4(
|
|
1147
|
+
const raw = readFileSync4(mcpPath, "utf-8");
|
|
1022
1148
|
const config = JSON.parse(raw);
|
|
1023
1149
|
const mcpServers = config.mcpServers;
|
|
1024
1150
|
if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
|
|
1025
1151
|
delete mcpServers[MCP_SERVER_KEY2];
|
|
1026
|
-
writeFileSync3(
|
|
1152
|
+
writeFileSync3(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1027
1153
|
}
|
|
1028
1154
|
} catch {
|
|
1029
1155
|
}
|
|
@@ -1033,14 +1159,13 @@ var init_install2 = __esm({
|
|
|
1033
1159
|
/**
|
|
1034
1160
|
* Check whether CLEO is installed in the current environment.
|
|
1035
1161
|
*
|
|
1036
|
-
* Checks for MCP server registered in .
|
|
1037
|
-
* Returns true if the CLEO MCP server entry is found.
|
|
1162
|
+
* Checks for MCP server registered in .cursor/mcp.json.
|
|
1038
1163
|
*/
|
|
1039
1164
|
async isInstalled() {
|
|
1040
|
-
const
|
|
1041
|
-
if (existsSync5(
|
|
1165
|
+
const mcpPath = join7(process.cwd(), ".cursor", "mcp.json");
|
|
1166
|
+
if (existsSync5(mcpPath)) {
|
|
1042
1167
|
try {
|
|
1043
|
-
const config = JSON.parse(readFileSync4(
|
|
1168
|
+
const config = JSON.parse(readFileSync4(mcpPath, "utf-8"));
|
|
1044
1169
|
const mcpServers = config.mcpServers;
|
|
1045
1170
|
if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
|
|
1046
1171
|
return true;
|
|
@@ -1051,31 +1176,31 @@ var init_install2 = __esm({
|
|
|
1051
1176
|
return false;
|
|
1052
1177
|
}
|
|
1053
1178
|
/**
|
|
1054
|
-
* Ensure
|
|
1179
|
+
* Ensure instruction files contain @-references to CLEO.
|
|
1055
1180
|
*
|
|
1056
|
-
*
|
|
1181
|
+
* Updates .cursorrules (legacy) and creates .cursor/rules/cleo.mdc (modern).
|
|
1057
1182
|
*
|
|
1058
1183
|
* @param projectDir - Project root directory
|
|
1059
1184
|
*/
|
|
1060
1185
|
async ensureInstructionReferences(projectDir) {
|
|
1061
|
-
this.
|
|
1186
|
+
this.updateInstructionFiles(projectDir);
|
|
1062
1187
|
}
|
|
1063
1188
|
/**
|
|
1064
|
-
* Register the CLEO MCP server in .
|
|
1189
|
+
* Register the CLEO MCP server in .cursor/mcp.json.
|
|
1065
1190
|
*
|
|
1066
|
-
*
|
|
1191
|
+
* Cursor stores MCP server configuration in .cursor/mcp.json
|
|
1067
1192
|
* under the mcpServers key.
|
|
1068
1193
|
*
|
|
1069
1194
|
* @returns true if registration was performed or updated
|
|
1070
1195
|
*/
|
|
1071
1196
|
registerMcpServer(projectDir, mcpServerPath) {
|
|
1072
|
-
const
|
|
1073
|
-
const
|
|
1197
|
+
const cursorDir = join7(projectDir, ".cursor");
|
|
1198
|
+
const mcpPath = join7(cursorDir, "mcp.json");
|
|
1074
1199
|
let config = {};
|
|
1075
|
-
mkdirSync2(
|
|
1076
|
-
if (existsSync5(
|
|
1200
|
+
mkdirSync2(cursorDir, { recursive: true });
|
|
1201
|
+
if (existsSync5(mcpPath)) {
|
|
1077
1202
|
try {
|
|
1078
|
-
config = JSON.parse(readFileSync4(
|
|
1203
|
+
config = JSON.parse(readFileSync4(mcpPath, "utf-8"));
|
|
1079
1204
|
} catch {
|
|
1080
1205
|
}
|
|
1081
1206
|
}
|
|
@@ -1087,250 +1212,114 @@ var init_install2 = __esm({
|
|
|
1087
1212
|
command: "node",
|
|
1088
1213
|
args: [mcpServerPath]
|
|
1089
1214
|
};
|
|
1090
|
-
writeFileSync3(
|
|
1215
|
+
writeFileSync3(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1091
1216
|
return true;
|
|
1092
1217
|
}
|
|
1093
1218
|
/**
|
|
1094
|
-
* Update
|
|
1219
|
+
* Update instruction files with CLEO @-references.
|
|
1095
1220
|
*
|
|
1096
|
-
*
|
|
1221
|
+
* Handles both legacy (.cursorrules) and modern (.cursor/rules/cleo.mdc) formats.
|
|
1222
|
+
*
|
|
1223
|
+
* @returns true if any file was created or modified
|
|
1097
1224
|
*/
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1225
|
+
updateInstructionFiles(projectDir) {
|
|
1226
|
+
let updated = false;
|
|
1227
|
+
if (this.updateLegacyRules(projectDir)) {
|
|
1228
|
+
updated = true;
|
|
1229
|
+
}
|
|
1230
|
+
if (this.updateModernRules(projectDir)) {
|
|
1231
|
+
updated = true;
|
|
1232
|
+
}
|
|
1233
|
+
return updated;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Update legacy .cursorrules file with @-references.
|
|
1237
|
+
* Only modifies the file if it already exists (does not create it).
|
|
1238
|
+
*
|
|
1239
|
+
* @returns true if the file was modified
|
|
1240
|
+
*/
|
|
1241
|
+
updateLegacyRules(projectDir) {
|
|
1242
|
+
const rulesPath = join7(projectDir, ".cursorrules");
|
|
1243
|
+
if (!existsSync5(rulesPath)) {
|
|
1244
|
+
return false;
|
|
1105
1245
|
}
|
|
1246
|
+
let content = readFileSync4(rulesPath, "utf-8");
|
|
1106
1247
|
const missingRefs = INSTRUCTION_REFERENCES2.filter((ref) => !content.includes(ref));
|
|
1107
1248
|
if (missingRefs.length === 0) {
|
|
1108
1249
|
return false;
|
|
1109
1250
|
}
|
|
1110
|
-
const
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1251
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
1252
|
+
content = content + separator + missingRefs.join("\n") + "\n";
|
|
1253
|
+
writeFileSync3(rulesPath, content, "utf-8");
|
|
1254
|
+
return true;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Create or update .cursor/rules/cleo.mdc with CLEO references.
|
|
1258
|
+
*
|
|
1259
|
+
* MDC (Markdown Component) format is Cursor's modern rule file format.
|
|
1260
|
+
* Each .mdc file in .cursor/rules/ is loaded as a rule set.
|
|
1261
|
+
*
|
|
1262
|
+
* @returns true if the file was created or modified
|
|
1263
|
+
*/
|
|
1264
|
+
updateModernRules(projectDir) {
|
|
1265
|
+
const rulesDir = join7(projectDir, ".cursor", "rules");
|
|
1266
|
+
const mdcPath = join7(rulesDir, "cleo.mdc");
|
|
1267
|
+
const expectedContent = [
|
|
1268
|
+
"---",
|
|
1269
|
+
"description: CLEO task management protocol references",
|
|
1270
|
+
'globs: "**/*"',
|
|
1271
|
+
"alwaysApply: true",
|
|
1272
|
+
"---",
|
|
1273
|
+
"",
|
|
1274
|
+
...INSTRUCTION_REFERENCES2,
|
|
1275
|
+
""
|
|
1276
|
+
].join("\n");
|
|
1277
|
+
if (existsSync5(mdcPath)) {
|
|
1278
|
+
const existing = readFileSync4(mdcPath, "utf-8");
|
|
1279
|
+
if (existing === expectedContent) {
|
|
1280
|
+
return false;
|
|
1281
|
+
}
|
|
1116
1282
|
}
|
|
1117
|
-
|
|
1283
|
+
mkdirSync2(rulesDir, { recursive: true });
|
|
1284
|
+
writeFileSync3(mdcPath, expectedContent, "utf-8");
|
|
1118
1285
|
return true;
|
|
1119
1286
|
}
|
|
1287
|
+
/**
|
|
1288
|
+
* Get list of instruction files that were updated.
|
|
1289
|
+
*/
|
|
1290
|
+
getUpdatedFileList(projectDir) {
|
|
1291
|
+
const files = [];
|
|
1292
|
+
if (existsSync5(join7(projectDir, ".cursorrules"))) {
|
|
1293
|
+
files.push(join7(projectDir, ".cursorrules"));
|
|
1294
|
+
}
|
|
1295
|
+
files.push(join7(projectDir, ".cursor", "rules", "cleo.mdc"));
|
|
1296
|
+
return files;
|
|
1297
|
+
}
|
|
1120
1298
|
};
|
|
1121
1299
|
}
|
|
1122
1300
|
});
|
|
1123
1301
|
|
|
1124
|
-
// packages/adapters/src/providers/
|
|
1125
|
-
import {
|
|
1126
|
-
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
1302
|
+
// packages/adapters/src/providers/cursor/adapter.js
|
|
1303
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
1127
1304
|
import { join as join8 } from "node:path";
|
|
1128
|
-
|
|
1129
|
-
function buildOpenCodeAgentMarkdown(description, instructions) {
|
|
1130
|
-
const normalizedDesc = description.replace(/\s+/g, " ").trim();
|
|
1131
|
-
return [
|
|
1132
|
-
"---",
|
|
1133
|
-
`description: ${JSON.stringify(normalizedDesc)}`,
|
|
1134
|
-
"mode: subagent",
|
|
1135
|
-
"hidden: true",
|
|
1136
|
-
"---",
|
|
1137
|
-
"",
|
|
1138
|
-
instructions.trim(),
|
|
1139
|
-
""
|
|
1140
|
-
].join("\n");
|
|
1141
|
-
}
|
|
1142
|
-
async function ensureSubagentDefinition(workingDirectory) {
|
|
1143
|
-
const agentDir = join8(workingDirectory, ".opencode", "agent");
|
|
1144
|
-
const agentPath = join8(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
|
|
1145
|
-
const description = "CLEO task executor with protocol compliance.";
|
|
1146
|
-
const instructions = [
|
|
1147
|
-
"# CLEO Subagent",
|
|
1148
|
-
"",
|
|
1149
|
-
"You are a CLEO subagent executing a delegated task.",
|
|
1150
|
-
"Follow the CLEO protocol and complete the assigned work.",
|
|
1151
|
-
"",
|
|
1152
|
-
"@~/.cleo/templates/CLEO-INJECTION.md"
|
|
1153
|
-
].join("\n");
|
|
1154
|
-
const content = buildOpenCodeAgentMarkdown(description, instructions);
|
|
1155
|
-
await mkdir2(agentDir, { recursive: true });
|
|
1156
|
-
let existing = null;
|
|
1157
|
-
try {
|
|
1158
|
-
existing = await readFile2(agentPath, "utf-8");
|
|
1159
|
-
} catch {
|
|
1160
|
-
existing = null;
|
|
1161
|
-
}
|
|
1162
|
-
if (existing !== content) {
|
|
1163
|
-
await writeFile2(agentPath, content, "utf-8");
|
|
1164
|
-
}
|
|
1165
|
-
return OPENCODE_SUBAGENT_NAME;
|
|
1166
|
-
}
|
|
1167
|
-
var execAsync3, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
|
|
1168
|
-
var init_spawn2 = __esm({
|
|
1169
|
-
"packages/adapters/src/providers/opencode/spawn.js"() {
|
|
1170
|
-
"use strict";
|
|
1171
|
-
execAsync3 = promisify3(exec3);
|
|
1172
|
-
OPENCODE_SUBAGENT_NAME = "cleo-subagent";
|
|
1173
|
-
OPENCODE_FALLBACK_AGENT = "general";
|
|
1174
|
-
OpenCodeSpawnProvider = class {
|
|
1175
|
-
/** Map of instance IDs to tracked process info. */
|
|
1176
|
-
processMap = /* @__PURE__ */ new Map();
|
|
1177
|
-
/**
|
|
1178
|
-
* Check if the OpenCode CLI is available in PATH.
|
|
1179
|
-
*
|
|
1180
|
-
* @returns true if `opencode` is found via `which`
|
|
1181
|
-
*/
|
|
1182
|
-
async canSpawn() {
|
|
1183
|
-
try {
|
|
1184
|
-
await execAsync3("which opencode");
|
|
1185
|
-
return true;
|
|
1186
|
-
} catch {
|
|
1187
|
-
return false;
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
/**
|
|
1191
|
-
* Spawn a subagent via OpenCode CLI.
|
|
1192
|
-
*
|
|
1193
|
-
* Ensures the CLEO subagent definition exists in the project's
|
|
1194
|
-
* .opencode/agent/ directory, then spawns a detached OpenCode
|
|
1195
|
-
* process. The process runs independently of the parent.
|
|
1196
|
-
*
|
|
1197
|
-
* @param context - Spawn context with taskId, prompt, and options
|
|
1198
|
-
* @returns Spawn result with instance ID and status
|
|
1199
|
-
*/
|
|
1200
|
-
async spawn(context) {
|
|
1201
|
-
const instanceId = `opencode-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1202
|
-
const startTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
1203
|
-
const workingDirectory = context.workingDirectory ?? process.cwd();
|
|
1204
|
-
try {
|
|
1205
|
-
let agentName;
|
|
1206
|
-
try {
|
|
1207
|
-
agentName = await ensureSubagentDefinition(workingDirectory);
|
|
1208
|
-
} catch {
|
|
1209
|
-
agentName = OPENCODE_FALLBACK_AGENT;
|
|
1210
|
-
}
|
|
1211
|
-
const child = nodeSpawn2("opencode", [
|
|
1212
|
-
"run",
|
|
1213
|
-
"--format",
|
|
1214
|
-
"json",
|
|
1215
|
-
"--agent",
|
|
1216
|
-
agentName,
|
|
1217
|
-
"--title",
|
|
1218
|
-
`CLEO ${context.taskId}`,
|
|
1219
|
-
context.prompt
|
|
1220
|
-
], {
|
|
1221
|
-
cwd: workingDirectory,
|
|
1222
|
-
detached: true,
|
|
1223
|
-
stdio: "ignore"
|
|
1224
|
-
});
|
|
1225
|
-
child.unref();
|
|
1226
|
-
if (child.pid) {
|
|
1227
|
-
this.processMap.set(instanceId, {
|
|
1228
|
-
pid: child.pid,
|
|
1229
|
-
taskId: context.taskId,
|
|
1230
|
-
startTime
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
child.on("exit", () => {
|
|
1234
|
-
this.processMap.delete(instanceId);
|
|
1235
|
-
});
|
|
1236
|
-
return {
|
|
1237
|
-
instanceId,
|
|
1238
|
-
taskId: context.taskId,
|
|
1239
|
-
providerId: "opencode",
|
|
1240
|
-
status: "running",
|
|
1241
|
-
startTime
|
|
1242
|
-
};
|
|
1243
|
-
} catch {
|
|
1244
|
-
return {
|
|
1245
|
-
instanceId,
|
|
1246
|
-
taskId: context.taskId,
|
|
1247
|
-
providerId: "opencode",
|
|
1248
|
-
status: "failed",
|
|
1249
|
-
startTime,
|
|
1250
|
-
endTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
/**
|
|
1255
|
-
* List currently running OpenCode subagent processes.
|
|
1256
|
-
*
|
|
1257
|
-
* Checks each tracked process via kill(pid, 0) to verify it is still alive.
|
|
1258
|
-
* Dead processes are automatically cleaned from the tracking map.
|
|
1259
|
-
*
|
|
1260
|
-
* @returns Array of spawn results for running processes
|
|
1261
|
-
*/
|
|
1262
|
-
async listRunning() {
|
|
1263
|
-
const running = [];
|
|
1264
|
-
for (const [instanceId, tracked] of this.processMap.entries()) {
|
|
1265
|
-
try {
|
|
1266
|
-
process.kill(tracked.pid, 0);
|
|
1267
|
-
running.push({
|
|
1268
|
-
instanceId,
|
|
1269
|
-
taskId: tracked.taskId,
|
|
1270
|
-
providerId: "opencode",
|
|
1271
|
-
status: "running",
|
|
1272
|
-
startTime: tracked.startTime
|
|
1273
|
-
});
|
|
1274
|
-
} catch {
|
|
1275
|
-
this.processMap.delete(instanceId);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
return running;
|
|
1279
|
-
}
|
|
1280
|
-
/**
|
|
1281
|
-
* Terminate a running spawn by instance ID.
|
|
1282
|
-
*
|
|
1283
|
-
* Sends SIGTERM to the tracked process. If the process is not found
|
|
1284
|
-
* or has already exited, this is a no-op.
|
|
1285
|
-
*
|
|
1286
|
-
* @param instanceId - ID of the spawn instance to terminate
|
|
1287
|
-
*/
|
|
1288
|
-
async terminate(instanceId) {
|
|
1289
|
-
const tracked = this.processMap.get(instanceId);
|
|
1290
|
-
if (!tracked)
|
|
1291
|
-
return;
|
|
1292
|
-
try {
|
|
1293
|
-
process.kill(tracked.pid, "SIGTERM");
|
|
1294
|
-
} catch {
|
|
1295
|
-
}
|
|
1296
|
-
this.processMap.delete(instanceId);
|
|
1297
|
-
}
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1300
|
-
});
|
|
1301
|
-
|
|
1302
|
-
// packages/adapters/src/providers/opencode/adapter.js
|
|
1303
|
-
import { exec as exec4 } from "node:child_process";
|
|
1304
|
-
import { existsSync as existsSync6 } from "node:fs";
|
|
1305
|
-
import { join as join9 } from "node:path";
|
|
1306
|
-
import { promisify as promisify4 } from "node:util";
|
|
1307
|
-
var execAsync4, OpenCodeAdapter;
|
|
1305
|
+
var CursorAdapter;
|
|
1308
1306
|
var init_adapter2 = __esm({
|
|
1309
|
-
"packages/adapters/src/providers/
|
|
1307
|
+
"packages/adapters/src/providers/cursor/adapter.js"() {
|
|
1310
1308
|
"use strict";
|
|
1311
1309
|
init_hooks2();
|
|
1312
1310
|
init_install2();
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
id = "opencode";
|
|
1317
|
-
name = "OpenCode";
|
|
1311
|
+
CursorAdapter = class {
|
|
1312
|
+
id = "cursor";
|
|
1313
|
+
name = "Cursor";
|
|
1318
1314
|
version = "1.0.0";
|
|
1319
1315
|
capabilities = {
|
|
1320
|
-
supportsHooks:
|
|
1321
|
-
supportedHookEvents: [
|
|
1322
|
-
|
|
1323
|
-
"onSessionEnd",
|
|
1324
|
-
"onToolStart",
|
|
1325
|
-
"onToolComplete",
|
|
1326
|
-
"onError",
|
|
1327
|
-
"onPromptSubmit"
|
|
1328
|
-
],
|
|
1329
|
-
supportsSpawn: true,
|
|
1316
|
+
supportsHooks: false,
|
|
1317
|
+
supportedHookEvents: [],
|
|
1318
|
+
supportsSpawn: false,
|
|
1330
1319
|
supportsInstall: true,
|
|
1331
1320
|
supportsMcp: true,
|
|
1332
1321
|
supportsInstructionFiles: true,
|
|
1333
|
-
instructionFilePattern: "
|
|
1322
|
+
instructionFilePattern: ".cursor/rules/*.mdc",
|
|
1334
1323
|
supportsContextMonitor: false,
|
|
1335
1324
|
supportsStatusline: false,
|
|
1336
1325
|
supportsProviderPaths: true,
|
|
@@ -1338,21 +1327,16 @@ var init_adapter2 = __esm({
|
|
|
1338
1327
|
supportsTaskSync: false
|
|
1339
1328
|
};
|
|
1340
1329
|
hooks;
|
|
1341
|
-
spawn;
|
|
1342
1330
|
install;
|
|
1343
1331
|
projectDir = null;
|
|
1344
1332
|
initialized = false;
|
|
1345
1333
|
constructor() {
|
|
1346
|
-
this.hooks = new
|
|
1347
|
-
this.
|
|
1348
|
-
this.install = new OpenCodeInstallProvider();
|
|
1334
|
+
this.hooks = new CursorHookProvider();
|
|
1335
|
+
this.install = new CursorInstallProvider();
|
|
1349
1336
|
}
|
|
1350
1337
|
/**
|
|
1351
1338
|
* Initialize the adapter for a given project directory.
|
|
1352
1339
|
*
|
|
1353
|
-
* Validates the environment by checking for the OpenCode CLI
|
|
1354
|
-
* and OpenCode configuration directory.
|
|
1355
|
-
*
|
|
1356
1340
|
* @param projectDir - Root directory of the project
|
|
1357
1341
|
*/
|
|
1358
1342
|
async initialize(projectDir) {
|
|
@@ -1361,8 +1345,6 @@ var init_adapter2 = __esm({
|
|
|
1361
1345
|
}
|
|
1362
1346
|
/**
|
|
1363
1347
|
* Dispose the adapter and clean up resources.
|
|
1364
|
-
*
|
|
1365
|
-
* Unregisters hooks and releases any tracked state.
|
|
1366
1348
|
*/
|
|
1367
1349
|
async dispose() {
|
|
1368
1350
|
if (this.hooks.isRegistered()) {
|
|
@@ -1372,12 +1354,12 @@ var init_adapter2 = __esm({
|
|
|
1372
1354
|
this.projectDir = null;
|
|
1373
1355
|
}
|
|
1374
1356
|
/**
|
|
1375
|
-
* Run a health check to verify
|
|
1357
|
+
* Run a health check to verify Cursor is accessible.
|
|
1376
1358
|
*
|
|
1377
1359
|
* Checks:
|
|
1378
1360
|
* 1. Adapter has been initialized
|
|
1379
|
-
* 2.
|
|
1380
|
-
* 3.
|
|
1361
|
+
* 2. .cursor/ configuration directory exists in the project
|
|
1362
|
+
* 3. CURSOR_EDITOR env var is set
|
|
1381
1363
|
*
|
|
1382
1364
|
* @returns Health status with details about each check
|
|
1383
1365
|
*/
|
|
@@ -1390,23 +1372,20 @@ var init_adapter2 = __esm({
|
|
|
1390
1372
|
details: { error: "Adapter not initialized" }
|
|
1391
1373
|
};
|
|
1392
1374
|
}
|
|
1393
|
-
let
|
|
1394
|
-
try {
|
|
1395
|
-
const { stdout } = await execAsync4("which opencode");
|
|
1396
|
-
cliAvailable = stdout.trim().length > 0;
|
|
1397
|
-
details.cliPath = stdout.trim();
|
|
1398
|
-
} catch {
|
|
1399
|
-
details.cliAvailable = false;
|
|
1400
|
-
}
|
|
1375
|
+
let configExists = false;
|
|
1401
1376
|
if (this.projectDir) {
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1377
|
+
const cursorConfigDir = join8(this.projectDir, ".cursor");
|
|
1378
|
+
configExists = existsSync6(cursorConfigDir);
|
|
1404
1379
|
details.configDirExists = configExists;
|
|
1405
1380
|
}
|
|
1406
|
-
const
|
|
1407
|
-
details.
|
|
1408
|
-
|
|
1409
|
-
|
|
1381
|
+
const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
|
|
1382
|
+
details.editorEnvSet = editorEnvSet;
|
|
1383
|
+
if (this.projectDir) {
|
|
1384
|
+
const legacyRulesExist = existsSync6(join8(this.projectDir, ".cursorrules"));
|
|
1385
|
+
details.legacyRulesExist = legacyRulesExist;
|
|
1386
|
+
}
|
|
1387
|
+
const healthy = configExists || editorEnvSet;
|
|
1388
|
+
details.detected = healthy;
|
|
1410
1389
|
return {
|
|
1411
1390
|
healthy,
|
|
1412
1391
|
provider: this.id,
|
|
@@ -1429,56 +1408,63 @@ var init_adapter2 = __esm({
|
|
|
1429
1408
|
}
|
|
1430
1409
|
});
|
|
1431
1410
|
|
|
1432
|
-
// packages/adapters/src/providers/
|
|
1433
|
-
var
|
|
1434
|
-
__export(
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
OpenCodeSpawnProvider: () => OpenCodeSpawnProvider,
|
|
1411
|
+
// packages/adapters/src/providers/cursor/index.js
|
|
1412
|
+
var cursor_exports = {};
|
|
1413
|
+
__export(cursor_exports, {
|
|
1414
|
+
CursorAdapter: () => CursorAdapter,
|
|
1415
|
+
CursorHookProvider: () => CursorHookProvider,
|
|
1416
|
+
CursorInstallProvider: () => CursorInstallProvider,
|
|
1439
1417
|
createAdapter: () => createAdapter2,
|
|
1440
|
-
default: () =>
|
|
1418
|
+
default: () => cursor_default
|
|
1441
1419
|
});
|
|
1442
1420
|
function createAdapter2() {
|
|
1443
|
-
return new
|
|
1421
|
+
return new CursorAdapter();
|
|
1444
1422
|
}
|
|
1445
|
-
var
|
|
1446
|
-
var
|
|
1447
|
-
"packages/adapters/src/providers/
|
|
1423
|
+
var cursor_default;
|
|
1424
|
+
var init_cursor = __esm({
|
|
1425
|
+
"packages/adapters/src/providers/cursor/index.js"() {
|
|
1448
1426
|
"use strict";
|
|
1449
1427
|
init_adapter2();
|
|
1450
1428
|
init_adapter2();
|
|
1451
1429
|
init_hooks2();
|
|
1452
|
-
init_spawn2();
|
|
1453
1430
|
init_install2();
|
|
1454
|
-
|
|
1431
|
+
cursor_default = CursorAdapter;
|
|
1455
1432
|
}
|
|
1456
1433
|
});
|
|
1457
1434
|
|
|
1458
|
-
// packages/adapters/src/providers/
|
|
1459
|
-
var
|
|
1435
|
+
// packages/adapters/src/providers/opencode/hooks.js
|
|
1436
|
+
var OPENCODE_EVENT_MAP, OpenCodeHookProvider;
|
|
1460
1437
|
var init_hooks3 = __esm({
|
|
1461
|
-
"packages/adapters/src/providers/
|
|
1438
|
+
"packages/adapters/src/providers/opencode/hooks.js"() {
|
|
1462
1439
|
"use strict";
|
|
1463
|
-
|
|
1440
|
+
OPENCODE_EVENT_MAP = {
|
|
1441
|
+
"session.start": "onSessionStart",
|
|
1442
|
+
"session.end": "onSessionEnd",
|
|
1443
|
+
"tool.start": "onToolStart",
|
|
1444
|
+
"tool.complete": "onToolComplete",
|
|
1445
|
+
error: "onError",
|
|
1446
|
+
"prompt.submit": "onPromptSubmit"
|
|
1447
|
+
};
|
|
1448
|
+
OpenCodeHookProvider = class {
|
|
1464
1449
|
registered = false;
|
|
1465
1450
|
/**
|
|
1466
|
-
* Map
|
|
1467
|
-
*
|
|
1468
|
-
* Always returns null since Cursor does not emit hook events.
|
|
1451
|
+
* Map an OpenCode native event name to a CAAMP hook event name.
|
|
1469
1452
|
*
|
|
1470
|
-
* @param
|
|
1471
|
-
* @returns null
|
|
1453
|
+
* @param providerEvent - OpenCode event name (e.g. "session.start", "tool.complete")
|
|
1454
|
+
* @returns CAAMP event name or null if unmapped
|
|
1472
1455
|
*/
|
|
1473
|
-
mapProviderEvent(
|
|
1474
|
-
return null;
|
|
1456
|
+
mapProviderEvent(providerEvent) {
|
|
1457
|
+
return OPENCODE_EVENT_MAP[providerEvent] ?? null;
|
|
1475
1458
|
}
|
|
1476
1459
|
/**
|
|
1477
1460
|
* Register native hooks for a project.
|
|
1478
1461
|
*
|
|
1479
|
-
*
|
|
1462
|
+
* For OpenCode, hooks are registered via the config system
|
|
1463
|
+
* (.opencode/config.json), which is handled by the install provider.
|
|
1464
|
+
* This method marks hooks as registered without performing
|
|
1465
|
+
* filesystem operations.
|
|
1480
1466
|
*
|
|
1481
|
-
* @param _projectDir -
|
|
1467
|
+
* @param _projectDir - Project directory (unused; config manages registration)
|
|
1482
1468
|
*/
|
|
1483
1469
|
async registerNativeHooks(_projectDir) {
|
|
1484
1470
|
this.registered = true;
|
|
@@ -1486,37 +1472,42 @@ var init_hooks3 = __esm({
|
|
|
1486
1472
|
/**
|
|
1487
1473
|
* Unregister native hooks.
|
|
1488
1474
|
*
|
|
1489
|
-
*
|
|
1475
|
+
* For OpenCode, this is a no-op since hooks are managed through
|
|
1476
|
+
* the config system. Unregistration happens via the install
|
|
1477
|
+
* provider's uninstall method.
|
|
1490
1478
|
*/
|
|
1491
1479
|
async unregisterNativeHooks() {
|
|
1492
1480
|
this.registered = false;
|
|
1493
1481
|
}
|
|
1494
1482
|
/**
|
|
1495
|
-
* Check whether hooks have been registered.
|
|
1483
|
+
* Check whether hooks have been registered via registerNativeHooks.
|
|
1496
1484
|
*/
|
|
1497
1485
|
isRegistered() {
|
|
1498
1486
|
return this.registered;
|
|
1499
1487
|
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Get the full event mapping for introspection/debugging.
|
|
1490
|
+
*/
|
|
1491
|
+
getEventMap() {
|
|
1492
|
+
return { ...OPENCODE_EVENT_MAP };
|
|
1493
|
+
}
|
|
1500
1494
|
};
|
|
1501
1495
|
}
|
|
1502
1496
|
});
|
|
1503
1497
|
|
|
1504
|
-
// packages/adapters/src/providers/
|
|
1498
|
+
// packages/adapters/src/providers/opencode/install.js
|
|
1505
1499
|
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1506
|
-
import { join as
|
|
1507
|
-
var INSTRUCTION_REFERENCES3, MCP_SERVER_KEY3,
|
|
1500
|
+
import { join as join9 } from "node:path";
|
|
1501
|
+
var INSTRUCTION_REFERENCES3, MCP_SERVER_KEY3, OpenCodeInstallProvider;
|
|
1508
1502
|
var init_install3 = __esm({
|
|
1509
|
-
"packages/adapters/src/providers/
|
|
1503
|
+
"packages/adapters/src/providers/opencode/install.js"() {
|
|
1510
1504
|
"use strict";
|
|
1511
|
-
INSTRUCTION_REFERENCES3 = [
|
|
1512
|
-
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
1513
|
-
"@.cleo/memory-bridge.md"
|
|
1514
|
-
];
|
|
1505
|
+
INSTRUCTION_REFERENCES3 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
|
|
1515
1506
|
MCP_SERVER_KEY3 = "cleo";
|
|
1516
|
-
|
|
1507
|
+
OpenCodeInstallProvider = class {
|
|
1517
1508
|
installedProjectDir = null;
|
|
1518
1509
|
/**
|
|
1519
|
-
* Install CLEO into
|
|
1510
|
+
* Install CLEO into an OpenCode project.
|
|
1520
1511
|
*
|
|
1521
1512
|
* @param options - Installation options including project directory and MCP server path
|
|
1522
1513
|
* @returns Result describing what was installed
|
|
@@ -1530,12 +1521,12 @@ var init_install3 = __esm({
|
|
|
1530
1521
|
if (mcpServerPath) {
|
|
1531
1522
|
mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
|
|
1532
1523
|
if (mcpRegistered) {
|
|
1533
|
-
details.mcpConfigPath =
|
|
1524
|
+
details.mcpConfigPath = join9(projectDir, ".opencode", "config.json");
|
|
1534
1525
|
}
|
|
1535
1526
|
}
|
|
1536
|
-
instructionFileUpdated = this.
|
|
1527
|
+
instructionFileUpdated = this.updateInstructionFile(projectDir);
|
|
1537
1528
|
if (instructionFileUpdated) {
|
|
1538
|
-
details.
|
|
1529
|
+
details.instructionFile = join9(projectDir, "AGENTS.md");
|
|
1539
1530
|
}
|
|
1540
1531
|
this.installedProjectDir = projectDir;
|
|
1541
1532
|
return {
|
|
@@ -1547,23 +1538,23 @@ var init_install3 = __esm({
|
|
|
1547
1538
|
};
|
|
1548
1539
|
}
|
|
1549
1540
|
/**
|
|
1550
|
-
* Uninstall CLEO from the current
|
|
1541
|
+
* Uninstall CLEO from the current OpenCode project.
|
|
1551
1542
|
*
|
|
1552
|
-
* Removes the MCP server registration from .
|
|
1553
|
-
* Does not remove
|
|
1543
|
+
* Removes the MCP server registration from .opencode/config.json.
|
|
1544
|
+
* Does not remove AGENTS.md references (they are harmless if CLEO is not present).
|
|
1554
1545
|
*/
|
|
1555
1546
|
async uninstall() {
|
|
1556
1547
|
if (!this.installedProjectDir)
|
|
1557
1548
|
return;
|
|
1558
|
-
const
|
|
1559
|
-
if (existsSync7(
|
|
1549
|
+
const configPath = join9(this.installedProjectDir, ".opencode", "config.json");
|
|
1550
|
+
if (existsSync7(configPath)) {
|
|
1560
1551
|
try {
|
|
1561
|
-
const raw = readFileSync5(
|
|
1552
|
+
const raw = readFileSync5(configPath, "utf-8");
|
|
1562
1553
|
const config = JSON.parse(raw);
|
|
1563
1554
|
const mcpServers = config.mcpServers;
|
|
1564
1555
|
if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
|
|
1565
1556
|
delete mcpServers[MCP_SERVER_KEY3];
|
|
1566
|
-
writeFileSync4(
|
|
1557
|
+
writeFileSync4(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1567
1558
|
}
|
|
1568
1559
|
} catch {
|
|
1569
1560
|
}
|
|
@@ -1573,13 +1564,14 @@ var init_install3 = __esm({
|
|
|
1573
1564
|
/**
|
|
1574
1565
|
* Check whether CLEO is installed in the current environment.
|
|
1575
1566
|
*
|
|
1576
|
-
* Checks for MCP server registered in .
|
|
1567
|
+
* Checks for MCP server registered in .opencode/config.json.
|
|
1568
|
+
* Returns true if the CLEO MCP server entry is found.
|
|
1577
1569
|
*/
|
|
1578
1570
|
async isInstalled() {
|
|
1579
|
-
const
|
|
1580
|
-
if (existsSync7(
|
|
1571
|
+
const configPath = join9(process.cwd(), ".opencode", "config.json");
|
|
1572
|
+
if (existsSync7(configPath)) {
|
|
1581
1573
|
try {
|
|
1582
|
-
const config = JSON.parse(readFileSync5(
|
|
1574
|
+
const config = JSON.parse(readFileSync5(configPath, "utf-8"));
|
|
1583
1575
|
const mcpServers = config.mcpServers;
|
|
1584
1576
|
if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
|
|
1585
1577
|
return true;
|
|
@@ -1590,31 +1582,31 @@ var init_install3 = __esm({
|
|
|
1590
1582
|
return false;
|
|
1591
1583
|
}
|
|
1592
1584
|
/**
|
|
1593
|
-
* Ensure
|
|
1585
|
+
* Ensure AGENTS.md contains @-references to CLEO instruction files.
|
|
1594
1586
|
*
|
|
1595
|
-
*
|
|
1587
|
+
* Creates AGENTS.md if it does not exist. Appends any missing references.
|
|
1596
1588
|
*
|
|
1597
1589
|
* @param projectDir - Project root directory
|
|
1598
1590
|
*/
|
|
1599
1591
|
async ensureInstructionReferences(projectDir) {
|
|
1600
|
-
this.
|
|
1592
|
+
this.updateInstructionFile(projectDir);
|
|
1601
1593
|
}
|
|
1602
1594
|
/**
|
|
1603
|
-
* Register the CLEO MCP server in .
|
|
1595
|
+
* Register the CLEO MCP server in .opencode/config.json.
|
|
1604
1596
|
*
|
|
1605
|
-
*
|
|
1597
|
+
* OpenCode stores its MCP server configuration in .opencode/config.json
|
|
1606
1598
|
* under the mcpServers key.
|
|
1607
1599
|
*
|
|
1608
1600
|
* @returns true if registration was performed or updated
|
|
1609
1601
|
*/
|
|
1610
1602
|
registerMcpServer(projectDir, mcpServerPath) {
|
|
1611
|
-
const
|
|
1612
|
-
const
|
|
1603
|
+
const openCodeDir = join9(projectDir, ".opencode");
|
|
1604
|
+
const configPath = join9(openCodeDir, "config.json");
|
|
1613
1605
|
let config = {};
|
|
1614
|
-
mkdirSync3(
|
|
1615
|
-
if (existsSync7(
|
|
1606
|
+
mkdirSync3(openCodeDir, { recursive: true });
|
|
1607
|
+
if (existsSync7(configPath)) {
|
|
1616
1608
|
try {
|
|
1617
|
-
config = JSON.parse(readFileSync5(
|
|
1609
|
+
config = JSON.parse(readFileSync5(configPath, "utf-8"));
|
|
1618
1610
|
} catch {
|
|
1619
1611
|
}
|
|
1620
1612
|
}
|
|
@@ -1626,114 +1618,250 @@ var init_install3 = __esm({
|
|
|
1626
1618
|
command: "node",
|
|
1627
1619
|
args: [mcpServerPath]
|
|
1628
1620
|
};
|
|
1629
|
-
writeFileSync4(
|
|
1621
|
+
writeFileSync4(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1630
1622
|
return true;
|
|
1631
1623
|
}
|
|
1632
1624
|
/**
|
|
1633
|
-
* Update
|
|
1634
|
-
*
|
|
1635
|
-
* Handles both legacy (.cursorrules) and modern (.cursor/rules/cleo.mdc) formats.
|
|
1625
|
+
* Update AGENTS.md with CLEO @-references.
|
|
1636
1626
|
*
|
|
1637
|
-
* @returns true if
|
|
1627
|
+
* @returns true if the file was created or modified
|
|
1638
1628
|
*/
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1629
|
+
updateInstructionFile(projectDir) {
|
|
1630
|
+
const agentsMdPath = join9(projectDir, "AGENTS.md");
|
|
1631
|
+
let content = "";
|
|
1632
|
+
let existed = false;
|
|
1633
|
+
if (existsSync7(agentsMdPath)) {
|
|
1634
|
+
content = readFileSync5(agentsMdPath, "utf-8");
|
|
1635
|
+
existed = true;
|
|
1643
1636
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1637
|
+
const missingRefs = INSTRUCTION_REFERENCES3.filter((ref) => !content.includes(ref));
|
|
1638
|
+
if (missingRefs.length === 0) {
|
|
1639
|
+
return false;
|
|
1646
1640
|
}
|
|
1647
|
-
|
|
1641
|
+
const refsBlock = missingRefs.join("\n");
|
|
1642
|
+
if (existed) {
|
|
1643
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
1644
|
+
content = content + separator + refsBlock + "\n";
|
|
1645
|
+
} else {
|
|
1646
|
+
content = refsBlock + "\n";
|
|
1647
|
+
}
|
|
1648
|
+
writeFileSync4(agentsMdPath, content, "utf-8");
|
|
1649
|
+
return true;
|
|
1648
1650
|
}
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
// packages/adapters/src/providers/opencode/spawn.js
|
|
1656
|
+
import { exec as exec3, spawn as nodeSpawn2 } from "node:child_process";
|
|
1657
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
1658
|
+
import { join as join10 } from "node:path";
|
|
1659
|
+
import { promisify as promisify3 } from "node:util";
|
|
1660
|
+
function buildOpenCodeAgentMarkdown(description, instructions) {
|
|
1661
|
+
const normalizedDesc = description.replace(/\s+/g, " ").trim();
|
|
1662
|
+
return [
|
|
1663
|
+
"---",
|
|
1664
|
+
`description: ${JSON.stringify(normalizedDesc)}`,
|
|
1665
|
+
"mode: subagent",
|
|
1666
|
+
"hidden: true",
|
|
1667
|
+
"---",
|
|
1668
|
+
"",
|
|
1669
|
+
instructions.trim(),
|
|
1670
|
+
""
|
|
1671
|
+
].join("\n");
|
|
1672
|
+
}
|
|
1673
|
+
async function ensureSubagentDefinition(workingDirectory) {
|
|
1674
|
+
const agentDir = join10(workingDirectory, ".opencode", "agent");
|
|
1675
|
+
const agentPath = join10(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
|
|
1676
|
+
const description = "CLEO task executor with protocol compliance.";
|
|
1677
|
+
const instructions = [
|
|
1678
|
+
"# CLEO Subagent",
|
|
1679
|
+
"",
|
|
1680
|
+
"You are a CLEO subagent executing a delegated task.",
|
|
1681
|
+
"Follow the CLEO protocol and complete the assigned work.",
|
|
1682
|
+
"",
|
|
1683
|
+
"@~/.cleo/templates/CLEO-INJECTION.md"
|
|
1684
|
+
].join("\n");
|
|
1685
|
+
const content = buildOpenCodeAgentMarkdown(description, instructions);
|
|
1686
|
+
await mkdir2(agentDir, { recursive: true });
|
|
1687
|
+
let existing = null;
|
|
1688
|
+
try {
|
|
1689
|
+
existing = await readFile2(agentPath, "utf-8");
|
|
1690
|
+
} catch {
|
|
1691
|
+
existing = null;
|
|
1692
|
+
}
|
|
1693
|
+
if (existing !== content) {
|
|
1694
|
+
await writeFile2(agentPath, content, "utf-8");
|
|
1695
|
+
}
|
|
1696
|
+
return OPENCODE_SUBAGENT_NAME;
|
|
1697
|
+
}
|
|
1698
|
+
var execAsync3, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
|
|
1699
|
+
var init_spawn2 = __esm({
|
|
1700
|
+
"packages/adapters/src/providers/opencode/spawn.js"() {
|
|
1701
|
+
"use strict";
|
|
1702
|
+
execAsync3 = promisify3(exec3);
|
|
1703
|
+
OPENCODE_SUBAGENT_NAME = "cleo-subagent";
|
|
1704
|
+
OPENCODE_FALLBACK_AGENT = "general";
|
|
1705
|
+
OpenCodeSpawnProvider = class {
|
|
1706
|
+
/** Map of instance IDs to tracked process info. */
|
|
1707
|
+
processMap = /* @__PURE__ */ new Map();
|
|
1649
1708
|
/**
|
|
1650
|
-
*
|
|
1651
|
-
* Only modifies the file if it already exists (does not create it).
|
|
1709
|
+
* Check if the OpenCode CLI is available in PATH.
|
|
1652
1710
|
*
|
|
1653
|
-
* @returns true if
|
|
1711
|
+
* @returns true if `opencode` is found via `which`
|
|
1654
1712
|
*/
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1713
|
+
async canSpawn() {
|
|
1714
|
+
try {
|
|
1715
|
+
await execAsync3("which opencode");
|
|
1716
|
+
return true;
|
|
1717
|
+
} catch {
|
|
1658
1718
|
return false;
|
|
1659
1719
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* Spawn a subagent via OpenCode CLI.
|
|
1723
|
+
*
|
|
1724
|
+
* Ensures the CLEO subagent definition exists in the project's
|
|
1725
|
+
* .opencode/agent/ directory, then spawns a detached OpenCode
|
|
1726
|
+
* process. The process runs independently of the parent.
|
|
1727
|
+
*
|
|
1728
|
+
* @param context - Spawn context with taskId, prompt, and options
|
|
1729
|
+
* @returns Spawn result with instance ID and status
|
|
1730
|
+
*/
|
|
1731
|
+
async spawn(context) {
|
|
1732
|
+
const instanceId = `opencode-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1733
|
+
const startTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
1734
|
+
const workingDirectory = context.workingDirectory ?? process.cwd();
|
|
1735
|
+
try {
|
|
1736
|
+
let agentName;
|
|
1737
|
+
try {
|
|
1738
|
+
agentName = await ensureSubagentDefinition(workingDirectory);
|
|
1739
|
+
} catch {
|
|
1740
|
+
agentName = OPENCODE_FALLBACK_AGENT;
|
|
1741
|
+
}
|
|
1742
|
+
const child = nodeSpawn2("opencode", [
|
|
1743
|
+
"run",
|
|
1744
|
+
"--format",
|
|
1745
|
+
"json",
|
|
1746
|
+
"--agent",
|
|
1747
|
+
agentName,
|
|
1748
|
+
"--title",
|
|
1749
|
+
`CLEO ${context.taskId}`,
|
|
1750
|
+
context.prompt
|
|
1751
|
+
], {
|
|
1752
|
+
cwd: workingDirectory,
|
|
1753
|
+
detached: true,
|
|
1754
|
+
stdio: "ignore"
|
|
1755
|
+
});
|
|
1756
|
+
child.unref();
|
|
1757
|
+
if (child.pid) {
|
|
1758
|
+
this.processMap.set(instanceId, {
|
|
1759
|
+
pid: child.pid,
|
|
1760
|
+
taskId: context.taskId,
|
|
1761
|
+
startTime
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1764
|
+
child.on("exit", () => {
|
|
1765
|
+
this.processMap.delete(instanceId);
|
|
1766
|
+
});
|
|
1767
|
+
return {
|
|
1768
|
+
instanceId,
|
|
1769
|
+
taskId: context.taskId,
|
|
1770
|
+
providerId: "opencode",
|
|
1771
|
+
status: "running",
|
|
1772
|
+
startTime
|
|
1773
|
+
};
|
|
1774
|
+
} catch {
|
|
1775
|
+
return {
|
|
1776
|
+
instanceId,
|
|
1777
|
+
taskId: context.taskId,
|
|
1778
|
+
providerId: "opencode",
|
|
1779
|
+
status: "failed",
|
|
1780
|
+
startTime,
|
|
1781
|
+
endTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
1782
|
+
};
|
|
1664
1783
|
}
|
|
1665
|
-
const separator = content.endsWith("\n") ? "" : "\n";
|
|
1666
|
-
content = content + separator + missingRefs.join("\n") + "\n";
|
|
1667
|
-
writeFileSync4(rulesPath, content, "utf-8");
|
|
1668
|
-
return true;
|
|
1669
1784
|
}
|
|
1670
1785
|
/**
|
|
1671
|
-
*
|
|
1786
|
+
* List currently running OpenCode subagent processes.
|
|
1672
1787
|
*
|
|
1673
|
-
*
|
|
1674
|
-
*
|
|
1788
|
+
* Checks each tracked process via kill(pid, 0) to verify it is still alive.
|
|
1789
|
+
* Dead processes are automatically cleaned from the tracking map.
|
|
1675
1790
|
*
|
|
1676
|
-
* @returns
|
|
1791
|
+
* @returns Array of spawn results for running processes
|
|
1677
1792
|
*/
|
|
1678
|
-
|
|
1679
|
-
const
|
|
1680
|
-
const
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
const existing = readFileSync5(mdcPath, "utf-8");
|
|
1693
|
-
if (existing === expectedContent) {
|
|
1694
|
-
return false;
|
|
1793
|
+
async listRunning() {
|
|
1794
|
+
const running = [];
|
|
1795
|
+
for (const [instanceId, tracked] of this.processMap.entries()) {
|
|
1796
|
+
try {
|
|
1797
|
+
process.kill(tracked.pid, 0);
|
|
1798
|
+
running.push({
|
|
1799
|
+
instanceId,
|
|
1800
|
+
taskId: tracked.taskId,
|
|
1801
|
+
providerId: "opencode",
|
|
1802
|
+
status: "running",
|
|
1803
|
+
startTime: tracked.startTime
|
|
1804
|
+
});
|
|
1805
|
+
} catch {
|
|
1806
|
+
this.processMap.delete(instanceId);
|
|
1695
1807
|
}
|
|
1696
1808
|
}
|
|
1697
|
-
|
|
1698
|
-
writeFileSync4(mdcPath, expectedContent, "utf-8");
|
|
1699
|
-
return true;
|
|
1809
|
+
return running;
|
|
1700
1810
|
}
|
|
1701
1811
|
/**
|
|
1702
|
-
*
|
|
1812
|
+
* Terminate a running spawn by instance ID.
|
|
1813
|
+
*
|
|
1814
|
+
* Sends SIGTERM to the tracked process. If the process is not found
|
|
1815
|
+
* or has already exited, this is a no-op.
|
|
1816
|
+
*
|
|
1817
|
+
* @param instanceId - ID of the spawn instance to terminate
|
|
1703
1818
|
*/
|
|
1704
|
-
|
|
1705
|
-
const
|
|
1706
|
-
if (
|
|
1707
|
-
|
|
1819
|
+
async terminate(instanceId) {
|
|
1820
|
+
const tracked = this.processMap.get(instanceId);
|
|
1821
|
+
if (!tracked)
|
|
1822
|
+
return;
|
|
1823
|
+
try {
|
|
1824
|
+
process.kill(tracked.pid, "SIGTERM");
|
|
1825
|
+
} catch {
|
|
1708
1826
|
}
|
|
1709
|
-
|
|
1710
|
-
return files;
|
|
1827
|
+
this.processMap.delete(instanceId);
|
|
1711
1828
|
}
|
|
1712
1829
|
};
|
|
1713
1830
|
}
|
|
1714
1831
|
});
|
|
1715
1832
|
|
|
1716
|
-
// packages/adapters/src/providers/
|
|
1833
|
+
// packages/adapters/src/providers/opencode/adapter.js
|
|
1834
|
+
import { exec as exec4 } from "node:child_process";
|
|
1717
1835
|
import { existsSync as existsSync8 } from "node:fs";
|
|
1718
1836
|
import { join as join11 } from "node:path";
|
|
1719
|
-
|
|
1837
|
+
import { promisify as promisify4 } from "node:util";
|
|
1838
|
+
var execAsync4, OpenCodeAdapter;
|
|
1720
1839
|
var init_adapter3 = __esm({
|
|
1721
|
-
"packages/adapters/src/providers/
|
|
1840
|
+
"packages/adapters/src/providers/opencode/adapter.js"() {
|
|
1722
1841
|
"use strict";
|
|
1723
1842
|
init_hooks3();
|
|
1724
1843
|
init_install3();
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1844
|
+
init_spawn2();
|
|
1845
|
+
execAsync4 = promisify4(exec4);
|
|
1846
|
+
OpenCodeAdapter = class {
|
|
1847
|
+
id = "opencode";
|
|
1848
|
+
name = "OpenCode";
|
|
1728
1849
|
version = "1.0.0";
|
|
1729
1850
|
capabilities = {
|
|
1730
|
-
supportsHooks:
|
|
1731
|
-
supportedHookEvents: [
|
|
1732
|
-
|
|
1851
|
+
supportsHooks: true,
|
|
1852
|
+
supportedHookEvents: [
|
|
1853
|
+
"onSessionStart",
|
|
1854
|
+
"onSessionEnd",
|
|
1855
|
+
"onToolStart",
|
|
1856
|
+
"onToolComplete",
|
|
1857
|
+
"onError",
|
|
1858
|
+
"onPromptSubmit"
|
|
1859
|
+
],
|
|
1860
|
+
supportsSpawn: true,
|
|
1733
1861
|
supportsInstall: true,
|
|
1734
1862
|
supportsMcp: true,
|
|
1735
1863
|
supportsInstructionFiles: true,
|
|
1736
|
-
instructionFilePattern: ".
|
|
1864
|
+
instructionFilePattern: "AGENTS.md",
|
|
1737
1865
|
supportsContextMonitor: false,
|
|
1738
1866
|
supportsStatusline: false,
|
|
1739
1867
|
supportsProviderPaths: true,
|
|
@@ -1741,16 +1869,21 @@ var init_adapter3 = __esm({
|
|
|
1741
1869
|
supportsTaskSync: false
|
|
1742
1870
|
};
|
|
1743
1871
|
hooks;
|
|
1872
|
+
spawn;
|
|
1744
1873
|
install;
|
|
1745
1874
|
projectDir = null;
|
|
1746
1875
|
initialized = false;
|
|
1747
1876
|
constructor() {
|
|
1748
|
-
this.hooks = new
|
|
1749
|
-
this.
|
|
1877
|
+
this.hooks = new OpenCodeHookProvider();
|
|
1878
|
+
this.spawn = new OpenCodeSpawnProvider();
|
|
1879
|
+
this.install = new OpenCodeInstallProvider();
|
|
1750
1880
|
}
|
|
1751
1881
|
/**
|
|
1752
1882
|
* Initialize the adapter for a given project directory.
|
|
1753
1883
|
*
|
|
1884
|
+
* Validates the environment by checking for the OpenCode CLI
|
|
1885
|
+
* and OpenCode configuration directory.
|
|
1886
|
+
*
|
|
1754
1887
|
* @param projectDir - Root directory of the project
|
|
1755
1888
|
*/
|
|
1756
1889
|
async initialize(projectDir) {
|
|
@@ -1759,6 +1892,8 @@ var init_adapter3 = __esm({
|
|
|
1759
1892
|
}
|
|
1760
1893
|
/**
|
|
1761
1894
|
* Dispose the adapter and clean up resources.
|
|
1895
|
+
*
|
|
1896
|
+
* Unregisters hooks and releases any tracked state.
|
|
1762
1897
|
*/
|
|
1763
1898
|
async dispose() {
|
|
1764
1899
|
if (this.hooks.isRegistered()) {
|
|
@@ -1768,12 +1903,12 @@ var init_adapter3 = __esm({
|
|
|
1768
1903
|
this.projectDir = null;
|
|
1769
1904
|
}
|
|
1770
1905
|
/**
|
|
1771
|
-
* Run a health check to verify
|
|
1906
|
+
* Run a health check to verify OpenCode is accessible.
|
|
1772
1907
|
*
|
|
1773
1908
|
* Checks:
|
|
1774
1909
|
* 1. Adapter has been initialized
|
|
1775
|
-
* 2.
|
|
1776
|
-
* 3.
|
|
1910
|
+
* 2. OpenCode CLI is available in PATH
|
|
1911
|
+
* 3. .opencode/ configuration directory exists in the project
|
|
1777
1912
|
*
|
|
1778
1913
|
* @returns Health status with details about each check
|
|
1779
1914
|
*/
|
|
@@ -1786,20 +1921,23 @@ var init_adapter3 = __esm({
|
|
|
1786
1921
|
details: { error: "Adapter not initialized" }
|
|
1787
1922
|
};
|
|
1788
1923
|
}
|
|
1789
|
-
let
|
|
1790
|
-
|
|
1791
|
-
const
|
|
1792
|
-
|
|
1793
|
-
details.
|
|
1924
|
+
let cliAvailable = false;
|
|
1925
|
+
try {
|
|
1926
|
+
const { stdout } = await execAsync4("which opencode");
|
|
1927
|
+
cliAvailable = stdout.trim().length > 0;
|
|
1928
|
+
details.cliPath = stdout.trim();
|
|
1929
|
+
} catch {
|
|
1930
|
+
details.cliAvailable = false;
|
|
1794
1931
|
}
|
|
1795
|
-
const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
|
|
1796
|
-
details.editorEnvSet = editorEnvSet;
|
|
1797
1932
|
if (this.projectDir) {
|
|
1798
|
-
const
|
|
1799
|
-
|
|
1933
|
+
const openCodeConfigDir = join11(this.projectDir, ".opencode");
|
|
1934
|
+
const configExists = existsSync8(openCodeConfigDir);
|
|
1935
|
+
details.configDirExists = configExists;
|
|
1800
1936
|
}
|
|
1801
|
-
const
|
|
1802
|
-
details.
|
|
1937
|
+
const versionEnvSet = process.env.OPENCODE_VERSION !== void 0;
|
|
1938
|
+
details.versionEnvSet = versionEnvSet;
|
|
1939
|
+
const healthy = cliAvailable;
|
|
1940
|
+
details.cliAvailable = cliAvailable;
|
|
1803
1941
|
return {
|
|
1804
1942
|
healthy,
|
|
1805
1943
|
provider: this.id,
|
|
@@ -1822,30 +1960,37 @@ var init_adapter3 = __esm({
|
|
|
1822
1960
|
}
|
|
1823
1961
|
});
|
|
1824
1962
|
|
|
1825
|
-
// packages/adapters/src/providers/
|
|
1826
|
-
var
|
|
1827
|
-
__export(
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1963
|
+
// packages/adapters/src/providers/opencode/index.js
|
|
1964
|
+
var opencode_exports = {};
|
|
1965
|
+
__export(opencode_exports, {
|
|
1966
|
+
OpenCodeAdapter: () => OpenCodeAdapter,
|
|
1967
|
+
OpenCodeHookProvider: () => OpenCodeHookProvider,
|
|
1968
|
+
OpenCodeInstallProvider: () => OpenCodeInstallProvider,
|
|
1969
|
+
OpenCodeSpawnProvider: () => OpenCodeSpawnProvider,
|
|
1831
1970
|
createAdapter: () => createAdapter3,
|
|
1832
|
-
default: () =>
|
|
1971
|
+
default: () => opencode_default
|
|
1833
1972
|
});
|
|
1834
1973
|
function createAdapter3() {
|
|
1835
|
-
return new
|
|
1974
|
+
return new OpenCodeAdapter();
|
|
1836
1975
|
}
|
|
1837
|
-
var
|
|
1838
|
-
var
|
|
1839
|
-
"packages/adapters/src/providers/
|
|
1976
|
+
var opencode_default;
|
|
1977
|
+
var init_opencode = __esm({
|
|
1978
|
+
"packages/adapters/src/providers/opencode/index.js"() {
|
|
1840
1979
|
"use strict";
|
|
1841
1980
|
init_adapter3();
|
|
1842
1981
|
init_adapter3();
|
|
1843
1982
|
init_hooks3();
|
|
1844
1983
|
init_install3();
|
|
1845
|
-
|
|
1984
|
+
init_spawn2();
|
|
1985
|
+
opencode_default = OpenCodeAdapter;
|
|
1846
1986
|
}
|
|
1847
1987
|
});
|
|
1848
1988
|
|
|
1989
|
+
// packages/adapters/src/index.ts
|
|
1990
|
+
init_claude_code();
|
|
1991
|
+
init_cursor();
|
|
1992
|
+
init_opencode();
|
|
1993
|
+
|
|
1849
1994
|
// packages/adapters/src/registry.js
|
|
1850
1995
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
1851
1996
|
import { dirname as dirname2, join as join12, resolve } from "node:path";
|
|
@@ -1880,26 +2025,6 @@ async function discoverProviders() {
|
|
|
1880
2025
|
});
|
|
1881
2026
|
return providers;
|
|
1882
2027
|
}
|
|
1883
|
-
|
|
1884
|
-
// packages/adapters/src/index.ts
|
|
1885
|
-
init_claude_code();
|
|
1886
|
-
init_claude_code();
|
|
1887
|
-
init_claude_code();
|
|
1888
|
-
init_claude_code();
|
|
1889
|
-
init_claude_code();
|
|
1890
|
-
init_claude_code();
|
|
1891
|
-
init_claude_code();
|
|
1892
|
-
init_claude_code();
|
|
1893
|
-
init_opencode();
|
|
1894
|
-
init_opencode();
|
|
1895
|
-
init_opencode();
|
|
1896
|
-
init_opencode();
|
|
1897
|
-
init_cursor();
|
|
1898
|
-
init_cursor();
|
|
1899
|
-
init_cursor();
|
|
1900
|
-
init_claude_code();
|
|
1901
|
-
init_opencode();
|
|
1902
|
-
init_cursor();
|
|
1903
2028
|
export {
|
|
1904
2029
|
ClaudeCodeAdapter,
|
|
1905
2030
|
ClaudeCodeContextMonitorProvider,
|
|
@@ -1917,8 +2042,8 @@ export {
|
|
|
1917
2042
|
OpenCodeSpawnProvider,
|
|
1918
2043
|
checkStatuslineIntegration,
|
|
1919
2044
|
createAdapter as createClaudeCodeAdapter,
|
|
1920
|
-
|
|
1921
|
-
|
|
2045
|
+
createAdapter2 as createCursorAdapter,
|
|
2046
|
+
createAdapter3 as createOpenCodeAdapter,
|
|
1922
2047
|
discoverProviders,
|
|
1923
2048
|
getProviderManifests,
|
|
1924
2049
|
getSetupInstructions,
|