@lmctl-ai/lmctl 0.1.178 → 0.1.180
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/README.md +9 -1
- package/dist/cli/index.js +640 -476
- package/dist/cli/schema.sql +112 -0
- package/package.json +1 -1
package/dist/cli/schema.sql
CHANGED
|
@@ -793,3 +793,115 @@ CREATE TRIGGER IF NOT EXISTS trg_agent_mailbox_response_request_update
|
|
|
793
793
|
BEGIN
|
|
794
794
|
SELECT RAISE(ABORT, 'agent_mailbox response requires request_mailbox_id');
|
|
795
795
|
END;
|
|
796
|
+
|
|
797
|
+
-- v53: event-log message substrate (design:
|
|
798
|
+
-- backlog/DESIGN-event-log-message-substrate-DRAFT.md §2/§4; impl plan:
|
|
799
|
+
-- backlog/IMPL-PLAN-event-log-message-substrate.md Phase A). Additive only —
|
|
800
|
+
-- no existing read/write path changes in this phase.
|
|
801
|
+
--
|
|
802
|
+
-- message_event is the append-only log. `seq` (not `ts`) is the ordering
|
|
803
|
+
-- authority; `ts` is display/audit only. `event_id` is the idempotency key
|
|
804
|
+
-- and MUST be deterministic from intent (hash of stream_id + event_type +
|
|
805
|
+
-- observed projection last_seq — see src/db/event-log.ts), never a random
|
|
806
|
+
-- per-attempt id. The generated sender/receiver columns are load-bearing
|
|
807
|
+
-- (promoted from caveat by the low-level-primitives review): hot selectors
|
|
808
|
+
-- cannot index json_extract() directly; they populate on CREATE/
|
|
809
|
+
-- RESPONSE_CREATE payloads and are NULL for lease/invocation/terminal
|
|
810
|
+
-- streams (json_extract returns NULL on a missing path).
|
|
811
|
+
CREATE TABLE IF NOT EXISTS message_event (
|
|
812
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
813
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
814
|
+
ts TEXT NOT NULL,
|
|
815
|
+
stream_id TEXT NOT NULL,
|
|
816
|
+
event_type TEXT NOT NULL,
|
|
817
|
+
payload TEXT NOT NULL CHECK(json_valid(payload)),
|
|
818
|
+
sender_teamfile TEXT GENERATED ALWAYS AS (json_extract(payload, '$.sender.teamfile')) STORED,
|
|
819
|
+
sender_alias TEXT GENERATED ALWAYS AS (json_extract(payload, '$.sender.alias')) STORED,
|
|
820
|
+
receiver_teamfile TEXT GENERATED ALWAYS AS (json_extract(payload, '$.receiver.teamfile')) STORED,
|
|
821
|
+
receiver_alias TEXT GENERATED ALWAYS AS (json_extract(payload, '$.receiver.alias')) STORED
|
|
822
|
+
);
|
|
823
|
+
CREATE INDEX IF NOT EXISTS idx_message_event_stream ON message_event(stream_id, seq);
|
|
824
|
+
CREATE INDEX IF NOT EXISTS idx_message_event_type ON message_event(event_type, seq);
|
|
825
|
+
CREATE INDEX IF NOT EXISTS idx_message_event_sender ON message_event(sender_teamfile, sender_alias, seq);
|
|
826
|
+
CREATE INDEX IF NOT EXISTS idx_message_event_receiver ON message_event(receiver_teamfile, receiver_alias, seq);
|
|
827
|
+
|
|
828
|
+
-- Mutex + terminal occupancy projection. Will replace agent_inflight + the
|
|
829
|
+
-- terminal-lock slice of runtime_state at cutover (Phase D). PK is the
|
|
830
|
+
-- actual mutual-exclusion constraint. The terminal_invocation_* slice is
|
|
831
|
+
-- dual-written by terminal-kind INVOCATION_START/HEARTBEAT/FINISH events so
|
|
832
|
+
-- ALL THREE busy-check tiers resolve from this one row (the phantom-tolerant
|
|
833
|
+
-- invocation_state below is never read by the busy check).
|
|
834
|
+
CREATE TABLE IF NOT EXISTS agent_state (
|
|
835
|
+
receiver_teamfile TEXT NOT NULL,
|
|
836
|
+
receiver_alias TEXT NOT NULL,
|
|
837
|
+
lease_id TEXT UNIQUE,
|
|
838
|
+
sender_teamfile TEXT,
|
|
839
|
+
sender_alias TEXT,
|
|
840
|
+
holder_pid INTEGER,
|
|
841
|
+
holder_host TEXT,
|
|
842
|
+
started_at TEXT,
|
|
843
|
+
last_heartbeat_at TEXT,
|
|
844
|
+
terminal_lock_id TEXT UNIQUE,
|
|
845
|
+
terminal_invocation_id TEXT UNIQUE,
|
|
846
|
+
terminal_invocation_pid INTEGER,
|
|
847
|
+
terminal_invocation_host TEXT,
|
|
848
|
+
terminal_invocation_heartbeat_at TEXT,
|
|
849
|
+
last_seq INTEGER NOT NULL,
|
|
850
|
+
PRIMARY KEY(receiver_teamfile, receiver_alias)
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
-- One row per undelivered/unhandled message. Will replace the
|
|
854
|
+
-- delivered_at/delivering_at slice of agent_mailbox. in_reply_to's UNIQUE
|
|
855
|
+
-- enforces "one response per request" at the schema level.
|
|
856
|
+
CREATE TABLE IF NOT EXISTS message_pending (
|
|
857
|
+
message_id TEXT PRIMARY KEY,
|
|
858
|
+
message_type TEXT NOT NULL CHECK(message_type IN ('request','response')),
|
|
859
|
+
in_reply_to TEXT UNIQUE,
|
|
860
|
+
sender_teamfile TEXT,
|
|
861
|
+
sender_alias TEXT,
|
|
862
|
+
receiver_teamfile TEXT NOT NULL,
|
|
863
|
+
receiver_alias TEXT NOT NULL,
|
|
864
|
+
lifecycle_state TEXT NOT NULL,
|
|
865
|
+
delivery_lease_id TEXT,
|
|
866
|
+
delivery_holder_pid INTEGER,
|
|
867
|
+
created_seq INTEGER NOT NULL,
|
|
868
|
+
last_seq INTEGER NOT NULL
|
|
869
|
+
);
|
|
870
|
+
CREATE INDEX IF NOT EXISTS idx_message_pending_lane
|
|
871
|
+
ON message_pending(sender_teamfile, sender_alias, receiver_teamfile,
|
|
872
|
+
receiver_alias, message_type, created_seq)
|
|
873
|
+
WHERE lifecycle_state = 'queued';
|
|
874
|
+
|
|
875
|
+
-- Diagnostic/observability projection: "what is a process doing right now."
|
|
876
|
+
-- Deliberately separate from agent_state (two correctness regimes): rows here
|
|
877
|
+
-- are EXPECTED to go stale on hard kills (#88 capture gap) and are cleaned by
|
|
878
|
+
-- a reconciliation probe, never consulted by the busy check.
|
|
879
|
+
CREATE TABLE IF NOT EXISTS invocation_state (
|
|
880
|
+
invocation_id TEXT PRIMARY KEY,
|
|
881
|
+
kind TEXT NOT NULL,
|
|
882
|
+
origin TEXT NOT NULL,
|
|
883
|
+
launch_source TEXT NOT NULL,
|
|
884
|
+
from_identity TEXT NOT NULL,
|
|
885
|
+
target_teamfile TEXT,
|
|
886
|
+
target_alias TEXT,
|
|
887
|
+
root_teamfile TEXT,
|
|
888
|
+
cwd TEXT,
|
|
889
|
+
command TEXT,
|
|
890
|
+
request_message_id TEXT,
|
|
891
|
+
request_payload TEXT,
|
|
892
|
+
holder_pid INTEGER,
|
|
893
|
+
holder_host TEXT,
|
|
894
|
+
status TEXT NOT NULL,
|
|
895
|
+
started_at TEXT NOT NULL,
|
|
896
|
+
last_heartbeat_at TEXT,
|
|
897
|
+
ended_at TEXT,
|
|
898
|
+
result_summary TEXT,
|
|
899
|
+
error TEXT,
|
|
900
|
+
notified_by TEXT,
|
|
901
|
+
notified_at TEXT,
|
|
902
|
+
last_seq INTEGER NOT NULL
|
|
903
|
+
);
|
|
904
|
+
CREATE INDEX IF NOT EXISTS idx_invocation_state_target_status
|
|
905
|
+
ON invocation_state(target_teamfile, target_alias, status, launch_source);
|
|
906
|
+
CREATE INDEX IF NOT EXISTS idx_invocation_state_from_time
|
|
907
|
+
ON invocation_state(from_identity, started_at DESC);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmctl-ai/lmctl",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.180",
|
|
4
4
|
"description": "A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://lmctl.com",
|