diff --git a/examples/deep-survey/package.json b/examples/deep-survey/package.json index 95abfa0b45..40ca50f612 100644 --- a/examples/deep-survey/package.json +++ b/examples/deep-survey/package.json @@ -4,7 +4,7 @@ "version": "0.1.25", "type": "module", "scripts": { - "dev": "pnpm run --parallel \"/^dev:/\"", + "dev": "pnpm run dev:server & pnpm run dev:ui", "dev:server": "tsx watch src/server/index.ts", "dev:ui": "vite", "build:ui": "vite build", diff --git a/examples/deep-survey/src/server/index.ts b/examples/deep-survey/src/server/index.ts index 81d725b1d7..6c3edb4ec3 100644 --- a/examples/deep-survey/src/server/index.ts +++ b/examples/deep-survey/src/server/index.ts @@ -1,13 +1,17 @@ +import { createHash } from 'node:crypto' +import { readFileSync } from 'node:fs' import path from 'node:path' +import { parseEnv } from 'node:util' // Load repo root .env first, then local .env (local values take precedence) -const envPaths = [ - path.resolve(import.meta.dirname, `../../../../.env`), - path.resolve(import.meta.dirname, `../../.env`), -] -for (const envPath of envPaths) { +function loadEnvFile(envPath: string, override: boolean): void { try { - process.loadEnvFile(envPath) + const env = parseEnv(readFileSync(envPath, `utf8`)) + for (const [key, value] of Object.entries(env)) { + if (override || process.env[key] === undefined) { + process.env[key] = value + } + } } catch (err) { if ((err as NodeJS.ErrnoException).code !== `ENOENT`) { console.error(`Failed to load .env file:`, err) @@ -15,6 +19,20 @@ for (const envPath of envPaths) { } } +loadEnvFile(path.resolve(import.meta.dirname, `../../../../.env`), false) +loadEnvFile(path.resolve(import.meta.dirname, `../../.env`), true) + +function envFingerprint(name: string): string { + const value = process.env[name]?.trim() + if (!value) return `${name}=unset` + + const fingerprint = createHash(`sha256`) + .update(value) + .digest(`hex`) + .slice(0, 8) + return `${name}=set sha256:${fingerprint}` +} + import { createEntityRegistry, createRuntimeHandler, @@ -136,5 +154,10 @@ server.listen(PORT, async () => { await runtime.registerTypes() console.log(`Deep Survey server ready on port ${PORT}`) console.log(`DARIX: ${DARIX_URL}`) + console.log( + `Model credentials: ${envFingerprint(`ANTHROPIC_API_KEY`)}, ${envFingerprint( + `MOONSHOT_API_KEY` + )}` + ) console.log(`${runtime.typeNames.length} entity types registered`) }) diff --git a/examples/deep-survey/src/server/orchestrator.ts b/examples/deep-survey/src/server/orchestrator.ts index c593f760a9..cdd6997ab5 100644 --- a/examples/deep-survey/src/server/orchestrator.ts +++ b/examples/deep-survey/src/server/orchestrator.ts @@ -1,10 +1,11 @@ import type { + ChildStatusEntry, EntityRegistry, HandlerContext, + ManifestEntry, SharedStateHandle, } from '@electric-ax/agents-runtime' import { db } from '@electric-ax/agents-runtime' -import { queryOnce } from '@durable-streams/state/db' import { Type } from '@sinclair/typebox' import { exec, execFile } from 'node:child_process' import type { AgentTool } from '@mariozechner/pi-agent-core' @@ -141,9 +142,7 @@ function createExploreCorpusTool( topics: string[] } - const existing = await queryOnce((q) => - q.from({ manifests: ctx.db.collections.manifests }) - ) + const existing = ctx.db.collections.manifests.toArray as ManifestEntry[] const hasChildren = existing.some( (m) => m.kind === `child` && m.entity_type === SURVEY_WORKER_ENTITY_TYPE ) @@ -269,12 +268,11 @@ function createSwarmStatusTool( const entries = readWiki(shared) const xrefs = readXrefs(shared) - const children = await queryOnce((q) => - q.from({ cs: ctx.db.collections.childStatus }) - ) + const children = ctx.db.collections.childStatus + .toArray as ChildStatusEntry[] const byStatus = { spawning: 0, running: 0, idle: 0, stopped: 0 } for (const c of children) { - const s = (c as any).status as string + const s = c.status if (s in byStatus) byStatus[s as keyof typeof byStatus]++ } const total = children.length