@kynver-app/openclaw-agent-os 0.1.18 → 0.1.20

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 CHANGED
@@ -24,6 +24,19 @@ openclaw plugins install @kynver-app/openclaw-agent-os@latest --force
24
24
  If your OpenClaw install does not support package installs yet, install this package into the OpenClaw
25
25
  extensions directory and enable the plugin from there. The runtime entry point is `dist/index.js`.
26
26
 
27
+ For a wiped machine or new-user setup, use the packaged bootstrap command:
28
+
29
+ ```bash
30
+ export KYNVER_API_URL="https://www.kynver.com"
31
+ export KYNVER_API_KEY="kynver_xxx"
32
+ export KYNVER_HARNESS_REPO="/path/to/Kynver" # optional, enables kynver_harness_* tools
33
+
34
+ npx -y -p @kynver-app/openclaw-agent-os@latest kynver-openclaw-agent-os-bootstrap
35
+ ```
36
+
37
+ See `docs/runbooks/openclaw-agent-os-bootstrap.md` in the Kynver repo for the
38
+ full recovery/onboarding runbook.
39
+
27
40
  ## Configure
28
41
 
29
42
  Recommended direct HTTP config:
@@ -31,14 +44,19 @@ Recommended direct HTTP config:
31
44
  ```json
32
45
  {
33
46
  "plugins": {
34
- "config": {
47
+ "entries": {
35
48
  "kynver-agent-os-tools": {
36
- "kynverApiUrl": "https://www.kynver.com",
37
- "kynverApiKey": "kynver_xxx",
38
- "enableDirectHttp": true,
39
- "enableSessionLifecycle": true,
40
- "enableRuntimeSkillManifest": true,
41
- "enableContinuityGuidance": true
49
+ "enabled": true,
50
+ "config": {
51
+ "kynverApiUrl": "https://www.kynver.com",
52
+ "kynverApiKey": "kynver_xxx",
53
+ "enableDirectHttp": true,
54
+ "enableSessionLifecycle": true,
55
+ "enableRuntimeSkillManifest": true,
56
+ "enableContinuityGuidance": true,
57
+ "enableHarnessTools": true,
58
+ "harnessRepo": "/path/to/Kynver"
59
+ }
42
60
  }
43
61
  }
44
62
  }
@@ -57,10 +75,13 @@ Compatibility config through an existing `mcporter.json` still works:
57
75
  ```json
58
76
  {
59
77
  "plugins": {
60
- "config": {
78
+ "entries": {
61
79
  "kynver-agent-os-tools": {
62
- "agentOsServer": "kynver-agent-os",
63
- "mcporterConfigPath": "<home>/.openclaw/workspace/config/mcporter.json"
80
+ "enabled": true,
81
+ "config": {
82
+ "agentOsServer": "kynver-agent-os",
83
+ "mcporterConfigPath": "<home>/.openclaw/workspace/config/mcporter.json"
84
+ }
64
85
  }
65
86
  }
66
87
  }
@@ -145,6 +166,22 @@ native Codex dynamic-tool bridge issue.
145
166
  - `agent_os_plan_add_link`
146
167
  - `agent_os_plan_list_links`
147
168
  - `agent_os_plan_list_versions`
169
+ - `agent_os_command_center_get`
170
+ - `agent_os_task_next_action`
171
+ - `agent_os_plan_progress_rows_list`
172
+ - `agent_os_plan_progress_rows_upsert`
173
+ - `agent_os_plan_progress_event_append`
174
+
175
+ `agent_os_command_center_get` returns the same unified Command Center rollup the
176
+ browser operator console uses (plan rollups, project hierarchy, action-required,
177
+ DQ inbox, goals, review lanes, harness summaries). It calls the by-id HTTP
178
+ surface and resolves `agentOsId` from the workspace slug when omitted.
179
+
180
+ `agent_os_task_next_action` posts harness completion signals to the deterministic
181
+ next-action router (review/fix/landing dispatch, close, or await-human).
182
+
183
+ Plan progress tools mirror the AgentOS MCP plan-progress surface for structured
184
+ checklist rows and role-lane events.
148
185
 
149
186
  Plan tools manage first-class AgentOS plans — versioned operational artifacts
150
187
  distinct from goals/projects/tasks. Each `AgentPlan` owns a chain of immutable
package/dist/index.js CHANGED
@@ -75,7 +75,8 @@ var pluginConfigSchema = {
75
75
  }
76
76
  }
77
77
  };
