@useorgx/openclaw-plugin 0.4.6 → 0.4.9

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.
Files changed (137) hide show
  1. package/README.md +310 -24
  2. package/dashboard/dist/assets/B5NEElEI.css +1 -0
  3. package/dashboard/dist/assets/BhapSNAs.js +215 -0
  4. package/dashboard/dist/assets/iFdvE7lx.js +1 -0
  5. package/dashboard/dist/assets/jRJsmpYM.js +1 -0
  6. package/dashboard/dist/index.html +2 -2
  7. package/dist/activity-actor-fields.d.ts +3 -0
  8. package/dist/activity-actor-fields.js +128 -0
  9. package/dist/activity-store.js +12 -19
  10. package/dist/agent-context-store.js +5 -25
  11. package/dist/agent-run-store.js +5 -25
  12. package/dist/agent-suite.js +1 -8
  13. package/dist/artifacts/register-artifact.d.ts +47 -0
  14. package/dist/artifacts/register-artifact.js +271 -0
  15. package/dist/auth/flows.d.ts +47 -0
  16. package/dist/auth/flows.js +169 -0
  17. package/dist/auth-store.js +14 -39
  18. package/dist/byok-store.js +5 -19
  19. package/dist/cli/orgx.d.ts +66 -0
  20. package/dist/cli/orgx.js +91 -0
  21. package/dist/config/refresh.d.ts +32 -0
  22. package/dist/config/refresh.js +55 -0
  23. package/dist/config/resolution.d.ts +37 -0
  24. package/dist/config/resolution.js +178 -0
  25. package/dist/contracts/client.d.ts +1 -0
  26. package/dist/contracts/client.js +7 -5
  27. package/dist/contracts/shared-types.d.ts +147 -0
  28. package/dist/contracts/shared-types.js +3 -0
  29. package/dist/contracts/types.d.ts +1 -130
  30. package/dist/contracts/types.js +5 -0
  31. package/dist/entities/auto-assignment.d.ts +36 -0
  32. package/dist/entities/auto-assignment.js +115 -0
  33. package/dist/entity-comment-store.js +5 -25
  34. package/dist/hash-utils.d.ts +2 -0
  35. package/dist/hash-utils.js +12 -0
  36. package/dist/http/helpers/activity-headline.d.ts +10 -0
  37. package/dist/http/helpers/activity-headline.js +192 -0
  38. package/dist/http/helpers/artifact-fallback.d.ts +13 -0
  39. package/dist/http/helpers/artifact-fallback.js +148 -0
  40. package/dist/http/helpers/auto-continue-engine.d.ts +298 -0
  41. package/dist/http/helpers/auto-continue-engine.js +1218 -0
  42. package/dist/http/helpers/autopilot-operations.d.ts +157 -0
  43. package/dist/http/helpers/autopilot-operations.js +403 -0
  44. package/dist/http/helpers/autopilot-runtime.d.ts +42 -0
  45. package/dist/http/helpers/autopilot-runtime.js +319 -0
  46. package/dist/http/helpers/autopilot-slice-utils.d.ts +38 -0
  47. package/dist/http/helpers/autopilot-slice-utils.js +476 -0
  48. package/dist/http/helpers/decision-mapper.d.ts +12 -0
  49. package/dist/http/helpers/decision-mapper.js +44 -0
  50. package/dist/http/helpers/dispatch-lifecycle.d.ts +102 -0
  51. package/dist/http/helpers/dispatch-lifecycle.js +604 -0
  52. package/dist/http/helpers/hash-utils.d.ts +1 -0
  53. package/dist/http/helpers/hash-utils.js +1 -0
  54. package/dist/http/helpers/kickoff-context.d.ts +12 -0
  55. package/dist/http/helpers/kickoff-context.js +154 -0
  56. package/dist/http/helpers/mission-control.d.ts +94 -0
  57. package/dist/http/helpers/mission-control.js +894 -0
  58. package/dist/http/helpers/openclaw-cli.d.ts +37 -0
  59. package/dist/http/helpers/openclaw-cli.js +283 -0
  60. package/dist/http/helpers/runtime-sse.d.ts +20 -0
  61. package/dist/http/helpers/runtime-sse.js +110 -0
  62. package/dist/http/helpers/value-utils.d.ts +6 -0
  63. package/dist/http/helpers/value-utils.js +67 -0
  64. package/dist/http/index.d.ts +88 -0
  65. package/dist/http/index.js +2353 -0
  66. package/dist/http/router.d.ts +23 -0
  67. package/dist/http/router.js +23 -0
  68. package/dist/http/routes/agent-control.d.ts +79 -0
  69. package/dist/http/routes/agent-control.js +684 -0
  70. package/dist/http/routes/agent-suite.d.ts +29 -0
  71. package/dist/http/routes/agent-suite.js +198 -0
  72. package/dist/http/routes/agents-catalog.d.ts +40 -0
  73. package/dist/http/routes/agents-catalog.js +83 -0
  74. package/dist/http/routes/billing.d.ts +23 -0
  75. package/dist/http/routes/billing.js +55 -0
  76. package/dist/http/routes/debug.d.ts +14 -0
  77. package/dist/http/routes/debug.js +21 -0
  78. package/dist/http/routes/decision-actions.d.ts +13 -0
  79. package/dist/http/routes/decision-actions.js +66 -0
  80. package/dist/http/routes/delegation.d.ts +19 -0
  81. package/dist/http/routes/delegation.js +32 -0
  82. package/dist/http/routes/entities.d.ts +47 -0
  83. package/dist/http/routes/entities.js +152 -0
  84. package/dist/http/routes/entity-dynamic.d.ts +25 -0
  85. package/dist/http/routes/entity-dynamic.js +191 -0
  86. package/dist/http/routes/health.d.ts +22 -0
  87. package/dist/http/routes/health.js +49 -0
  88. package/dist/http/routes/live-legacy.d.ts +110 -0
  89. package/dist/http/routes/live-legacy.js +598 -0
  90. package/dist/http/routes/live-misc.d.ts +69 -0
  91. package/dist/http/routes/live-misc.js +206 -0
  92. package/dist/http/routes/live-snapshot.d.ts +90 -0
  93. package/dist/http/routes/live-snapshot.js +297 -0
  94. package/dist/http/routes/mission-control-actions.d.ts +83 -0
  95. package/dist/http/routes/mission-control-actions.js +541 -0
  96. package/dist/http/routes/mission-control-read.d.ts +28 -0
  97. package/dist/http/routes/mission-control-read.js +67 -0
  98. package/dist/http/routes/onboarding.d.ts +34 -0
  99. package/dist/http/routes/onboarding.js +101 -0
  100. package/dist/http/routes/run-control.d.ts +24 -0
  101. package/dist/http/routes/run-control.js +86 -0
  102. package/dist/http/routes/runtime-hooks.d.ts +69 -0
  103. package/dist/http/routes/runtime-hooks.js +437 -0
  104. package/dist/http/routes/settings-byok.d.ts +23 -0
  105. package/dist/http/routes/settings-byok.js +163 -0
  106. package/dist/http/routes/summary.d.ts +18 -0
  107. package/dist/http/routes/summary.js +42 -0
  108. package/dist/http/routes/work-artifacts.d.ts +9 -0
  109. package/dist/http/routes/work-artifacts.js +36 -0
  110. package/dist/http/shared-state.d.ts +16 -0
  111. package/dist/http/shared-state.js +1 -0
  112. package/dist/http-handler.d.ts +1 -88
  113. package/dist/http-handler.js +1 -9664
  114. package/dist/index.js +122 -2121
  115. package/dist/json-utils.d.ts +1 -0
  116. package/dist/json-utils.js +8 -0
  117. package/dist/local-openclaw.js +8 -0
  118. package/dist/mcp-client-setup.js +75 -90
  119. package/dist/next-up-queue-store.js +4 -18
  120. package/dist/runtime-instance-store.js +8 -34
  121. package/dist/services/background.d.ts +23 -0
  122. package/dist/services/background.js +23 -0
  123. package/dist/services/instrumentation.d.ts +29 -0
  124. package/dist/services/instrumentation.js +136 -0
  125. package/dist/snapshot-store.js +5 -25
  126. package/dist/stores/json-store.d.ts +11 -0
  127. package/dist/stores/json-store.js +42 -0
  128. package/dist/sync/outbox-replay.d.ts +55 -0
  129. package/dist/sync/outbox-replay.js +514 -0
  130. package/dist/tools/core-tools.d.ts +76 -0
  131. package/dist/tools/core-tools.js +1005 -0
  132. package/dist/worker-supervisor.js +15 -0
  133. package/package.json +6 -1
  134. package/dashboard/dist/assets/0tOC3wSN.js +0 -214
  135. package/dashboard/dist/assets/Bm8QnMJ_.js +0 -1
  136. package/dashboard/dist/assets/CyxZio4Y.js +0 -1
  137. package/dashboard/dist/assets/DaAIOik3.css +0 -1
