@useorgx/openclaw-plugin 0.4.3 → 0.4.4

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.
@@ -201,16 +201,36 @@ export class OrgXClient {
201
201
  // Spawn Guard (Quality Gate + Model Routing)
202
202
  // ===========================================================================
203
203
  async checkSpawnGuard(domain, taskId) {
204
- return this.post("/api/client/spawn", {
204
+ const response = await this.post("/api/client/spawn", {
205
205
  domain,
206
206
  taskId,
207
207
  });
208
+ // Newer servers wrap responses in { ok, data } while older clients expect the
209
+ // SpawnGuardResult fields at top-level.
210
+ if (response &&
211
+ typeof response === "object" &&
212
+ "data" in response &&
213
+ response.data) {
214
+ return response.data;
215
+ }
216
+ return response;
208
217
  }
209
218
  // ===========================================================================
210
219
  // Quality Scores
211
220
  // ===========================================================================
212
221
  async recordQuality(score) {
213
- return this.post("/api/client/quality", score);
222
+ const response = await this.post("/api/client/quality", score);
223
+ // Backwards-compatible: accept either { success: true } or { ok: true, data: ... }.
224
+ if (response &&
225
+ typeof response === "object" &&
226
+ "success" in response &&
227
+ typeof response.success === "boolean") {
228
+ return response;
229
+ }
230
+ if (response && typeof response === "object" && "ok" in response) {
231
+ return { success: Boolean(response.ok) };
232
+ }
233
+ return { success: true };
214
234
  }
215
235
  // ===========================================================================
216
236
  // Entity CRUD
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ import { clearPersistedSnapshot, readPersistedSnapshot, writePersistedSnapshot,
22
22
  import { appendToOutbox, readOutbox, readOutboxSummary, replaceOutbox, } from "./outbox.js";
23
23
  import { extractProgressOutboxMessage } from "./reporting/outbox-replay.js";
24
24
  import { ensureGatewayWatchdog } from "./gateway-watchdog.js";
25
+ import { posthogCapture } from "./telemetry/posthog.js";
25
26
  export { OrgXClient } from "./api.js";
26
27
  const DEFAULT_BASE_URL = "https://www.useorgx.com";
27
28
  const DEFAULT_DOCS_URL = "https://orgx.mintlify.site/guides/openclaw-plugin-setup";
@@ -325,6 +326,19 @@ export default function register(api) {
325
326
  api.log?.info?.("[orgx] Plugin disabled");
326
327
  return;
327
328
  }
329
+ void posthogCapture({
330
+ event: "openclaw_plugin_loaded",
331
+ distinctId: config.installationId,
332
+ properties: {
333
+ plugin_version: config.pluginVersion,
334
+ dashboard_enabled: config.dashboardEnabled,
335
+ has_api_key: Boolean(config.apiKey),
336
+ api_key_source: config.apiKeySource,
337
+ base_url: config.baseUrl,
338
+ },
339
+ }).catch(() => {
340
+ // best effort
341
+ });
328
342
  if (!config.apiKey) {
329
343
  api.log?.warn?.("[orgx] No API key. Set plugins.entries.orgx.config.apiKey, ORGX_API_KEY env, or ~/Code/orgx/orgx/.env.local");
330
344
  }
@@ -391,6 +405,140 @@ export default function register(api) {
391
405
  return err.message;
392
406
  return typeof err === "string" ? err : "Unexpected error";
393
407
  }
408
+ const registerTool = api.registerTool.bind(api);
409
+ api.registerTool = (tool, options) => {
410
+ const toolName = tool.name;
411
+ const optional = Boolean(options?.optional);
412
+ registerTool({
413
+ ...tool,
414
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
415
+ execute: async (callId, params) => {
416
+ const startedAt = Date.now();
417
+ void posthogCapture({
418
+ event: "openclaw_tool_called",
419
+ distinctId: config.installationId,
420
+ properties: {
421
+ tool_name: toolName,
422
+ tool_optional: optional,
423
+ call_id: callId,
424
+ plugin_version: config.pluginVersion,
425
+ },
426
+ }).catch(() => {
427
+ // best effort
428
+ });
429
+ try {
430
+ const result = await tool.execute(callId, params);
431
+ const durationMs = Date.now() - startedAt;
432
+ void posthogCapture({
433
+ event: "openclaw_tool_succeeded",
434
+ distinctId: config.installationId,
435
+ properties: {
436
+ tool_name: toolName,
437
+ tool_optional: optional,
438
+ call_id: callId,
439
+ duration_ms: durationMs,
440
+ plugin_version: config.pluginVersion,
441
+ },
442
+ }).catch(() => {
443
+ // best effort
444
+ });
445
+ return result;
446
+ }
447
+ catch (err) {
448
+ const durationMs = Date.now() - startedAt;
449
+ void posthogCapture({
450
+ event: "openclaw_tool_failed",
451
+ distinctId: config.installationId,
452
+ properties: {
453
+ tool_name: toolName,
454
+ tool_optional: optional,
455
+ call_id: callId,
456
+ duration_ms: durationMs,
457
+ plugin_version: config.pluginVersion,
458
+ error: toErrorMessage(err),
459
+ },
460
+ }).catch(() => {
461
+ // best effort
462
+ });
463
+ throw err;
464
+ }
465
+ },
466
+ }, options);
467
+ };
468
+ const registerService = api.registerService.bind(api);
469
+ api.registerService = (service) => {
470
+ registerService({
471
+ ...service,
472
+ start: async () => {
473
+ const startedAt = Date.now();
474
+ try {
475
+ await service.start();
476
+ const durationMs = Date.now() - startedAt;
477
+ void posthogCapture({
478
+ event: "openclaw_service_started",
479
+ distinctId: config.installationId,
480
+ properties: {
481
+ service_id: service.id,
482
+ duration_ms: durationMs,
483
+ plugin_version: config.pluginVersion,
484
+ },
485
+ }).catch(() => {
486
+ // best effort
487
+ });
488
+ }
489
+ catch (err) {
490
+ const durationMs = Date.now() - startedAt;
491
+ void posthogCapture({
492
+ event: "openclaw_service_start_failed",
493
+ distinctId: config.installationId,
494
+ properties: {
495
+ service_id: service.id,
496
+ duration_ms: durationMs,
497
+ plugin_version: config.pluginVersion,
498
+ error: toErrorMessage(err),
499
+ },
500
+ }).catch(() => {
501
+ // best effort
502
+ });
503
+ throw err;
504
+ }
505
+ },
506
+ stop: async () => {
507
+ const startedAt = Date.now();
508
+ try {
509
+ await service.stop();
510
+ const durationMs = Date.now() - startedAt;
511
+ void posthogCapture({
512
+ event: "openclaw_service_stopped",
513
+ distinctId: config.installationId,
514
+ properties: {
515
+ service_id: service.id,
516
+ duration_ms: durationMs,
517
+ plugin_version: config.pluginVersion,
518
+ },
519
+ }).catch(() => {
520
+ // best effort
521
+ });
522
+ }
523
+ catch (err) {
524
+ const durationMs = Date.now() - startedAt;
525
+ void posthogCapture({
526
+ event: "openclaw_service_stop_failed",
527
+ distinctId: config.installationId,
528
+ properties: {
529
+ service_id: service.id,
530
+ duration_ms: durationMs,
531
+ plugin_version: config.pluginVersion,
532
+ error: toErrorMessage(err),
533
+ },
534
+ }).catch(() => {
535
+ // best effort
536
+ });
537
+ throw err;
538
+ }
539
+ },
540
+ });
541
+ };
394
542
  function clearPairingState() {
395
543
  activePairing = null;
396
544
  updateOnboardingState({
@@ -0,0 +1,8 @@
1
+ export declare function isOrgxTelemetryDisabled(): boolean;
2
+ export declare function resolvePosthogApiKey(): string | null;
3
+ export declare function resolvePosthogHost(): string;
4
+ export declare function posthogCapture(input: {
5
+ event: string;
6
+ distinctId: string;
7
+ properties?: Record<string, unknown>;
8
+ }): Promise<void>;
@@ -0,0 +1,81 @@
1
+ const POSTHOG_DEFAULT_API_KEY = "phc_s4KPgkYEFZgvkMYw4zXG41H5FN6haVwbEWPYHfNjxOc";
2
+ const POSTHOG_DEFAULT_HOST = "https://us.i.posthog.com";
3
+ function isTruthyEnv(value) {
4
+ if (!value)
5
+ return false;
6
+ switch (value.trim().toLowerCase()) {
7
+ case "1":
8
+ case "true":
9
+ case "yes":
10
+ case "y":
11
+ case "on":
12
+ return true;
13
+ default:
14
+ return false;
15
+ }
16
+ }
17
+ export function isOrgxTelemetryDisabled() {
18
+ return (isTruthyEnv(process.env.ORGX_TELEMETRY_DISABLED) ||
19
+ isTruthyEnv(process.env.OPENCLAW_TELEMETRY_DISABLED) ||
20
+ isTruthyEnv(process.env.POSTHOG_DISABLED));
21
+ }
22
+ export function resolvePosthogApiKey() {
23
+ const fromEnv = process.env.ORGX_POSTHOG_API_KEY ??
24
+ process.env.POSTHOG_API_KEY ??
25
+ process.env.ORGX_POSTHOG_KEY ??
26
+ process.env.POSTHOG_KEY ??
27
+ "";
28
+ const trimmed = fromEnv.trim();
29
+ if (trimmed)
30
+ return trimmed;
31
+ return POSTHOG_DEFAULT_API_KEY;
32
+ }
33
+ export function resolvePosthogHost() {
34
+ const fromEnv = process.env.ORGX_POSTHOG_HOST ??
35
+ process.env.POSTHOG_HOST ??
36
+ process.env.ORGX_POSTHOG_API_HOST ??
37
+ process.env.POSTHOG_API_HOST ??
38
+ "";
39
+ const trimmed = fromEnv.trim();
40
+ return trimmed || POSTHOG_DEFAULT_HOST;
41
+ }
42
+ function toPosthogBatchUrl(host) {
43
+ try {
44
+ return new URL("/batch/", host).toString();
45
+ }
46
+ catch {
47
+ return `${POSTHOG_DEFAULT_HOST}/batch/`;
48
+ }
49
+ }
50
+ export async function posthogCapture(input) {
51
+ if (isOrgxTelemetryDisabled())
52
+ return;
53
+ const apiKey = resolvePosthogApiKey();
54
+ if (!apiKey)
55
+ return;
56
+ const url = toPosthogBatchUrl(resolvePosthogHost());
57
+ const now = new Date().toISOString();
58
+ const body = {
59
+ api_key: apiKey,
60
+ batch: [
61
+ {
62
+ type: "capture",
63
+ event: input.event,
64
+ distinct_id: input.distinctId,
65
+ properties: {
66
+ $lib: "orgx-openclaw-plugin",
67
+ ...(input.properties ?? {}),
68
+ },
69
+ timestamp: now,
70
+ },
71
+ ],
72
+ sent_at: now,
73
+ };
74
+ await fetch(url, {
75
+ method: "POST",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ },
79
+ body: JSON.stringify(body),
80
+ }).then(() => undefined);
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useorgx/openclaw-plugin",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "OrgX plugin for OpenClaw — agent orchestration, quality gates, model routing, and live dashboard",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- var z={exports:{}},K={};var Y;function le(){return Y||(Y=1,(function(e){function n(t,i){var a=t.length;t.push(i);e:for(;0<a;){var l=a-1>>>1,f=t[l];if(0<o(f,i))t[l]=i,t[a]=f,a=l;else break e}}function r(t){return t.length===0?null:t[0]}function s(t){if(t.length===0)return null;var i=t[0],a=t.pop();if(a!==i){t[0]=a;e:for(var l=0,f=t.length,S=f>>>1;l<S;){var E=2*(l+1)-1,R=t[E],w=E+1,G=t[w];if(0>o(R,a))w<f&&0>o(G,R)?(t[l]=G,t[w]=a,l=w):(t[l]=R,t[E]=a,l=E);else if(w<f&&0>o(G,a))t[l]=G,t[w]=a,l=w;else break e}}return i}function o(t,i){var a=t.sortIndex-i.sortIndex;return a!==0?a:t.id-i.id}if(typeof performance=="object"&&typeof performance.now=="function"){var d=performance;e.unstable_now=function(){return d.now()}}else{var T=Date,h=T.now();e.unstable_now=function(){return T.now()-h}}var u=[],m=[],g=1,p=null,c=3,y=!1,b=!1,P=!1,j=typeof setTimeout=="function"?setTimeout:null,x=typeof clearTimeout=="function"?clearTimeout:null,H=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function B(t){for(var i=r(m);i!==null;){if(i.callback===null)s(m);else if(i.startTime<=t)s(m),i.sortIndex=i.expirationTime,n(u,i);else break;i=r(m)}}function D(t){if(P=!1,B(t),!b)if(r(u)!==null)b=!0,q(M);else{var i=r(m);i!==null&&F(D,i.startTime-t)}}function M(t,i){b=!1,P&&(P=!1,x(A),A=-1),y=!0;var a=c;try{for(B(i),p=r(u);p!==null&&(!(p.expirationTime>i)||t&&!Q());){var l=p.callback;if(typeof l=="function"){p.callback=null,c=p.priorityLevel;var f=l(p.expirationTime<=i);i=e.unstable_now(),typeof f=="function"?p.callback=f:p===r(u)&&s(u),B(i)}else s(u);p=r(u)}if(p!==null)var S=!0;else{var E=r(m);E!==null&&F(D,E.startTime-i),S=!1}return S}finally{p=null,c=a,y=!1}}var I=!1,C=null,A=-1,V=5,J=-1;function Q(){return!(e.unstable_now()-J<V)}function N(){if(C!==null){var t=e.unstable_now();J=t;var i=!0;try{i=C(!0,t)}finally{i?_():(I=!1,C=null)}}else I=!1}var _;if(typeof H=="function")_=function(){H(N)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,ue=X.port2;X.port1.onmessage=N,_=function(){ue.postMessage(null)}}else _=function(){j(N,0)};function q(t){C=t,I||(I=!0,_())}function F(t,i){A=j(function(){t(e.unstable_now())},i)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(t){t.callback=null},e.unstable_continueExecution=function(){b||y||(b=!0,q(M))},e.unstable_forceFrameRate=function(t){0>t||125<t||(V=0<t?Math.floor(1e3/t):5)},e.unstable_getCurrentPriorityLevel=function(){return c},e.unstable_getFirstCallbackNode=function(){return r(u)},e.unstable_next=function(t){switch(c){case 1:case 2:case 3:var i=3;break;default:i=c}var a=c;c=i;try{return t()}finally{c=a}},e.unstable_pauseExecution=function(){},e.unstable_requestPaint=function(){},e.unstable_runWithPriority=function(t,i){switch(t){case 1:case 2:case 3:case 4:case 5:break;default:t=3}var a=c;c=t;try{return i()}finally{c=a}},e.unstable_scheduleCallback=function(t,i,a){var l=e.unstable_now();switch(typeof a=="object"&&a!==null?(a=a.delay,a=typeof a=="number"&&0<a?l+a:l):a=l,t){case 1:var f=-1;break;case 2:f=250;break;case 5:f=1073741823;break;case 4:f=1e4;break;default:f=5e3}return f=a+f,t={id:g++,callback:i,priorityLevel:t,startTime:a,expirationTime:f,sortIndex:-1},a>l?(t.sortIndex=a,n(m,t),r(u)===null&&t===r(m)&&(P?(x(A),A=-1):P=!0,F(D,a-l))):(t.sortIndex=f,n(u,t),b||y||(b=!0,q(M))),t},e.unstable_shouldYield=Q,e.unstable_wrapCallback=function(t){var i=c;return function(){var a=c;c=i;try{return t.apply(this,arguments)}finally{c=a}}}})(K)),K}var Z;function Ae(){return Z||(Z=1,z.exports=le()),z.exports}const ce=e=>e;let _e=ce;function re(e){let n;return()=>(n===void 0&&(n=e()),n)}const fe=(e,n,r)=>{const s=n-e;return s===0?1:(r-e)/s},ke=e=>e*1e3,Le=e=>e/1e3,de=re(()=>window.ScrollTimeline!==void 0);class pe{constructor(n){this.stop=()=>this.runAll("stop"),this.animations=n.filter(Boolean)}get finished(){return Promise.all(this.animations.map(n=>"finished"in n?n.finished:n))}getAll(n){return this.animations[0][n]}setAll(n,r){for(let s=0;s<this.animations.length;s++)this.animations[s][n]=r}attachTimeline(n,r){const s=this.animations.map(o=>{if(de()&&o.attachTimeline)return o.attachTimeline(n);if(typeof r=="function")return r(o)});return()=>{s.forEach((o,d)=>{o&&o(),this.animations[d].stop()})}}get time(){return this.getAll("time")}set time(n){this.setAll("time",n)}get speed(){return this.getAll("speed")}set speed(n){this.setAll("speed",n)}get startTime(){return this.getAll("startTime")}get duration(){let n=0;for(let r=0;r<this.animations.length;r++)n=Math.max(n,this.animations[r].duration);return n}runAll(n){this.animations.forEach(r=>r[n]())}flatten(){this.runAll("flatten")}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}class Ie extends pe{then(n,r){return Promise.all(this.animations).then(n).catch(r)}}function Ce(e,n){return e?e[n]||e.default||e:void 0}const $=2e4;function Se(e){let n=0;const r=50;let s=e.next(n);for(;!s.done&&n<$;)n+=r,s=e.next(n);return n>=$?1/0:n}function Ge(e){return typeof e=="function"}function Be(e,n){e.timeline=n,e.onfinish=null}const ie=e=>Array.isArray(e)&&typeof e[0]=="number",he={linearEasing:void 0};function me(e,n){const r=re(e);return()=>{var s;return(s=he[n])!==null&&s!==void 0?s:r()}}const U=me(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing"),ye=(e,n,r=10)=>{let s="";const o=Math.max(Math.round(n/r),2);for(let d=0;d<o;d++)s+=e(fe(0,o-1,d))+", ";return`linear(${s.substring(0,s.length-2)})`};function ve(e){return!!(typeof e=="function"&&U()||!e||typeof e=="string"&&(e in W||U())||ie(e)||Array.isArray(e)&&e.every(ve))}const k=([e,n,r,s])=>`cubic-bezier(${e}, ${n}, ${r}, ${s})`,W={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:k([0,.65,.55,1]),circOut:k([.55,0,1,.45]),backIn:k([.31,.01,.66,-.59]),backOut:k([.33,1.53,.69,.99])};function be(e,n){if(e)return typeof e=="function"&&U()?ye(e,n):ie(e)?k(e):Array.isArray(e)?e.map(r=>be(r,n)||W.easeOut):W[e]}const v={x:!1,y:!1};function se(){return v.x||v.y}function ge(e,n,r){var s;if(e instanceof Element)return[e];if(typeof e=="string"){let o=document;const d=(s=void 0)!==null&&s!==void 0?s:o.querySelectorAll(e);return d?Array.from(d):[]}return Array.from(e)}function ae(e,n){const r=ge(e),s=new AbortController,o={passive:!0,...n,signal:s.signal};return[r,o,()=>s.abort()]}function ee(e){return n=>{n.pointerType==="touch"||se()||e(n)}}function De(e,n,r={}){const[s,o,d]=ae(e,r),T=ee(h=>{const{target:u}=h,m=n(h);if(typeof m!="function"||!u)return;const g=ee(p=>{m(p),u.removeEventListener("pointerleave",g)});u.addEventListener("pointerleave",g,o)});return s.forEach(h=>{h.addEventListener("pointerenter",T,o)}),d}const oe=(e,n)=>n?e===n?!0:oe(e,n.parentElement):!1,Ee=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1,we=new Set(["BUTTON","INPUT","SELECT","TEXTAREA","A"]);function Te(e){return we.has(e.tagName)||e.tabIndex!==-1}const L=new WeakSet;function ne(e){return n=>{n.key==="Enter"&&e(n)}}function O(e,n){e.dispatchEvent(new PointerEvent("pointer"+n,{isPrimary:!0,bubbles:!0}))}const Pe=(e,n)=>{const r=e.currentTarget;if(!r)return;const s=ne(()=>{if(L.has(r))return;O(r,"down");const o=ne(()=>{O(r,"up")}),d=()=>O(r,"cancel");r.addEventListener("keyup",o,n),r.addEventListener("blur",d,n)});r.addEventListener("keydown",s,n),r.addEventListener("blur",()=>r.removeEventListener("keydown",s),n)};function te(e){return Ee(e)&&!se()}function Me(e,n,r={}){const[s,o,d]=ae(e,r),T=h=>{const u=h.currentTarget;if(!te(h)||L.has(u))return;L.add(u);const m=n(h),g=(y,b)=>{window.removeEventListener("pointerup",p),window.removeEventListener("pointercancel",c),!(!te(y)||!L.has(u))&&(L.delete(u),typeof m=="function"&&m(y,{success:b}))},p=y=>{g(y,r.useGlobalTarget||oe(u,y.target))},c=y=>{g(y,!1)};window.addEventListener("pointerup",p,o),window.addEventListener("pointercancel",c,o)};return s.forEach(h=>{!Te(h)&&h.getAttribute("tabindex")===null&&(h.tabIndex=0),(r.useGlobalTarget?window:h).addEventListener("pointerdown",T,o),h.addEventListener("focus",m=>Pe(m,o),o)}),d}function Ne(e){return e==="x"||e==="y"?v[e]?null:(v[e]=!0,()=>{v[e]=!1}):v.x||v.y?null:(v.x=v.y=!0,()=>{v.x=v.y=!1})}export{Ie as G,$ as a,ie as b,Se as c,_e as d,be as e,re as f,ye as g,U as h,Ge as i,Be as j,ve as k,Ce as l,Le as m,ce as n,Ee as o,fe as p,Ne as q,Ae as r,ke as s,De as t,Me as u};