openclaw-remote 0.5.5 → 0.5.7

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 (2) hide show
  1. package/dist/index.js +238 -4
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2781,6 +2781,55 @@ async function getBoardHealth(account) {
2781
2781
  }
2782
2782
  );
2783
2783
  }
2784
+ async function getGoals(account, filters) {
2785
+ const params = new URLSearchParams();
2786
+ if (filters?.status) params.set("status", filters.status);
2787
+ if (filters?.parent_id !== void 0) params.set("parent_id", filters.parent_id);
2788
+ if (filters?.assigned_to) params.set("assigned_to", filters.assigned_to);
2789
+ const qs = params.toString();
2790
+ const path = `/api/v1/goals${qs ? `?${qs}` : ""}`;
2791
+ return apiFetch(
2792
+ buildUrl(account, path),
2793
+ {
2794
+ method: "GET",
2795
+ headers: buildHeaders(account)
2796
+ }
2797
+ );
2798
+ }
2799
+ async function createGoal(account, data) {
2800
+ return apiFetch(
2801
+ buildUrl(account, "/api/v1/goals"),
2802
+ {
2803
+ method: "POST",
2804
+ headers: buildHeaders(account),
2805
+ body: JSON.stringify(data)
2806
+ }
2807
+ );
2808
+ }
2809
+ async function updateGoal(account, goalId, updates) {
2810
+ return apiFetch(
2811
+ buildUrl(account, `/api/v1/goals/${encodeURIComponent(goalId)}`),
2812
+ {
2813
+ method: "PATCH",
2814
+ headers: buildHeaders(account),
2815
+ body: JSON.stringify(updates)
2816
+ }
2817
+ );
2818
+ }
2819
+ async function updateRoleBundle(account, roleId, data) {
2820
+ return apiFetch(
2821
+ buildUrl(account, `/api/v1/roles/${encodeURIComponent(roleId)}/bundle`),
2822
+ {
2823
+ method: "PATCH",
2824
+ headers: buildHeaders(account),
2825
+ body: JSON.stringify({
2826
+ bundle_slug: data.bundle_slug,
2827
+ bundle_version: data.bundle_version,
2828
+ status: data.generation_status
2829
+ })
2830
+ }
2831
+ );
2832
+ }
2784
2833
  async function getTeam(account) {
2785
2834
  return apiFetch(
2786
2835
  buildUrl(account, "/api/v1/team"),
@@ -3130,6 +3179,9 @@ function createRemotePlugin() {
3130
3179
  ),
3131
3180
  epic_id: Type.Optional(
3132
3181
  Type.String({ description: "Epic ID to group the task under" })
3182
+ ),
3183
+ goal_id: Type.Optional(
3184
+ Type.String({ description: "Goal ID to link the task to" })
3133
3185
  )
3134
3186
  }),
3135
3187
  execute: async (_toolCallId, args) => {
@@ -3140,7 +3192,8 @@ function createRemotePlugin() {
3140
3192
  type: args.type,
3141
3193
  priority: args.priority,
3142
3194
  assigned_role_id: args.assigned_role_id,
3143
- epic_id: args.epic_id
3195
+ epic_id: args.epic_id,
3196
+ goal_id: args.goal_id
3144
3197
  });
