@pleri/olam-cli 0.1.159 → 0.1.160
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/dist/agent-stream/agent-sdk-to-chunks.js +3 -0
- package/dist/agent-stream/driver-runner.js +9 -4
- package/dist/agent-stream/host-driver-launch.js +48 -0
- package/dist/commands/flywheel/check-persona-skeleton.d.ts +30 -2
- package/dist/commands/flywheel/check-persona-skeleton.d.ts.map +1 -1
- package/dist/commands/flywheel/check-persona-skeleton.js +143 -6
- package/dist/commands/flywheel/check-persona-skeleton.js.map +1 -1
- package/dist/commands/flywheel/diversity-check.d.ts +12 -2
- package/dist/commands/flywheel/diversity-check.d.ts.map +1 -1
- package/dist/commands/flywheel/diversity-check.js +56 -6
- package/dist/commands/flywheel/diversity-check.js.map +1 -1
- package/dist/commands/flywheel/index.d.ts.map +1 -1
- package/dist/commands/flywheel/index.js +2 -0
- package/dist/commands/flywheel/index.js.map +1 -1
- package/dist/commands/flywheel/install-shims.d.ts +36 -3
- package/dist/commands/flywheel/install-shims.d.ts.map +1 -1
- package/dist/commands/flywheel/install-shims.js +118 -7
- package/dist/commands/flywheel/install-shims.js.map +1 -1
- package/dist/commands/flywheel/k10-measure.d.ts +12 -2
- package/dist/commands/flywheel/k10-measure.d.ts.map +1 -1
- package/dist/commands/flywheel/k10-measure.js +55 -6
- package/dist/commands/flywheel/k10-measure.js.map +1 -1
- package/dist/commands/flywheel/migrate-overlays.d.ts +115 -0
- package/dist/commands/flywheel/migrate-overlays.d.ts.map +1 -0
- package/dist/commands/flywheel/migrate-overlays.js +766 -0
- package/dist/commands/flywheel/migrate-overlays.js.map +1 -0
- package/dist/commands/flywheel/sanitize-persona-output.d.ts +33 -2
- package/dist/commands/flywheel/sanitize-persona-output.d.ts.map +1 -1
- package/dist/commands/flywheel/sanitize-persona-output.js +94 -6
- package/dist/commands/flywheel/sanitize-persona-output.js.map +1 -1
- package/dist/commands/memory/index.d.ts.map +1 -1
- package/dist/commands/memory/index.js +2 -0
- package/dist/commands/memory/index.js.map +1 -1
- package/dist/commands/memory/install-hooks.d.ts +22 -0
- package/dist/commands/memory/install-hooks.d.ts.map +1 -0
- package/dist/commands/memory/install-hooks.js +156 -0
- package/dist/commands/memory/install-hooks.js.map +1 -0
- package/dist/commands/skills-doctor.js +2 -2
- package/dist/commands/skills-doctor.js.map +1 -1
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +10 -0
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +169 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/image-digests.json +7 -7
- package/dist/index.js +3046 -718
- package/dist/lib/flywheel-probes.d.ts +58 -0
- package/dist/lib/flywheel-probes.d.ts.map +1 -0
- package/dist/lib/flywheel-probes.js +163 -0
- package/dist/lib/flywheel-probes.js.map +1 -0
- package/dist/lib/shim-generator.d.ts +51 -0
- package/dist/lib/shim-generator.d.ts.map +1 -0
- package/dist/lib/shim-generator.js +88 -0
- package/dist/lib/shim-generator.js.map +1 -0
- package/dist/lib/skills-apply-overlays.d.ts +35 -0
- package/dist/lib/skills-apply-overlays.d.ts.map +1 -0
- package/dist/lib/skills-apply-overlays.js +243 -0
- package/dist/lib/skills-apply-overlays.js.map +1 -0
- package/dist/mcp-server.js +1106 -453
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/30-configmap.yaml +11 -0
- package/host-cp/k8s/manifests/memory-service/35-configmap-iii-config.yaml +76 -0
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +11 -1
- package/host-cp/src/crystallize-planning.mjs +261 -0
- package/host-cp/src/plan-chat-service.mjs +84 -2
- package/host-cp/src/planning-sessions.mjs +270 -0
- package/package.json +1 -1
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// planning-sessions — host-cp surface for creating and inspecting in-flight
|
|
2
|
+
// planning sessions stored under world_id = PLANNING_WORLD_ID ('_planning').
|
|
3
|
+
//
|
|
4
|
+
// Formalises what the plan-chat-spa dev substrate does ad hoc:
|
|
5
|
+
//
|
|
6
|
+
// createPlanningSession({ actorId, pool })
|
|
7
|
+
// Seeds a session with one 'system' chunk so the Electric shape subscriber
|
|
8
|
+
// gets a non-empty initial response on its first long-poll cycle. Also
|
|
9
|
+
// INSERTs a row into the planning_sessions sidecar table inside the same
|
|
10
|
+
// transaction so no partial state can exist (chunk written, no metadata row).
|
|
11
|
+
// Returns the allocated world_id, session_id, and the inserted seed chunk.
|
|
12
|
+
//
|
|
13
|
+
// loadPlanningSession({ pool, sessionId })
|
|
14
|
+
// Lightweight metadata read: chunk count, first/last timestamps, first
|
|
15
|
+
// operator content (for title derivation). SPA still streams live chunks
|
|
16
|
+
// via the existing /v1/shape proxy — this is metadata-only.
|
|
17
|
+
//
|
|
18
|
+
// recordPlanningSession({ pool, sessionId, actorId, summary })
|
|
19
|
+
// UPSERT into planning_sessions. Used by createPlanningSession (wrapped in
|
|
20
|
+
// a transaction) and later to update the summary as the session evolves.
|
|
21
|
+
//
|
|
22
|
+
// setCrystallizeStatus({ pool, sessionId, status, worldId })
|
|
23
|
+
// UPDATE planning_sessions.crystallize_status + crystallized_world_id.
|
|
24
|
+
// Throws if status is not in PLANNING_SESSION_STATUSES.
|
|
25
|
+
//
|
|
26
|
+
// listPlanningSessions({ pool, actorId, limit })
|
|
27
|
+
// SELECT rows for actorId, ordered created_at DESC. Returns array.
|
|
28
|
+
//
|
|
29
|
+
// Neither function calls validateChunkInput — that's for the public POST
|
|
30
|
+
// surface. INSERTs here are built directly against the chunks column list.
|
|
31
|
+
//
|
|
32
|
+
// Pool errors surface loudly (never swallowed) so the caller sees the full
|
|
33
|
+
// pg error message and can diagnose connectivity or constraint failures.
|
|
34
|
+
|
|
35
|
+
import { randomUUID } from 'node:crypto';
|
|
36
|
+
import { PLANNING_WORLD_ID, PLANNING_SESSION_STATUSES } from '@olam/chunks/schema';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* UPSERT a row in planning_sessions for the given sessionId.
|
|
40
|
+
*
|
|
41
|
+
* On first call (from createPlanningSession): inserts a fresh row.
|
|
42
|
+
* On subsequent calls: updates summary + updated_at only (leaves
|
|
43
|
+
* crystallize_status and crystallized_world_id untouched).
|
|
44
|
+
*
|
|
45
|
+
* @param {object} opts
|
|
46
|
+
* @param {object} opts.pool
|
|
47
|
+
* @param {string} opts.sessionId
|
|
48
|
+
* @param {string} opts.actorId
|
|
49
|
+
* @param {string | null} [opts.summary]
|
|
50
|
+
*/
|
|
51
|
+
export async function recordPlanningSession({ pool, sessionId, actorId, summary = null }) {
|
|
52
|
+
await pool.query(
|
|
53
|
+
`INSERT INTO planning_sessions (session_id, actor_id, summary)
|
|
54
|
+
VALUES ($1, $2, $3)
|
|
55
|
+
ON CONFLICT (session_id) DO UPDATE
|
|
56
|
+
SET summary = EXCLUDED.summary,
|
|
57
|
+
updated_at = NOW()`,
|
|
58
|
+
[sessionId, actorId, summary],
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a new in-flight planning session under world_id='_planning'.
|
|
64
|
+
*
|
|
65
|
+
* Allocates a fresh session_id (UUID v4) and, inside a single transaction:
|
|
66
|
+
* 1. INSERTs a seed chunk (actor_type='system', seq=0) so the Electric shape
|
|
67
|
+
* subscriber receives a non-empty initial long-poll response.
|
|
68
|
+
* 2. INSERTs a planning_sessions sidecar row (via recordPlanningSession) so
|
|
69
|
+
* listPlanningSessions can return it immediately.
|
|
70
|
+
*
|
|
71
|
+
* Transaction guarantee: both INSERTs succeed or both roll back. A chunk
|
|
72
|
+
* written without a corresponding planning_sessions row is the partial-state
|
|
73
|
+
* bug this transaction prevents.
|
|
74
|
+
*
|
|
75
|
+
* @param {object} opts
|
|
76
|
+
* @param {string} opts.actorId — actor_id to attribute the seed chunk to
|
|
77
|
+
* (typically 'system' or the host-cp service id)
|
|
78
|
+
* @param {object} opts.pool — pg.Pool-compatible object with .query() and
|
|
79
|
+
* optionally .connect() for transactional clients.
|
|
80
|
+
* Tests may supply a stub with a transaction-aware
|
|
81
|
+
* .query() (BEGIN / INSERT / INSERT / COMMIT).
|
|
82
|
+
* @returns {Promise<{
|
|
83
|
+
* world_id: string,
|
|
84
|
+
* session_id: string,
|
|
85
|
+
* seed_chunk: {
|
|
86
|
+
* world_id: string, session_id: string, message_id: string, seq: number,
|
|
87
|
+
* actor_id: string, actor_type: string, role: string, chunk: string,
|
|
88
|
+
* chunk_type: string,
|
|
89
|
+
* },
|
|
90
|
+
* }>}
|
|
91
|
+
*/
|
|
92
|
+
export async function createPlanningSession({ actorId, pool }) {
|
|
93
|
+
const sessionId = randomUUID();
|
|
94
|
+
const messageId = randomUUID();
|
|
95
|
+
const seq = 0;
|
|
96
|
+
const actorType = 'system';
|
|
97
|
+
const role = 'system';
|
|
98
|
+
const chunk = 'Planning session created.';
|
|
99
|
+
const chunkType = 'text';
|
|
100
|
+
|
|
101
|
+
// Use a transactional client when pool.connect() is available (real pg.Pool).
|
|
102
|
+
// Test stubs that only implement .query() fall through to the flat path;
|
|
103
|
+
// the transactional contract is proven by the test that uses a stub whose
|
|
104
|
+
// second .query() throws and asserts the chunk INSERT was rolled back.
|
|
105
|
+
if (typeof pool.connect === 'function') {
|
|
106
|
+
const client = await pool.connect();
|
|
107
|
+
try {
|
|
108
|
+
await client.query('BEGIN');
|
|
109
|
+
await client.query(
|
|
110
|
+
`INSERT INTO chunks
|
|
111
|
+
(world_id, session_id, message_id, seq, actor_id, actor_type, role, chunk, chunk_type)
|
|
112
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
|
113
|
+
[PLANNING_WORLD_ID, sessionId, messageId, seq, actorId, actorType, role, chunk, chunkType],
|
|
114
|
+
);
|
|
115
|
+
await recordPlanningSession({ pool: client, sessionId, actorId, summary: null });
|
|
116
|
+
await client.query('COMMIT');
|
|
117
|
+
} catch (err) {
|
|
118
|
+
await client.query('ROLLBACK');
|
|
119
|
+
throw err;
|
|
120
|
+
} finally {
|
|
121
|
+
client.release();
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
// Flat path for test stubs: queries run sequentially on the stub pool.
|
|
125
|
+
await pool.query(
|
|
126
|
+
`INSERT INTO chunks
|
|
127
|
+
(world_id, session_id, message_id, seq, actor_id, actor_type, role, chunk, chunk_type)
|
|
128
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
|
129
|
+
[PLANNING_WORLD_ID, sessionId, messageId, seq, actorId, actorType, role, chunk, chunkType],
|
|
130
|
+
);
|
|
131
|
+
await recordPlanningSession({ pool, sessionId, actorId, summary: null });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
world_id: PLANNING_WORLD_ID,
|
|
136
|
+
session_id: sessionId,
|
|
137
|
+
seed_chunk: {
|
|
138
|
+
world_id: PLANNING_WORLD_ID,
|
|
139
|
+
session_id: sessionId,
|
|
140
|
+
message_id: messageId,
|
|
141
|
+
seq,
|
|
142
|
+
actor_id: actorId,
|
|
143
|
+
actor_type: actorType,
|
|
144
|
+
role,
|
|
145
|
+
chunk,
|
|
146
|
+
chunk_type: chunkType,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Update crystallize_status (and optionally crystallized_world_id) for a
|
|
153
|
+
* planning session.
|
|
154
|
+
*
|
|
155
|
+
* @param {object} opts
|
|
156
|
+
* @param {object} opts.pool
|
|
157
|
+
* @param {string} opts.sessionId
|
|
158
|
+
* @param {string} opts.status — must be in PLANNING_SESSION_STATUSES
|
|
159
|
+
* @param {string | null} [opts.worldId] — required when status='crystallized'
|
|
160
|
+
*/
|
|
161
|
+
export async function setCrystallizeStatus({ pool, sessionId, status, worldId = null }) {
|
|
162
|
+
if (!PLANNING_SESSION_STATUSES.includes(status)) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`setCrystallizeStatus: invalid status "${status}"; ` +
|
|
165
|
+
`must be one of ${PLANNING_SESSION_STATUSES.join(', ')}`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
await pool.query(
|
|
169
|
+
`UPDATE planning_sessions
|
|
170
|
+
SET crystallize_status = $2,
|
|
171
|
+
crystallized_world_id = $3,
|
|
172
|
+
updated_at = NOW()
|
|
173
|
+
WHERE session_id = $1`,
|
|
174
|
+
[sessionId, status, worldId],
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* List planning sessions for a given actorId, ordered by created_at DESC.
|
|
180
|
+
*
|
|
181
|
+
* @param {object} opts
|
|
182
|
+
* @param {object} opts.pool
|
|
183
|
+
* @param {string} opts.actorId
|
|
184
|
+
* @param {number} [opts.limit=50]
|
|
185
|
+
* @returns {Promise<Array<{
|
|
186
|
+
* session_id: string,
|
|
187
|
+
* summary: string | null,
|
|
188
|
+
* crystallize_status: string,
|
|
189
|
+
* crystallized_world_id: string | null,
|
|
190
|
+
* created_at: string,
|
|
191
|
+
* updated_at: string,
|
|
192
|
+
* }>>}
|
|
193
|
+
*/
|
|
194
|
+
export async function listPlanningSessions({ pool, actorId, limit = 50 }) {
|
|
195
|
+
const result = await pool.query(
|
|
196
|
+
`SELECT session_id, summary, crystallize_status, crystallized_world_id,
|
|
197
|
+
created_at, updated_at
|
|
198
|
+
FROM planning_sessions
|
|
199
|
+
WHERE actor_id = $1
|
|
200
|
+
ORDER BY created_at DESC
|
|
201
|
+
LIMIT $2`,
|
|
202
|
+
[actorId, limit],
|
|
203
|
+
);
|
|
204
|
+
return result.rows;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Load lightweight metadata for an existing in-flight planning session.
|
|
209
|
+
*
|
|
210
|
+
* Performs two queries scoped to world_id='_planning' AND session_id=<sessionId>:
|
|
211
|
+
* 1. Aggregate: chunk_count, first_chunk_at, last_chunk_at.
|
|
212
|
+
* 2. First operator content: earliest chunk where actor_type='operator',
|
|
213
|
+
* used by the SPA for session title derivation.
|
|
214
|
+
*
|
|
215
|
+
* The SPA streams live chunks via the existing /v1/shape proxy; this function
|
|
216
|
+
* is metadata-only and does NOT subscribe to any Electric shape.
|
|
217
|
+
*
|
|
218
|
+
* @param {object} opts
|
|
219
|
+
* @param {object} opts.pool — pg.Pool-compatible object with a .query(sql, params) method
|
|
220
|
+
* @param {string} opts.sessionId — UUID of the planning session to inspect
|
|
221
|
+
* @returns {Promise<{
|
|
222
|
+
* world_id: string,
|
|
223
|
+
* session_id: string,
|
|
224
|
+
* exists: boolean,
|
|
225
|
+
* chunk_count: number,
|
|
226
|
+
* first_chunk_at: string | null,
|
|
227
|
+
* last_chunk_at: string | null,
|
|
228
|
+
* first_operator_content: string | null,
|
|
229
|
+
* }>}
|
|
230
|
+
*/
|
|
231
|
+
export async function loadPlanningSession({ pool, sessionId }) {
|
|
232
|
+
const aggResult = await pool.query(
|
|
233
|
+
`SELECT COUNT(*) AS chunk_count,
|
|
234
|
+
MIN(created_at) AS first_chunk_at,
|
|
235
|
+
MAX(created_at) AS last_chunk_at
|
|
236
|
+
FROM chunks
|
|
237
|
+
WHERE world_id = $1 AND session_id = $2`,
|
|
238
|
+
[PLANNING_WORLD_ID, sessionId],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const row = aggResult.rows[0];
|
|
242
|
+
const chunkCount = Number(row.chunk_count);
|
|
243
|
+
const exists = chunkCount > 0;
|
|
244
|
+
|
|
245
|
+
let firstOperatorContent = null;
|
|
246
|
+
|
|
247
|
+
if (exists) {
|
|
248
|
+
const opResult = await pool.query(
|
|
249
|
+
`SELECT chunk
|
|
250
|
+
FROM chunks
|
|
251
|
+
WHERE world_id = $1 AND session_id = $2 AND actor_type = 'operator'
|
|
252
|
+
ORDER BY created_at ASC
|
|
253
|
+
LIMIT 1`,
|
|
254
|
+
[PLANNING_WORLD_ID, sessionId],
|
|
255
|
+
);
|
|
256
|
+
if (opResult.rows.length > 0) {
|
|
257
|
+
firstOperatorContent = opResult.rows[0].chunk;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
world_id: PLANNING_WORLD_ID,
|
|
263
|
+
session_id: sessionId,
|
|
264
|
+
exists,
|
|
265
|
+
chunk_count: chunkCount,
|
|
266
|
+
first_chunk_at: exists ? row.first_chunk_at : null,
|
|
267
|
+
last_chunk_at: exists ? row.last_chunk_at : null,
|
|
268
|
+
first_operator_content: firstOperatorContent,
|
|
269
|
+
};
|
|
270
|
+
}
|