@wirecat/cli-core 0.440.0 → 0.441.0

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/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ shape of this file.
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.441.0 — 26.10.2026
11
+
12
+ ### Added
13
+
14
+ - **`tasks list claimed_by:<holder>` lists the tasks a holder has claimed**, and `claimed_by:*` every claimed task.
15
+ A caller that wanted one agent's claims read every open task and filtered them itself. The filter matches live
16
+ claims only: a claim whose lease has lapsed holds nothing, as `tasks claim` and the list's own `claimed_by` field
17
+ already read it, so `NOT claimed_by:*` lists what no one is working on. A wildcard such as `claimed_by:claude-code:*`
18
+ matches by pattern.
19
+
20
+ ### Fixed
21
+
22
+ - **`tasks claim` and `tasks release` work on a project task**, which belongs to no messenger account, as `tasks show`
23
+ and `tasks update` already did. They refused it as "no task for this account", so memo, which mounts these
24
+ commands, could not claim its own project tasks.
25
+
10
26
  ## 0.440.0 — 26.10.2026
11
27
 
12
28
  ### Added
@@ -15,17 +15,7 @@ export const TASK_QUERY = {
15
15
  entity: "task",
16
16
  backend: "sql",
17
17
  fields: queryFieldsOf(taskEntity, {
18
- exclude: [
19
- "ref",
20
- "description",
21
- "project",
22
- "account",
23
- "priority",
24
- "parent",
25
- "claimed_by",
26
- "claimed_until",
27
- "close_suggestion",
28
- ],
18
+ exclude: ["ref", "description", "project", "account", "priority", "parent", "claimed_until", "close_suggestion"],
29
19
  relations: {
30
20
  close: {
31
21
  type: "enum",
@@ -47,6 +37,7 @@ export const TASK_QUERY = {
47
37
  chat: "chat:12345",
48
38
  title: "title:*invoice*",
49
39
  source_message: 'source_message:"msg:telegram/1/2/3"',
40
+ claimed_by: "claimed_by:session-1",
50
41
  },
51
42
  }),
52
43
  };
@@ -84,6 +75,13 @@ const taskColumns = (groups, tags) => ({
84
75
  : { sql: "t.source_group = ?", params: [groups.get(node.value) ?? ""] },
85
76
  },
86
77
  source_message: { type: "ref", sql: "t.source_locator" },
78
+ // A lapsed claim holds nothing, as tasks claim and the list's own claimed_by read it.
79
+ claimed_by: {
80
+ where: (node) => ({
81
+ sql: `t.claimed_by ${node.operator === "wildcard" ? "GLOB" : "="} ? AND t.claimed_until >= ?`,
82
+ params: [node.value, Date.now()],
83
+ }),
84
+ },
87
85
  reason: { type: "kw", sql: "t.close_reason_folded", folded: true },
88
86
  close: { where: () => ({ sql: "t.close_suggested_as IS NOT NULL", params: [] }) },
89
87
  assignee: {
@@ -343,16 +341,21 @@ export const tasksService = (deps, categories) => {
343
341
  const { pair } = await store.tasks.unmerge(dup, by === "owner" ? "owner" : { bot: by });
344
342
  return { pair, task: await cardOf(store, dup) };
345
343
  }),
346
- claim: (id, holder, forMs) => inStore(async (store, account) => {
347
- await owned(store, account, id);
344
+ // A project task belongs to no messenger account, as show reads it.
345
+ claim: async (id, holder, forMs) => {
346
+ const store = await deps.store();
347
+ if (!(await store.tasks.projectTask(id)))
348
+ await owned(store, await deps.account(), id);
348
349
  await store.tasks.claim(id, holder, new Date(Date.now() + forMs));
349
350
  return cardOf(store, id);
350
- }),
351
- release: (id, holder) => inStore(async (store, account) => {
352
- await owned(store, account, id);
351
+ },
352
+ release: async (id, holder) => {
353
+ const store = await deps.store();
354
+ if (!(await store.tasks.projectTask(id)))
355
+ await owned(store, await deps.account(), id);
353
356
  await store.tasks.release(id, holder);
354
357
  return cardOf(store, id);
355
- }),
358
+ },
356
359
  close: (id, { as, reason, by, agent, certainty, suggestOnly }) => inStore(async (store, account) => {
357
360
  const existing = await owned(store, account, id);
358
361
  const suggested = existing.state === "open" ? await store.tasks.closeSuggestion(id) : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.440.0",
3
+ "version": "0.441.0",
4
4
  "description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",