3145
3198
  if (!result.ok) {
3146
3199
  return {
@@ -3187,6 +3240,9 @@ function createRemotePlugin() {
3187
3240
  epic_id: Type.Optional(
3188
3241
  Type.String({ description: "Epic ID to group the task under (or null to remove)" })
3189
3242
  ),
3243
+ goal_id: Type.Optional(
3244
+ Type.String({ description: "Goal ID to link the task to (or null to remove)" })
3245
+ ),
3190
3246
  assigned_role_id: Type.Optional(
3191
3247
  Type.String({ description: "Role ID to assign the task to" })
3192
3248
  )
@@ -3485,6 +3541,177 @@ function createRemotePlugin() {
3485
3541
  details: { ok: true, team, total, humans, agents }
3486
3542
  };
3487
3543
  }
3544
+ },
3545
+ // 9. remote_list_goals
3546
+ {
3547
+ name: "remote_list_goals",
3548
+ label: "List goals on the Remote project board",
3549
+ description: "List goals on the Remote project board. Optionally filter by status (active/achieved/abandoned), parent_id (null for top-level), or assigned_to (me).",
3550
+ parameters: Type.Object({
3551
+ status: optionalStringEnum(["active", "achieved", "abandoned"], {
3552
+ description: "Filter by status: active, achieved, or abandoned"
3553
+ }),
3554
+ parent_id: Type.Optional(
3555
+ Type.String({ description: "Filter by parent goal ID. Use 'null' for top-level goals." })
3556
+ ),
3557
+ assigned_to: Type.Optional(
3558
+ Type.String({ description: "Filter by assignee. Use 'me' for goals owned by your roles." })
3559
+ )
3560
+ }),
3561
+ execute: async (_toolCallId, args) => {
3562
+ const account = resolveToolAccount();
3563
+ const result = await getGoals(account, {
3564
+ status: args.status,
3565
+ parent_id: args.parent_id,
3566
+ assigned_to: args.assigned_to
3567
+ });
3568
+ if (!result.ok) {
3569
+ return {
3570
+ content: [{ type: "text", text: `\u274C Failed to list goals: ${result.error}` }],
3571
+ details: { ok: false, error: result.error }
3572
+ };
3573
+ }
3574
+ const goals = result.data.goals;
3575
+ if (goals.length === 0) {
3576
+ return {
3577
+ content: [{ type: "text", text: `\u{1F3AF} No goals found.` }],
3578
+ details: { ok: true, goals: [] }
3579
+ };
3580
+ }
3581
+ const lines = [`\u{1F3AF} **${goals.length} goal(s):**`, ""];
3582
+ for (const g of goals) {
3583
+ const pct = g.progress ?? 0;
3584
+ const bar = "\u2588".repeat(Math.round(pct / 10)) + "\u2591".repeat(10 - Math.round(pct / 10));
3585
+ const role = g.project_roles?.role_name || "";
3586
+ const date = g.target_date ? ` \u{1F3AF} ${new Date(g.target_date).toLocaleDateString()}` : "";
3587
+ const kids = g.children_count ? ` (${g.children_count} sub-goals)` : "";
3588
+ lines.push(`- **${g.title}** [${g.status}] ${bar} ${pct}%${role ? ` \u2014 ${role}` : ""}${date}${kids} (id: ${g.id})`);
3589
+ }
3590
+ return {
3591
+ content: [{ type: "text", text: lines.join("\n") }],
3592
+ details: { ok: true, goals }
3593
+ };
3594
+ }
3595
+ },
3596
+ // 10. remote_create_goal
3597
+ {
3598
+ name: "remote_create_goal",
3599
+ label: "Create a goal on the Remote project board",
3600
+ description: "Create a new goal on the Remote project board. Specify title, and optionally description, success_criteria, parent_id (for sub-goals), owner_role_id, and target_date.",
3601
+ parameters: Type.Object({
3602
+ title: Type.String({ description: "Goal title" }),
3603
+ description: Type.Optional(Type.String({ description: "Goal description" })),
3604
+ success_criteria: Type.Optional(Type.String({ description: "How to measure achievement" })),
3605
+ parent_id: Type.Optional(Type.String({ description: "Parent goal ID (for sub-goals)" })),
3606
+ owner_role_id: Type.Optional(Type.String({ description: "Role ID that owns this goal" })),
3607
+ target_date: Type.Optional(Type.String({ description: "Target date (ISO format)" }))
3608
+ }),
3609
+ execute: async (_toolCallId, args) => {
3610
+ const account = resolveToolAccount();
3611
+ const result = await createGoal(account, {
3612
+ title: args.title,
3613
+ description: args.description,
3614
+ success_criteria: args.success_criteria,
3615
+ parent_id: args.parent_id,
3616
+ owner_role_id: args.owner_role_id,
3617
+ target_date: args.target_date
3618
+ });
3619
+ if (!result.ok) {
3620
+ return {
3621
+ content: [{ type: "text", text: `\u274C Failed to create goal: ${result.error}` }],
3622
+ details: { ok: false, error: result.error }
3623
+ };
3624
+ }
3625
+ const goal = result.data.goal;
3626
+ const text = [
3627
+ `\u2705 Goal created!`,
3628
+ `- **Title**: ${goal.title}`,
3629
+ `- **ID**: ${goal.id}`,
3630
+ `- **Status**: ${goal.status}`,
3631
+ goal.parent_id ? `- **Parent**: ${goal.parent_id}` : null
3632
+ ].filter(Boolean).join("\n");
3633
+ return {
3634
+ content: [{ type: "text", text }],
3635
+ details: { ok: true, goal }
3636
+ };
3637
+ }
3638
+ },
3639
+ // 11. remote_update_goal
3640
+ {
3641
+ name: "remote_update_goal",
3642
+ label: "Update a goal on the Remote project board",
3643
+ description: "Update an existing goal. Specify goal_id and any fields to change: title, description, status (active/achieved/abandoned), success_criteria, target_date, owner_role_id.",
3644
+ parameters: Type.Object({
3645
+ goal_id: Type.String({ description: "ID of the goal to update" }),
3646
+ title: Type.Optional(Type.String({ description: "New goal title" })),
3647
+ description: Type.Optional(Type.String({ description: "New description" })),
3648
+ status: optionalStringEnum(["active", "achieved", "abandoned"], {
3649
+ description: "New status: active, achieved, or abandoned"
3650
+ }),
3651
+ success_criteria: Type.Optional(Type.String({ description: "New success criteria" })),
3652
+ target_date: Type.Optional(Type.String({ description: "New target date (ISO format)" })),
3653
+ owner_role_id: Type.Optional(Type.String({ description: "New owner role ID" }))
3654
+ }),
3655
+ execute: async (_toolCallId, args) => {
3656
+ const account = resolveToolAccount();
3657
+ const { goal_id, ...updates } = args;
3658
+ const result = await updateGoal(account, goal_id, updates);
3659
+ if (!result.ok) {
3660
+ return {
3661
+ content: [{ type: "text", text: `\u274C Failed to update goal: ${result.error}` }],
3662
+ details: { ok: false, error: result.error }
3663
+ };
3664
+ }
3665
+ const goal = result.data.goal;
3666
+ const text = [
3667
+ `\u2705 Goal updated!`,
3668
+ `- **Title**: ${goal.title}`,
3669
+ `- **Status**: ${goal.status}`,
3670
+ `- **Progress**: ${goal.progress}%`
3671
+ ].join("\n");
3672
+ return {
3673
+ content: [{ type: "text", text }],
3674
+ details: { ok: true, goal }
3675
+ };
3676
+ }
3677
+ },
3678
+ // remote_update_role — update role bundle info (agent callback)
3679
+ {
3680
+ name: "remote_update_role",
3681
+ label: "Update a role's agent bundle info",
3682
+ description: "Update a role's bundle_slug, bundle_version, and generation_status. Used by the agent-builder to report back after generating a bundle.",
3683
+ parameters: Type.Object({
3684
+ role_id: Type.String({ description: "ID of the role to update" }),
3685
+ bundle_slug: Type.Optional(Type.String({ description: "Published bundle slug (e.g. @org/agent-name)" })),
3686
+ bundle_version: Type.Optional(Type.String({ description: "Published bundle version" })),
3687
+ generation_status: optionalStringEnum(["published", "failed"], {
3688
+ description: "Generation status: published or failed"
3689
+ })
3690
+ }),
3691
+ execute: async (_toolCallId, args) => {
3692
+ const account = resolveToolAccount();
3693
+ const result = await updateRoleBundle(account, args.role_id, {
3694
+ bundle_slug: args.bundle_slug,
3695
+ bundle_version: args.bundle_version,
3696
+ generation_status: args.generation_status
3697
+ });
3698
+ if (!result.ok) {
3699
+ return {
3700
+ content: [{ type: "text", text: `\u274C Failed to update role bundle: ${result.error}` }],
3701
+ details: { ok: false, error: result.error }
3702
+ };
3703
+ }
3704
+ const text = [
3705
+ `\u2705 Role bundle updated!`,
3706
+ args.bundle_slug ? `- **Bundle**: ${args.bundle_slug}` : "",
3707
+ args.bundle_version ? `- **Version**: ${args.bundle_version}` : "",
3708
+ args.generation_status ? `- **Status**: ${args.generation_status}` : ""
3709
+ ].filter(Boolean).join("\n");
3710
+ return {
3711
+ content: [{ type: "text", text }],
3712
+ details: { ok: true }
3713
+ };
3714
+ }
3488
3715
  }
3489
3716
  ];
