@plasm_lang/vercel-agent 0.3.63
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 +235 -0
- package/agent/.plasm/archives/runs/runs/pr2d5c4a99707b4c19b650553d50229a1d600d28e3d98a9c58f18e5026cecc86ca.json +64 -0
- package/agent/.plasm/archives/runs/runs/pr2e0c0d8ad443c63c82da7435ee1a002b0e0fa718b640263c0a9d3e6e5944812f.json +64 -0
- package/agent/.plasm/archives/runs/runs/pr2faedb8354f40ee6d828e3af07b421fda9ccda973a4f7347fce3639f03a0a869.json +64 -0
- package/agent/.plasm/archives/runs/runs/pr586b47c55547b0702c572bce4255558b22dbe5e682d6359169577e0ea75fe98f.json +64 -0
- package/agent/.plasm/archives/runs/runs/pr76212356445e3b00fcf256835aaec18bac68576324b90d0be92d47f0b4a862a7.json +56 -0
- package/agent/.plasm/archives/runs/runs/pr9ec805d689e00db9270a9539858f2fb7216c24acbfea943d450e37b641149da1.json +64 -0
- package/agent/.plasm/archives/runs/runs/prc3c0c4ba2e28fc94ed6d37b6796e277a7997d9cb3184640d14c35c98bc6d136f.json +64 -0
- package/agent/.plasm/archives/runs/runs/prf04de32522f2fdcb17818907d91bccce7dcaecbd1259041cc448d447b6993244.json +64 -0
- package/agent/.plasm/archives/traces/traces/local/00000000000000000000000000000000/records.ndjson +1 -0
- package/agent/.plasm/archives/traces/traces/local/00000000000000000000000000000000/summary.json +13 -0
- package/agent/.plasm/discovery/manifest.json +126 -0
- package/agent/.plasm/sessions/TGlzdCBwcm9kdWN0cyBmcm9tIHRoZSBleGVjdXRlX3RpbnkgY2F0YWxvZw.json +44 -0
- package/agent/.plasm/sessions/TGlzdCBwcm9kdWN0cyBmcm9tIHRoZSBleGVjdXRlX3RpbnkgY2F0YWxvZw.teaching.tsv +23 -0
- package/agent/.plasm/sessions/bGlzdCBleGVjdXRlX3RpbnkgcHJvZHVjdHM.json +151 -0
- package/agent/.plasm/sessions/bGlzdCBleGVjdXRlX3RpbnkgcHJvZHVjdHM.teaching.tsv +131 -0
- package/agent/.plasm/sessions/bGlzdCBleGVjdXRlX3RpbnkgcHJvZHVjdHMgYXN5bmMgdHJhbnNwb3J0.json +44 -0
- package/agent/.plasm/sessions/bGlzdCBleGVjdXRlX3RpbnkgcHJvZHVjdHMgYXN5bmMgdHJhbnNwb3J0.teaching.tsv +23 -0
- package/agent/.plasm/stubs/.gitkeep +0 -0
- package/agent/.plasm/stubs/execute_tiny.ts +107 -0
- package/agent/agent.ts +52 -0
- package/agent/catalogs/README.md +15 -0
- package/agent/channels/.gitkeep +0 -0
- package/agent/channels/execute-tiny-webhook.ts +59 -0
- package/agent/channels/health.ts +16 -0
- package/agent/hooks/.gitkeep +0 -0
- package/agent/hooks/trace-log.ts +10 -0
- package/agent/instructions.md +25 -0
- package/agent/schedules/.gitkeep +0 -0
- package/agent/schedules/ping.ts +13 -0
- package/agent/skills/.gitkeep +0 -0
- package/agent/skills/plasm-authoring.md +8 -0
- package/agent/subagents/.gitkeep +0 -0
- package/agent/subagents/tiny/agent.ts +28 -0
- package/bin/plasm-agent.mjs +18 -0
- package/package.json +77 -0
- package/scripts/plasm-node.mjs +19 -0
- package/scripts/resolve-ts-extension.mjs +18 -0
- package/src/archive/adapters.ts +27 -0
- package/src/archive/index.ts +99 -0
- package/src/archive/local-run-archive.ts +90 -0
- package/src/archive/local-trace-archive.ts +91 -0
- package/src/archive/paths.ts +15 -0
- package/src/archive/postgres-kv-adapter.ts +72 -0
- package/src/archive/prod-archive-store.ts +143 -0
- package/src/archive/resolve-backend.ts +60 -0
- package/src/archive/run-id.ts +23 -0
- package/src/archive/types.ts +75 -0
- package/src/archive/vercel-blob-adapter.ts +21 -0
- package/src/archive/vercel-kv-adapter.ts +24 -0
- package/src/authoring/channel-dispatch.ts +44 -0
- package/src/authoring/context.ts +34 -0
- package/src/authoring/define-channel.ts +83 -0
- package/src/authoring/define-hook.ts +51 -0
- package/src/authoring/define-schedule.ts +64 -0
- package/src/authoring/define-skill.ts +38 -0
- package/src/authoring/hook-runner.ts +18 -0
- package/src/authoring/schedule-manager.ts +118 -0
- package/src/authoring/slot-loader.ts +253 -0
- package/src/authoring/subagent-loader.ts +121 -0
- package/src/catalog/loader.ts +71 -0
- package/src/cli/build.ts +54 -0
- package/src/cli/dev.ts +60 -0
- package/src/cli/info.ts +12 -0
- package/src/cli/init.ts +372 -0
- package/src/cli/link.ts +68 -0
- package/src/cli/project-root.ts +57 -0
- package/src/define-agent.ts +150 -0
- package/src/dev/client/ansi.ts +36 -0
- package/src/dev/client/http-session.ts +180 -0
- package/src/dev/client/repl.ts +92 -0
- package/src/dev/client/slash.ts +119 -0
- package/src/dev/dev-session.ts +153 -0
- package/src/dev/http.ts +29 -0
- package/src/dev/server.ts +147 -0
- package/src/dev/session-routes.ts +185 -0
- package/src/discovery/project-walker.ts +272 -0
- package/src/engine/connect-auth.ts +135 -0
- package/src/engine/create-host-transport.ts +7 -0
- package/src/engine/fixture-mock-transport.ts +54 -0
- package/src/engine/host-transport-bridge.ts +32 -0
- package/src/engine/host-transport.ts +84 -0
- package/src/engine/napi-binding.ts +265 -0
- package/src/evals/define-eval.ts +56 -0
- package/src/evals/run-eval.ts +136 -0
- package/src/gateway-model.ts +43 -0
- package/src/index.ts +296 -0
- package/src/instrumentation.ts +56 -0
- package/src/load-env.ts +63 -0
- package/src/operator/routes.ts +287 -0
- package/src/operator/types.ts +63 -0
- package/src/operator/ui-shell.ts +134 -0
- package/src/project-info.ts +229 -0
- package/src/runtime/agent-runtime.ts +469 -0
- package/src/runtime/compaction.ts +81 -0
- package/src/runtime/logical-session.ts +72 -0
- package/src/runtime/plasm-agent.ts +199 -0
- package/src/server/plasm-handler.ts +331 -0
- package/src/session-state.ts +135 -0
- package/src/state/define-state.ts +57 -0
- package/src/state/fs-state-adapter.ts +72 -0
- package/src/state/kv-state-adapter.ts +62 -0
- package/src/state/postgres-state-adapter.ts +116 -0
- package/src/stubs/capability-invoke-shape.ts +135 -0
- package/src/stubs/catalog-client.ts +170 -0
- package/src/stubs/catalog-hash.ts +11 -0
- package/src/stubs/catalog-introspection.ts +121 -0
- package/src/stubs/cgs-ts-types.ts +164 -0
- package/src/stubs/domain-parser.ts +203 -0
- package/src/stubs/generator.ts +390 -0
- package/src/stubs/input-type-to-ts.ts +233 -0
- package/src/stubs/plasm-value-emitter.ts +162 -0
- package/src/stubs/program-builder.ts +82 -0
- package/src/stubs/stub-symbols.ts +89 -0
- package/src/symbol-registry.ts +74 -0
- package/src/telemetry/plasm-spans.ts +83 -0
- package/src/tools/descriptions.ts +94 -0
- package/src/tools/format.ts +29 -0
- package/src/tools/harness-tools.ts +65 -0
- package/src/tools/plasm-tools.ts +104 -0
- package/src/workflow/world-bootstrap.ts +52 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export interface OperatorStubFreshness {
|
|
2
|
+
stubPath: string;
|
|
3
|
+
liveCatalogCgsHash: string;
|
|
4
|
+
generatedCatalogCgsHash: string | null;
|
|
5
|
+
fresh: boolean;
|
|
6
|
+
lastBuiltAt: string | null;
|
|
7
|
+
validationErrors: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface OperatorCatalogEntry {
|
|
11
|
+
entryId: string;
|
|
12
|
+
label: string;
|
|
13
|
+
rootDir: string;
|
|
14
|
+
catalogCgsHash: string;
|
|
15
|
+
authScheme?: string;
|
|
16
|
+
entityCount: number;
|
|
17
|
+
capabilityCount: number;
|
|
18
|
+
stub: OperatorStubFreshness;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface OperatorCatalogsResponse {
|
|
22
|
+
catalogs: OperatorCatalogEntry[];
|
|
23
|
+
generatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface OperatorSessionEntry {
|
|
27
|
+
intent: string;
|
|
28
|
+
logicalSessionRef: string;
|
|
29
|
+
logicalSessionId: string;
|
|
30
|
+
waveCount: number;
|
|
31
|
+
seedCount: number;
|
|
32
|
+
planCommitCount: number;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface OperatorSessionsResponse {
|
|
37
|
+
sessions: OperatorSessionEntry[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface OperatorPlanCommit {
|
|
41
|
+
intent: string;
|
|
42
|
+
logicalSessionRef: string;
|
|
43
|
+
ref: string;
|
|
44
|
+
program: string;
|
|
45
|
+
at: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface OperatorPlansResponse {
|
|
49
|
+
plans: OperatorPlanCommit[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface OperatorOpsResponse {
|
|
53
|
+
nativeEngineAvailable: boolean;
|
|
54
|
+
engineMode: "napi" | "stub";
|
|
55
|
+
agentRoot: string;
|
|
56
|
+
catalogCount: number;
|
|
57
|
+
sessionCount: number;
|
|
58
|
+
planCommitCount: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface OperatorHealthResponse {
|
|
62
|
+
status: string;
|
|
63
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/** Read-only operator shell — fetches `/operator/*` BFF JSON. */
|
|
2
|
+
export function renderOperatorShell(basePath = "/operator"): string {
|
|
3
|
+
const base = basePath.replace(/\/$/, "");
|
|
4
|
+
return `<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
9
|
+
<title>Plasm Operator</title>
|
|
10
|
+
<style>
|
|
11
|
+
:root { color-scheme: dark; font-family: ui-sans-serif, system-ui, sans-serif; }
|
|
12
|
+
body { margin: 0; background: #0b0d10; color: #e8eaed; }
|
|
13
|
+
header { padding: 1rem 1.25rem; border-bottom: 1px solid #22262d; display: flex; gap: 1rem; align-items: center; }
|
|
14
|
+
header h1 { font-size: 1rem; font-weight: 600; margin: 0; letter-spacing: 0.02em; }
|
|
15
|
+
nav { display: flex; gap: 0.5rem; flex-wrap: wrap; }
|
|
16
|
+
nav button { background: #151922; border: 1px solid #2a3140; color: #c9d1d9; padding: 0.35rem 0.7rem; border-radius: 6px; cursor: pointer; }
|
|
17
|
+
nav button.active { background: #1f6feb33; border-color: #388bfd; color: #fff; }
|
|
18
|
+
main { padding: 1rem 1.25rem 2rem; }
|
|
19
|
+
.meta { color: #8b949e; font-size: 0.85rem; margin-bottom: 1rem; }
|
|
20
|
+
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
|
|
21
|
+
th, td { text-align: left; padding: 0.5rem 0.65rem; border-bottom: 1px solid #22262d; vertical-align: top; }
|
|
22
|
+
th { color: #8b949e; font-weight: 500; }
|
|
23
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.82rem; }
|
|
24
|
+
.badge { display: inline-block; padding: 0.1rem 0.45rem; border-radius: 999px; font-size: 0.75rem; }
|
|
25
|
+
.ok { background: #23863633; color: #3fb950; }
|
|
26
|
+
.warn { background: #9e6a0333; color: #d29922; }
|
|
27
|
+
pre { background: #11151c; border: 1px solid #22262d; padding: 0.75rem; border-radius: 8px; overflow: auto; font-size: 0.8rem; }
|
|
28
|
+
.error { color: #f85149; }
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<header>
|
|
33
|
+
<h1>Plasm Operator</h1>
|
|
34
|
+
<nav id="nav"></nav>
|
|
35
|
+
</header>
|
|
36
|
+
<main>
|
|
37
|
+
<div class="meta" id="meta"></div>
|
|
38
|
+
<div id="content"></div>
|
|
39
|
+
</main>
|
|
40
|
+
<script>
|
|
41
|
+
const BASE = ${JSON.stringify(base)};
|
|
42
|
+
const PANES = [
|
|
43
|
+
{ id: "ops", label: "Ops", path: "/ops" },
|
|
44
|
+
{ id: "catalogs", label: "Catalogs", path: "/catalogs" },
|
|
45
|
+
{ id: "sessions", label: "Sessions", path: "/sessions" },
|
|
46
|
+
{ id: "plans", label: "Plans", path: "/plans" },
|
|
47
|
+
{ id: "runs", label: "Runs", path: "/runs" },
|
|
48
|
+
{ id: "traces", label: "Traces", path: "/traces" },
|
|
49
|
+
{ id: "archives", label: "Archives", path: "/archives" },
|
|
50
|
+
];
|
|
51
|
+
let active = "catalogs";
|
|
52
|
+
const nav = document.getElementById("nav");
|
|
53
|
+
const meta = document.getElementById("meta");
|
|
54
|
+
const content = document.getElementById("content");
|
|
55
|
+
function setActive(id) {
|
|
56
|
+
active = id;
|
|
57
|
+
for (const btn of nav.querySelectorAll("button")) {
|
|
58
|
+
btn.classList.toggle("active", btn.dataset.id === id);
|
|
59
|
+
}
|
|
60
|
+
void loadPane(id);
|
|
61
|
+
}
|
|
62
|
+
for (const pane of PANES) {
|
|
63
|
+
const btn = document.createElement("button");
|
|
64
|
+
btn.textContent = pane.label;
|
|
65
|
+
btn.dataset.id = pane.id;
|
|
66
|
+
btn.onclick = () => setActive(pane.id);
|
|
67
|
+
nav.appendChild(btn);
|
|
68
|
+
}
|
|
69
|
+
async function fetchJson(path) {
|
|
70
|
+
const res = await fetch(BASE + path);
|
|
71
|
+
if (!res.ok) throw new Error(res.status + " " + path);
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
function esc(s) {
|
|
75
|
+
return String(s).replace(/[&<>"]/g, (c) => ({ "&":"&","<":"<",">":">",'"':""" }[c]));
|
|
76
|
+
}
|
|
77
|
+
function renderTable(rows, columns) {
|
|
78
|
+
if (!rows.length) return "<p>No rows.</p>";
|
|
79
|
+
const head = columns.map((c) => "<th>" + esc(c.label) + "</th>").join("");
|
|
80
|
+
const body = rows.map((row) =>
|
|
81
|
+
"<tr>" + columns.map((c) => "<td>" + esc(c.render(row)) + "</td>").join("") + "</tr>"
|
|
82
|
+
).join("");
|
|
83
|
+
return "<table><thead><tr>" + head + "</tr></thead><tbody>" + body + "</tbody></table>";
|
|
84
|
+
}
|
|
85
|
+
async function loadPane(id) {
|
|
86
|
+
meta.textContent = "Loading…";
|
|
87
|
+
content.innerHTML = "";
|
|
88
|
+
try {
|
|
89
|
+
const pane = PANES.find((p) => p.id === id);
|
|
90
|
+
const data = await fetchJson(pane.path);
|
|
91
|
+
meta.textContent = "Updated " + new Date().toLocaleString();
|
|
92
|
+
if (id === "ops") {
|
|
93
|
+
content.innerHTML = "<pre>" + esc(JSON.stringify(data, null, 2)) + "</pre>";
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (id === "catalogs") {
|
|
97
|
+
content.innerHTML = renderTable(data.catalogs || [], [
|
|
98
|
+
{ label: "entry", render: (r) => r.entryId },
|
|
99
|
+
{ label: "hash", render: (r) => (r.catalogCgsHash || "").slice(0, 12) + "…" },
|
|
100
|
+
{ label: "stub", render: (r) => r.stub?.fresh ? "fresh" : "stale" },
|
|
101
|
+
{ label: "caps", render: (r) => String(r.capabilityCount ?? "") },
|
|
102
|
+
]);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (id === "sessions") {
|
|
106
|
+
content.innerHTML = renderTable(data.sessions || [], [
|
|
107
|
+
{ label: "intent", render: (r) => r.intent },
|
|
108
|
+
{ label: "ref", render: (r) => r.logicalSessionRef },
|
|
109
|
+
{ label: "plans", render: (r) => String(r.planCommitCount ?? 0) },
|
|
110
|
+
]);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (id === "plans") {
|
|
114
|
+
content.innerHTML = renderTable(data.plans || [], [
|
|
115
|
+
{ label: "pc", render: (r) => r.ref },
|
|
116
|
+
{ label: "intent", render: (r) => r.intent },
|
|
117
|
+
{ label: "program", render: (r) => (r.program || "").slice(0, 48) },
|
|
118
|
+
]);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (id === "runs" || id === "traces" || id === "archives") {
|
|
122
|
+
content.innerHTML = "<pre>" + esc(JSON.stringify(data, null, 2)) + "</pre>";
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
content.innerHTML = "<pre>" + esc(JSON.stringify(data, null, 2)) + "</pre>";
|
|
126
|
+
} catch (err) {
|
|
127
|
+
meta.innerHTML = '<span class="error">' + esc(String(err)) + "</span>";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
setActive("catalogs");
|
|
131
|
+
</script>
|
|
132
|
+
</body>
|
|
133
|
+
</html>`;
|
|
134
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { listChannelRoutes } from "./authoring/channel-dispatch.js";
|
|
4
|
+
import { loadAuthoredSlots, summarizeLoadedSlots } from "./authoring/slot-loader.js";
|
|
5
|
+
import { loadSubagents, summarizeSubagents } from "./authoring/subagent-loader.js";
|
|
6
|
+
import type { AgentDefinition } from "./define-agent.js";
|
|
7
|
+
import type { ProjectDiscovery } from "./discovery/project-walker.js";
|
|
8
|
+
import { walkAgentProject } from "./discovery/project-walker.js";
|
|
9
|
+
import { isNativeEngineAvailable } from "./engine/napi-binding.js";
|
|
10
|
+
import { exportScheduleCronManifest } from "./authoring/schedule-manager.js";
|
|
11
|
+
import { isGatewayConfigured } from "./gateway-model.js";
|
|
12
|
+
import type { LoadedProjectSlots } from "./authoring/slot-loader.js";
|
|
13
|
+
import { resolveCatalogLiveHash } from "./stubs/catalog-hash.js";
|
|
14
|
+
import { stubFreshness } from "./stubs/generator.js";
|
|
15
|
+
|
|
16
|
+
export const PLASM_LANGUAGE_TOOLS = [
|
|
17
|
+
"discover_capabilities",
|
|
18
|
+
"plasm_context",
|
|
19
|
+
"plasm",
|
|
20
|
+
"plasm_run",
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
export const FRAMEWORK_NAME = "@plasm_lang/vercel-agent";
|
|
24
|
+
export const FRAMEWORK_VERSION = "0.0.1";
|
|
25
|
+
|
|
26
|
+
export interface CatalogInfoEntry {
|
|
27
|
+
name: string;
|
|
28
|
+
entryId?: string;
|
|
29
|
+
stubPath: string;
|
|
30
|
+
stubFresh?: Awaited<ReturnType<typeof stubFreshness>>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ProjectInfoRoutes {
|
|
34
|
+
health: string;
|
|
35
|
+
info: string;
|
|
36
|
+
session: string;
|
|
37
|
+
sessionContinue: string;
|
|
38
|
+
sessionStream: string;
|
|
39
|
+
channels: Array<{ method: string; path: string }>;
|
|
40
|
+
scheduleCrons: string[];
|
|
41
|
+
operator: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ProjectInfoPayload {
|
|
45
|
+
status: "ok" | "degraded";
|
|
46
|
+
framework: string;
|
|
47
|
+
version: string;
|
|
48
|
+
projectRoot: string;
|
|
49
|
+
agentRoot: string;
|
|
50
|
+
packageName?: string;
|
|
51
|
+
engine: {
|
|
52
|
+
native: boolean;
|
|
53
|
+
mode: "napi" | "stub";
|
|
54
|
+
};
|
|
55
|
+
gateway: {
|
|
56
|
+
configured: boolean;
|
|
57
|
+
};
|
|
58
|
+
discovery: ProjectDiscovery;
|
|
59
|
+
loadedSlots: ReturnType<typeof summarizeLoadedSlots> & {
|
|
60
|
+
subagents: ReturnType<typeof summarizeSubagents>;
|
|
61
|
+
};
|
|
62
|
+
catalogs: CatalogInfoEntry[];
|
|
63
|
+
diagnostics: Array<{
|
|
64
|
+
level: string;
|
|
65
|
+
slot: string;
|
|
66
|
+
path: string;
|
|
67
|
+
message: string;
|
|
68
|
+
}>;
|
|
69
|
+
languageTools: readonly string[];
|
|
70
|
+
/** Present on dev-server `/plasm/v1/info` only. */
|
|
71
|
+
dev?: {
|
|
72
|
+
model: AgentDefinition["model"];
|
|
73
|
+
compaction: AgentDefinition["compaction"] | null;
|
|
74
|
+
modelOptions: AgentDefinition["modelOptions"] | null;
|
|
75
|
+
build: AgentDefinition["build"] | null;
|
|
76
|
+
experimental: AgentDefinition["experimental"] | null;
|
|
77
|
+
scheduleCrons: ReturnType<typeof exportScheduleCronManifest> | null;
|
|
78
|
+
sessions: { active: number };
|
|
79
|
+
routes: ProjectInfoRoutes;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface CollectProjectInfoOptions {
|
|
84
|
+
projectRoot: string;
|
|
85
|
+
agentRoot: string;
|
|
86
|
+
packageName?: string;
|
|
87
|
+
cached?: {
|
|
88
|
+
discovery: ProjectDiscovery;
|
|
89
|
+
loadedSlots: LoadedProjectSlots;
|
|
90
|
+
subagents: ReturnType<typeof summarizeSubagents>;
|
|
91
|
+
};
|
|
92
|
+
dev?: {
|
|
93
|
+
definition: AgentDefinition;
|
|
94
|
+
sessionCount: number;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function catalogEntries(
|
|
99
|
+
project: { projectRoot: string; agentRoot: string },
|
|
100
|
+
discovery: ProjectDiscovery,
|
|
101
|
+
): Promise<CatalogInfoEntry[]> {
|
|
102
|
+
const catalogs: CatalogInfoEntry[] = [];
|
|
103
|
+
for (const catalog of discovery.catalogs) {
|
|
104
|
+
const entryId = catalog.entryId ?? catalog.name;
|
|
105
|
+
const stubPath = path.join(project.agentRoot, ".plasm", "stubs", `${entryId}.ts`);
|
|
106
|
+
let stubFresh: Awaited<ReturnType<typeof stubFreshness>> | undefined;
|
|
107
|
+
try {
|
|
108
|
+
const liveHash = await resolveCatalogLiveHash(catalog.path);
|
|
109
|
+
stubFresh = await stubFreshness(liveHash, stubPath);
|
|
110
|
+
} catch {
|
|
111
|
+
stubFresh = undefined;
|
|
112
|
+
}
|
|
113
|
+
catalogs.push({
|
|
114
|
+
name: catalog.name,
|
|
115
|
+
entryId: catalog.entryId,
|
|
116
|
+
stubPath: path.relative(project.projectRoot, stubPath),
|
|
117
|
+
stubFresh,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return catalogs;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function collectProjectInfo(
|
|
124
|
+
options: CollectProjectInfoOptions,
|
|
125
|
+
): Promise<ProjectInfoPayload> {
|
|
126
|
+
const { projectRoot, agentRoot, packageName, cached, dev } = options;
|
|
127
|
+
|
|
128
|
+
let discovery: ProjectDiscovery;
|
|
129
|
+
let loadedSlots: LoadedProjectSlots;
|
|
130
|
+
let subagentSummary: ReturnType<typeof summarizeSubagents>;
|
|
131
|
+
let subDiagnostics: Array<{ level: string; slot: string; path: string; message: string }>;
|
|
132
|
+
|
|
133
|
+
if (cached) {
|
|
134
|
+
discovery = cached.discovery;
|
|
135
|
+
loadedSlots = cached.loadedSlots;
|
|
136
|
+
subagentSummary = cached.subagents;
|
|
137
|
+
subDiagnostics = [];
|
|
138
|
+
} else {
|
|
139
|
+
discovery = await walkAgentProject(agentRoot);
|
|
140
|
+
loadedSlots = await loadAuthoredSlots({ discovery });
|
|
141
|
+
const loaded = await loadSubagents({ discovery, parentSlots: loadedSlots });
|
|
142
|
+
subagentSummary = summarizeSubagents(loaded.subagents, agentRoot);
|
|
143
|
+
subDiagnostics = loaded.diagnostics;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const diagnostics = [
|
|
147
|
+
...loadedSlots.diagnostics,
|
|
148
|
+
...subDiagnostics,
|
|
149
|
+
...discovery.diagnostics,
|
|
150
|
+
];
|
|
151
|
+
const catalogs = await catalogEntries({ projectRoot, agentRoot }, discovery);
|
|
152
|
+
const hasErrors = diagnostics.some((d) => d.level === "error");
|
|
153
|
+
const native = isNativeEngineAvailable();
|
|
154
|
+
|
|
155
|
+
const payload: ProjectInfoPayload = {
|
|
156
|
+
status: hasErrors ? "degraded" : "ok",
|
|
157
|
+
framework: FRAMEWORK_NAME,
|
|
158
|
+
version: FRAMEWORK_VERSION,
|
|
159
|
+
projectRoot,
|
|
160
|
+
agentRoot,
|
|
161
|
+
packageName,
|
|
162
|
+
engine: {
|
|
163
|
+
native,
|
|
164
|
+
mode: native ? "napi" : "stub",
|
|
165
|
+
},
|
|
166
|
+
gateway: { configured: isGatewayConfigured() },
|
|
167
|
+
discovery,
|
|
168
|
+
loadedSlots: {
|
|
169
|
+
...summarizeLoadedSlots(loadedSlots, agentRoot),
|
|
170
|
+
subagents: subagentSummary,
|
|
171
|
+
},
|
|
172
|
+
catalogs,
|
|
173
|
+
diagnostics,
|
|
174
|
+
languageTools: PLASM_LANGUAGE_TOOLS,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
if (dev) {
|
|
178
|
+
const scheduleCrons = exportScheduleCronManifest(loadedSlots.schedules);
|
|
179
|
+
payload.dev = {
|
|
180
|
+
model: dev.definition.model,
|
|
181
|
+
compaction: dev.definition.compaction ?? null,
|
|
182
|
+
modelOptions: dev.definition.modelOptions ?? null,
|
|
183
|
+
build: dev.definition.build ?? null,
|
|
184
|
+
experimental: dev.definition.experimental ?? null,
|
|
185
|
+
scheduleCrons,
|
|
186
|
+
sessions: { active: dev.sessionCount },
|
|
187
|
+
routes: {
|
|
188
|
+
health: "GET /plasm/v1/health",
|
|
189
|
+
info: "GET /plasm/v1/info",
|
|
190
|
+
session: "POST /plasm/v1/session",
|
|
191
|
+
sessionContinue: "POST /plasm/v1/session/:sessionId",
|
|
192
|
+
sessionStream: "GET /plasm/v1/session/:id/stream",
|
|
193
|
+
channels: listChannelRoutes(loadedSlots.channels),
|
|
194
|
+
scheduleCrons: scheduleCrons.crons.map((c) => `GET ${c.path}`),
|
|
195
|
+
operator: "GET /operator",
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return payload;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function formatPlasmInfoHuman(info: ProjectInfoPayload): string {
|
|
204
|
+
const lines: string[] = [];
|
|
205
|
+
lines.push(`${info.framework} status=${info.status}`);
|
|
206
|
+
lines.push(`project: ${info.projectRoot}`);
|
|
207
|
+
lines.push(`agent: ${info.agentRoot}`);
|
|
208
|
+
lines.push(`engine: ${info.engine.mode}${info.engine.native ? " (native)" : " (fallback)"}`);
|
|
209
|
+
lines.push(
|
|
210
|
+
`gateway: ${info.gateway.configured ? "configured" : "missing — set AI_GATEWAY_API_KEY or run plasm-agent link"}`,
|
|
211
|
+
);
|
|
212
|
+
lines.push("");
|
|
213
|
+
lines.push(`catalogs (${info.discovery.catalogs.length})`);
|
|
214
|
+
for (const c of info.catalogs) {
|
|
215
|
+
const fresh = c.stubFresh?.fresh ? "fresh" : c.stubFresh ? "stale" : "missing";
|
|
216
|
+
lines.push(` - ${c.name} entry_id=${c.entryId ?? "?"} stub=${fresh}`);
|
|
217
|
+
}
|
|
218
|
+
lines.push(`channels: ${info.discovery.channels.length} schedules: ${info.discovery.schedules.length}`);
|
|
219
|
+
lines.push(`skills: ${info.discovery.skills.length} hooks: ${info.discovery.hooks.length}`);
|
|
220
|
+
lines.push(`subagents: ${info.loadedSlots.subagents.length}`);
|
|
221
|
+
if (info.diagnostics.length) {
|
|
222
|
+
lines.push("");
|
|
223
|
+
lines.push("diagnostics:");
|
|
224
|
+
for (const d of info.diagnostics) {
|
|
225
|
+
lines.push(` [${d.level}] ${d.slot}: ${d.message} (${d.path})`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return lines.join("\n");
|
|
229
|
+
}
|