@wipcomputer/wip-ldm-os 0.2.13 → 0.3.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/SKILL.md +1 -1
- package/bin/ldm.js +242 -0
- package/dist/bridge/chunk-KWGJCDGS.js +424 -0
- package/dist/bridge/cli.d.ts +1 -0
- package/dist/bridge/cli.js +215 -0
- package/dist/bridge/core.d.ts +74 -0
- package/dist/bridge/core.js +40 -0
- package/dist/bridge/mcp-server.d.ts +2 -0
- package/dist/bridge/mcp-server.js +284 -0
- package/docs/TECHNICAL.md +290 -0
- package/docs/acp-compatibility.md +30 -0
- package/docs/optional-skills.md +77 -0
- package/docs/recall.md +29 -0
- package/docs/shared-workspace.md +37 -0
- package/docs/system-pulse.md +26 -0
- package/docs/universal-installer.md +84 -0
- package/lib/messages.mjs +195 -0
- package/lib/sessions.mjs +145 -0
- package/lib/updates.mjs +173 -0
- package/package.json +9 -2
- package/src/boot/boot-hook.mjs +36 -1
- package/src/bridge/cli.ts +245 -0
- package/src/bridge/core.ts +622 -0
- package/src/bridge/mcp-server.ts +371 -0
- package/src/bridge/package.json +18 -0
- package/src/bridge/tsconfig.json +19 -0
- package/src/cron/update-check.mjs +28 -0
- package/src/hooks/stop-hook.mjs +24 -0
package/SKILL.md
CHANGED
package/bin/ldm.js
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* ldm install Install/update all registered components
|
|
10
10
|
* ldm doctor Check health of all extensions
|
|
11
11
|
* ldm status Show LDM OS version and extension count
|
|
12
|
+
* ldm sessions List active sessions
|
|
13
|
+
* ldm msg send <to> <b> Send a message to a session
|
|
14
|
+
* ldm msg list List pending messages
|
|
15
|
+
* ldm msg broadcast <b> Send to all sessions
|
|
16
|
+
* ldm updates Show available updates
|
|
12
17
|
* ldm --version Show version
|
|
13
18
|
*/
|
|
14
19
|
|
|
@@ -47,6 +52,8 @@ const JSON_OUTPUT = args.includes('--json');
|
|
|
47
52
|
const YES_FLAG = args.includes('--yes') || args.includes('-y');
|
|
48
53
|
const NONE_FLAG = args.includes('--none');
|
|
49
54
|
const FIX_FLAG = args.includes('--fix');
|
|
55
|
+
const CLEANUP_FLAG = args.includes('--cleanup');
|
|
56
|
+
const CHECK_FLAG = args.includes('--check');
|
|
50
57
|
|
|
51
58
|
function readJSON(path) {
|
|
52
59
|
try {
|
|
@@ -83,7 +90,10 @@ async function cmdInit() {
|
|
|
83
90
|
join(LDM_ROOT, 'agents'),
|
|
84
91
|
join(LDM_ROOT, 'memory'),
|
|
85
92
|
join(LDM_ROOT, 'state'),
|
|
93
|
+
join(LDM_ROOT, 'sessions'),
|
|
94
|
+
join(LDM_ROOT, 'messages'),
|
|
86
95
|
join(LDM_ROOT, 'shared', 'boot'),
|
|
96
|
+
join(LDM_ROOT, 'shared', 'cron'),
|
|
87
97
|
];
|
|
88
98
|
|
|
89
99
|
const existing = existsSync(VERSION_PATH);
|
|
@@ -636,6 +646,8 @@ async function cmdDoctor() {
|
|
|
636
646
|
{ path: join(LDM_ROOT, 'memory'), label: 'memory/' },
|
|
637
647
|
{ path: join(LDM_ROOT, 'agents'), label: 'agents/' },
|
|
638
648
|
{ path: join(LDM_ROOT, 'state'), label: 'state/' },
|
|
649
|
+
{ path: join(LDM_ROOT, 'sessions'), label: 'sessions/' },
|
|
650
|
+
{ path: join(LDM_ROOT, 'messages'), label: 'messages/' },
|
|
639
651
|
];
|
|
640
652
|
|
|
641
653
|
for (const s of sacred) {
|
|
@@ -716,6 +728,218 @@ function cmdStatus() {
|
|
|
716
728
|
console.log('');
|
|
717
729
|
}
|
|
718
730
|
|
|
731
|
+
// ── ldm sessions ──
|
|
732
|
+
|
|
733
|
+
async function cmdSessions() {
|
|
734
|
+
const { listSessions } = await import('../lib/sessions.mjs');
|
|
735
|
+
const sessions = listSessions({ includeStale: CLEANUP_FLAG });
|
|
736
|
+
|
|
737
|
+
if (CLEANUP_FLAG) {
|
|
738
|
+
// listSessions already cleans stale when includeStale is false.
|
|
739
|
+
// With --cleanup, we list stale ones so user can see them, then re-run without stale.
|
|
740
|
+
const stale = sessions.filter(s => !s.alive);
|
|
741
|
+
if (stale.length > 0) {
|
|
742
|
+
const { deregisterSession } = await import('../lib/sessions.mjs');
|
|
743
|
+
for (const s of stale) {
|
|
744
|
+
deregisterSession(s.name);
|
|
745
|
+
}
|
|
746
|
+
console.log(` Cleaned ${stale.length} stale session(s).`);
|
|
747
|
+
} else {
|
|
748
|
+
console.log(' No stale sessions found.');
|
|
749
|
+
}
|
|
750
|
+
console.log('');
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const live = sessions.filter(s => s.alive);
|
|
755
|
+
|
|
756
|
+
if (JSON_OUTPUT) {
|
|
757
|
+
console.log(JSON.stringify(live, null, 2));
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
console.log('');
|
|
762
|
+
console.log(' Active Sessions');
|
|
763
|
+
console.log(' ────────────────────────────────────');
|
|
764
|
+
|
|
765
|
+
if (live.length === 0) {
|
|
766
|
+
console.log(' No active sessions.');
|
|
767
|
+
} else {
|
|
768
|
+
for (const s of live) {
|
|
769
|
+
const age = timeSince(s.startTime);
|
|
770
|
+
console.log(` ${s.name} agent=${s.agentId} pid=${s.pid} up=${age}`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
console.log('');
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function timeSince(isoString) {
|
|
778
|
+
try {
|
|
779
|
+
const ms = Date.now() - new Date(isoString).getTime();
|
|
780
|
+
const secs = Math.floor(ms / 1000);
|
|
781
|
+
if (secs < 60) return `${secs}s`;
|
|
782
|
+
const mins = Math.floor(secs / 60);
|
|
783
|
+
if (mins < 60) return `${mins}m`;
|
|
784
|
+
const hours = Math.floor(mins / 60);
|
|
785
|
+
if (hours < 24) return `${hours}h ${mins % 60}m`;
|
|
786
|
+
const days = Math.floor(hours / 24);
|
|
787
|
+
return `${days}d ${hours % 24}h`;
|
|
788
|
+
} catch {
|
|
789
|
+
return '?';
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// ── ldm msg ──
|
|
794
|
+
|
|
795
|
+
async function cmdMsg() {
|
|
796
|
+
const subcommand = args[1];
|
|
797
|
+
|
|
798
|
+
if (!subcommand || subcommand === 'list') {
|
|
799
|
+
return cmdMsgList();
|
|
800
|
+
}
|
|
801
|
+
if (subcommand === 'send') {
|
|
802
|
+
return cmdMsgSend();
|
|
803
|
+
}
|
|
804
|
+
if (subcommand === 'broadcast') {
|
|
805
|
+
return cmdMsgBroadcast();
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
console.error(` Unknown msg subcommand: ${subcommand}`);
|
|
809
|
+
console.error(' Usage: ldm msg [send <to> <body> | list | broadcast <body>]');
|
|
810
|
+
process.exit(1);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
async function cmdMsgList() {
|
|
814
|
+
const { readMessages } = await import('../lib/messages.mjs');
|
|
815
|
+
const sessionName = process.env.CLAUDE_SESSION_NAME || 'unknown';
|
|
816
|
+
const messages = readMessages(sessionName, { markRead: false });
|
|
817
|
+
|
|
818
|
+
if (JSON_OUTPUT) {
|
|
819
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
console.log('');
|
|
824
|
+
console.log(` Messages for "${sessionName}"`);
|
|
825
|
+
console.log(' ────────────────────────────────────');
|
|
826
|
+
|
|
827
|
+
if (messages.length === 0) {
|
|
828
|
+
console.log(' No pending messages.');
|
|
829
|
+
} else {
|
|
830
|
+
for (const m of messages) {
|
|
831
|
+
const ts = m.timestamp?.split('T')[1]?.split('.')[0] || '';
|
|
832
|
+
console.log(` [${m.type}] ${ts} from=${m.from}: ${m.body}`);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
console.log('');
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
async function cmdMsgSend() {
|
|
840
|
+
const { sendMessage } = await import('../lib/messages.mjs');
|
|
841
|
+
// args: ['msg', 'send', '<to>', '<body...>']
|
|
842
|
+
const to = args[2];
|
|
843
|
+
const body = args.slice(3).filter(a => !a.startsWith('--')).join(' ');
|
|
844
|
+
|
|
845
|
+
if (!to || !body) {
|
|
846
|
+
console.error(' Usage: ldm msg send <to> <body>');
|
|
847
|
+
process.exit(1);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
const sessionName = process.env.CLAUDE_SESSION_NAME || 'ldm-cli';
|
|
851
|
+
const id = sendMessage({ from: sessionName, to, body, type: 'chat' });
|
|
852
|
+
|
|
853
|
+
if (id) {
|
|
854
|
+
console.log(` Message sent to "${to}" (id: ${id})`);
|
|
855
|
+
} else {
|
|
856
|
+
console.error(' x Failed to send message.');
|
|
857
|
+
process.exit(1);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
async function cmdMsgBroadcast() {
|
|
862
|
+
const { sendMessage } = await import('../lib/messages.mjs');
|
|
863
|
+
// args: ['msg', 'broadcast', '<body...>']
|
|
864
|
+
const body = args.slice(2).filter(a => !a.startsWith('--')).join(' ');
|
|
865
|
+
|
|
866
|
+
if (!body) {
|
|
867
|
+
console.error(' Usage: ldm msg broadcast <body>');
|
|
868
|
+
process.exit(1);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const sessionName = process.env.CLAUDE_SESSION_NAME || 'ldm-cli';
|
|
872
|
+
const id = sendMessage({ from: sessionName, to: 'all', body, type: 'chat' });
|
|
873
|
+
|
|
874
|
+
if (id) {
|
|
875
|
+
console.log(` Broadcast sent (id: ${id})`);
|
|
876
|
+
} else {
|
|
877
|
+
console.error(' x Failed to send broadcast.');
|
|
878
|
+
process.exit(1);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// ── ldm updates ──
|
|
883
|
+
|
|
884
|
+
async function cmdUpdates() {
|
|
885
|
+
if (CHECK_FLAG) {
|
|
886
|
+
// Re-check npm registry
|
|
887
|
+
const { checkForUpdates } = await import('../lib/updates.mjs');
|
|
888
|
+
console.log(' Checking npm for updates...');
|
|
889
|
+
console.log('');
|
|
890
|
+
const result = checkForUpdates();
|
|
891
|
+
|
|
892
|
+
if (JSON_OUTPUT) {
|
|
893
|
+
console.log(JSON.stringify(result, null, 2));
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (result.updatesAvailable === 0) {
|
|
898
|
+
console.log(` Checked ${result.checked} extensions. Everything is up to date.`);
|
|
899
|
+
} else {
|
|
900
|
+
console.log(` Checked ${result.checked} extensions. ${result.updatesAvailable} update(s) available:`);
|
|
901
|
+
console.log('');
|
|
902
|
+
for (const u of result.updates) {
|
|
903
|
+
console.log(` ${u.name}: ${u.currentVersion} -> ${u.latestVersion} (${u.packageName})`);
|
|
904
|
+
}
|
|
905
|
+
console.log('');
|
|
906
|
+
console.log(' Run: ldm install');
|
|
907
|
+
}
|
|
908
|
+
console.log('');
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// Show cached results
|
|
913
|
+
const { readUpdateManifest } = await import('../lib/updates.mjs');
|
|
914
|
+
const manifest = readUpdateManifest();
|
|
915
|
+
|
|
916
|
+
if (JSON_OUTPUT) {
|
|
917
|
+
console.log(JSON.stringify(manifest || {}, null, 2));
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
console.log('');
|
|
922
|
+
console.log(' Available Updates');
|
|
923
|
+
console.log(' ────────────────────────────────────');
|
|
924
|
+
|
|
925
|
+
if (!manifest) {
|
|
926
|
+
console.log(' No update check has been run yet.');
|
|
927
|
+
console.log(' Run: ldm updates --check');
|
|
928
|
+
} else if (manifest.updatesAvailable === 0) {
|
|
929
|
+
console.log(` Everything is up to date. (checked ${manifest.checkedAt?.split('T')[0] || 'unknown'})`);
|
|
930
|
+
} else {
|
|
931
|
+
console.log(` ${manifest.updatesAvailable} update(s) available (checked ${manifest.checkedAt?.split('T')[0] || 'unknown'}):`);
|
|
932
|
+
console.log('');
|
|
933
|
+
for (const u of manifest.updates) {
|
|
934
|
+
console.log(` ${u.name}: ${u.currentVersion} -> ${u.latestVersion}`);
|
|
935
|
+
}
|
|
936
|
+
console.log('');
|
|
937
|
+
console.log(' Run: ldm install');
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
console.log('');
|
|
941
|
+
}
|
|
942
|
+
|
|
719
943
|
// ── Main ──
|
|
720
944
|
|
|
721
945
|
async function main() {
|
|
@@ -730,10 +954,19 @@ async function main() {
|
|
|
730
954
|
console.log(' ldm install Update all registered extensions');
|
|
731
955
|
console.log(' ldm doctor Check health of all extensions');
|
|
732
956
|
console.log(' ldm status Show version and extension list');
|
|
957
|
+
console.log(' ldm sessions List active sessions');
|
|
958
|
+
console.log(' ldm sessions --cleanup Remove stale session entries');
|
|
959
|
+
console.log(' ldm msg send <to> <body> Send a message to a session');
|
|
960
|
+
console.log(' ldm msg list List pending messages');
|
|
961
|
+
console.log(' ldm msg broadcast <body> Send to all sessions');
|
|
962
|
+
console.log(' ldm updates Show available updates from cache');
|
|
963
|
+
console.log(' ldm updates --check Re-check npm registry for updates');
|
|
733
964
|
console.log('');
|
|
734
965
|
console.log(' Flags:');
|
|
735
966
|
console.log(' --dry-run Show what would happen without making changes');
|
|
736
967
|
console.log(' --json Output results as JSON');
|
|
968
|
+
console.log(' --cleanup Remove stale entries (sessions)');
|
|
969
|
+
console.log(' --check Re-check registry (updates)');
|
|
737
970
|
console.log('');
|
|
738
971
|
console.log(' Interfaces detected:');
|
|
739
972
|
console.log(' CLI ... package.json bin -> npm install -g');
|
|
@@ -770,6 +1003,15 @@ async function main() {
|
|
|
770
1003
|
case 'status':
|
|
771
1004
|
cmdStatus();
|
|
772
1005
|
break;
|
|
1006
|
+
case 'sessions':
|
|
1007
|
+
await cmdSessions();
|
|
1008
|
+
break;
|
|
1009
|
+
case 'msg':
|
|
1010
|
+
await cmdMsg();
|
|
1011
|
+
break;
|
|
1012
|
+
case 'updates':
|
|
1013
|
+
await cmdUpdates();
|
|
1014
|
+
break;
|
|
773
1015
|
default:
|
|
774
1016
|
console.error(` Unknown command: ${command}`);
|
|
775
1017
|
console.error(` Run: ldm --help`);
|