manifest 5.2.7 → 5.2.11
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 +18 -0
- package/dist/index.js +12 -4
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -16,6 +16,24 @@ Or with environment variables:
|
|
|
16
16
|
export MANIFEST_API_KEY=mnfst_YOUR_KEY
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
## Local mode
|
|
20
|
+
|
|
21
|
+
Run the full Manifest dashboard locally — no cloud account needed. Data is stored in SQLite at `~/.openclaw/manifest/`.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
openclaw plugins install manifest
|
|
25
|
+
openclaw config set plugins.entries.manifest.config.mode "local"
|
|
26
|
+
openclaw gateway restart
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Open `http://127.0.0.1:2099` to view the dashboard.
|
|
30
|
+
|
|
31
|
+
| Option | Type | Default | Description |
|
|
32
|
+
|--------|------|---------|-------------|
|
|
33
|
+
| `mode` | string | `cloud` | `local` for embedded server, `cloud` for hosted |
|
|
34
|
+
| `port` | number | `2099` | Local server port |
|
|
35
|
+
| `host` | string | `127.0.0.1` | Local server bind address |
|
|
36
|
+
|
|
19
37
|
## Configuration
|
|
20
38
|
|
|
21
39
|
| Option | Type | Default | Description |
|
package/dist/index.js
CHANGED
|
@@ -16,11 +16,19 @@ To resolve the conflict:`,(0,Xo.getConflictResolutionRecipe)(u,r))),c=a):QM.diag
|
|
|
16
16
|
openclaw config set plugins.entries.manifest.config.endpoint https://app.manifest.build/otlp`:`Invalid apiKey format. Keys must start with '${Ie}'. Fix it via:
|
|
17
17
|
openclaw config set manifest.apiKey ${Ie}YOUR_KEY`:`Missing apiKey. Set it via:
|
|
18
18
|
openclaw config set manifest.apiKey ${Ie}YOUR_KEY
|
|
19
|
-
or export MANIFEST_API_KEY=${Ie}YOUR_KEY`}var $i=ve(sM()),Qi=ve(pi()),wI=ve(LI()),BI=ve(VI()),GI=ve(Eo());m();var Wr=null,zr=null,Mc=null,gc=null;function Zi(o,r){let i=new GI.Resource({"service.name":o.serviceName,"service.version":"5.2.
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
or export MANIFEST_API_KEY=${Ie}YOUR_KEY`}var $i=ve(sM()),Qi=ve(pi()),wI=ve(LI()),BI=ve(VI()),GI=ve(Eo());m();var Wr=null,zr=null,Mc=null,gc=null;function Zi(o,r){let i=new GI.Resource({"service.name":o.serviceName,"service.version":"5.2.11","manifest.plugin":"true"}),c={Authorization:`Bearer ${o.apiKey}`},a=new wI.OTLPTraceExporter({url:`${o.endpoint}/v1/traces`,headers:c});Wr=new $i.BasicTracerProvider({resource:i,spanProcessors:[new $i.BatchSpanProcessor(a,{scheduledDelayMillis:5e3,maxQueueSize:2048,maxExportBatchSize:512})]}),Wr.register(),r.info(`[manifest] Trace exporter -> ${o.endpoint}/v1/traces`);let u=new BI.OTLPMetricExporter({url:`${o.endpoint}/v1/metrics`,headers:c});return zr=new Qi.MeterProvider({resource:i,readers:[new Qi.PeriodicExportingMetricReader({exporter:u,exportIntervalMillis:o.metricsIntervalMs})]}),Rt.setGlobalMeterProvider(zr),r.info(`[manifest] Metrics exporter -> ${o.endpoint}/v1/metrics (interval=${o.metricsIntervalMs}ms)`),Mc=He.getTracer("manifest-plugin","5.2.11"),gc=Rt.getMeter("manifest-plugin","5.2.11"),{tracer:Mc,meter:gc}}async function ea(o){o.info("[manifest] Shutting down telemetry..."),Wr&&(await Wr.shutdown(),Wr=null),zr&&(await zr.shutdown(),zr=null),Mc=null,gc=null,o.info("[manifest] Telemetry shut down")}m();var cr=new Map,HI,kI,YI,FI,P5,KI,jI,qI,WI;function ta(o){HI=o.createCounter(Oe.LLM_REQUESTS,{description:"Total LLM inference requests"}),kI=o.createCounter(Oe.LLM_TOKENS_INPUT,{description:"Total input tokens sent to LLM"}),YI=o.createCounter(Oe.LLM_TOKENS_OUTPUT,{description:"Total output tokens from LLM"}),FI=o.createCounter(Oe.LLM_TOKENS_CACHE_READ,{description:"Total cache-read tokens"}),P5=o.createHistogram(Oe.LLM_DURATION,{description:"LLM request duration in ms",unit:"ms"}),KI=o.createCounter(Oe.TOOL_CALLS,{description:"Total tool invocations"}),jI=o.createCounter(Oe.TOOL_ERRORS,{description:"Total tool errors"}),qI=o.createHistogram(Oe.TOOL_DURATION,{description:"Tool execution duration in ms",unit:"ms"}),WI=o.createCounter(Oe.MESSAGES_RECEIVED,{description:"Total messages received from users"})}function ra(o,r,i,c){o.on("message_received",a=>{let u=a.sessionKey||a.session?.key||`agent:${a.agent||"main"}:main`,t=a.channel||"unknown",e=r.startSpan(Zr.REQUEST,{kind:Be.SERVER,attributes:{[w.SESSION_KEY]:u,[w.CHANNEL]:t}});cr.set(u,{root:e}),WI.add(1,{[w.CHANNEL]:t}),c.debug(`[manifest] Root span started for session=${u}`)}),o.on("before_agent_start",a=>{let u=a.sessionKey||a.session?.key||`agent:${a.agent||"main"}:main`,t=a.agent||"main",e=cr.get(u),n=e?.root?He.setSpan(Ge.active(),e.root):Ge.active(),s=r.startSpan(Zr.AGENT_TURN,{kind:Be.INTERNAL,attributes:{[w.AGENT_NAME]:t,[w.SESSION_KEY]:u}},n);e?e.turn=s:cr.set(u,{root:s,turn:s}),c.debug(`[manifest] Agent turn started: agent=${t}, session=${u}`)}),o.on("tool_result_persist",a=>{let u=a.toolName||a.tool||"unknown",t=a.durationMs||0,e=a.error==null,n=a.sessionKey||"unknown",s=cr.get(n),l=s?.turn?He.setSpan(Ge.active(),s.turn):Ge.active(),E=r.startSpan(`${Zr.TOOL_PREFIX}${u}`,{kind:Be.INTERNAL,attributes:{[w.TOOL_NAME]:u,[w.TOOL_SUCCESS]:String(e),[w.SESSION_KEY]:n}},l);e||(E.setStatus({code:Nt.ERROR,message:a.error?.message||"Tool execution failed"}),jI.add(1,{[w.TOOL_NAME]:u})),E.end(),KI.add(1,{[w.TOOL_NAME]:u}),qI.record(t,{[w.TOOL_NAME]:u})}),o.on("agent_end",a=>{let u=a.sessionKey||a.session?.key||`agent:${a.agent||"main"}:main`,e=[...a.messages||[]].reverse().find(Xr=>Xr.role==="assistant"&&Xr.usage),n=e?.model||a.model||"unknown",s=e?.provider||a.provider||"unknown",l=e?.usage||a.usage||{},E=l.input||l.inputTokens||0,O=l.output||l.outputTokens||0,g=l.cacheRead||l.cacheReadTokens||0,pe=l.cacheWrite||l.cacheWriteTokens||0,Ae=cr.get(u);Ae?.turn&&(Ae.turn.setAttributes({[w.MODEL]:n,[w.PROVIDER]:s,[w.INPUT_TOKENS]:E,[w.OUTPUT_TOKENS]:O,[w.CACHE_READ_TOKENS]:g,[w.CACHE_WRITE_TOKENS]:pe}),Ae.turn.end()),Ae?.root&&Ae.root!==Ae.turn&&Ae.root.end(),cr.delete(u);let Le={[w.MODEL]:n,[w.PROVIDER]:s};HI.add(1,Le),kI.add(E,Le),YI.add(O,Le),g>0&&FI.add(g,Le),c.debug(`[manifest] agent_end tokens: in=${E}, out=${O}, cache=${g}`),c.debug(`[manifest] Trace completed for session=${u}`)}),c.info("[manifest] All hooks registered")}async function na(o){let r=o.endpoint.replace(/\/otlp(\/v1)?\/?$/,""),i={endpointReachable:!1,authValid:!1,agentName:null,error:null};try{let c=await fetch(`${r}/api/v1/health`,{signal:AbortSignal.timeout(5e3)});if(!c.ok)return i.error=`Health endpoint returned ${c.status}`,i;i.endpointReachable=!0}catch(c){let a=c instanceof Error?c.message:String(c);return i.error=`Cannot reach endpoint: ${a}`,i}try{let c=await fetch(`${r}/api/v1/agent/usage?range=24h`,{headers:{Authorization:`Bearer ${o.apiKey}`},signal:AbortSignal.timeout(5e3)});if(c.status===401||c.status===403)return i.error="API key rejected \u2014 check your mnfst_ key is correct",i;if(!c.ok)return i.error=`Usage endpoint returned ${c.status}`,i;i.authValid=!0;let a=await c.json();a&&typeof a.agentName=="string"&&(i.agentName=a.agentName)}catch(c){let a=c instanceof Error?c.message:String(c);return i.error=`Auth check failed: ${a}`,i}return i}var zI={today:"24h",week:"7d",month:"30d"};async function JI(o,r,i,c){let a=`${o}${r}`;try{let u=await fetch(a,{headers:{Authorization:`Bearer ${i}`}});return u.ok?{result:await u.json()}:{error:`API returned ${u.status}`}}catch(u){let t=u instanceof Error?u.message:String(u);return c.error(`[manifest] API call failed: ${t}`),{error:t}}}function oa(o,r,i){let c=r.endpoint.replace(/\/otlp(\/v1)?\/?$/,"");o.registerTool({name:"manifest_usage",description:"Get token consumption for this agent: total, input, output, cache-read tokens, and action count. Use when the user asks about token usage or consumption.",parameters:{type:"object",properties:{period:{type:"string",enum:["today","week","month"],default:"today",description:"Time period"}}},handler:async a=>{let u=zI[a.period||"today"]||"24h";return JI(c,`/api/v1/agent/usage?range=${u}`,r.apiKey,i)}}),o.registerTool({name:"manifest_costs",description:"Get cost breakdown for this agent in USD, grouped by model. Use when the user asks about costs, spending, or money burned.",parameters:{type:"object",properties:{period:{type:"string",enum:["today","week","month"],default:"week",description:"Time period"}}},handler:async a=>{let u=zI[a.period||"week"]||"7d";return JI(c,`/api/v1/agent/costs?range=${u}`,r.apiKey,i)}}),o.registerTool({name:"manifest_health",description:"Check whether Manifest observability is connected and working. Use when the user asks if monitoring is set up or wants a connectivity test.",parameters:{type:"object",properties:{}},handler:async()=>{let a=await na(r);return a.error?{error:a.error}:{result:{endpointReachable:a.endpointReachable,authValid:a.authValid,agentName:a.agentName,status:"ok"}}}}),i.info("[manifest] Registered agent tools: manifest_usage, manifest_costs, manifest_health")}var de=require("fs"),aa=require("path"),XI=require("os"),$I=require("crypto");var ia=(0,aa.join)((0,XI.homedir)(),".openclaw","manifest"),Jr=(0,aa.join)(ia,"config.json");function M5(){(0,de.existsSync)(ia)||(0,de.mkdirSync)(ia,{recursive:!0,mode:448})}function g5(){if(M5(),(0,de.existsSync)(Jr))try{let i=JSON.parse((0,de.readFileSync)(Jr,"utf-8"));if(i.apiKey&&i.apiKey.startsWith(Ie))return i.apiKey}catch{}let o=`${Ie}local_${(0,$I.randomBytes)(24).toString("hex")}`,r={};if((0,de.existsSync)(Jr))try{r=JSON.parse((0,de.readFileSync)(Jr,"utf-8"))}catch{}return(0,de.writeFileSync)(Jr,JSON.stringify({...r,apiKey:o},null,2),{mode:384}),o}function QI(o,r,i){let c=r.port,a=r.host,u=g5(),t=(0,aa.join)(ia,"manifest.db");i.info("[manifest] Local mode \u2014 starting embedded server...");let e;try{e=require("@mnfst/server")}catch{i.error(`[manifest] @mnfst/server is not installed. Local mode cannot start.
|
|
20
|
+
Try reinstalling the plugin:
|
|
21
|
+
openclaw plugins install manifest && openclaw gateway restart
|
|
22
|
+
|
|
23
|
+
If that doesn't help, install the server globally:
|
|
24
|
+
npm install -g @mnfst/server
|
|
25
|
+
openclaw gateway restart
|
|
26
|
+
|
|
27
|
+
Or switch to cloud mode:
|
|
28
|
+
openclaw config set plugins.entries.manifest.config.mode cloud
|
|
29
|
+
openclaw gateway restart`);return}let n=`http://${a}:${c}/otlp`,s={...r,apiKey:u,endpoint:n},{tracer:l,meter:E}=Zi(s,i);ta(E),ra(o,l,s,i),typeof o.registerTool=="function"&&oa(o,s,i),o.registerService({id:"manifest-local",start:async()=>{try{await e.start({port:c,host:a,dbPath:t,quiet:!0}),i.info(`[manifest] Local server running on http://${a}:${c}`),i.info(`[manifest] Dashboard: http://${a}:${c}`),i.info(`[manifest] DB: ${t}`)}catch(O){let g=O instanceof Error?O.message:String(O);g.includes("EADDRINUSE")||g.includes("address already in use")?i.error(`[manifest] Port ${c} is already in use.
|
|
22
30
|
Change it with: openclaw config set plugins.entries.manifest.config.port ${c+1}
|
|
23
|
-
Then restart the gateway.`):i.error(`[manifest] Failed to start local server: ${g}`)}},stop:async()=>{await ea(i)}})}var eC=require("crypto"),De=require("os"),ua=require("fs"),tC=require("path"),rC=require("os"),L5="https://eu.i.posthog.com",I5="phc_g5pLOu5bBRjhVJBwAsx0eCzJFWq0cri2TyVLQLxf045",ZI=(0,tC.join)((0,rC.homedir)(),".openclaw","manifest","config.json");function C5(){let o=__fromEnv.MANIFEST_TELEMETRY_OPTOUT;if(o==="1"||o==="true")return!0;try{if((0,ua.existsSync)(ZI)&&JSON.parse((0,ua.readFileSync)(ZI,"utf-8")).telemetryOptOut===!0)return!0}catch{}return!1}function x5(){let o=`${(0,De.hostname)()}-${(0,De.platform)()}-${(0,De.arch)()}`;return(0,eC.createHash)("sha256").update(o).digest("hex").slice(0,16)}function Lc(o,r){if(C5())return;let i={api_key:I5,event:o,properties:{distinct_id:x5(),os:(0,De.platform)(),os_version:(0,De.release)(),node_version:process.versions.node,package_version:"5.2.
|
|
31
|
+
Then restart the gateway.`):i.error(`[manifest] Failed to start local server: ${g}`)}},stop:async()=>{await ea(i)}})}var eC=require("crypto"),De=require("os"),ua=require("fs"),tC=require("path"),rC=require("os"),L5="https://eu.i.posthog.com",I5="phc_g5pLOu5bBRjhVJBwAsx0eCzJFWq0cri2TyVLQLxf045",ZI=(0,tC.join)((0,rC.homedir)(),".openclaw","manifest","config.json");function C5(){let o=__fromEnv.MANIFEST_TELEMETRY_OPTOUT;if(o==="1"||o==="true")return!0;try{if((0,ua.existsSync)(ZI)&&JSON.parse((0,ua.readFileSync)(ZI,"utf-8")).telemetryOptOut===!0)return!0}catch{}return!1}function x5(){let o=`${(0,De.hostname)()}-${(0,De.platform)()}-${(0,De.arch)()}`;return(0,eC.createHash)("sha256").update(o).digest("hex").slice(0,16)}function Lc(o,r){if(C5())return;let i={api_key:I5,event:o,properties:{distinct_id:x5(),os:(0,De.platform)(),os_version:(0,De.release)(),node_version:process.versions.node,package_version:"5.2.11",...r},timestamp:new Date().toISOString()};fetch(`${L5}/capture`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}).catch(()=>{})}module.exports={id:"manifest",name:"Manifest \u2014 Agent Observability",register(o){let r=o.logger||{info:(...e)=>console.log(...e),debug:()=>{},error:(...e)=>console.error(...e),warn:(...e)=>console.warn(...e)},i=xc(o.pluginConfig);if(Lc("plugin_registered"),Lc("plugin_mode_selected",{mode:i.mode}),i.mode==="local"){QI(o,i,r);return}let c=bc(i);if(c){i.apiKey?r.error(`[manifest] Configuration error:
|
|
24
32
|
${c}`):r.info(`[manifest] Installed! Complete setup:
|
|
25
33
|
1. openclaw config set plugins.entries.manifest.config.apiKey mnfst_YOUR_KEY
|
|
26
34
|
2. openclaw gateway restart`);return}if((o.config?.plugins?.entries||{})["diagnostics-otel"]?.enabled){r.error(`[manifest] ERROR: Built-in 'diagnostics-otel' is also enabled. This causes duplicate OTel registration errors. Disable it now:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "manifest",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.11",
|
|
4
4
|
"description": "Observability plugin for OpenClaw — traces, metrics, and cost tracking for your AI agent",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,6 +54,9 @@
|
|
|
54
54
|
"telemetry",
|
|
55
55
|
"agent-analytics"
|
|
56
56
|
],
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@mnfst/server": "^5.2.11"
|
|
59
|
+
},
|
|
57
60
|
"devDependencies": {
|
|
58
61
|
"@opentelemetry/api": "^1.9.0",
|
|
59
62
|
"@opentelemetry/sdk-trace-base": "^1.30.0",
|