@pleri/olam-cli 0.1.188 → 0.1.196
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 +1 -1
- package/dist/ask/knowledge-pack.generated.d.ts.map +1 -1
- package/dist/ask/knowledge-pack.generated.js +39 -12
- package/dist/ask/knowledge-pack.generated.js.map +1 -1
- package/dist/commands/bootstrap.d.ts +4 -0
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +6 -9
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/clean.js +1 -1
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +1 -4
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +6 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/crystallize.js +12 -14
- package/dist/commands/crystallize.js.map +1 -1
- package/dist/commands/destroy.d.ts +13 -1
- package/dist/commands/destroy.d.ts.map +1 -1
- package/dist/commands/destroy.js +52 -6
- package/dist/commands/destroy.js.map +1 -1
- package/dist/commands/dispatch.d.ts +9 -0
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/dispatch.js +21 -2
- package/dist/commands/dispatch.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +29 -22
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/enter.d.ts +3 -3
- package/dist/commands/enter.d.ts.map +1 -1
- package/dist/commands/enter.js +57 -44
- package/dist/commands/enter.js.map +1 -1
- package/dist/commands/flywheel/index.d.ts.map +1 -1
- package/dist/commands/flywheel/index.js +1 -1
- package/dist/commands/flywheel/index.js.map +1 -1
- package/dist/commands/host-cp.d.ts.map +1 -1
- package/dist/commands/host-cp.js +2 -1
- package/dist/commands/host-cp.js.map +1 -1
- package/dist/commands/implode.d.ts.map +1 -1
- package/dist/commands/implode.js +1 -1
- package/dist/commands/implode.js.map +1 -1
- package/dist/commands/init.d.ts +20 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +102 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/kg-build.d.ts.map +1 -1
- package/dist/commands/kg-build.js +3 -0
- package/dist/commands/kg-build.js.map +1 -1
- package/dist/commands/kg-classify.d.ts +20 -0
- package/dist/commands/kg-classify.d.ts.map +1 -1
- package/dist/commands/kg-classify.js +59 -42
- package/dist/commands/kg-classify.js.map +1 -1
- package/dist/commands/kg-mirror.d.ts +40 -0
- package/dist/commands/kg-mirror.d.ts.map +1 -0
- package/dist/commands/kg-mirror.js +228 -0
- package/dist/commands/kg-mirror.js.map +1 -0
- package/dist/commands/mcp/index.js +1 -1
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/memory/index.d.ts.map +1 -1
- package/dist/commands/memory/index.js +1 -1
- package/dist/commands/memory/index.js.map +1 -1
- package/dist/commands/resume.d.ts.map +1 -1
- package/dist/commands/resume.js +1 -1
- package/dist/commands/resume.js.map +1 -1
- package/dist/commands/services-tls.d.ts +120 -0
- package/dist/commands/services-tls.d.ts.map +1 -0
- package/dist/commands/services-tls.js +448 -0
- package/dist/commands/services-tls.js.map +1 -0
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +28 -1
- package/dist/commands/services.js.map +1 -1
- package/dist/commands/setup-linux-gate.d.ts.map +1 -1
- package/dist/commands/setup-linux-gate.js +1 -3
- package/dist/commands/setup-linux-gate.js.map +1 -1
- package/dist/commands/setup-metrics.d.ts.map +1 -1
- package/dist/commands/setup-metrics.js +1 -2
- package/dist/commands/setup-metrics.js.map +1 -1
- package/dist/commands/setup-phase-5a-skill-source.d.ts +17 -1
- package/dist/commands/setup-phase-5a-skill-source.d.ts.map +1 -1
- package/dist/commands/setup-phase-5a-skill-source.js +69 -6
- package/dist/commands/setup-phase-5a-skill-source.js.map +1 -1
- package/dist/commands/setup.d.ts +26 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +233 -56
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills-onboard.d.ts.map +1 -1
- package/dist/commands/skills-onboard.js +4 -1
- package/dist/commands/skills-onboard.js.map +1 -1
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +90 -5
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +1 -3
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/yolo.d.ts.map +1 -1
- package/dist/commands/yolo.js +1 -1
- package/dist/commands/yolo.js.map +1 -1
- package/dist/context.d.ts +4 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +3 -2
- package/dist/context.js.map +1 -1
- package/dist/image-digests.json +8 -8
- package/dist/index.js +4150 -2267
- package/dist/index.js.map +1 -1
- package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -1
- package/dist/lib/auth-refresh-kubernetes.js +14 -5
- package/dist/lib/auth-refresh-kubernetes.js.map +1 -1
- package/dist/lib/bootstrap-kubernetes.d.ts +41 -0
- package/dist/lib/bootstrap-kubernetes.d.ts.map +1 -1
- package/dist/lib/bootstrap-kubernetes.js +289 -36
- package/dist/lib/bootstrap-kubernetes.js.map +1 -1
- package/dist/lib/cf-access-token.d.ts.map +1 -1
- package/dist/lib/cf-access-token.js +2 -3
- package/dist/lib/cf-access-token.js.map +1 -1
- package/dist/lib/config.d.ts +28 -4
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +82 -11
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +36 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/help-groups.d.ts +36 -0
- package/dist/lib/help-groups.d.ts.map +1 -0
- package/dist/lib/help-groups.js +124 -0
- package/dist/lib/help-groups.js.map +1 -0
- package/dist/lib/k8s-bootstrap.d.ts +6 -0
- package/dist/lib/k8s-bootstrap.d.ts.map +1 -1
- package/dist/lib/k8s-bootstrap.js +15 -2
- package/dist/lib/k8s-bootstrap.js.map +1 -1
- package/dist/lib/k8s-secret-render.d.ts.map +1 -1
- package/dist/lib/k8s-secret-render.js +17 -10
- package/dist/lib/k8s-secret-render.js.map +1 -1
- package/dist/lib/memory-secret.d.ts +15 -2
- package/dist/lib/memory-secret.d.ts.map +1 -1
- package/dist/lib/memory-secret.js +25 -8
- package/dist/lib/memory-secret.js.map +1 -1
- package/dist/lib/upgrade-check.d.ts +60 -0
- package/dist/lib/upgrade-check.d.ts.map +1 -0
- package/dist/lib/upgrade-check.js +169 -0
- package/dist/lib/upgrade-check.js.map +1 -0
- package/dist/lib/upgrade-kubernetes.d.ts +17 -0
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
- package/dist/lib/upgrade-kubernetes.js +125 -1
- package/dist/lib/upgrade-kubernetes.js.map +1 -1
- package/dist/mcp-server.js +2775 -2853
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/30-configmap.yaml +8 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/60-service.yaml +12 -4
- package/host-cp/k8s/manifests/65-tls-secret-template.yaml.tmpl +35 -0
- package/host-cp/k8s/manifests/70-ingressroute.yaml +58 -0
- 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/50-deployment.yaml +1 -1
- package/host-cp/src/plan-chat-secret.mjs +16 -1
- package/host-cp/src/plan-chat-service.mjs +493 -11
- package/host-cp/src/planning-sessions.mjs +252 -0
- package/host-cp/src/server.mjs +92 -2
- package/package.json +2 -1
|
@@ -175,6 +175,216 @@ export async function setCrystallizeStatus({ pool, sessionId, status, worldId =
|
|
|
175
175
|
);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Create a new multi-turn DISPATCH session (multi-turn-cloud-sandbox-dispatch
|
|
180
|
+
* Phase A2 — distinct from createPlanningSession which is for planning-flow
|
|
181
|
+
* crystallization sessions under world_id='_planning').
|
|
182
|
+
*
|
|
183
|
+
* Allocates a UUID session_id, INSERTs a planning_sessions row with
|
|
184
|
+
* session_type='dispatch' + caller-supplied world_id, applies operator-supplied
|
|
185
|
+
* budget_usd_cap / allow_unpriced_models defaults, returns the session_id.
|
|
186
|
+
*
|
|
187
|
+
* No seed chunk: dispatch sessions accumulate chunks from the agent runtime
|
|
188
|
+
* (via /v1/chunks); we don't pre-seed a system chunk because Electric shape
|
|
189
|
+
* subscribers for dispatch sessions can wait for the first real agent chunk.
|
|
190
|
+
*
|
|
191
|
+
* @param {object} opts
|
|
192
|
+
* @param {object} opts.pool
|
|
193
|
+
* @param {string} opts.actorId
|
|
194
|
+
* @param {string} opts.worldId — operator-supplied; identifies the dispatch
|
|
195
|
+
* target world (NOT the '_planning' sentinel used by createPlanningSession).
|
|
196
|
+
* @param {number | null} [opts.budgetUsdCap=null] — per-session budget cap;
|
|
197
|
+
* null = uncapped. When null AND `OLAM_SESSION_BUDGET_DEFAULT_USD` is set,
|
|
198
|
+
* the env-default applies at /v1/dispatch-turn check time (Phase D); here
|
|
199
|
+
* we record the row exactly as supplied.
|
|
200
|
+
* @param {boolean} [opts.allowUnpricedModels=false] — opt session into the
|
|
201
|
+
* pricingForModel-returns-null fallback (Plan A T11 mitigation; default
|
|
202
|
+
* refuses unknown models with 502).
|
|
203
|
+
* @returns {Promise<{ session_id: string }>}
|
|
204
|
+
*/
|
|
205
|
+
export async function createDispatchSession({
|
|
206
|
+
pool,
|
|
207
|
+
actorId,
|
|
208
|
+
worldId,
|
|
209
|
+
budgetUsdCap = null,
|
|
210
|
+
allowUnpricedModels = false,
|
|
211
|
+
sessionId: providedSessionId = null,
|
|
212
|
+
}) {
|
|
213
|
+
if (!actorId || typeof actorId !== 'string') {
|
|
214
|
+
throw new Error('createDispatchSession: actorId required');
|
|
215
|
+
}
|
|
216
|
+
if (!worldId || typeof worldId !== 'string') {
|
|
217
|
+
throw new Error('createDispatchSession: worldId required');
|
|
218
|
+
}
|
|
219
|
+
// A6 (Decision 9 always-on threading): callers MAY supply session_id to
|
|
220
|
+
// upsert an existing planning_sessions row (e.g. /api/cloud-dispatch
|
|
221
|
+
// pre-creating the thread before forwarding to plan-DO). When omitted,
|
|
222
|
+
// we generate a UUID. ON CONFLICT DO NOTHING handles the race where
|
|
223
|
+
// the SPA called /v1/sessions/create concurrently AND server-side
|
|
224
|
+
// cloud-dispatch tried to pre-create the same row.
|
|
225
|
+
const sessionId = providedSessionId ?? randomUUID();
|
|
226
|
+
await pool.query(
|
|
227
|
+
`INSERT INTO planning_sessions
|
|
228
|
+
(session_id, actor_id, session_type, world_id, budget_usd_cap, allow_unpriced_models)
|
|
229
|
+
VALUES ($1, $2, 'dispatch', $3, $4, $5)
|
|
230
|
+
ON CONFLICT (session_id) DO NOTHING`,
|
|
231
|
+
[sessionId, actorId, worldId, budgetUsdCap, allowUnpricedModels],
|
|
232
|
+
);
|
|
233
|
+
return { session_id: sessionId };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Atomic test-and-set lock claim on a dispatch session
|
|
238
|
+
* (multi-turn-cloud-sandbox-dispatch Phase A3 — Decision 4 + T5 mitigation).
|
|
239
|
+
*
|
|
240
|
+
* Pattern: single-statement UPDATE ... WHERE in_flight_turn_id IS NULL RETURNING.
|
|
241
|
+
* Two concurrent attempts: first claim wins (RETURNING yields 1 row); second
|
|
242
|
+
* sees empty result + must return 409 to caller. Matches the established
|
|
243
|
+
* planning-sessions.mjs:169 setCrystallizeStatus atomic-write idiom.
|
|
244
|
+
*
|
|
245
|
+
* @param {object} opts
|
|
246
|
+
* @param {object} opts.pool
|
|
247
|
+
* @param {string} opts.sessionId
|
|
248
|
+
* @param {string} opts.turnId — operator-or-server-generated turn UUID
|
|
249
|
+
* @returns {Promise<boolean>} true if lock claimed, false if already held
|
|
250
|
+
*/
|
|
251
|
+
export async function claimDispatchTurnLock({ pool, sessionId, turnId }) {
|
|
252
|
+
const result = await pool.query(
|
|
253
|
+
`UPDATE planning_sessions
|
|
254
|
+
SET in_flight_turn_id = $1,
|
|
255
|
+
in_flight_turn_started_at = NOW(),
|
|
256
|
+
last_turn_at = NOW()
|
|
257
|
+
WHERE session_id = $2
|
|
258
|
+
AND session_type = 'dispatch'
|
|
259
|
+
AND in_flight_turn_id IS NULL
|
|
260
|
+
RETURNING session_id`,
|
|
261
|
+
[turnId, sessionId],
|
|
262
|
+
);
|
|
263
|
+
return (result.rows?.length ?? 0) > 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Clear the in-flight turn lock after dispatch completes (success OR failure).
|
|
268
|
+
*
|
|
269
|
+
* @param {object} opts
|
|
270
|
+
* @param {object} opts.pool
|
|
271
|
+
* @param {string} opts.sessionId
|
|
272
|
+
*/
|
|
273
|
+
export async function clearDispatchTurnLock({ pool, sessionId }) {
|
|
274
|
+
await pool.query(
|
|
275
|
+
`UPDATE planning_sessions
|
|
276
|
+
SET in_flight_turn_id = NULL,
|
|
277
|
+
in_flight_turn_started_at = NULL
|
|
278
|
+
WHERE session_id = $1
|
|
279
|
+
AND session_type = 'dispatch'`,
|
|
280
|
+
[sessionId],
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Halt a dispatch session — operator-driven "block next turn" state (T13).
|
|
286
|
+
*
|
|
287
|
+
* Sets halted_at to NOW() AND clears in_flight_turn_id. Future /v1/dispatch-turn
|
|
288
|
+
* calls return 409 'session_halted' until reactivateDispatchSession clears
|
|
289
|
+
* halted_at. Does NOT stop an in-flight container — the running container
|
|
290
|
+
* completes its current turn naturally. UX is "Block next turn" not "Stop"
|
|
291
|
+
* (Plan A Phase C C6).
|
|
292
|
+
*
|
|
293
|
+
* Scoped by actor_id for ownership isolation.
|
|
294
|
+
*
|
|
295
|
+
* @param {object} opts
|
|
296
|
+
* @param {object} opts.pool
|
|
297
|
+
* @param {string} opts.sessionId
|
|
298
|
+
* @param {string} opts.actorId
|
|
299
|
+
* @returns {Promise<boolean>} true if a session row was updated; false if
|
|
300
|
+
* the session_id was not found / not owned by actorId.
|
|
301
|
+
*/
|
|
302
|
+
export async function haltDispatchSession({ pool, sessionId, actorId }) {
|
|
303
|
+
const result = await pool.query(
|
|
304
|
+
`UPDATE planning_sessions
|
|
305
|
+
SET halted_at = NOW(),
|
|
306
|
+
in_flight_turn_id = NULL,
|
|
307
|
+
in_flight_turn_started_at = NULL
|
|
308
|
+
WHERE session_id = $1
|
|
309
|
+
AND session_type = 'dispatch'
|
|
310
|
+
AND actor_id = $2
|
|
311
|
+
RETURNING session_id`,
|
|
312
|
+
[sessionId, actorId],
|
|
313
|
+
);
|
|
314
|
+
return (result.rows?.length ?? 0) > 0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Reactivate a halted dispatch session — clears halted_at so subsequent
|
|
319
|
+
* /v1/dispatch-turn calls can claim the lock again. Idempotent (clearing an
|
|
320
|
+
* already-null halted_at is a no-op).
|
|
321
|
+
*
|
|
322
|
+
* @param {object} opts
|
|
323
|
+
* @param {object} opts.pool
|
|
324
|
+
* @param {string} opts.sessionId
|
|
325
|
+
* @param {string} opts.actorId
|
|
326
|
+
* @returns {Promise<boolean>} true if a session row was updated; false if
|
|
327
|
+
* the session_id was not found / not owned by actorId.
|
|
328
|
+
*/
|
|
329
|
+
export async function reactivateDispatchSession({ pool, sessionId, actorId }) {
|
|
330
|
+
const result = await pool.query(
|
|
331
|
+
`UPDATE planning_sessions
|
|
332
|
+
SET halted_at = NULL
|
|
333
|
+
WHERE session_id = $1
|
|
334
|
+
AND session_type = 'dispatch'
|
|
335
|
+
AND actor_id = $2
|
|
336
|
+
RETURNING session_id`,
|
|
337
|
+
[sessionId, actorId],
|
|
338
|
+
);
|
|
339
|
+
return (result.rows?.length ?? 0) > 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Read a dispatch session by session_id + scope to caller's actor_id
|
|
344
|
+
* (ownership check). Returns the session metadata needed for budget check
|
|
345
|
+
* + plan-DO forward, OR null when not found / not owned.
|
|
346
|
+
*
|
|
347
|
+
* @param {object} opts
|
|
348
|
+
* @param {object} opts.pool
|
|
349
|
+
* @param {string} opts.sessionId
|
|
350
|
+
* @param {string} opts.actorId
|
|
351
|
+
* @returns {Promise<null | {
|
|
352
|
+
* session_id: string,
|
|
353
|
+
* world_id: string | null,
|
|
354
|
+
* actor_id: string,
|
|
355
|
+
* total_usd: number,
|
|
356
|
+
* budget_usd_cap: number | null,
|
|
357
|
+
* allow_unpriced_models: boolean,
|
|
358
|
+
* halted_at: string | null,
|
|
359
|
+
* }>}
|
|
360
|
+
*/
|
|
361
|
+
export async function getDispatchSession({ pool, sessionId, actorId }) {
|
|
362
|
+
const result = await pool.query(
|
|
363
|
+
`SELECT session_id, world_id, actor_id,
|
|
364
|
+
total_usd, budget_usd_cap, allow_unpriced_models,
|
|
365
|
+
halted_at
|
|
366
|
+
FROM planning_sessions
|
|
367
|
+
WHERE session_id = $1
|
|
368
|
+
AND session_type = 'dispatch'
|
|
369
|
+
AND actor_id = $2`,
|
|
370
|
+
[sessionId, actorId],
|
|
371
|
+
);
|
|
372
|
+
const row = result.rows?.[0];
|
|
373
|
+
if (!row) return null;
|
|
374
|
+
return {
|
|
375
|
+
session_id: row.session_id,
|
|
376
|
+
world_id: row.world_id ?? null,
|
|
377
|
+
actor_id: row.actor_id,
|
|
378
|
+
total_usd: Number(row.total_usd ?? 0),
|
|
379
|
+
budget_usd_cap:
|
|
380
|
+
row.budget_usd_cap === null || row.budget_usd_cap === undefined
|
|
381
|
+
? null
|
|
382
|
+
: Number(row.budget_usd_cap),
|
|
383
|
+
allow_unpriced_models: Boolean(row.allow_unpriced_models),
|
|
384
|
+
halted_at: row.halted_at ?? null,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
178
388
|
/**
|
|
179
389
|
* List planning sessions for a given actorId, ordered by created_at DESC.
|
|
180
390
|
*
|
|
@@ -204,6 +414,48 @@ export async function listPlanningSessions({ pool, actorId, limit = 50 }) {
|
|
|
204
414
|
return result.rows;
|
|
205
415
|
}
|
|
206
416
|
|
|
417
|
+
/**
|
|
418
|
+
* List multi-turn DISPATCH sessions for a given actorId, ordered by
|
|
419
|
+
* last_turn_at DESC (most recently active first), excluding archived sessions.
|
|
420
|
+
*
|
|
421
|
+
* Distinct from listPlanningSessions: this returns only `session_type='dispatch'`
|
|
422
|
+
* rows + projects the multi-turn-specific columns (total_usd, in_flight_turn_id,
|
|
423
|
+
* halted_at, etc.) that the SPA's SessionsListView (Phase C C3) renders.
|
|
424
|
+
*
|
|
425
|
+
* @param {object} opts
|
|
426
|
+
* @param {object} opts.pool
|
|
427
|
+
* @param {string} opts.actorId
|
|
428
|
+
* @param {number} [opts.limit=50]
|
|
429
|
+
* @returns {Promise<Array<{
|
|
430
|
+
* session_id: string,
|
|
431
|
+
* world_id: string | null,
|
|
432
|
+
* total_usd: string,
|
|
433
|
+
* budget_usd_cap: string | null,
|
|
434
|
+
* in_flight_turn_id: string | null,
|
|
435
|
+
* halted_at: string | null,
|
|
436
|
+
* last_turn_at: string | null,
|
|
437
|
+
* created_at: string,
|
|
438
|
+
* summary: string | null,
|
|
439
|
+
* }>>}
|
|
440
|
+
*/
|
|
441
|
+
export async function listDispatchSessions({ pool, actorId, limit = 50 }) {
|
|
442
|
+
const result = await pool.query(
|
|
443
|
+
`SELECT session_id, world_id,
|
|
444
|
+
total_usd, budget_usd_cap,
|
|
445
|
+
in_flight_turn_id, halted_at,
|
|
446
|
+
last_turn_at, created_at,
|
|
447
|
+
summary
|
|
448
|
+
FROM planning_sessions
|
|
449
|
+
WHERE actor_id = $1
|
|
450
|
+
AND session_type = 'dispatch'
|
|
451
|
+
AND archived_at IS NULL
|
|
452
|
+
ORDER BY last_turn_at DESC NULLS LAST, created_at DESC
|
|
453
|
+
LIMIT $2`,
|
|
454
|
+
[actorId, limit],
|
|
455
|
+
);
|
|
456
|
+
return result.rows;
|
|
457
|
+
}
|
|
458
|
+
|
|
207
459
|
/**
|
|
208
460
|
* Load lightweight metadata for an existing in-flight planning session.
|
|
209
461
|
*
|
package/host-cp/src/server.mjs
CHANGED
|
@@ -354,6 +354,50 @@ function readDogfoodRepoUrl() {
|
|
|
354
354
|
return '';
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Resolve the cloud-kg-mirror classifier proxy URL the runner forwards
|
|
359
|
+
* into spawned CF Sandbox child worlds. When set, host-cp enriches
|
|
360
|
+
* cloud-dispatch bodies with `kgProxyUrl` + `kgProxyBearer`; the runner
|
|
361
|
+
* injects those into the sandbox env so the PreToolUse hook's
|
|
362
|
+
* cloud-sandbox flavor can POST /v1/classify against the
|
|
363
|
+
* kg-mirror-worker. Source order: OLAM_KG_PROXY_URL env, then
|
|
364
|
+
* ~/.olam/kg-proxy-url file. Absent → no injection (dispatched worlds
|
|
365
|
+
* see no proxy URL → hook falls through to grep via existing fail-open).
|
|
366
|
+
* Mirrors readAnthropicBaseUrl() — operators have ONE pattern.
|
|
367
|
+
*
|
|
368
|
+
* Phase 1 (cloud-kg-mirror): docs/plans/cloud-kg-mirror/README.md §6-7.
|
|
369
|
+
*/
|
|
370
|
+
function readKgProxyUrl() {
|
|
371
|
+
const fromOlamEnv = process.env['OLAM_KG_PROXY_URL'];
|
|
372
|
+
if (fromOlamEnv && fromOlamEnv.length > 0) return fromOlamEnv.trim();
|
|
373
|
+
try {
|
|
374
|
+
const file = path.join(os.homedir(), '.olam', 'kg-proxy-url');
|
|
375
|
+
const content = fs.readFileSync(file, 'utf-8').trim();
|
|
376
|
+
if (content.length > 0) return content;
|
|
377
|
+
} catch {
|
|
378
|
+
// file absent — fall through
|
|
379
|
+
}
|
|
380
|
+
return '';
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Bearer that pairs with readKgProxyUrl(). Stored in
|
|
385
|
+
* ~/.olam/kg-proxy-bearer (chmod 600 by operator). Mirrors the
|
|
386
|
+
* source-order convention; absent → no injection.
|
|
387
|
+
*/
|
|
388
|
+
function readKgProxyBearer() {
|
|
389
|
+
const fromOlamEnv = process.env['OLAM_KG_PROXY_BEARER'];
|
|
390
|
+
if (fromOlamEnv && fromOlamEnv.length > 0) return fromOlamEnv.trim();
|
|
391
|
+
try {
|
|
392
|
+
const file = path.join(os.homedir(), '.olam', 'kg-proxy-bearer');
|
|
393
|
+
const content = fs.readFileSync(file, 'utf-8').trim();
|
|
394
|
+
if (content.length > 0) return content;
|
|
395
|
+
} catch {
|
|
396
|
+
// file absent — fall through
|
|
397
|
+
}
|
|
398
|
+
return '';
|
|
399
|
+
}
|
|
400
|
+
|
|
357
401
|
/** @type {Record<string, number>} */
|
|
358
402
|
let WORLDS = {};
|
|
359
403
|
|
|
@@ -2584,6 +2628,35 @@ const server = http.createServer(instrumentHandler('host-cp', async (req, res) =
|
|
|
2584
2628
|
// Keep `messages` too — plan-DO may use it for multi-turn fidelity later.
|
|
2585
2629
|
}
|
|
2586
2630
|
|
|
2631
|
+
// multi-turn-cloud-sandbox-dispatch Phase A6 (Decision 9 always-on
|
|
2632
|
+
// threading): pre-create the planning_sessions row server-side so
|
|
2633
|
+
// EVERY cloud dispatch surfaces as a SPA thread — including pre-PR
|
|
2634
|
+
// #1182-style one-shot calls that never invoked /v1/sessions/create
|
|
2635
|
+
// directly. Idempotent (ON CONFLICT DO NOTHING in createDispatchSession).
|
|
2636
|
+
// Fail-soft: thread-creation failure does NOT block the dispatch
|
|
2637
|
+
// (the operator's task still ships); we log + continue.
|
|
2638
|
+
try {
|
|
2639
|
+
if (parsed.world_id && parsed.session_id) {
|
|
2640
|
+
const planChatBearer = readPlanChatSecret();
|
|
2641
|
+
const planChatBase = process.env.PLAN_CHAT_SERVICE_URL || 'http://127.0.0.1:3200';
|
|
2642
|
+
await fetch(`${planChatBase}/v1/sessions/create`, {
|
|
2643
|
+
method: 'POST',
|
|
2644
|
+
headers: {
|
|
2645
|
+
'content-type': 'application/json',
|
|
2646
|
+
authorization: `Bearer ${planChatBearer}`,
|
|
2647
|
+
},
|
|
2648
|
+
body: JSON.stringify({
|
|
2649
|
+
world_id: parsed.world_id,
|
|
2650
|
+
session_id: parsed.session_id,
|
|
2651
|
+
}),
|
|
2652
|
+
});
|
|
2653
|
+
}
|
|
2654
|
+
} catch (threadErr) {
|
|
2655
|
+
console.warn(
|
|
2656
|
+
`[cloud-dispatch] thread pre-create failed (continuing): ${threadErr?.message ?? threadErr}`,
|
|
2657
|
+
);
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2587
2660
|
// Gap 3: enrich the dispatch body with the operator's anthropicBaseUrl
|
|
2588
2661
|
// so plan-DO can propagate it to spawned CF Sandbox child worlds.
|
|
2589
2662
|
// Only injected when not already set by the SPA (SPA has no auth-worker
|
|
@@ -2596,9 +2669,18 @@ const server = http.createServer(instrumentHandler('host-cp', async (req, res) =
|
|
|
2596
2669
|
// ~/.olam/dogfood-repo-url file. Absent → no injection (the dispatch
|
|
2597
2670
|
// runs text-only, like before this change).
|
|
2598
2671
|
const dogfoodRepoUrl = readDogfoodRepoUrl();
|
|
2672
|
+
// cloud-kg-mirror Phase 1: propagate the classifier Worker URL +
|
|
2673
|
+
// bearer so the runner can inject them into the sandbox env. When
|
|
2674
|
+
// either is missing the dispatched world's PreToolUse hook falls
|
|
2675
|
+
// through to grep via the existing fail-open path. Operator opts
|
|
2676
|
+
// in by writing ~/.olam/kg-proxy-url + ~/.olam/kg-proxy-bearer.
|
|
2677
|
+
const kgProxyUrl = readKgProxyUrl();
|
|
2678
|
+
const kgProxyBearer = readKgProxyBearer();
|
|
2599
2679
|
let enrichedObj = null;
|
|
2600
2680
|
if (anthropicBaseUrl && !parsed.anthropicBaseUrl) enrichedObj = { ...(enrichedObj ?? parsed), anthropicBaseUrl };
|
|
2601
2681
|
if (dogfoodRepoUrl && !parsed.repoUrl) enrichedObj = { ...(enrichedObj ?? parsed), repoUrl: dogfoodRepoUrl };
|
|
2682
|
+
if (kgProxyUrl && !parsed.kgProxyUrl) enrichedObj = { ...(enrichedObj ?? parsed), kgProxyUrl };
|
|
2683
|
+
if (kgProxyBearer && !parsed.kgProxyBearer) enrichedObj = { ...(enrichedObj ?? parsed), kgProxyBearer };
|
|
2602
2684
|
// Use `parsed` (not raw `body`) as the no-enrichment fallback so that the
|
|
2603
2685
|
// messages→prompt normalisation above is always forwarded even when no
|
|
2604
2686
|
// env-var enrichments are applied.
|
|
@@ -2667,10 +2749,18 @@ const server = http.createServer(instrumentHandler('host-cp', async (req, res) =
|
|
|
2667
2749
|
// bearer registration without additional plan metadata.
|
|
2668
2750
|
}
|
|
2669
2751
|
|
|
2670
|
-
// Enrich with anthropicBaseUrl from the host config.
|
|
2752
|
+
// Enrich with anthropicBaseUrl + kgProxy from the host config.
|
|
2671
2753
|
const anthropicBaseUrl = readAnthropicBaseUrl();
|
|
2754
|
+
const kgProxyUrl = readKgProxyUrl();
|
|
2755
|
+
const kgProxyBearer = readKgProxyBearer();
|
|
2672
2756
|
const planId = parsed.planId ?? parsed.session_id ?? `plan-${Date.now()}`;
|
|
2673
|
-
const requestBody = {
|
|
2757
|
+
const requestBody = {
|
|
2758
|
+
...parsed,
|
|
2759
|
+
planId,
|
|
2760
|
+
...(anthropicBaseUrl ? { anthropicBaseUrl } : {}),
|
|
2761
|
+
...(kgProxyUrl ? { kgProxyUrl } : {}),
|
|
2762
|
+
...(kgProxyBearer ? { kgProxyBearer } : {}),
|
|
2763
|
+
};
|
|
2674
2764
|
|
|
2675
2765
|
const basicAuth = Buffer.from(`operator:${showcasePw}`).toString('base64');
|
|
2676
2766
|
// Phase H h2: attach CF Access service-token headers when configured.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pleri/olam-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.196",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"olam": "./bin/olam.cjs"
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"test": "vitest run --passWithNoTests",
|
|
33
33
|
"test:ci": "vitest run --reporter=basic --passWithNoTests",
|
|
34
34
|
"test:docker": "vitest run --config vitest.config.docker.ts",
|
|
35
|
+
"test:e2e:k3d-https": "node e2e/k3d-https-e2e.spec.mjs",
|
|
35
36
|
"audit:publish-deps": "node scripts/audit-publish-deps.mjs",
|
|
36
37
|
"audit:cli-bundle-k8s": "node scripts/audit-cli-bundle-k8s.mjs",
|
|
37
38
|
"audit:cli-package-contents": "node scripts/audit-cli-package-contents.mjs"
|