3490
3717
  }),
@@ -3497,14 +3724,18 @@ function createRemotePlugin() {
3497
3724
  "**Replying**: When you reply to a task notification, your reply is posted as a comment on that task.",
3498
3725
  "",
3499
3726
  "**Available tools**:",
3500
- "- `remote_create_task` \u2014 Create a new task (title, type, priority, assigned_role_id, epic_id)",
3501
- "- `remote_update_task` \u2014 Update a task (status, priority, title, description, type, epic_id, assigned_role_id)",
3727
+ "- `remote_create_task` \u2014 Create a new task (title, type, priority, assigned_role_id, epic_id, goal_id)",
3728
+ "- `remote_update_task` \u2014 Update a task (status, priority, title, description, type, epic_id, goal_id, assigned_role_id)",
3502
3729
  "- `remote_list_tasks` \u2014 List/filter tasks on the board",
3503
3730
  "- `remote_board_health` \u2014 Get board health stats (task counts, epics, roles, recent activity)",
3504
3731
  "- `remote_list_roles` \u2014 List project roles with vacancy info (find valid assigned_role_id values)",
3505
3732
  "- `remote_list_epics` \u2014 List epics with task counts (find valid epic_id values)",
3506
3733
  "- `remote_create_epic` \u2014 Create a new epic (name, description, color)",
3507
3734
  "- `remote_list_team` \u2014 List all team members with roles and @mention handles",
3735
+ "- `remote_list_goals` \u2014 List goals with progress (filter by status, parent_id, assigned_to)",
3736
+ "- `remote_create_goal` \u2014 Create a goal (title, description, success_criteria, parent_id, owner_role_id, target_date)",
3737
+ "- `remote_update_goal` \u2014 Update a goal (status, title, description, success_criteria, target_date, owner_role_id)",
3738
+ "- `remote_update_role` \u2014 Update a role's bundle info (bundle_slug, bundle_version, generation_status)",
3508
3739
  "",
3509
3740
  "**Task lifecycle**: todo \u2192 in_progress \u2192 review \u2192 done",
3510
3741
  "**Task types**: feature, task, bug",
@@ -3518,7 +3749,10 @@ function createRemotePlugin() {
3518
3749
  "- Use `remote_list_roles` before creating tasks to find valid role IDs for assignment",
3519
3750
  "- Use `remote_list_epics` before creating tasks to find valid epic IDs for grouping",
3520
3751
  "- Use `remote_list_team` to find teammates and their @mention handles for tagging in comments",
3521
- "- Tag team members with @name in comments when you need their input or want to delegate"
3752
+ "- Tag team members with @name in comments when you need their input or want to delegate",
3753
+ "- Use `remote_list_goals` to see goal hierarchy and progress",
3754
+ "- Goals auto-calculate progress from linked tasks (leaf goals) or child goals",
3755
+ "- Link tasks to goals with goal_id when creating or updating tasks"
3522
3756
  ]
3523
3757
  }
3524
3758
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-remote",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Remote project board channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -25,4 +25,4 @@
25
25
  "peerDependencies": {
26
26
  "openclaw": "*"
27
27
  }
28
- }
28
+ }