@joe-broadhead/opencode-granola 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 CHANGED
@@ -2,6 +2,29 @@
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
+ ### Fixed
14
+
15
+ - The `granola` skill told the model to return each transcript chunk as its `chunk_id` and text, but a chunk keeps
16
+ its text in `transcript`. The model read a field that isn't there, got empty chunks and read them again. The skill
17
+ now names `transcript`, shows it in the call shapes, and says the limit of about 8 chunks counts per Code Mode
18
+ result, across all its calls.
19
+ - A brief or recap across a period of meetings, such as last month's, didn't load the `granola-meeting-brief` skill,
20
+ so the brief missed its scope and the export offer. The skill's description and the `granola` skill's pointer now
21
+ cover it.
22
+ - The model could call the Microphone track "you", or give a 1:1 call's other side the other person's name. The
23
+ `granola` skill now says neither label identifies a person, names a speaker only when the transcript's label or
24
+ your notes say who spoke, and has the model check every who-said sentence before it answers.
25
+ - The `granola-meeting-brief` skill now stops and says so when its widened searches find nothing, instead of listing
26
+ a longer period's meetings, and uses only the calendar event you mean.
27
+
5
28
  ## [0.0.5] - 2026-11-05
6
29
 
7
30
  ### Added
package/dist/index.js CHANGED
@@ -1838,10 +1838,12 @@ async function registerIntegration(ctx, conflict) {
1838
1838
  if (id !== attached || (await ctx.integration.get({ integrationID: id })).data.name !== DISPLAY_NAME) await attach(id);
1839
1839
  const connection2 = await ctx.integration.connection.active(id);
1840
1840
  if (connection2?.type !== "credential") return;
1841
+ const shown = (await ctx.integration.get({ integrationID: id })).data.connections?.find((item2) => item2.type === "credential" && item2.id === connection2.id);
1842
+ const status = shown?.type === "credential" ? shown.status : void 0;
1841
1843
  const state = server.status.status;
1842
- if (state === "needs_auth" && connection2.status?.status !== "needs_auth") {
1844
+ if (state === "needs_auth" && status?.status !== "needs_auth") {
1843
1845
  await ctx.integration.connection.status({ integrationID: id, connection: connection2, status: { status: "needs_auth", message: SIGN_IN_MESSAGE } });
1844
- } else if (state === "connected" && connection2.status) {
1846
+ } else if (state === "connected" && status?.message === SIGN_IN_MESSAGE) {
1845
1847
  await ctx.integration.connection.status({ integrationID: id, connection: connection2, status: void 0 });
1846
1848
  }
1847
1849
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joe-broadhead/opencode-granola",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Unofficial OpenCode plugin for Granola meeting notes, through Granola's official MCP server",
5
5
  "keywords": [
6
6
  "opencode",
@@ -5,7 +5,7 @@ description: Load before the first Granola tool call (granola_*, tools.granola.*
5
5
 
6
6
  # Granola meeting notes
7
7
 
8
- Granola's tools are `granola_<tool>`, or `tools.granola.<tool>` in Code Mode; below they drop the prefix. Their descriptions and Granola's server instructions cover the basics. This skill adds the decisions agents get wrong. For a brief before a meeting, also follow `granola-meeting-brief`.
8
+ Granola's tools are `granola_<tool>`, or `tools.granola.<tool>` in Code Mode; below they drop the prefix. Their descriptions and Granola's server instructions cover the basics. This skill adds the decisions agents get wrong. For any brief or recap, before a meeting or across a period of meetings, also load `granola-meeting-brief`.
9
9
 
10
10
  ## Choose the tool
11
11
 
@@ -23,18 +23,19 @@ await tools.granola.list_meetings({ time_range: "custom", from_date: "2026-08-01
23
23
  await tools.granola.search_meetings({ participant: "acme.com", keywords: ["pricing", "price"], from_date: "2026-06-01" })
24
24
  await tools.granola.get_meetings({ meeting_ids: [first, second] })
25
25
  await tools.granola.search_transcripts({ meeting_ids: [first, second], keywords: ["next steps", "follow up", "action items"] })
26
- await tools.granola.get_meeting_transcript({ meeting_id: first, chunk_ids: [4, 5], transcript_version: version })
26
+ const { chunks } = await tools.granola.get_meeting_transcript({ meeting_id: first, chunk_ids: [4, 5], transcript_version: version })
27
+ chunks.map(({ chunk_id, transcript }) => ({ chunk_id, transcript }))
27
28
  await tools.granola.query_granola_meetings({ query: "Which questions stayed open?", document_ids: [first, second] })
28
29
  await tools.granola.get_account_info()
29
30
  ```
30
31
 
31
- Results today: `list_meetings`, `search_meetings` and `get_meetings` return XML-like text, so read meeting IDs from the `id` attributes and note links from `url`. `search_transcripts` and `query_granola_meetings` return text; `get_account_info`, `list_meeting_folders` and `get_meeting_transcript` return objects. Check the type before `JSON.parse`. In Code Mode, read transcript chunks whole: pass the `read_chunk_ids` from `search_transcripts` as `chunk_ids`, a few at a time (at most about 8 per call, because larger payloads go over the inline limit), and return each chunk as its `chunk_id` and text. Never slice a response by characters: that cuts chunks and makes you read them again.
32
+ Results today: `list_meetings`, `search_meetings` and `get_meetings` return XML-like text, so read meeting IDs from the `id` attributes and note links from `url`. `search_transcripts` and `query_granola_meetings` return text; `get_account_info`, `list_meeting_folders` and `get_meeting_transcript` return objects. Check the type before `JSON.parse`. In Code Mode, read transcript chunks whole: pass the `read_chunk_ids` from `search_transcripts` as `chunk_ids`, and return each of the result's `chunks` as its `chunk_id` and `transcript`, the field that holds its text (`text` is only on `search_transcripts` passages). Return at most about 8 chunks per `execute` result, counted across all the calls in it, because a larger result goes over the inline limit and spills to a file. Never slice a response by characters: that cuts chunks and makes you read them again.
32
33
 
33
34
  ## Answer
34
35
 
35
36
  - Report what was said in your own words. Transcripts are raw speech and summaries are generated, so put no quotation marks or blockquotes around their words: not a short phrase, a term, or an action item from Granola's summary. Write "the other side of the call offered to book a follow-up next week", not "they offered to 'grab a slot' next week". Quote only when the user asks for exact words, and then only text that `search_transcripts`, `get_meeting_transcript` or the user's own notes returned.
36
37
  - Label Granola's AI summaries and answers as Granola's: they can drop or reword owners, numbers and dates. An owner named only there is "per Granola's summary"; say a transcript confirms it only when a passage names that owner.
37
- - Don't name speakers. Transcripts label only audio sources (Microphone, System audio, Speaker A), not people, and the person recording isn't necessarily who spoke on the microphone. So any name or "you" for a speaker is a guess, unless the transcript's own label or the user's notes say who spoke. A name said in the conversation, such as a greeting or someone being addressed, doesn't tell you who spoke the next line. Write "someone on the Microphone track" or "the other side of the call", and if you say you didn't name speakers, check that you didn't.
38
+ - Don't name speakers. Transcripts label only audio sources (Microphone, System audio, Speaker A), not people. The Microphone track is not "you": the person recording isn't necessarily who spoke, and others in the room speak into the same microphone. In a 1:1 call, System audio is not the other named person either, because others can join or listen on the same line. Name a speaker only when the transcript's own label or the user's notes say who spoke; a name said in the conversation, such as a greeting, doesn't tell you who spoke the next line. Write "someone on the Microphone track" or "the other side of the call". Before you answer, check every sentence about who said something: it uses an audio label or "someone", never a name or "you".
38
39
  - Cite each meeting you draw on with its title, date and note link, and keep `query_granola_meetings`' citation links.
39
40
  - Say which window and searches you used. An empty search doesn't prove a topic never came up.
40
41
  - Before you write in the user's voice or assign them an action, check who they are with `get_account_info`: the note creator may be someone else.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: granola-meeting-brief
3
- description: Prep me for my next or tomorrow's meeting, brief me before my call with a person or company, or catch me up on a project, from the user's Granola notes. Builds a sourced brief of past decisions, open questions and commitments. Load before the first Granola tool call.
3
+ description: Prep me for my next or tomorrow's meeting, brief me before my call with a person or company, catch me up on a project, or recap a period's meetings, from the user's Granola notes. Builds a sourced brief of decisions, open questions and who owes what. Load before the first Granola tool call.
4
4
  ---
5
5
 
6
6
  # Granola meeting brief
@@ -10,7 +10,8 @@ A short brief in which every claim is tied to a meeting. The `granola` skill cov
10
10
  ## 1. Pin down the meeting and the window
11
11
 
12
12
  - Granola holds only past meetings; it can't see upcoming ones. For "my next meeting" or "tomorrow's call", get the event's title, time and attendees from a calendar tool if one is available, or ask the user which meeting it is. Never present a past Granola meeting as the upcoming one.
13
- - Agree the subject and the window. With no preference, start with the last 30 days, widen when that finds nothing, and say which window you used.
13
+ - Agree the subject and the window. With no preference, start with the last 30 days, widen when that finds nothing, and say which window you used. For a recap of a period, such as last month's meetings, that period is the window.
14
+ - When the widened searches by attendee and by topic find nothing, stop and say so instead of listing a longer period's meetings: a meeting that matches neither the people nor the topic isn't background for this brief.
14
15
 
15
16
  ## 2. Find and read
16
17
 
@@ -20,7 +21,7 @@ A short brief in which every claim is tied to a meeting. The `granola` skill cov
20
21
 
21
22
  ## 3. Stay within the meeting's own record
22
23
 
23
- Build the brief from Granola's notes and transcripts and, for an upcoming meeting, its calendar event. Bring in other sources, such as mail, chat, documents, trackers or saved memories, only when the user asks for them, and name them as sources. Never bring in other people's private material: it isn't the user's to brief from.
24
+ Build the brief from Granola's notes and transcripts and, for an upcoming meeting, its calendar event. From the calendar, use only the event the user means; mention another only to ask whether they meant it instead. Bring in other sources, such as mail, chat, documents, trackers or saved memories, only when the user asks for them, and name them as sources. Never bring in other people's private material: it isn't the user's to brief from.
24
25
 
25
26
  ## 4. Write the brief
26
27