78
- function resolvePluginConfig(raw) {
78
+ function resolvePluginConfig(rawEntry) {
79
+ const raw = rawEntry?.config && typeof rawEntry.config === "object" && !Array.isArray(rawEntry.config) ? rawEntry.config : rawEntry;
79
80
  const rawServer = typeof raw?.agentOsServer === "string" && raw.agentOsServer.trim() ? raw.agentOsServer.trim() : "kynver-agent-os";
80
81
  if (!/^[a-zA-Z0-9_-]+$/.test(rawServer)) {
81
82
  throw new Error("Invalid agentOsServer: use letters, numbers, hyphens, and underscores only.");
@@ -301,6 +302,36 @@ function directConfigFromEnv(agentOsSlug, kynverApiKey) {
301
302
  };
302
303
  }
303
304
  var primarySlugCache = /* @__PURE__ */ new Map();
305
+ var agentOsIdCache = /* @__PURE__ */ new Map();
306
+ async function resolveAgentOsId(config, slug, timeoutMs) {
307
+ const cacheKey = `${config.apiUrl}|${config.apiKey || ""}|${slug}`;
308
+ const cached = agentOsIdCache.get(cacheKey);
309
+ if (cached) return cached;
310
+ const controller = new AbortController();
311
+ const timer = setTimeout(() => controller.abort(), Math.max(1e3, Math.min(timeoutMs, 1e4)));
312
+ try {
313
+ const res = await fetch(`${config.apiUrl}/api/agent-os/${encodeURIComponent(slug)}`, {
314
+ method: "GET",
315
+ headers: {
316
+ Accept: "application/json",
317
+ ...config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}
318
+ },
319
+ signal: controller.signal
320
+ });
321
+ if (!res.ok) return void 0;
322
+ const text = await res.text();
323
+ const payload = text ? safeJson(text) : null;
324
+ if (!payload || typeof payload !== "object") return void 0;
325
+ const id = typeof payload.id === "string" ? payload.id.trim() : "";
326
+ if (!id) return void 0;
327
+ agentOsIdCache.set(cacheKey, id);
328
+ return id;
329
+ } catch {
330
+ return void 0;
331
+ } finally {
332
+ clearTimeout(timer);
333
+ }
334
+ }
304
335
  async function resolvePrimarySlug(config, timeoutMs) {
305
336
  const cacheKey = `${config.apiUrl}|${config.apiKey || ""}`;
306
337
  const cached = primarySlugCache.get(cacheKey);
@@ -350,14 +381,25 @@ async function callAgentOsApiDirect(toolName2, params, timeoutMs, config) {
350
381
  "AgentOS slug could not be resolved. Set agentOsSlug in plugin config, or ensure the account has a primary AgentOS workspace at GET /api/agent-os."
351
382
  );
352
383
  }
353
- const { slug, path: path3, method, body } = directRequestForTool(toolName2, params, resolvedSlug);
384
+ const request = directRequestForTool(toolName2, params, resolvedSlug);
385
+ const { slug, path: path3, method, body } = request;
354
386
  if (!slug) {
355
387
  throw new Error("AgentOS slug could not be resolved.");
356
388
  }
389
+ let url = `${config.apiUrl}/api/agent-os/${encodeURIComponent(slug)}${path3}`;
390
+ if (request.route === "by-id") {
391
+ const agentOsId = request.agentOsId || stringParam(params.agentOsId) || await resolveAgentOsId(config, slug, timeoutMs);
392
+ if (!agentOsId) {
393
+ throw new Error(
394
+ "AgentOS id could not be resolved for by-id Command Center routes. Pass agentOsId or ensure GET /api/agent-os/{slug} returns id."
395
+ );
396
+ }
397
+ url = `${config.apiUrl}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}${path3}`;
398
+ }
357
399
  const controller = new AbortController();
358
400
  const timer = setTimeout(() => controller.abort(), timeoutMs);
359
401
  try {
360
- const res = await fetch(`${config.apiUrl}/api/agent-os/${encodeURIComponent(slug)}${path3}`, {
402
+ const res = await fetch(url, {
361
403
  method,
362
404
  headers: {
363
405
  "Content-Type": "application/json",
@@ -379,7 +421,7 @@ async function callAgentOsApiDirect(toolName2, params, timeoutMs, config) {
379
421
  }
380
422
  function directRequestForTool(toolName2, params, resolvedSlug) {
381
423
  const slug = stringParam(params.slug) || resolvedSlug;
382
- const withoutSlug = stripKeys(params, ["slug"]);
424
+ const withoutSlug = stripKeys(params, ["slug", "agentOsId"]);
383
425
  switch (toolName2) {
384
426
  case "agent_os_get_context":
385
427
  return { slug, method: "GET", path: "/stats" };
@@ -655,6 +697,51 @@ function directRequestForTool(toolName2, params, resolvedSlug) {
655
697
  path: `/plans/${encodeURIComponent(planId)}/links`
656
698
  };
657
699
  }
700
+ case "agent_os_command_center_get":
701
+ return {
702
+ route: "by-id",
703
+ agentOsId: stringParam(params.agentOsId),
704
+ slug,
705
+ method: "GET",
706
+ path: `/command-center${queryString(params, ["since", "limit", "harnessLimit"])}`
707
+ };
708
+ case "agent_os_task_next_action": {
709
+ const taskId = requiredString(params.taskId, "taskId");
710
+ return {
711
+ slug,
712
+ method: "POST",
713
+ path: `/tasks/${encodeURIComponent(taskId)}/next-action`,
714
+ body: stripKeys(params, ["slug", "taskId"])
715
+ };
716
+ }
717
+ case "agent_os_plan_progress_rows_list": {
718
+ const planId = requiredString(params.planId, "planId");
719
+ return {
720
+ slug,
721
+ method: "GET",
722
+ path: `/plans/${encodeURIComponent(planId)}/progress-rows`
723
+ };
724
+ }
725
+ case "agent_os_plan_progress_rows_upsert": {
726
+ const planId = requiredString(params.planId, "planId");
727
+ return {
728
+ slug,
729
+ method: "POST",
730
+ path: `/plans/${encodeURIComponent(planId)}/progress-rows`,
731
+ body: { rows: params.rows }
732
+ };
733
+ }
734
+ case "agent_os_plan_progress_event_append": {
735
+ const planId = requiredString(params.planId, "planId");
736
+ const body = stripKeys(params, ["slug", "planId", "remainingWork"]);
737
+ const remainingWork = stringParam(params.remainingWork);
738
+ return {
739
+ slug,
740
+ method: "POST",
741
+ path: `/plans/${encodeURIComponent(planId)}/progress-events`,
742
+ body: remainingWork === void 0 ? body : { ...body, remaining: remainingWork }
743
+ };
744
+ }
658
745
  default:
659
746
  throw new Error(`Unsupported AgentOS direct tool: ${toolName2}`);
660
747
  }
@@ -806,7 +893,17 @@ function buildAgentOsContinuityGuidanceContext(config) {
806
893
  "",
807
894
  "Local markdown memory (CLAUDE.md, AGENTS.md, /memory, scratch notes) is a fallback and a cache. Use it when AgentOS is unreachable or for in-conversation scratch; do not treat it as authoritative when AgentOS is available.",
808
895
  "Privacy: AgentOS context is personal to the signed-in account. Do not expose AgentOS identity, goals, projects, contacts, or memory excerpts in shared, broadcast, group, or multi-tenant contexts unless the user explicitly asks for it. If you cannot determine the channel scope, withhold AgentOS specifics by default.",
809
- "If an AgentOS call fails or returns unavailable, say so explicitly, fall back to local markdown or conversation memory for that turn, and ask the user before persisting anything that would normally go to AgentOS."
896
+ "If an AgentOS call fails or returns unavailable, say so explicitly, fall back to local markdown or conversation memory for that turn, and ask the user before persisting anything that would normally go to AgentOS.",
897
+ "",
898
+ "Command Center (operational control plane):",
899
+ "- For the same unified rollup the browser Command Center uses (projects, plans, action-required, DQ inbox, harness summaries), call agent_os_command_center_get. Omit slug to resolve the account primary workspace; pass agentOsId when you already have it from a prior identity fetch.",
900
+ "",
901
+ "Plan execution progress (Agentic OS operational flow):",
902
+ "- Workers (`kynver plan progress`, harness/by-id route): emit checkpoints only \u2014 `running`, `partial`, or `blocked` as implementer with evidence and `executorRef`. The harness route rejects `status: done` and confirm events; never propose or confirm row closure from the worker CLI.",
903
+ "- Chat agents / orchestrators (MCP `agent_os_plan_progress_event_append` on the slug route): propose row done (`proposed: true`, `status: done`, evidence) and confirm (`proposed: false`, reviewer lanes). Split implementer vs reviewer across models when possible.",
904
+ "- Discovery that needs the operator, runtime, or another reviewer: create a linked review/decision AgentTask via `agent_os_plan_review_task_create` (or `agent_os_ask_human` for human decisions), link it on the progress row, and mark the row blocked until resolved.",
905
+ "- Respect review ordering: completion-report review before deep implementation review; deep review before follow-up-for-completion closure.",
906
+ "- Runtime verification (`kynver plan verify` or operator Verify plan in Command Center) is required before plan closure \u2014 worker completion alone is not sufficient."
810
907
  ];
811
908
  return lines.join("\n");
812
909
  }
@@ -2430,6 +2527,186 @@ function createHarnessTools(config) {
2430
2527
  }));
2431
2528
  }
2432
2529
 
2530
+ // src/schemas/command-center.ts
2531
+ var slugField = {
2532
+ type: "string",
2533
+ description: "AgentOS workspace slug. Omit to use the account's primary AgentOS workspace."
2534
+ };
2535
+ var commandCenterGetSchema = {
2536
+ type: "object",
2537
+ properties: {
2538
+ slug: slugField,
2539
+ agentOsId: {
2540
+ type: "string",
2541
+ description: "Optional AgentOS row id. When omitted, resolved from slug via GET /api/agent-os/{slug}."
2542
+ },
2543
+ since: {
2544
+ type: "string",
2545
+ description: "ISO timestamp \u2014 only include tasks updated after this instant."
2546
+ },
2547
+ limit: {
2548
+ type: "number",
2549
+ description: "Max tasks to load (server cap 10000, default operator console uses 10000)."
2550
+ },
2551
+ harnessLimit: {
2552
+ type: "number",
2553
+ description: "Max harness runs in the rollup (server cap 200)."
2554
+ }
2555
+ },
2556
+ additionalProperties: false,
2557
+ $schema: "http://json-schema.org/draft-07/schema#"
2558
+ };
2559
+ var taskNextActionSchema = {
2560
+ type: "object",
2561
+ properties: {
2562
+ taskId: { type: "string", description: "Subject AgentTask id." },
2563
+ lane: {
2564
+ type: "string",
2565
+ enum: ["worker", "reviewer", "landing"],
2566
+ description: "Which harness lane just finished and is handing control to the router."
2567
+ },
2568
+ verdict: {
2569
+ type: "string",
2570
+ enum: ["pass", "changes_requested", "needs_input", "blocked", "in_progress"]
2571
+ },
2572
+ landingSucceeded: { type: "boolean" },
2573
+ blockerText: { type: "string" },
2574
+ sourceId: { type: "string" },
2575
+ runId: { type: "string", description: "Required when lane is worker." },
2576
+ workerName: { type: "string", description: "Required when lane is worker." },
2577
+ startedAt: { type: "string" },
2578
+ finishedAt: { type: "string" },
2579
+ lastActivityAt: { type: "string" },
2580
+ payload: { type: "object", additionalProperties: true },
2581
+ slug: slugField
2582
+ },
2583
+ required: ["taskId", "lane"],
2584
+ additionalProperties: false,
2585
+ $schema: "http://json-schema.org/draft-07/schema#"
2586
+ };
2587
+ var progressStatus = {
2588
+ type: "string",
2589
+ enum: ["todo", "running", "partial", "blocked", "done"]
2590
+ };
2591
+ var roleLane = {
2592
+ type: "string",
2593
+ enum: [
2594
+ "plan_author",
2595
+ "plan_reviewer",
2596
+ "implementer",
2597
+ "report_reviewer",
2598
+ "deep_reviewer",
2599
+ "repair_implementer",
2600
+ "runtime_verifier",
2601
+ "user",
2602
+ "system"
2603
+ ]
2604
+ };
2605
+ var progressRow = {
2606
+ type: "object",
2607
+ properties: {
2608
+ rowKey: { type: "string" },
2609
+ title: { type: "string" },
2610
+ description: { type: "string" },
2611
+ ordinal: { type: "number" },
2612
+ stageId: { type: "string" },
2613
+ ownerLane: roleLane,
2614
+ taskId: { type: "string" }
2615
+ },
2616
+ required: ["rowKey", "title", "ordinal"],
2617
+ additionalProperties: false
2618
+ };
2619
+ var planProgressRowsListSchema = {
2620
+ type: "object",
2621
+ properties: {
2622
+ planId: { type: "string" },
2623
+ slug: slugField
2624
+ },
2625
+ required: ["planId"],
2626
+ additionalProperties: false,
2627
+ $schema: "http://json-schema.org/draft-07/schema#"
2628
+ };
2629
+ var planProgressRowsUpsertSchema = {
2630
+ type: "object",
2631
+ properties: {
2632
+ planId: { type: "string" },
2633
+ rows: { type: "array", items: progressRow },
2634
+ slug: slugField
2635
+ },
2636
+ required: ["planId", "rows"],
2637
+ additionalProperties: false,
2638
+ $schema: "http://json-schema.org/draft-07/schema#"
2639
+ };
2640
+ var planProgressEventAppendSchema = {
2641
+ type: "object",
2642
+ properties: {
2643
+ planId: { type: "string" },
2644
+ rowKey: { type: "string" },
2645
+ rowId: { type: "string" },
2646
+ taskId: { type: "string" },
2647
+ reviewTaskId: { type: "string" },
2648
+ roleLane,
2649
+ status: progressStatus,
2650
+ note: { type: "string" },
2651
+ remainingWork: { type: "string" },
2652
+ evidence: { type: "array", items: { type: "object", additionalProperties: true } },
2653
+ proposed: { type: "boolean" },
2654
+ executorRef: { type: "string" },
2655
+ slug: slugField
2656
+ },
2657
+ required: ["planId", "roleLane", "status"],
2658
+ additionalProperties: false,
2659
+ $schema: "http://json-schema.org/draft-07/schema#"
2660
+ };
2661
+
2662
+ // src/tools/command-center.ts
2663
+ function createCommandCenterTools(config) {
2664
+ const mk = (name, description, parameters) => ({
2665
+ name,
2666
+ label: name,
2667
+ description,
2668
+ parameters,
2669
+ execute: (_toolCallId, params) => callAgentOsTool({
2670
+ serverName: config.agentOsServer,
2671
+ toolName: name,
2672
+ params,
2673
+ timeoutMs: config.timeoutMs,
2674
+ mcporterConfigPath: config.mcporterConfigPath,
2675
+ kynverApiUrl: config.kynverApiUrl,
2676
+ kynverApiKey: config.kynverApiKey,
2677
+ agentOsSlug: config.agentOsSlug,
2678
+ enableDirectHttp: config.enableDirectHttp
2679
+ })
2680
+ });
2681
+ return [
2682
+ mk(
2683
+ "agent_os_command_center_get",
2684
+ "Fetch the unified Command Center rollup for the AgentOS workspace: plan rollups, project hierarchy, action-required items, DQ inbox, goals, review lanes, and harness summaries \u2014 the same aggregate the browser Command Center uses.",
2685
+ commandCenterGetSchema
2686
+ ),
2687
+ mk(
2688
+ "agent_os_task_next_action",
2689
+ "Route the deterministic next harness action after a worker, reviewer, or landing lane completes (dispatch review/fix/landing, close, or await human). Same POST surface as the production harness completion hook.",
2690
+ taskNextActionSchema
2691
+ ),
2692
+ mk(
2693
+ "agent_os_plan_progress_rows_list",
2694
+ "List structured plan progress rows (canonical checklist state) for one plan.",
2695
+ planProgressRowsListSchema
2696
+ ),
2697
+ mk(
2698
+ "agent_os_plan_progress_rows_upsert",
2699
+ "Seed or update structured plan progress rows for one plan.",
2700
+ planProgressRowsUpsertSchema
2701
+ ),
2702
+ mk(
2703
+ "agent_os_plan_progress_event_append",
2704
+ "Append a role-lane progress event and apply allowed row transition rules for one plan.",
2705
+ planProgressEventAppendSchema
2706
+ )
2707
+ ];
2708
+ }
2709
+
2433
2710
  // src/tools/index.ts
2434
2711
  function createAllTools(config) {
2435
2712
  return [
@@ -2443,6 +2720,7 @@ function createAllTools(config) {
2443
2720
  ...createContactTools(config),
2444
2721
  ...createTaskTools(config),
2445
2722
  ...createPlanTools(config),
2723
+ ...createCommandCenterTools(config),
2446
2724
  ...createHarnessTools(config)
2447
2725
  ];
2448
2726
  }
@@ -2454,7 +2732,7 @@ var plugin = {
2454
2732
  description: "First-class OpenClaw tools for Kynver AgentOS, using direct Kynver HTTP with mcporter fallback.",
2455
2733
  configSchema: pluginConfigSchema,
2456
2734
  register(api) {
2457
- const config = resolvePluginConfig(api?.config);
2735
+ const config = resolvePluginConfig(api?.pluginConfig ?? api?.config);
2458
2736
  const tools = createAllTools(config);
2459
2737
  for (const tool of tools) {
2460
2738
  api.registerTool(tool);