@joe-broadhead/opencode-linear 0.0.5 → 0.0.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.
- package/CHANGELOG.md +19 -0
- package/dist/index.js +5 -3
- package/package.json +1 -1
- package/skills/linear/SKILL.md +33 -21
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [0.0.7] - 2026-11-06
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `/connect` now clears the "Sign in required" mark on the account after you sign in again.
|
|
10
|
+
|
|
11
|
+
## [0.0.6] - 2026-11-05
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- The `linear` skill says that `id` is an issue's identifier, such as ENG-123 (there is no `identifier` field), and
|
|
16
|
+
lists the other useful `fields` values, so a `list_issues` call no longer fails on a guessed field.
|
|
17
|
+
- The `linear` skill computes every number an answer states, group totals included, in the first Code Mode call, and
|
|
18
|
+
returns only those numbers and the few issues it names, also for "what am I working on".
|
|
19
|
+
- The `linear` skill finds the team for "this cycle" with `list_teams` when you name none, and calls `list_cycles`
|
|
20
|
+
once without `type` to tell "no cycles" from "no current cycle".
|
|
21
|
+
- The `linear` skill's scripts section says a script uses a session created for it, never one borrowed from history
|
|
22
|
+
or a list, and links the scripting guide as a plain file.
|
|
23
|
+
|
|
5
24
|
## [0.0.5] - 2026-11-05
|
|
6
25
|
|
|
7
26
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -540,8 +540,10 @@ function watchIntegration(ctx, owned) {
|
|
|
540
540
|
}
|
|
541
541
|
const connection2 = await ctx.integration.connection.active(id);
|
|
542
542
|
if (connection2?.type !== "credential") return;
|
|
543
|
-
const
|
|
544
|
-
|
|
543
|
+
const shown = (await ctx.integration.get({ integrationID: id })).data.connections?.find((item) => item.type === "credential" && item.id === connection2.id);
|
|
544
|
+
const status = shown?.type === "credential" ? shown.status : void 0;
|
|
545
|
+
const reported = status?.message === SIGN_IN_AGAIN;
|
|
546
|
+
if (server.status.status === "needs_auth" && !status) {
|
|
545
547
|
await ctx.integration.connection.status({ integrationID: id, connection: connection2, status: { status: "needs_auth", message: SIGN_IN_AGAIN } });
|
|
546
548
|
} else if (server.status.status === "connected" && reported) {
|
|
547
549
|
await ctx.integration.connection.status({ integrationID: id, connection: connection2, status: void 0 });
|
|
@@ -791,7 +793,7 @@ function registerSkills(skill, skills) {
|
|
|
791
793
|
}
|
|
792
794
|
|
|
793
795
|
// src/version.ts
|
|
794
|
-
var VERSION = "0.0.
|
|
796
|
+
var VERSION = "0.0.7";
|
|
795
797
|
|
|
796
798
|
// src/status.ts
|
|
797
799
|
var SIGN_IN = `Run /connect and choose Linear, then press o or Enter to open the link (in a terminal, opencode mcp auth ${SERVER_NAME} opens it automatically).`;
|
package/package.json
CHANGED
package/skills/linear/SKILL.md
CHANGED
|
@@ -21,9 +21,8 @@ the reference for every field; this skill covers the choices they don't explain.
|
|
|
21
21
|
list call first. `get_issue` returns no comments: read the discussion with `linear_list_comments` and `issueId`.
|
|
22
22
|
- **Projects, documents, initiatives, milestones**: the matching `list_*` and `get_*` tools, such as
|
|
23
23
|
`linear_get_project` with `query` (a name, identifier or slug).
|
|
24
|
-
- **Which workspace am I in**: `linear_get_workspace`.
|
|
25
|
-
`linear_get_user` is only for a
|
|
26
|
-
- **How Linear itself works**: `linear_search_documentation`.
|
|
24
|
+
- **Which workspace am I in**: `linear_get_workspace`. **How Linear works**: `linear_search_documentation`. Don't
|
|
25
|
+
look up "me" first: filters take `"me"` directly; `linear_get_user` is only for a person's profile.
|
|
27
26
|
|
|
28
27
|
## Filters
|
|
29
28
|
|
|
@@ -34,29 +33,40 @@ the reference for every field; this skill covers the choices they don't explain.
|
|
|
34
33
|
`linear_list_issue_statuses` with `team` gives a team's state names.
|
|
35
34
|
- Dates (`createdAt`, `updatedAt`, `completedAt`) mean "after" and take an ISO-8601 date or a duration such as
|
|
36
35
|
`-P7D`. `completedAt` also drops issues that are not completed.
|
|
37
|
-
- "This cycle": `linear_list_cycles` with `teamId` (a team name, key or ID)
|
|
38
|
-
means the team has no
|
|
36
|
+
- "This cycle": `linear_list_cycles` with `teamId` (a team name, key or ID); with no team named, `linear_list_teams`
|
|
37
|
+
gives them, rather than paging issues. Call it once without `type`: `[]` means the team has no cycles, so none is
|
|
38
|
+
current. Only if it has cycles, `type: "current"` gives the running one. Say so plainly rather than guessing from
|
|
39
|
+
dates, and label a fallback, such as the user's started issues, as that, not as "this cycle".
|
|
39
40
|
|
|
40
41
|
## Result size and pages
|
|
41
42
|
|
|
42
|
-
- By default each listed issue carries its whole description, about 1.6 KB
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
- By default each listed issue carries its whole description, about 1.6 KB: pass `fields` with only what the answer
|
|
44
|
+
needs. `id` is the identifier, such as `"ENG-123"` (`uuid` is the UUID); there is no `identifier` field. Others:
|
|
45
|
+
`title`, `url`, `status` (the state's name), `statusType`, `priority` (`{ value, name }`), `team`, `project` and
|
|
46
|
+
`assignee` (names), `teamId` (a UUID), `labels`, `parentId` (an identifier), `cycleId`, `createdAt`, `updatedAt`,
|
|
47
|
+
`completedAt`, `dueDate`. A field outside the schema's list fails the call.
|
|
48
|
+
- `limit` is 50 by default and at most 250 (`list_projects`: 50). A page ends with `hasNextPage` and `cursor`: while
|
|
49
|
+
`hasNextPage` is true, call again with the same filters and that `cursor`. If you stop early, say so.
|
|
50
|
+
- For a count, a breakdown or "what am I working on", decide the grouping first, and in the first Code Mode call
|
|
51
|
+
compute every number you will state (each count, every group's total, the overall total) and pick the few rows you
|
|
52
|
+
will name. Return only those, never all the rows: even with `fields`, a hundred rows are tens of KB, and sums done
|
|
53
|
+
by eye go wrong. If you name only some rows, say how many you left out. For example, the user's issues by state
|
|
54
|
+
type, with the 5 most recently updated of each:
|
|
50
55
|
|
|
51
56
|
```js
|
|
52
|
-
const
|
|
53
|
-
let cursor
|
|
57
|
+
const groups = {}
|
|
58
|
+
let total = 0, cursor
|
|
54
59
|
do {
|
|
55
|
-
const page = await tools.linear.list_issues({ assignee: "me", fields: ["id", "statusType"], limit: 250, ...(cursor ? { cursor } : {}) })
|
|
56
|
-
for (const
|
|
60
|
+
const page = await tools.linear.list_issues({ assignee: "me", fields: ["id", "title", "statusType", "url"], limit: 250, ...(cursor ? { cursor } : {}) })
|
|
61
|
+
for (const { id, title, statusType, url } of page.issues) {
|
|
62
|
+
const group = (groups[statusType] ??= { count: 0, newest: [] })
|
|
63
|
+
group.count++
|
|
64
|
+
if (group.newest.length < 5) group.newest.push({ id, title, url })
|
|
65
|
+
}
|
|
66
|
+
total += page.issues.length
|
|
57
67
|
cursor = page.hasNextPage ? page.cursor : undefined
|
|
58
68
|
} while (cursor)
|
|
59
|
-
return
|
|
69
|
+
return { total, groups }
|
|
60
70
|
```
|
|
61
71
|
|
|
62
72
|
## Changes
|
|
@@ -78,9 +88,11 @@ Name each item by its identifier (or a project's name) and give the `url` Linear
|
|
|
78
88
|
|
|
79
89
|
## Scripts
|
|
80
90
|
|
|
81
|
-
A cron job or shell script can run the same reads with no model through the tools RPC `linear.workspace.tools
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
A cron job or shell script can run the same reads with no model through the tools RPC `linear.workspace.tools`;
|
|
92
|
+
writes are never available there. It runs as a session's agent, under its rules, so a script, or a test of one, uses
|
|
93
|
+
a session created for it (`opencode api post /api/session -d '{"title":"…","agent":"build"}'`, keep `data.id`).
|
|
94
|
+
Never borrow an existing session found through history or a list. Details:
|
|
95
|
+
https://raw.githubusercontent.com/joe-broadhead/opencode-linear/HEAD/docs/scripting.md
|
|
84
96
|
|
|
85
97
|
## When Linear is not available
|
|
86
98
|
|