pilotswarm-sdk 0.1.19 → 0.1.21

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.
Files changed (95) hide show
  1. package/README.md +6 -0
  2. package/dist/artifact-tools.d.ts.map +1 -1
  3. package/dist/artifact-tools.js +20 -5
  4. package/dist/artifact-tools.js.map +1 -1
  5. package/dist/blob-store.d.ts +6 -4
  6. package/dist/blob-store.d.ts.map +1 -1
  7. package/dist/blob-store.js +55 -12
  8. package/dist/blob-store.js.map +1 -1
  9. package/dist/client.d.ts +4 -1
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +4 -0
  12. package/dist/client.js.map +1 -1
  13. package/dist/cms-migrations.d.ts.map +1 -1
  14. package/dist/cms-migrations.js +628 -0
  15. package/dist/cms-migrations.js.map +1 -1
  16. package/dist/cms.d.ts +145 -0
  17. package/dist/cms.d.ts.map +1 -1
  18. package/dist/cms.js +288 -17
  19. package/dist/cms.js.map +1 -1
  20. package/dist/facts-migrations.d.ts.map +1 -1
  21. package/dist/facts-migrations.js +227 -0
  22. package/dist/facts-migrations.js.map +1 -1
  23. package/dist/facts-store.d.ts +21 -0
  24. package/dist/facts-store.d.ts.map +1 -1
  25. package/dist/facts-store.js +34 -1
  26. package/dist/facts-store.js.map +1 -1
  27. package/dist/facts-tools.d.ts +7 -0
  28. package/dist/facts-tools.d.ts.map +1 -1
  29. package/dist/facts-tools.js +29 -2
  30. package/dist/facts-tools.js.map +1 -1
  31. package/dist/index.d.ts +6 -5
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/inspect-tools.d.ts +42 -0
  36. package/dist/inspect-tools.d.ts.map +1 -0
  37. package/dist/inspect-tools.js +800 -0
  38. package/dist/inspect-tools.js.map +1 -0
  39. package/dist/managed-session.d.ts.map +1 -1
  40. package/dist/managed-session.js +76 -35
  41. package/dist/managed-session.js.map +1 -1
  42. package/dist/management-client.d.ts +64 -2
  43. package/dist/management-client.d.ts.map +1 -1
  44. package/dist/management-client.js +109 -0
  45. package/dist/management-client.js.map +1 -1
  46. package/dist/orchestration-registry.d.ts.map +1 -1
  47. package/dist/orchestration-registry.js +6 -2
  48. package/dist/orchestration-registry.js.map +1 -1
  49. package/dist/orchestration-version.d.ts +1 -1
  50. package/dist/orchestration-version.js +1 -1
  51. package/dist/orchestration.d.ts +3 -3
  52. package/dist/orchestration.d.ts.map +1 -1
  53. package/dist/orchestration.js +27 -4
  54. package/dist/orchestration.js.map +1 -1
  55. package/dist/orchestration_1_0_43.d.ts +12 -0
  56. package/dist/orchestration_1_0_43.d.ts.map +1 -0
  57. package/dist/orchestration_1_0_43.js +2710 -0
  58. package/dist/orchestration_1_0_43.js.map +1 -0
  59. package/dist/orchestration_1_0_44.d.ts +12 -0
  60. package/dist/orchestration_1_0_44.d.ts.map +1 -0
  61. package/dist/orchestration_1_0_44.js +2710 -0
  62. package/dist/orchestration_1_0_44.js.map +1 -0
  63. package/dist/session-manager.d.ts +9 -0
  64. package/dist/session-manager.d.ts.map +1 -1
  65. package/dist/session-manager.js +40 -3
  66. package/dist/session-manager.js.map +1 -1
  67. package/dist/session-owner-utils.d.ts +25 -0
  68. package/dist/session-owner-utils.d.ts.map +1 -0
  69. package/dist/session-owner-utils.js +82 -0
  70. package/dist/session-owner-utils.js.map +1 -0
  71. package/dist/session-proxy.d.ts +5 -1
  72. package/dist/session-proxy.d.ts.map +1 -1
  73. package/dist/session-proxy.js +70 -8
  74. package/dist/session-proxy.js.map +1 -1
  75. package/dist/session-store.d.ts +38 -6
  76. package/dist/session-store.d.ts.map +1 -1
  77. package/dist/session-store.js +187 -9
  78. package/dist/session-store.js.map +1 -1
  79. package/dist/types.d.ts +19 -1
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/types.js.map +1 -1
  82. package/dist/worker.d.ts.map +1 -1
  83. package/dist/worker.js +11 -2
  84. package/dist/worker.js.map +1 -1
  85. package/package.json +10 -4
  86. package/plugins/mgmt/agents/agent-tuner.agent.md +222 -0
  87. package/plugins/mgmt/agents/facts-manager.agent.md +8 -1
  88. package/plugins/mgmt/agents/pilotswarm.agent.md +13 -10
  89. package/plugins/mgmt/agents/resourcemgr.agent.md +11 -4
  90. package/plugins/mgmt/agents/sweeper.agent.md +5 -4
  91. package/plugins/mgmt/skills/cost-latency-analysis/SKILL.md +117 -0
  92. package/plugins/mgmt/skills/orchestration-session-lifecycle/SKILL.md +117 -0
  93. package/plugins/mgmt/skills/resourcemgr/SKILL.md +1 -1
  94. package/plugins/mgmt/skills/sweeper/SKILL.md +4 -4
  95. package/plugins/system/agents/default.agent.md +22 -0