@@ -0,0 +1,29 @@
1
+ import type { Router } from "../router.js";
2
+ type JsonRecord = Record<string, unknown>;
3
+ type ReadSkillPackStateFn = typeof import("../../skill-pack-state.js").readSkillPackState;
4
+ type UpdateSkillPackPolicyFn = typeof import("../../skill-pack-state.js").updateSkillPackPolicy;
5
+ type ComputeOrgxAgentSuitePlanFn = typeof import("../../agent-suite.js").computeOrgxAgentSuitePlan;
6
+ type ApplyOrgxAgentSuitePlanFn = typeof import("../../agent-suite.js").applyOrgxAgentSuitePlan;
7
+ type OrgxSkillPackOverrides = import("../../agent-suite.js").OrgxSkillPackOverrides;
8
+ type RegisterAgentSuiteRoutesDeps<TReq, TRes> = {
9
+ pluginVersion: string | null | undefined;
10
+ telemetryDistinctId: string;
11
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
12
+ resolveSkillPackOverrides: (input: {
13
+ force?: boolean;
14
+ }) => Promise<OrgxSkillPackOverrides | null>;
15
+ readSkillPackState: ReadSkillPackStateFn;
16
+ computeOrgxAgentSuitePlan: ComputeOrgxAgentSuitePlanFn;
17
+ applyOrgxAgentSuitePlan: ApplyOrgxAgentSuitePlanFn;
18
+ generateAgentSuiteOperationId: () => string;
19
+ updateSkillPackPolicy: UpdateSkillPackPolicyFn;
20
+ posthogCapture: (input: {
21
+ event: string;
22
+ distinctId: string;
23
+ properties: Record<string, unknown>;
24
+ }) => Promise<unknown>;
25
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
26
+ safeErrorMessage: (err: unknown) => string;
27
+ };
28
+ export declare function registerAgentSuiteRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterAgentSuiteRoutesDeps<TReq, TRes>): void;
29
+ export {};
@@ -0,0 +1,198 @@
1
+ function getPluginVersion(pluginVersion) {
2
+ const normalized = (pluginVersion ?? "").trim();
3
+ return normalized.length > 0 ? normalized : null;
4
+ }
5
+ function toRecord(value) {
6
+ return value && typeof value === "object" && !Array.isArray(value)
7
+ ? value
8
+ : {};
9
+ }
10
+ function readBoolean(payload, ...keys) {
11
+ for (const key of keys) {
12
+ const value = payload[key];
13
+ if (typeof value === "boolean") {
14
+ return value;
15
+ }
16
+ }
17
+ return false;
18
+ }
19
+ function computeUpdateAvailable(state) {
20
+ return Boolean(state.remote?.checksum &&
21
+ state.pack?.checksum &&
22
+ state.remote.checksum !== state.pack.checksum);
23
+ }
24
+ export function registerAgentSuiteRoutes(router, deps) {
25
+ async function renderStatus(res) {
26
+ try {
27
+ // Resolve skill pack overrides opportunistically; fallback to builtins.
28
+ let skillPack = null;
29
+ try {
30
+ skillPack = await deps.resolveSkillPackOverrides({});
31
+ }
32
+ catch {
33
+ // Ignore resolver errors and use local defaults.
34
+ }
35
+ const state = deps.readSkillPackState();
36
+ const plan = deps.computeOrgxAgentSuitePlan({
37
+ packVersion: deps.pluginVersion || "0.0.0",
38
+ skillPack,
39
+ skillPackRemote: state.remote,
40
+ skillPackPolicy: state.policy,
41
+ skillPackUpdateAvailable: computeUpdateAvailable(state),
42
+ });
43
+ deps.sendJson(res, 200, {
44
+ ok: true,
45
+ data: plan,
46
+ });
47
+ }
48
+ catch (err) {
49
+ deps.sendJson(res, 500, {
50
+ ok: false,
51
+ error: deps.safeErrorMessage(err),
52
+ });
53
+ }
54
+ }
55
+ router.add("GET", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status");
56
+ router.add("HEAD", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status (HEAD)");
57
+ router.add("POST", "agent-suite/install", async ({ req, res }) => {
58
+ try {
59
+ const payload = toRecord(await deps.parseJsonRequest(req));
60
+ const dryRun = readBoolean(payload, "dryRun", "dry_run");
61
+ const forceSkillPack = readBoolean(payload, "forceSkillPack", "force_skill_pack");
62
+ const skillPack = await deps.resolveSkillPackOverrides({ force: forceSkillPack });
63
+ const state = deps.readSkillPackState();
64
+ const plan = deps.computeOrgxAgentSuitePlan({
65
+ packVersion: deps.pluginVersion || "0.0.0",
66
+ skillPack,
67
+ skillPackRemote: state.remote,
68
+ skillPackPolicy: state.policy,
69
+ skillPackUpdateAvailable: computeUpdateAvailable(state),
70
+ });
71
+ const result = deps.applyOrgxAgentSuitePlan({ plan, dryRun, skillPack });
72
+ const counts = {
73
+ create: 0,
74
+ update: 0,
75
+ noop: 0,
76
+ conflict: 0,
77
+ };
78
+ for (const entry of result.plan.workspaceFiles ?? []) {
79
+ if (entry.action in counts) {
80
+ counts[entry.action] += 1;
81
+ }
82
+ }
83
+ void deps
84
+ .posthogCapture({
85
+ event: "openclaw_agent_suite_install",
86
+ distinctId: deps.telemetryDistinctId,
87
+ properties: {
88
+ plugin_version: getPluginVersion(deps.pluginVersion),
89
+ dry_run: Boolean(dryRun),
90
+ applied: Boolean(result.applied),
91
+ openclaw_config_updated: Boolean(result.plan.openclawConfigWouldUpdate),
92
+ added_agents_count: result.plan.openclawConfigAddedAgents.length,
93
+ files_create: counts.create,
94
+ files_update: counts.update,
95
+ files_noop: counts.noop,
96
+ files_conflict: counts.conflict,
97
+ skill_pack_source: result.plan.skillPack?.source ?? null,
98
+ skill_pack_checksum: result.plan.skillPack?.checksum ?? null,
99
+ skill_pack_version: result.plan.skillPack?.version ?? null,
100
+ },
101
+ })
102
+ .catch(() => {
103
+ // best effort
104
+ });
105
+ deps.sendJson(res, 200, {
106
+ ok: true,
107
+ operationId: deps.generateAgentSuiteOperationId(),
108
+ dryRun,
109
+ applied: result.applied,
110
+ data: result.plan,
111
+ });
112
+ }
113
+ catch (err) {
114
+ void deps
115
+ .posthogCapture({
116
+ event: "openclaw_agent_suite_install_failed",
117
+ distinctId: deps.telemetryDistinctId,
118
+ properties: {
119
+ plugin_version: getPluginVersion(deps.pluginVersion),
120
+ error: deps.safeErrorMessage(err),
121
+ },
122
+ })
123
+ .catch(() => {
124
+ // best effort
125
+ });
126
+ deps.sendJson(res, 500, {
127
+ ok: false,
128
+ error: deps.safeErrorMessage(err),
129
+ });
130
+ }
131
+ }, "Install managed OrgX agent suite");
132
+ router.add("*", "agent-suite/install", ({ res }) => {
133
+ deps.sendJson(res, 405, {
134
+ ok: false,
135
+ error: "Use POST /orgx/api/agent-suite/install",
136
+ });
137
+ }, "Reject unsupported methods for agent-suite/install");
138
+ router.add("GET", "skill-pack/policy", ({ res }) => {
139
+ const state = deps.readSkillPackState();
140
+ deps.sendJson(res, 200, {
141
+ ok: true,
142
+ data: {
143
+ policy: state.policy,
144
+ pack: state.pack,
145
+ remote: state.remote,
146
+ updateAvailable: computeUpdateAvailable(state),
147
+ lastCheckedAt: state.lastCheckedAt,
148
+ lastError: state.lastError,
149
+ },
150
+ });
151
+ }, "Read skill-pack policy");
152
+ router.add("POST", "skill-pack/policy", async ({ req, res }) => {
153
+ try {
154
+ const payload = toRecord(await deps.parseJsonRequest(req));
155
+ const frozenRaw = payload.frozen;
156
+ const frozen = typeof frozenRaw === "boolean" ? frozenRaw : undefined;
157
+ const pinToCurrent = readBoolean(payload, "pinToCurrent", "pin_to_current");
158
+ const clearPin = readBoolean(payload, "clearPin", "clear_pin");
159
+ const pinnedChecksumRaw = payload.pinnedChecksum;
160
+ const pinnedChecksum = typeof pinnedChecksumRaw === "string"
161
+ ? pinnedChecksumRaw
162
+ : pinnedChecksumRaw === null
163
+ ? null
164
+ : undefined;
165
+ const state = deps.updateSkillPackPolicy({
166
+ frozen,
167
+ pinToCurrent,
168
+ clearPin,
169
+ pinnedChecksum,
170
+ });
171
+ void deps
172
+ .posthogCapture({
173
+ event: "openclaw_skill_pack_policy_updated",
174
+ distinctId: deps.telemetryDistinctId,
175
+ properties: {
176
+ plugin_version: getPluginVersion(deps.pluginVersion),
177
+ frozen: state.policy.frozen,
178
+ pinned_checksum_prefix: state.policy.pinnedChecksum
179
+ ? state.policy.pinnedChecksum.slice(0, 12)
180
+ : null,
181
+ },
182
+ })
183
+ .catch(() => {
184
+ // best effort
185
+ });
186
+ deps.sendJson(res, 200, { ok: true, data: state.policy });
187
+ }
188
+ catch (err) {
189
+ deps.sendJson(res, 400, { ok: false, error: deps.safeErrorMessage(err) });
190
+ }
191
+ }, "Update skill-pack policy");
192
+ router.add("*", "skill-pack/policy", ({ res }) => {
193
+ deps.sendJson(res, 405, {
194
+ ok: false,
195
+ error: "Use GET/POST /orgx/api/skill-pack/policy",
196
+ });
197
+ }, "Reject unsupported methods for skill-pack/policy");
198
+ }
@@ -0,0 +1,40 @@
1
+ import type { Router } from "../router.js";
2
+ type OpenClawAgentEntry = {
3
+ id?: string;
4
+ name?: string;
5
+ workspace?: string;
6
+ model?: string;
7
+ isDefault?: boolean;
8
+ };
9
+ type LocalAgentSnapshot = {
10
+ id: string;
11
+ status: string;
12
+ currentTask: string | null;
13
+ runId: string | null;
14
+ startedAt: string | null;
15
+ blockers: string[];
16
+ };
17
+ type LocalSnapshot = {
18
+ agents: LocalAgentSnapshot[];
19
+ };
20
+ type AgentRun = {
21
+ agentId: string;
22
+ startedAt: string | null;
23
+ status: string;
24
+ };
25
+ type AgentRunStoreSnapshot = {
26
+ runs: Record<string, AgentRun & Record<string, unknown>>;
27
+ };
28
+ type AgentContextStoreSnapshot = {
29
+ agents: Record<string, unknown>;
30
+ };
31
+ type AgentsCatalogDeps<TRes> = {
32
+ listAgents: () => Promise<OpenClawAgentEntry[]>;
33
+ loadLocalSnapshot: () => Promise<LocalSnapshot | null>;
34
+ readAgentContexts: () => AgentContextStoreSnapshot;
35
+ readAgentRuns: () => AgentRunStoreSnapshot;
36
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
37
+ safeErrorMessage: (err: unknown) => string;
38
+ };
39
+ export declare function registerAgentsCatalogRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: AgentsCatalogDeps<TRes>): void;
40
+ export {};
@@ -0,0 +1,83 @@
1
+ export function registerAgentsCatalogRoutes(router, deps) {
2
+ async function handle(res) {
3
+ try {
4
+ const [openclawAgents, localSnapshot] = await Promise.all([
5
+ deps.listAgents(),
6
+ deps.loadLocalSnapshot(),
7
+ ]);
8
+ const localById = new Map();
9
+ if (localSnapshot) {
10
+ for (const agent of localSnapshot.agents) {
11
+ localById.set(agent.id, {
12
+ status: agent.status,
13
+ currentTask: agent.currentTask,
14
+ runId: agent.runId,
15
+ startedAt: agent.startedAt,
16
+ blockers: agent.blockers,
17
+ });
18
+ }
19
+ }
20
+ const contexts = deps.readAgentContexts().agents;
21
+ const runs = deps.readAgentRuns().runs;
22
+ const latestRunByAgent = new Map();
23
+ for (const run of Object.values(runs)) {
24
+ if (!run || typeof run !== "object")
25
+ continue;
26
+ const agentId = typeof run.agentId === "string" ? run.agentId.trim() : "";
27
+ if (!agentId)
28
+ continue;
29
+ const existing = latestRunByAgent.get(agentId);
30
+ const nextTs = Date.parse(run.startedAt ?? "");
31
+ const existingTs = existing ? Date.parse(existing.startedAt ?? "") : 0;
32
+ if (!existing) {
33
+ latestRunByAgent.set(agentId, run);
34
+ continue;
35
+ }
36
+ const existingRunning = existing.status === "running";
37
+ const nextRunning = run.status === "running";
38
+ if (nextRunning && !existingRunning) {
39
+ latestRunByAgent.set(agentId, run);
40
+ continue;
41
+ }
42
+ if (nextRunning === existingRunning && nextTs > existingTs) {
43
+ latestRunByAgent.set(agentId, run);
44
+ }
45
+ }
46
+ const agents = openclawAgents.map((entry) => {
47
+ const id = typeof entry.id === "string" ? entry.id.trim() : "";
48
+ const name = typeof entry.name === "string" && entry.name.trim().length > 0
49
+ ? entry.name.trim()
50
+ : id || "unknown";
51
+ const local = id ? localById.get(id) ?? null : null;
52
+ const context = id ? contexts[id] ?? null : null;
53
+ const runFromSession = id && local?.runId ? runs[local.runId] ?? null : null;
54
+ const run = runFromSession ?? (id ? latestRunByAgent.get(id) ?? null : null);
55
+ return {
56
+ id,
57
+ name,
58
+ workspace: typeof entry.workspace === "string" ? entry.workspace : null,
59
+ model: typeof entry.model === "string" ? entry.model : null,
60
+ isDefault: Boolean(entry.isDefault),
61
+ status: local?.status ?? null,
62
+ currentTask: local?.currentTask ?? null,
63
+ runId: local?.runId ?? null,
64
+ startedAt: local?.startedAt ?? null,
65
+ blockers: local?.blockers ?? [],
66
+ context,
67
+ run,
68
+ };
69
+ });
70
+ deps.sendJson(res, 200, {
71
+ generatedAt: new Date().toISOString(),
72
+ agents,
73
+ });
74
+ }
75
+ catch (err) {
76
+ deps.sendJson(res, 500, {
77
+ error: deps.safeErrorMessage(err),
78
+ });
79
+ }
80
+ }
81
+ router.add("GET", "agents/catalog", async ({ res }) => handle(res), "Agent catalog");
82
+ router.add("HEAD", "agents/catalog", async ({ res }) => handle(res), "Agent catalog (HEAD)");
83
+ }
@@ -0,0 +1,23 @@
1
+ import type { BillingCheckoutRequest } from "../../types.js";
2
+ import type { Router } from "../router.js";
3
+ type JsonRecord = Record<string, unknown>;
4
+ type BillingClientLike = {
5
+ getBaseUrl: () => string;
6
+ getBillingStatus: () => Promise<unknown>;
7
+ createBillingCheckout: (input: BillingCheckoutRequest) => Promise<{
8
+ url?: string | null;
9
+ checkout_url?: string | null;
10
+ }>;
11
+ createBillingPortal: () => Promise<{
12
+ url?: string | null;
13
+ }>;
14
+ };
15
+ type RegisterBillingRoutesDeps<TReq, TRes> = {
16
+ client: BillingClientLike;
17
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
18
+ pickString: (input: JsonRecord, keys: string[]) => string | null;
19
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
20
+ safeErrorMessage: (err: unknown) => string;
21
+ };
22
+ export declare function registerBillingRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterBillingRoutesDeps<TReq, TRes>): void;
23
+ export {};
@@ -0,0 +1,55 @@
1
+ export function registerBillingRoutes(router, deps) {
2
+ router.add("GET", "billing/status", async ({ res }) => {
3
+ try {
4
+ const status = await deps.client.getBillingStatus();
5
+ deps.sendJson(res, 200, { ok: true, data: status });
6
+ }
7
+ catch (err) {
8
+ deps.sendJson(res, 200, { ok: false, error: deps.safeErrorMessage(err) });
9
+ }
10
+ }, "Get billing plan/status");
11
+ router.add("POST", "billing/checkout", async ({ req, res }) => {
12
+ const basePricingUrl = `${deps.client.getBaseUrl().replace(/\/+$/, "")}/pricing`;
13
+ try {
14
+ const payload = await deps.parseJsonRequest(req);
15
+ const planIdRaw = (deps.pickString(payload, ["planId", "plan_id", "plan"]) ?? "starter")
16
+ .trim()
17
+ .toLowerCase();
18
+ const billingCycleRaw = (deps.pickString(payload, ["billingCycle", "billing_cycle"]) ?? "monthly")
19
+ .trim()
20
+ .toLowerCase();
21
+ const planId = planIdRaw === "team" || planIdRaw === "enterprise" ? planIdRaw : "starter";
22
+ const billingCycle = billingCycleRaw === "annual" ? "annual" : "monthly";
23
+ const result = await deps.client.createBillingCheckout({
24
+ planId,
25
+ billingCycle,
26
+ });
27
+ const url = result?.url ?? result?.checkout_url ?? null;
28
+ deps.sendJson(res, 200, { ok: true, data: { url: url ?? basePricingUrl } });
29
+ }
30
+ catch {
31
+ // If remote billing endpoints are unavailable, degrade gracefully.
32
+ deps.sendJson(res, 200, { ok: true, data: { url: basePricingUrl } });
33
+ }
34
+ }, "Create billing checkout session");
35
+ router.add("POST", "billing/portal", async ({ res }) => {
36
+ const basePricingUrl = `${deps.client.getBaseUrl().replace(/\/+$/, "")}/pricing`;
37
+ try {
38
+ const result = await deps.client.createBillingPortal();
39
+ const url = result?.url ?? null;
40
+ deps.sendJson(res, 200, { ok: true, data: { url: url ?? basePricingUrl } });
41
+ }
42
+ catch {
43
+ deps.sendJson(res, 200, { ok: true, data: { url: basePricingUrl } });
44
+ }
45
+ }, "Create billing portal session");
46
+ router.add("*", "billing/status", ({ res }) => {
47
+ deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
48
+ }, "Reject unsupported methods for billing/status");
49
+ router.add("*", "billing/checkout", ({ res }) => {
50
+ deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
51
+ }, "Reject unsupported methods for billing/checkout");
52
+ router.add("*", "billing/portal", ({ res }) => {
53
+ deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
54
+ }, "Reject unsupported methods for billing/portal");
55
+ }
@@ -0,0 +1,14 @@
1
+ import type { Router } from "../router.js";
2
+ type CodexBinInfo = {
3
+ bin: string | null;
4
+ version: unknown;
5
+ versionString: string | null;
6
+ };
7
+ type DebugRoutesDeps<TRes> = {
8
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
9
+ safeErrorMessage: (err: unknown) => string;
10
+ resolveCodexBinInfo: () => CodexBinInfo;
11
+ getCachedCodexProbeSummary: () => unknown;
12
+ };
13
+ export declare function registerDebugRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: DebugRoutesDeps<TRes>): void;
14
+ export {};
@@ -0,0 +1,21 @@
1
+ export function registerDebugRoutes(router, deps) {
2
+ router.add("GET", "debug/codex-bin", ({ res }) => {
3
+ try {
4
+ const codex = deps.resolveCodexBinInfo();
5
+ deps.sendJson(res, 200, {
6
+ ok: true,
7
+ spawnGuardBypassEnv: Boolean((process.env.ORGX_SPAWN_GUARD_BYPASS ?? "").trim() ||
8
+ ["off", "bypass"].includes((process.env.ORGX_SPAWN_GUARD_MODE ?? "").trim().toLowerCase())),
9
+ codex: {
10
+ bin: codex.bin,
11
+ version: codex.version,
12
+ versionString: codex.versionString,
13
+ },
14
+ probe: deps.getCachedCodexProbeSummary(),
15
+ });
16
+ }
17
+ catch (err) {
18
+ deps.sendJson(res, 500, { ok: false, error: deps.safeErrorMessage(err) });
19
+ }
20
+ }, "Debug codex binary/probe status");
21
+ }
@@ -0,0 +1,13 @@
1
+ import type { Router } from "../router.js";
2
+ type JsonRecord = Record<string, unknown>;
3
+ type DecisionAction = "approve" | "reject";
4
+ type RegisterDecisionActionsRoutesDeps<TReq, TRes> = {
5
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
6
+ bulkDecideDecisions: (ids: string[], action: DecisionAction, note?: string) => Promise<Array<{
7
+ ok?: boolean;
8
+ }>>;
9
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
10
+ safeErrorMessage: (err: unknown) => string;
11
+ };
12
+ export declare function registerDecisionActionsRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterDecisionActionsRoutesDeps<TReq, TRes>): void;
13
+ export {};
@@ -0,0 +1,66 @@
1
+ function extractIdsFromPayload(payload) {
2
+ const raw = payload.ids;
3
+ if (!Array.isArray(raw))
4
+ return [];
5
+ return raw
6
+ .filter((id) => typeof id === "string")
7
+ .map((id) => id.trim())
8
+ .filter(Boolean);
9
+ }
10
+ async function handleApproveRequest(req, res, deps, routeIds) {
11
+ const payload = await deps.parseJsonRequest(req);
12
+ const action = payload.action === "reject" ? "reject" : "approve";
13
+ const note = typeof payload.note === "string" && payload.note.trim().length > 0
14
+ ? payload.note.trim()
15
+ : undefined;
16
+ const ids = routeIds ?? extractIdsFromPayload(payload);
17
+ if (ids.length === 0) {
18
+ deps.sendJson(res, 400, {
19
+ error: "Decision IDs are required.",
20
+ expected: {
21
+ route: "/orgx/api/live/decisions/approve",
22
+ body: { ids: ["decision-id"], action: "approve|reject" },
23
+ },
24
+ });
25
+ return;
26
+ }
27
+ const results = await deps.bulkDecideDecisions(ids, action, note);
28
+ const updated = results.filter((result) => result.ok === true).length;
29
+ const failed = results.length - updated;
30
+ deps.sendJson(res, failed > 0 ? 207 : 200, {
31
+ action,
32
+ requested: ids.length,
33
+ updated,
34
+ failed,
35
+ results,
36
+ });
37
+ }
38
+ export function registerDecisionActionsRoutes(router, deps) {
39
+ router.add("POST", "live/decisions/approve", async ({ req, res }) => {
40
+ try {
41
+ await handleApproveRequest(req, res, deps, null);
42
+ }
43
+ catch (err) {
44
+ deps.sendJson(res, 500, {
45
+ error: deps.safeErrorMessage(err),
46
+ });
47
+ }
48
+ }, "Bulk decision approve/reject");
49
+ router.add("POST", "live/decisions/*", async ({ req, res, path }) => {
50
+ const decisionApproveMatch = path.match(/^live\/decisions\/([^/]+)\/approve$/);
51
+ if (!decisionApproveMatch) {
52
+ deps.sendJson(res, 404, { error: "Unknown API endpoint" });
53
+ return;
54
+ }
55
+ try {
56
+ await handleApproveRequest(req, res, deps, [
57
+ decodeURIComponent(decisionApproveMatch[1]),
58
+ ]);
59
+ }
60
+ catch (err) {
61
+ deps.sendJson(res, 500, {
62
+ error: deps.safeErrorMessage(err),
63
+ });
64
+ }
65
+ }, "Single decision approve/reject");
66
+ }
@@ -0,0 +1,19 @@
1
+ import type { Router } from "../router.js";
2
+ type JsonRecord = Record<string, unknown>;
3
+ type DelegationClientLike = {
4
+ delegationPreflight: (input: {
5
+ intent: string;
6
+ acceptanceCriteria?: string[];
7
+ constraints?: string[];
8
+ domains?: string[];
9
+ }) => Promise<unknown>;
10
+ };
11
+ type RegisterDelegationRoutesDeps<TReq, TRes> = {
12
+ client: DelegationClientLike;
13
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
14
+ pickString: (input: JsonRecord, keys: string[]) => string | null;
15
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
16
+ safeErrorMessage: (err: unknown) => string;
17
+ };
18
+ export declare function registerDelegationRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterDelegationRoutesDeps<TReq, TRes>): void;
19
+ export {};
@@ -0,0 +1,32 @@
1
+ function toStringArray(value) {
2
+ return Array.isArray(value)
3
+ ? value.filter((entry) => typeof entry === "string")
4
+ : undefined;
5
+ }
6
+ export function registerDelegationRoutes(router, deps) {
7
+ router.add("POST", "delegation/preflight", async ({ req, res }) => {
8
+ try {
9
+ const payload = await deps.parseJsonRequest(req);
10
+ const intent = deps.pickString(payload, ["intent"]);
11
+ if (!intent) {
12
+ deps.sendJson(res, 400, { error: "intent is required" });
13
+ return;
14
+ }
15
+ const data = await deps.client.delegationPreflight({
16
+ intent,
17
+ acceptanceCriteria: toStringArray(payload.acceptanceCriteria),
18
+ constraints: toStringArray(payload.constraints),
19
+ domains: toStringArray(payload.domains),
20
+ });
21
+ deps.sendJson(res, 200, data);
22
+ }
23
+ catch (err) {
24
+ deps.sendJson(res, 500, {
25
+ error: deps.safeErrorMessage(err),
26
+ });
27
+ }
28
+ }, "Delegation preflight");
29
+ router.add("*", "delegation/preflight", ({ res }) => {
30
+ deps.sendJson(res, 405, { error: "Use POST /orgx/api/delegation/preflight" });
31
+ }, "Reject unsupported methods for delegation/preflight");
32
+ }
@@ -0,0 +1,47 @@
1
+ import type { Entity, OrgSnapshot } from "../../types.js";
2
+ import type { Router } from "../router.js";
3
+ type JsonRecord = Record<string, unknown>;
4
+ type AutoAssignmentResult = {
5
+ ok: boolean;
6
+ assignment_source: "orchestrator" | "fallback" | "manual";
7
+ assigned_agents: unknown[];
8
+ warnings: string[];
9
+ updated_entity?: Entity;
10
+ };
11
+ type EntityClientLike = {
12
+ createEntity: (type: string, data: Record<string, unknown>) => Promise<Entity>;
13
+ updateEntity: (type: string, id: string, updates: Record<string, unknown>) => Promise<Entity>;
14
+ listEntities: (type: string, input: {
15
+ status?: string;
16
+ initiative_id?: string;
17
+ limit?: number;
18
+ }) => Promise<unknown>;
19
+ };
20
+ type RegisterEntitiesRoutesDeps<TReq, TRes> = {
21
+ client: EntityClientLike;
22
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
23
+ pickString: (input: Record<string, unknown>, keys: string[]) => string | null;
24
+ normalizeEntityMutationPayload: (input: Record<string, unknown>) => Record<string, unknown>;
25
+ resolveAutoAssignments: (input: {
26
+ entityId: string;
27
+ entityType: string;
28
+ initiativeId: string | null;
29
+ title: string;
30
+ summary: string | null;
31
+ }) => Promise<AutoAssignmentResult>;
32
+ setLocalInitiativeStatusOverride: (initiativeId: string, status: string) => void;
33
+ clearLocalInitiativeStatusOverride: (initiativeId: string) => void;
34
+ isUnauthorizedOrgxError: (err: unknown) => boolean;
35
+ applyLocalInitiativeOverrides: (rows: Array<Record<string, unknown>>) => Array<Record<string, unknown>>;
36
+ formatInitiatives: (snapshot: OrgSnapshot | null) => Array<{
37
+ id: string;
38
+ title: string;
39
+ status: string;
40
+ progress?: number | null;
41
+ }>;
42
+ getSnapshot: () => OrgSnapshot | null;
43
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
44
+ safeErrorMessage: (err: unknown) => string;
45
+ };
46
+ export declare function registerEntitiesRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterEntitiesRoutesDeps<TReq, TRes>): void;
47
+ export {};