@stackbone/cli 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/main.js +7468 -4123
- package/migrations/0094_rag_document_versions.sql +61 -0
- package/migrations/0095_rag_document_version_counters.sql +22 -0
- package/migrations/0096_trigger_subscriptions_target_kind.sql +29 -0
- package/migrations/0098_model_selections_provider_id.sql +23 -0
- package/migrations/0099_memory.sql +35 -0
- package/migrations/0100_memory_call_run.sql +9 -0
- package/package.json +1 -1
- package/stackbone-cli-0.6.3.tgz +0 -0
- package/stackbone-cli-0.6.2.tgz +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
-- 0094_rag_document_versions.sql — RAG document versions (STA3-8)
|
|
2
|
+
-- Every version of a document is its own row, with its own `source` (its storage
|
|
3
|
+
-- key) and its own chunks, so rollback flips a flag and re-embeds nothing. The
|
|
4
|
+
-- versions of one document share a `document_key`; the agent reads only the
|
|
5
|
+
-- `is_active` one.
|
|
6
|
+
--
|
|
7
|
+
-- A document that existed before this is its own version 1, published, keyed by
|
|
8
|
+
-- its `source`.
|
|
9
|
+
|
|
10
|
+
ALTER TABLE stackbone_platform.rag_documents
|
|
11
|
+
ADD COLUMN IF NOT EXISTS document_key text,
|
|
12
|
+
ADD COLUMN IF NOT EXISTS version integer NOT NULL DEFAULT 1,
|
|
13
|
+
ADD COLUMN IF NOT EXISTS is_active boolean NOT NULL DEFAULT true;
|
|
14
|
+
|
|
15
|
+
-- Two overlapping ingests of one source could leave two rows before PLA-2327's
|
|
16
|
+
-- lock. The newest keeps the source as its key; the older ones become documents
|
|
17
|
+
-- of their own, still published, so nothing the agent reads changes and the
|
|
18
|
+
-- unique index below can build. Deleting them would lose data.
|
|
19
|
+
UPDATE stackbone_platform.rag_documents d
|
|
20
|
+
SET document_key = CASE WHEN ranked.rn = 1 THEN d.source ELSE d.source || '#' || d.id END
|
|
21
|
+
FROM (
|
|
22
|
+
SELECT id, row_number() OVER (
|
|
23
|
+
PARTITION BY collection_id, source ORDER BY created_at DESC, id DESC
|
|
24
|
+
) AS rn
|
|
25
|
+
FROM stackbone_platform.rag_documents
|
|
26
|
+
WHERE document_key IS NULL
|
|
27
|
+
) ranked
|
|
28
|
+
WHERE d.id = ranked.id;
|
|
29
|
+
|
|
30
|
+
-- Postgres cannot default one column to another. A workspace on an SDK older
|
|
31
|
+
-- than this migration inserts without the key, so the trigger fills it in
|
|
32
|
+
-- instead of failing every ingest on NOT NULL.
|
|
33
|
+
CREATE OR REPLACE FUNCTION stackbone_platform.rag_documents_default_key()
|
|
34
|
+
RETURNS trigger
|
|
35
|
+
LANGUAGE plpgsql
|
|
36
|
+
AS $$
|
|
37
|
+
BEGIN
|
|
38
|
+
NEW.document_key := COALESCE(NEW.document_key, NEW.source);
|
|
39
|
+
RETURN NEW;
|
|
40
|
+
END;
|
|
41
|
+
$$;
|
|
42
|
+
|
|
43
|
+
DROP TRIGGER IF EXISTS rag_documents_default_key ON stackbone_platform.rag_documents;
|
|
44
|
+
CREATE TRIGGER rag_documents_default_key
|
|
45
|
+
BEFORE INSERT ON stackbone_platform.rag_documents
|
|
46
|
+
FOR EACH ROW EXECUTE FUNCTION stackbone_platform.rag_documents_default_key();
|
|
47
|
+
|
|
48
|
+
ALTER TABLE stackbone_platform.rag_documents
|
|
49
|
+
ALTER COLUMN document_key SET NOT NULL;
|
|
50
|
+
|
|
51
|
+
-- At most one published version per document. Non-deferrable, so publishing is
|
|
52
|
+
-- two statements (unpublish the siblings, then publish the target): one swapping
|
|
53
|
+
-- UPDATE can reach the target before the sibling and fail on the check.
|
|
54
|
+
CREATE UNIQUE INDEX IF NOT EXISTS rag_documents_active_key_uq
|
|
55
|
+
ON stackbone_platform.rag_documents (collection_id, document_key)
|
|
56
|
+
WHERE is_active;
|
|
57
|
+
|
|
58
|
+
-- Covers unpublished versions too: a writer that misses the key lock and hands
|
|
59
|
+
-- out a version number twice fails here instead of leaving two v2s behind.
|
|
60
|
+
CREATE UNIQUE INDEX IF NOT EXISTS rag_documents_key_version_uq
|
|
61
|
+
ON stackbone_platform.rag_documents (collection_id, document_key, version);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- 0095_rag_document_version_counters.sql — a version number is never reused (STA3-8 D11)
|
|
2
|
+
-- The last version number each document handed out. Numbering from the rows
|
|
3
|
+
-- left (`max(version) + 1`) gave a deleted draft's number to the next upload,
|
|
4
|
+
-- and the activity log then showed "deleted v3" next to a live, different v3.
|
|
5
|
+
-- A new version takes this counter or the rows' highest version, whichever is
|
|
6
|
+
-- greater, plus one, under the document's key lock. Deleting the whole document
|
|
7
|
+
-- drops its row; deleting one version leaves it alone.
|
|
8
|
+
|
|
9
|
+
CREATE TABLE IF NOT EXISTS stackbone_platform.rag_document_version_counters (
|
|
10
|
+
collection_id uuid NOT NULL REFERENCES stackbone_platform.rag_collections (id) ON DELETE CASCADE,
|
|
11
|
+
document_key text NOT NULL,
|
|
12
|
+
last_version integer NOT NULL,
|
|
13
|
+
PRIMARY KEY (collection_id, document_key)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- A document from before this starts from the highest version it still holds:
|
|
17
|
+
-- a number deleted before 0095 cannot be told apart from one never handed out.
|
|
18
|
+
INSERT INTO stackbone_platform.rag_document_version_counters (collection_id, document_key, last_version)
|
|
19
|
+
SELECT collection_id, document_key, max(version)
|
|
20
|
+
FROM stackbone_platform.rag_documents
|
|
21
|
+
GROUP BY collection_id, document_key
|
|
22
|
+
ON CONFLICT (collection_id, document_key) DO NOTHING;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- 0096_trigger_subscriptions_target_kind.sql — a link's destination carries a kind (PLA-967)
|
|
2
|
+
-- A connector trigger is about to start a deep agent as well as a workflow (PLA-951),
|
|
3
|
+
-- and `workflow_name` (0021) gave the destination a name and no kind. The column
|
|
4
|
+
-- becomes `target_name` beside a `target_kind`, the same pair `eval_suites` uses
|
|
5
|
+
-- (0038). Every link that existed before reads as a workflow link through the default.
|
|
6
|
+
--
|
|
7
|
+
-- No CHECK on `target_kind`, as `eval_suites.target_kind` (0038) and `runs.entity_kind`
|
|
8
|
+
-- (0037): a box running an older build must be able to store a kind it cannot run
|
|
9
|
+
-- rather than reject the write. The register endpoint refuses what it cannot start.
|
|
10
|
+
--
|
|
11
|
+
-- `RENAME COLUMN` has no `IF EXISTS`, and a DBA who applies the platform SQL by hand
|
|
12
|
+
-- (`STACKBONE_SKIP_MIGRATIONS=1`) can run it twice, so the rename is guarded on the
|
|
13
|
+
-- old column still being there.
|
|
14
|
+
|
|
15
|
+
DO $$
|
|
16
|
+
BEGIN
|
|
17
|
+
IF EXISTS (
|
|
18
|
+
SELECT 1 FROM information_schema.columns
|
|
19
|
+
WHERE table_schema = 'stackbone_platform'
|
|
20
|
+
AND table_name = 'trigger_subscriptions'
|
|
21
|
+
AND column_name = 'workflow_name'
|
|
22
|
+
) THEN
|
|
23
|
+
ALTER TABLE stackbone_platform.trigger_subscriptions
|
|
24
|
+
RENAME COLUMN workflow_name TO target_name;
|
|
25
|
+
END IF;
|
|
26
|
+
END $$;
|
|
27
|
+
|
|
28
|
+
ALTER TABLE stackbone_platform.trigger_subscriptions
|
|
29
|
+
ADD COLUMN IF NOT EXISTS target_kind text NOT NULL DEFAULT 'workflow';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- 0098_model_selections_provider_id.sql — the provider an operator picked next
|
|
2
|
+
-- to the model, for a box that runs more than one (STA3-17, decision D10).
|
|
3
|
+
--
|
|
4
|
+
-- Two providers may serve the same model id. A pick that names only the id is
|
|
5
|
+
-- ambiguous there, so the pick also names the provider that serves it. The SDK
|
|
6
|
+
-- composes `<providerId>::<modelId>` when it reads a pick; this column is where
|
|
7
|
+
-- the provider half lives.
|
|
8
|
+
--
|
|
9
|
+
-- Its own column, not a `b::gpt-4o` string in `model_id`: every box reader of
|
|
10
|
+
-- `model_id` would then have to split it (D10).
|
|
11
|
+
--
|
|
12
|
+
-- NULLABLE, with no default and no backfill. Every pick saved before this file
|
|
13
|
+
-- named no provider, and "no provider" keeps today's resolution: the box sends
|
|
14
|
+
-- the id to the one provider that serves it, or refuses it as ambiguous when two
|
|
15
|
+
-- do. Free text with NO CHECK and no foreign key (providers live in system
|
|
16
|
+
-- secrets, not a table), for the same reason 0073 has none on `model_id`: the
|
|
17
|
+
-- provider may be removed while a pick still names it, and that fails at run
|
|
18
|
+
-- time, not at write.
|
|
19
|
+
--
|
|
20
|
+
-- The PRIMARY KEY stays (owner_kind, owner_name, key): one pick per key, whatever
|
|
21
|
+
-- provider serves it.
|
|
22
|
+
ALTER TABLE stackbone_platform.model_selections
|
|
23
|
+
ADD COLUMN IF NOT EXISTS provider_id text;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
-- 0099_memory.sql — per-person long-term facts and call history (FDE-68)
|
|
2
|
+
-- Memory is platform-owned box state: it follows RAG into the
|
|
3
|
+
-- stackbone_platform schema so every deployed workspace receives it.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS stackbone_platform.memory_calls (
|
|
6
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
7
|
+
user_id text NOT NULL,
|
|
8
|
+
started_at timestamptz NOT NULL,
|
|
9
|
+
duration_seconds integer CHECK (duration_seconds >= 0),
|
|
10
|
+
outcome text CHECK (outcome IS NULL OR char_length(outcome) BETWEEN 1 AND 100),
|
|
11
|
+
summary text NOT NULL CHECK (char_length(summary) BETWEEN 1 AND 600),
|
|
12
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS memory_calls_user_started_idx
|
|
16
|
+
ON stackbone_platform.memory_calls (user_id, started_at DESC, created_at DESC);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS stackbone_platform.memory_facts (
|
|
19
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
20
|
+
user_id text NOT NULL,
|
|
21
|
+
content text NOT NULL CHECK (char_length(content) BETWEEN 1 AND 500),
|
|
22
|
+
insertion_order bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
|
|
23
|
+
created_call_id uuid REFERENCES stackbone_platform.memory_calls(id) ON DELETE SET NULL,
|
|
24
|
+
updated_call_id uuid REFERENCES stackbone_platform.memory_calls(id) ON DELETE SET NULL,
|
|
25
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
26
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX IF NOT EXISTS memory_facts_user_idx
|
|
30
|
+
ON stackbone_platform.memory_facts (user_id);
|
|
31
|
+
|
|
32
|
+
CREATE TABLE IF NOT EXISTS stackbone_platform.memory_user_revisions (
|
|
33
|
+
user_id text PRIMARY KEY,
|
|
34
|
+
revision bigint NOT NULL DEFAULT 0 CHECK (revision >= 0)
|
|
35
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- A memory record keeps the run that owns the full transcript without copying
|
|
2
|
+
-- transcript content into memory itself.
|
|
3
|
+
|
|
4
|
+
ALTER TABLE stackbone_platform.memory_calls
|
|
5
|
+
ADD COLUMN IF NOT EXISTS run_id uuid
|
|
6
|
+
REFERENCES stackbone_platform.runs(id) ON DELETE SET NULL;
|
|
7
|
+
|
|
8
|
+
CREATE INDEX IF NOT EXISTS memory_calls_run_idx
|
|
9
|
+
ON stackbone_platform.memory_calls (run_id);
|
package/package.json
CHANGED
|
Binary file
|
package/stackbone-cli-0.6.2.tgz
DELETED
|
Binary file
|