@@ -32,6 +32,31 @@ export function CMS_MIGRATIONS(schema) {
32
32
  name: "stored_procedures",
33
33
  sql: migration_0004_stored_procedures(schema),
34
34
  },
35
+ {
36
+ version: "0005",
37
+ name: "skill_usage_procs",
38
+ sql: migration_0005_skill_usage_procs(schema),
39
+ },
40
+ {
41
+ version: "0006",
42
+ name: "fleet_cache_columns",
43
+ sql: migration_0006_fleet_cache_columns(schema),
44
+ },
45
+ {
46
+ version: "0007",
47
+ name: "session_tree_stats_by_model",
48
+ sql: migration_0007_session_tree_stats_by_model(schema),
49
+ },
50
+ {
51
+ version: "0008",
52
+ name: "session_owner_users",
53
+ sql: migration_0008_session_owner_users(schema),
54
+ },
55
+ {
56
+ version: "0009",
57
+ name: "user_stats_by_model",
58
+ sql: migration_0009_user_stats_by_model(schema),
59
+ },
35
60
  ];
36
61
  }
37
62
  // ─── Migration 0001: Baseline ────────────────────────────────────
@@ -552,4 +577,607 @@ END;
552
577
  $$ LANGUAGE plpgsql;
553
578
  `;
554
579
  }
580
+ // ─── Migration 0005: Skill Usage Procs ───────────────────────────
581
+ function migration_0005_skill_usage_procs(schema) {
582
+ const s = `"${schema}"`;
583
+ return `
584
+ -- 0005_skill_usage_procs: per-session, tree, and fleet skill-usage queries.
585
+ -- Two source event types, both rare relative to assistant.delta /
586
+ -- tool.execution_*:
587
+ -- * 'skill.invoked' — Copilot SDK fires this when the model expands
588
+ -- a static skill from a plugin's skills/ dir.
589
+ -- Payload: { name, pluginName?, pluginVersion?, ... }
590
+ -- * 'learned_skill.read' — emitted by the read_facts tool wrapper when
591
+ -- the call touches the 'skills/' fact namespace.
592
+ -- Payload: { name (key|keyPattern), scope, matchCount, ... }
593
+ --
594
+ -- Each row carries a 'kind' discriminator so callers can distinguish the
595
+ -- two flavors without inspecting event_type. 'name' is the static skill
596
+ -- name OR the requested learned-skill key/keyPattern. Plugin metadata is
597
+ -- only meaningful for static skills.
598
+
599
+ -- ── Unified partial index for skill-signal rows ──────────────────
600
+ CREATE INDEX IF NOT EXISTS idx_${schema}_events_skill_signals
601
+ ON ${s}.session_events (session_id, created_at DESC)
602
+ WHERE event_type IN ('skill.invoked', 'learned_skill.read');
603
+
604
+ -- ── cms_get_session_skill_usage ──────────────────────────────────
605
+ CREATE OR REPLACE FUNCTION ${s}.cms_get_session_skill_usage(
606
+ p_session_id TEXT,
607
+ p_since TIMESTAMPTZ
608
+ ) RETURNS TABLE (
609
+ kind TEXT,
610
+ name TEXT,
611
+ plugin_name TEXT,
612
+ plugin_version TEXT,
613
+ invocations BIGINT,
614
+ first_used_at TIMESTAMPTZ,
615
+ last_used_at TIMESTAMPTZ
616
+ ) AS $$
617
+ BEGIN
618
+ RETURN QUERY
619
+ SELECT
620
+ CASE WHEN e.event_type = 'skill.invoked'
621
+ THEN 'static' ELSE 'learned' END::TEXT AS kind,
622
+ COALESCE(e.data->>'name', '')::TEXT AS name,
623
+ NULLIF(e.data->>'pluginName', '')::TEXT AS plugin_name,
624
+ NULLIF(e.data->>'pluginVersion', '')::TEXT AS plugin_version,
625
+ COUNT(*)::BIGINT AS invocations,
626
+ MIN(e.created_at) AS first_used_at,
627
+ MAX(e.created_at) AS last_used_at
628
+ FROM ${s}.session_events e
629
+ WHERE e.session_id = p_session_id
630
+ AND e.event_type IN ('skill.invoked', 'learned_skill.read')
631
+ AND (p_since IS NULL OR e.created_at >= p_since)
632
+ GROUP BY 1, 2, 3, 4
633
+ ORDER BY invocations DESC, last_used_at DESC;
634
+ END;
635
+ $$ LANGUAGE plpgsql;
636
+
637
+ -- ── cms_get_session_tree_skill_usage ─────────────────────────────
638
+ CREATE OR REPLACE FUNCTION ${s}.cms_get_session_tree_skill_usage(
639
+ p_session_id TEXT,
640
+ p_since TIMESTAMPTZ
641
+ ) RETURNS TABLE (
642
+ session_id TEXT,
643
+ agent_id TEXT,
644
+ kind TEXT,
645
+ name TEXT,
646
+ plugin_name TEXT,
647
+ plugin_version TEXT,
648
+ invocations BIGINT,
649
+ first_used_at TIMESTAMPTZ,
650
+ last_used_at TIMESTAMPTZ
651
+ ) AS $$
652
+ BEGIN
653
+ RETURN QUERY
654
+ WITH RECURSIVE tree AS (
655
+ SELECT s0.session_id, s0.agent_id FROM ${s}.sessions s0 WHERE s0.session_id = p_session_id
656
+ UNION ALL
657
+ SELECT s1.session_id, s1.agent_id FROM ${s}.sessions s1
658
+ INNER JOIN tree t ON s1.parent_session_id = t.session_id
659
+ )
660
+ SELECT
661
+ e.session_id AS session_id,
662
+ t.agent_id AS agent_id,
663
+ CASE WHEN e.event_type = 'skill.invoked'
664
+ THEN 'static' ELSE 'learned' END::TEXT AS kind,
665
+ COALESCE(e.data->>'name', '')::TEXT AS name,
666
+ NULLIF(e.data->>'pluginName', '')::TEXT AS plugin_name,
667
+ NULLIF(e.data->>'pluginVersion', '')::TEXT AS plugin_version,
668
+ COUNT(*)::BIGINT AS invocations,
669
+ MIN(e.created_at) AS first_used_at,
670
+ MAX(e.created_at) AS last_used_at
671
+ FROM ${s}.session_events e
672
+ INNER JOIN tree t ON e.session_id = t.session_id
673
+ WHERE e.event_type IN ('skill.invoked', 'learned_skill.read')
674
+ AND (p_since IS NULL OR e.created_at >= p_since)
675
+ GROUP BY e.session_id, t.agent_id, kind, name, plugin_name, plugin_version
676
+ ORDER BY e.session_id, invocations DESC;
677
+ END;
678
+ $$ LANGUAGE plpgsql;
679
+
680
+ -- ── cms_get_fleet_skill_usage ────────────────────────────────────
681
+ -- Joined to the sessions row for agent_id. p_include_deleted controls
682
+ -- whether soft-deleted sessions contribute. p_since bounds the scan.
683
+ CREATE OR REPLACE FUNCTION ${s}.cms_get_fleet_skill_usage(
684
+ p_since TIMESTAMPTZ,
685
+ p_include_deleted BOOLEAN
686
+ ) RETURNS TABLE (
687
+ agent_id TEXT,
688
+ kind TEXT,
689
+ name TEXT,
690
+ plugin_name TEXT,
691
+ plugin_version TEXT,
692
+ session_count BIGINT,
693
+ invocations BIGINT,
694
+ last_used_at TIMESTAMPTZ
695
+ ) AS $$
696
+ BEGIN
697
+ RETURN QUERY
698
+ SELECT
699
+ s.agent_id AS agent_id,
700
+ CASE WHEN e.event_type = 'skill.invoked'
701
+ THEN 'static' ELSE 'learned' END::TEXT AS kind,
702
+ COALESCE(e.data->>'name', '')::TEXT AS name,
703
+ NULLIF(e.data->>'pluginName', '')::TEXT AS plugin_name,
704
+ NULLIF(e.data->>'pluginVersion', '')::TEXT AS plugin_version,
705
+ COUNT(DISTINCT e.session_id)::BIGINT AS session_count,
706
+ COUNT(*)::BIGINT AS invocations,
707
+ MAX(e.created_at) AS last_used_at
708
+ FROM ${s}.session_events e
709
+ INNER JOIN ${s}.sessions s ON s.session_id = e.session_id
710
+ WHERE e.event_type IN ('skill.invoked', 'learned_skill.read')
711
+ AND (p_include_deleted OR s.deleted_at IS NULL)
712
+ AND (p_since IS NULL OR e.created_at >= p_since)
713
+ GROUP BY s.agent_id, kind, name, plugin_name, plugin_version
714
+ ORDER BY invocations DESC, last_used_at DESC;
715
+ END;
716
+ $$ LANGUAGE plpgsql;
717
+ `;
718
+ }
719
+ // ─── Migration 0006: Fleet Cache Columns ─────────────────────────
720
+ function migration_0006_fleet_cache_columns(schema) {
721
+ const s = `"${schema}"`;
722
+ return `
723
+ -- 0006_fleet_cache_columns: surface prompt-cache token counts at the fleet
724
+ -- aggregation level. Data is already collected per session in
725
+ -- session_metric_summaries.tokens_cache_read / tokens_cache_write; the prior
726
+ -- fleet procs simply ignored those columns. This migration adds them to the
727
+ -- two fleet read paths.
728
+ --
729
+ -- PostgreSQL refuses CREATE OR REPLACE FUNCTION when the RETURNS TABLE shape
730
+ -- changes. We DROP-then-CREATE for both procs. Idempotent via IF EXISTS.
731
+
732
+ -- ── cms_get_fleet_stats_by_agent (drop + recreate) ───────────────
733
+ DROP FUNCTION IF EXISTS ${s}.cms_get_fleet_stats_by_agent(BOOLEAN, TIMESTAMPTZ);
734
+ CREATE FUNCTION ${s}.cms_get_fleet_stats_by_agent(
735
+ p_include_deleted BOOLEAN,
736
+ p_since TIMESTAMPTZ
737
+ ) RETURNS TABLE (
738
+ agent_id TEXT,
739
+ model TEXT,
740
+ session_count INT,
741
+ total_snapshot_size_bytes BIGINT,
742
+ total_dehydration_count INT,
743
+ total_hydration_count INT,
744
+ total_lossy_handoff_count INT,
745
+ total_tokens_input BIGINT,
746
+ total_tokens_output BIGINT,
747
+ total_tokens_cache_read BIGINT,
748
+ total_tokens_cache_write BIGINT
749
+ ) AS $$
750
+ BEGIN
751
+ RETURN QUERY
752
+ SELECT
753
+ m.agent_id,
754
+ m.model,
755
+ COUNT(*)::int AS session_count,
756
+ COALESCE(SUM(m.snapshot_size_bytes), 0)::bigint AS total_snapshot_size_bytes,
757
+ COALESCE(SUM(m.dehydration_count), 0)::int AS total_dehydration_count,
758
+ COALESCE(SUM(m.hydration_count), 0)::int AS total_hydration_count,
759
+ COALESCE(SUM(m.lossy_handoff_count), 0)::int AS total_lossy_handoff_count,
760
+ COALESCE(SUM(m.tokens_input), 0)::bigint AS total_tokens_input,
761
+ COALESCE(SUM(m.tokens_output), 0)::bigint AS total_tokens_output,
762
+ COALESCE(SUM(m.tokens_cache_read), 0)::bigint AS total_tokens_cache_read,
763
+ COALESCE(SUM(m.tokens_cache_write), 0)::bigint AS total_tokens_cache_write
764
+ FROM ${s}.session_metric_summaries m
765
+ WHERE (p_include_deleted OR m.deleted_at IS NULL)
766
+ AND (p_since IS NULL OR m.created_at >= p_since)
767
+ GROUP BY m.agent_id, m.model;
768
+ END;
769
+ $$ LANGUAGE plpgsql;
770
+
771
+ -- ── cms_get_fleet_stats_totals (drop + recreate) ─────────────────
772
+ DROP FUNCTION IF EXISTS ${s}.cms_get_fleet_stats_totals(BOOLEAN, TIMESTAMPTZ);
773
+ CREATE FUNCTION ${s}.cms_get_fleet_stats_totals(
774
+ p_include_deleted BOOLEAN,
775
+ p_since TIMESTAMPTZ
776
+ ) RETURNS TABLE (
777
+ session_count INT,
778
+ total_snapshot_size_bytes BIGINT,
779
+ total_tokens_input BIGINT,
780
+ total_tokens_output BIGINT,
781
+ total_tokens_cache_read BIGINT,
782
+ total_tokens_cache_write BIGINT,
783
+ earliest_session_created_at TIMESTAMPTZ
784
+ ) AS $$
785
+ BEGIN
786
+ RETURN QUERY
787
+ SELECT
788
+ COUNT(*)::int AS session_count,
789
+ COALESCE(SUM(m.snapshot_size_bytes), 0)::bigint AS total_snapshot_size_bytes,
790
+ COALESCE(SUM(m.tokens_input), 0)::bigint AS total_tokens_input,
791
+ COALESCE(SUM(m.tokens_output), 0)::bigint AS total_tokens_output,
792
+ COALESCE(SUM(m.tokens_cache_read), 0)::bigint AS total_tokens_cache_read,
793
+ COALESCE(SUM(m.tokens_cache_write), 0)::bigint AS total_tokens_cache_write,
794
+ MIN(m.created_at) AS earliest_session_created_at
795
+ FROM ${s}.session_metric_summaries m
796
+ WHERE (p_include_deleted OR m.deleted_at IS NULL)
797
+ AND (p_since IS NULL OR m.created_at >= p_since);
798
+ END;
799
+ $$ LANGUAGE plpgsql;
800
+ `;
801
+ }
802
+ // ─── Migration 0007: Session-Tree Stats By Model ─────────────────
803
+ function migration_0007_session_tree_stats_by_model(schema) {
804
+ const s = `"${schema}"`;
805
+ return `
806
+ -- 0007_session_tree_stats_by_model: per-model breakdown across the
807
+ -- spawn tree rooted at a session. Mirrors the shape of
808
+ -- cms_get_fleet_stats_by_agent so the TUI/portal "By Model" card can
809
+ -- render uniformly for both the fleet view and the per-session tree
810
+ -- view. Uses the same recursive-descendant CTE pattern as
811
+ -- cms_get_session_tree_stats so they stay in sync.
812
+
813
+ CREATE OR REPLACE FUNCTION ${s}.cms_get_session_tree_stats_by_model(
814
+ p_session_id TEXT
815
+ ) RETURNS TABLE (
816
+ model TEXT,
817
+ session_count INT,
818
+ total_tokens_input BIGINT,
819
+ total_tokens_output BIGINT,
820
+ total_tokens_cache_read BIGINT,
821
+ total_tokens_cache_write BIGINT,
822
+ total_snapshot_size_bytes BIGINT
823
+ ) AS $$
824
+ BEGIN
825
+ RETURN QUERY
826
+ WITH RECURSIVE tree AS (
827
+ SELECT m.session_id FROM ${s}.session_metric_summaries m
828
+ WHERE m.session_id = p_session_id
829
+ UNION ALL
830
+ SELECT m.session_id FROM ${s}.session_metric_summaries m
831
+ INNER JOIN tree t ON m.parent_session_id = t.session_id
832
+ )
833
+ SELECT
834
+ COALESCE(m.model, '(unknown)') AS model,
835
+ COUNT(*)::int AS session_count,
836
+ COALESCE(SUM(m.tokens_input), 0)::bigint AS total_tokens_input,
837
+ COALESCE(SUM(m.tokens_output), 0)::bigint AS total_tokens_output,
838
+ COALESCE(SUM(m.tokens_cache_read), 0)::bigint AS total_tokens_cache_read,
839
+ COALESCE(SUM(m.tokens_cache_write), 0)::bigint AS total_tokens_cache_write,
840
+ COALESCE(SUM(m.snapshot_size_bytes), 0)::bigint AS total_snapshot_size_bytes
841
+ FROM ${s}.session_metric_summaries m
842
+ WHERE m.session_id IN (SELECT tree.session_id FROM tree)
843
+ GROUP BY m.model
844
+ ORDER BY total_tokens_input DESC, model;
845
+ END;
846
+ $$ LANGUAGE plpgsql;
847
+ `;
848
+ }
849
+ // ─── Migration 0008: Session Owner Users ─────────────────────────
850
+ function migration_0008_session_owner_users(schema) {
851
+ const s = `"${schema}"`;
852
+ return `
853
+ -- 0008_session_owner_users: lazily catalog authenticated users and link
854
+ -- non-system sessions to their first-seen owner. CMS access remains behind
855
+ -- stored procedures; callers do not read or mutate these tables directly.
856
+
857
+ CREATE TABLE IF NOT EXISTS ${s}.users (
858
+ user_id BIGSERIAL PRIMARY KEY,
859
+ provider TEXT NOT NULL,
860
+ subject TEXT NOT NULL,
861
+ email TEXT,
862
+ display_name TEXT,
863
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
864
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
865
+ );
866
+
867
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_${schema}_users_provider_subject
868
+ ON ${s}.users(provider, subject);
869
+
870
+ CREATE TABLE IF NOT EXISTS ${s}.session_owners (
871
+ session_id TEXT PRIMARY KEY REFERENCES ${s}.sessions(session_id) ON DELETE CASCADE,
872
+ user_id BIGINT NOT NULL REFERENCES ${s}.users(user_id),
873
+ assigned_at TIMESTAMPTZ NOT NULL DEFAULT now()
874
+ );
875
+
876
+ CREATE INDEX IF NOT EXISTS idx_${schema}_session_owners_user
877
+ ON ${s}.session_owners(user_id);
878
+
879
+ -- ── cms_register_user ────────────────────────────────────────────
880
+ CREATE OR REPLACE FUNCTION ${s}.cms_register_user(
881
+ p_provider TEXT,
882
+ p_subject TEXT,
883
+ p_email TEXT,
884
+ p_display_name TEXT
885
+ ) RETURNS BIGINT AS $$
886
+ DECLARE
887
+ v_provider TEXT := NULLIF(BTRIM(p_provider), '');
888
+ v_subject TEXT := NULLIF(BTRIM(p_subject), '');
889
+ v_user_id BIGINT;
890
+ BEGIN
891
+ IF v_provider IS NULL OR v_subject IS NULL THEN
892
+ RAISE EXCEPTION 'User provider and subject are required';
893
+ END IF;
894
+
895
+ -- First-seen-write-wins: do not refresh profile fields on later sightings.
896
+ INSERT INTO ${s}.users (provider, subject, email, display_name)
897
+ VALUES (
898
+ v_provider,
899
+ v_subject,
900
+ NULLIF(BTRIM(p_email), ''),
901
+ NULLIF(BTRIM(p_display_name), '')
902
+ )
903
+ ON CONFLICT (provider, subject) DO NOTHING;
904
+
905
+ SELECT user_id INTO v_user_id
906
+ FROM ${s}.users
907
+ WHERE provider = v_provider AND subject = v_subject;
908
+
909
+ RETURN v_user_id;
910
+ END;
911
+ $$ LANGUAGE plpgsql;
912
+
913
+ -- ── cms_set_session_owner ────────────────────────────────────────
914
+ CREATE OR REPLACE FUNCTION ${s}.cms_set_session_owner(
915
+ p_session_id TEXT,
916
+ p_provider TEXT,
917
+ p_subject TEXT,
918
+ p_email TEXT,
919
+ p_display_name TEXT
920
+ ) RETURNS VOID AS $$
921
+ DECLARE
922
+ v_user_id BIGINT;
923
+ v_is_system BOOLEAN;
924
+ BEGIN
925
+ SELECT is_system INTO v_is_system
926
+ FROM ${s}.sessions
927
+ WHERE session_id = p_session_id AND deleted_at IS NULL;
928
+
929
+ IF NOT FOUND OR v_is_system THEN
930
+ RETURN;
931
+ END IF;
932
+
933
+ v_user_id := ${s}.cms_register_user(p_provider, p_subject, p_email, p_display_name);
934
+
935
+ -- First assignment wins for a session.
936
+ INSERT INTO ${s}.session_owners (session_id, user_id)
937
+ VALUES (p_session_id, v_user_id)
938
+ ON CONFLICT (session_id) DO NOTHING;
939
+ END;
940
+ $$ LANGUAGE plpgsql;
941
+
942
+ -- ── cms_inherit_session_owner ────────────────────────────────────
943
+ CREATE OR REPLACE FUNCTION ${s}.cms_inherit_session_owner(
944
+ p_session_id TEXT,
945
+ p_parent_session_id TEXT
946
+ ) RETURNS VOID AS $$
947
+ DECLARE
948
+ v_is_system BOOLEAN;
949
+ BEGIN
950
+ SELECT is_system INTO v_is_system
951
+ FROM ${s}.sessions
952
+ WHERE session_id = p_session_id AND deleted_at IS NULL;
953
+
954
+ IF NOT FOUND OR v_is_system THEN
955
+ RETURN;
956
+ END IF;
957
+
958
+ INSERT INTO ${s}.session_owners (session_id, user_id)
959
+ SELECT p_session_id, so.user_id
960
+ FROM ${s}.session_owners so
961
+ WHERE so.session_id = p_parent_session_id
962
+ ON CONFLICT (session_id) DO NOTHING;
963
+ END;
964
+ $$ LANGUAGE plpgsql;
965
+
966
+ -- PostgreSQL refuses CREATE OR REPLACE FUNCTION when the return row shape
967
+ -- changes, so the read functions are drop-then-create.
968
+
969
+ -- ── cms_list_sessions (drop + recreate with owner join) ──────────
970
+ DROP FUNCTION IF EXISTS ${s}.cms_list_sessions();
971
+ CREATE FUNCTION ${s}.cms_list_sessions()
972
+ RETURNS TABLE (
973
+ session_id TEXT,
974
+ orchestration_id TEXT,
975
+ title TEXT,
976
+ title_locked BOOLEAN,
977
+ state TEXT,
978
+ model TEXT,
979
+ created_at TIMESTAMPTZ,
980
+ updated_at TIMESTAMPTZ,
981
+ last_active_at TIMESTAMPTZ,
982
+ deleted_at TIMESTAMPTZ,
983
+ current_iteration INTEGER,
984
+ last_error TEXT,
985
+ parent_session_id TEXT,
986
+ wait_reason TEXT,
987
+ is_system BOOLEAN,
988
+ agent_id TEXT,
989
+ splash TEXT,
990
+ owner_provider TEXT,
991
+ owner_subject TEXT,
992
+ owner_email TEXT,
993
+ owner_display_name TEXT
994
+ ) AS $$
995
+ BEGIN
996
+ RETURN QUERY
997
+ SELECT
998
+ sess.session_id,
999
+ sess.orchestration_id,
1000
+ sess.title,
1001
+ sess.title_locked,
1002
+ sess.state,
1003
+ sess.model,
1004
+ sess.created_at,
1005
+ sess.updated_at,
1006
+ sess.last_active_at,
1007
+ sess.deleted_at,
1008
+ sess.current_iteration,
1009
+ sess.last_error,
1010
+ sess.parent_session_id,
1011
+ sess.wait_reason,
1012
+ sess.is_system,
1013
+ sess.agent_id,
1014
+ sess.splash,
1015
+ u.provider AS owner_provider,
1016
+ u.subject AS owner_subject,
1017
+ u.email AS owner_email,
1018
+ u.display_name AS owner_display_name
1019
+ FROM ${s}.sessions sess
1020
+ LEFT JOIN ${s}.session_owners so ON so.session_id = sess.session_id
1021
+ LEFT JOIN ${s}.users u ON u.user_id = so.user_id
1022
+ WHERE sess.deleted_at IS NULL
1023
+ ORDER BY sess.updated_at DESC;
1024
+ END;
1025
+ $$ LANGUAGE plpgsql;
1026
+
1027
+ -- ── cms_get_session (drop + recreate with owner join) ────────────
1028
+ DROP FUNCTION IF EXISTS ${s}.cms_get_session(TEXT);
1029
+ CREATE FUNCTION ${s}.cms_get_session(
1030
+ p_session_id TEXT
1031
+ ) RETURNS TABLE (
1032
+ session_id TEXT,
1033
+ orchestration_id TEXT,
1034
+ title TEXT,
1035
+ title_locked BOOLEAN,
1036
+ state TEXT,
1037
+ model TEXT,
1038
+ created_at TIMESTAMPTZ,
1039
+ updated_at TIMESTAMPTZ,
1040
+ last_active_at TIMESTAMPTZ,
1041
+ deleted_at TIMESTAMPTZ,
1042
+ current_iteration INTEGER,
1043
+ last_error TEXT,
1044
+ parent_session_id TEXT,
1045
+ wait_reason TEXT,
1046
+ is_system BOOLEAN,
1047
+ agent_id TEXT,
1048
+ splash TEXT,
1049
+ owner_provider TEXT,
1050
+ owner_subject TEXT,
1051
+ owner_email TEXT,
1052
+ owner_display_name TEXT
1053
+ ) AS $$
1054
+ BEGIN
1055
+ RETURN QUERY
1056
+ SELECT
1057
+ sess.session_id,
1058
+ sess.orchestration_id,
1059
+ sess.title,
1060
+ sess.title_locked,
1061
+ sess.state,
1062
+ sess.model,
1063
+ sess.created_at,
1064
+ sess.updated_at,
1065
+ sess.last_active_at,
1066
+ sess.deleted_at,
1067
+ sess.current_iteration,
1068
+ sess.last_error,
1069
+ sess.parent_session_id,
1070
+ sess.wait_reason,
1071
+ sess.is_system,
1072
+ sess.agent_id,
1073
+ sess.splash,
1074
+ u.provider AS owner_provider,
1075
+ u.subject AS owner_subject,
1076
+ u.email AS owner_email,
1077
+ u.display_name AS owner_display_name
1078
+ FROM ${s}.sessions sess
1079
+ LEFT JOIN ${s}.session_owners so ON so.session_id = sess.session_id
1080
+ LEFT JOIN ${s}.users u ON u.user_id = so.user_id
1081
+ WHERE sess.session_id = p_session_id AND sess.deleted_at IS NULL;
1082
+ END;
1083
+ $$ LANGUAGE plpgsql;
1084
+ `;
1085
+ }
1086
+ // ─── Migration 0009: User Stats By Model ─────────────────────────
1087
+ function migration_0009_user_stats_by_model(schema) {
1088
+ const s = `"${schema}"`;
1089
+ return `
1090
+ -- 0009_user_stats_by_model: user/session-owner aggregate for the stats pane.
1091
+ -- Runtime orchestration history bytes are enriched by management code because
1092
+ -- they live in the orchestration provider, not in CMS tables.
1093
+
1094
+ CREATE OR REPLACE FUNCTION ${s}.cms_get_user_stats_by_model(
1095
+ p_include_deleted BOOLEAN,
1096
+ p_since TIMESTAMPTZ
1097
+ ) RETURNS TABLE (
1098
+ owner_kind TEXT,
1099
+ owner_provider TEXT,
1100
+ owner_subject TEXT,
1101
+ owner_email TEXT,
1102
+ owner_display_name TEXT,
1103
+ model TEXT,
1104
+ session_ids TEXT[],
1105
+ session_count INT,
1106
+ total_snapshot_size_bytes BIGINT,
1107
+ total_dehydration_count INT,
1108
+ total_hydration_count INT,
1109
+ total_lossy_handoff_count INT,
1110
+ total_tokens_input BIGINT,
1111
+ total_tokens_output BIGINT,
1112
+ total_tokens_cache_read BIGINT,
1113
+ total_tokens_cache_write BIGINT,
1114
+ earliest_session_created_at TIMESTAMPTZ
1115
+ ) AS $$
1116
+ BEGIN
1117
+ RETURN QUERY
1118
+ WITH base AS (
1119
+ SELECT
1120
+ CASE
1121
+ WHEN sess.is_system THEN 'system'
1122
+ WHEN u.user_id IS NULL THEN 'unowned'
1123
+ ELSE 'user'
1124
+ END::text AS owner_kind,
1125
+ u.provider AS owner_provider,
1126
+ u.subject AS owner_subject,
1127
+ u.email AS owner_email,
1128
+ u.display_name AS owner_display_name,
1129
+ m.model,
1130
+ m.session_id,
1131
+ m.created_at,
1132
+ m.snapshot_size_bytes,
1133
+ m.dehydration_count,
1134
+ m.hydration_count,
1135
+ m.lossy_handoff_count,
1136
+ m.tokens_input,
1137
+ m.tokens_output,
1138
+ m.tokens_cache_read,
1139
+ m.tokens_cache_write
1140
+ FROM ${s}.session_metric_summaries m
1141
+ INNER JOIN ${s}.sessions sess ON sess.session_id = m.session_id
1142
+ LEFT JOIN ${s}.session_owners so ON so.session_id = m.session_id
1143
+ LEFT JOIN ${s}.users u ON u.user_id = so.user_id
1144
+ WHERE (p_include_deleted OR m.deleted_at IS NULL)
1145
+ AND (p_since IS NULL OR m.created_at >= p_since)
1146
+ )
1147
+ SELECT
1148
+ b.owner_kind AS owner_kind,
1149
+ b.owner_provider AS owner_provider,
1150
+ b.owner_subject AS owner_subject,
1151
+ b.owner_email AS owner_email,
1152
+ b.owner_display_name AS owner_display_name,
1153
+ b.model AS model,
1154
+ ARRAY_AGG(b.session_id ORDER BY b.created_at DESC) AS session_ids,
1155
+ COUNT(*)::int AS session_count,
1156
+ COALESCE(SUM(b.snapshot_size_bytes), 0)::bigint AS total_snapshot_size_bytes,
1157
+ COALESCE(SUM(b.dehydration_count), 0)::int AS total_dehydration_count,
1158
+ COALESCE(SUM(b.hydration_count), 0)::int AS total_hydration_count,
1159
+ COALESCE(SUM(b.lossy_handoff_count), 0)::int AS total_lossy_handoff_count,
1160
+ COALESCE(SUM(b.tokens_input), 0)::bigint AS total_tokens_input,
1161
+ COALESCE(SUM(b.tokens_output), 0)::bigint AS total_tokens_output,
1162
+ COALESCE(SUM(b.tokens_cache_read), 0)::bigint AS total_tokens_cache_read,
1163
+ COALESCE(SUM(b.tokens_cache_write), 0)::bigint AS total_tokens_cache_write,
1164
+ MIN(b.created_at) AS earliest_session_created_at
1165
+ FROM base b
1166
+ GROUP BY
1167
+ b.owner_kind,
1168
+ b.owner_provider,
1169
+ b.owner_subject,
1170
+ b.owner_email,
1171
+ b.owner_display_name,
1172
+ b.model
1173
+ ORDER BY
1174
+ COALESCE(SUM(b.tokens_input), 0)::bigint DESC,
1175
+ b.owner_kind,
1176
+ b.owner_display_name,
1177
+ b.owner_email,
1178
+ b.model;
1179
+ END;
1180
+ $$ LANGUAGE plpgsql;
1181
+ `;
1182
+ }
555
1183
  //# sourceMappingURL=cms-migrations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cms-migrations.js","sourceRoot":"","sources":["../src/cms-migrations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cms-migrations.js","sourceRoot":"","sources":["../src/cms-migrations.ts"],"names":[],"mappings":"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"}