kibi-cursor 0.2.0 → 0.2.1

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
3
  "displayName": "Kibi",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "description": "Optional Cursor adapter for Kibi. Requires SWI-Prolog 9+ and project-local kibi-cli, kibi-mcp, and kibi-core before the bundled MCP server can start.",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "author": {
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # kibi-cursor
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 5d2975a: Cursor stop hooks no longer inject a long multi-line Kibi freshness reminder after every agent response. Follow-ups are now one line, and most sessions stay silent.
8
+
9
+ - Track `kb_upsert`, `kb_delete`, and `kb_check` MCP usage during the session.
10
+ - Emit no stop follow-up when nothing KB-relevant changed, or when `kb_check` already ran after edits.
11
+ - Emit a short summary (`Kibi KB updated (kb_upsert).`) after KB mutations, or a single-line sync nudge when source files changed without KB activity.
12
+ - Fix publish workflow to build and pack `kibi-cursor` tarballs before npm publish.
13
+
14
+ - Cursor sessions now use Cursor's documented workspace root payload when deciding whether Kibi is already configured. This prevents the plugin from telling agents that Kibi needs bootstrapping just because the hook process is running from the plugin install directory instead of the actual workspace. The bootstrap reminder now names the missing `.kb/config.json` condition directly instead of implying MCP is unavailable.
15
+
16
+ - Parse `workspace_roots` from Cursor hook payloads and prefer the first workspace root for Kibi config detection.
17
+ - Add a regression test covering `sessionStart` without `cwd` when `workspace_roots` points at a configured workspace.
18
+ - Reword the bootstrap reminder to describe a missing workspace config rather than generic initialization failure.
19
+
3
20
  ## 0.2.0
4
21
 
5
22
  ### Minor Changes
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
3
  "displayName": "Kibi",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "description": "Optional Cursor adapter for Kibi. Requires SWI-Prolog 9+ and project-local kibi-cli, kibi-mcp, and kibi-core before the bundled MCP server can start.",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "author": {
@@ -2,6 +2,7 @@ export type HookEvent = "sessionStart" | "preToolUse" | "postToolUse" | "beforeR
2
2
  export type HookInput = {
3
3
  event: string;
4
4
  cwd?: string;
5
+ workspaceRoots?: readonly string[];
5
6
  toolName?: string;
6
7
  toolInput?: unknown;
7
8
  conversationId?: string;
@@ -10,6 +10,19 @@ function readString(record, keys) {
10
10
  }
11
11
  return undefined;
12
12
  }
13
+ function readStringArray(record, keys) {
14
+ for (const key of keys) {
15
+ const value = record[key];
16
+ if (!Array.isArray(value)) {
17
+ continue;
18
+ }
19
+ const strings = value.filter((item) => typeof item === "string" && item.length > 0);
20
+ if (strings.length > 0) {
21
+ return strings;
22
+ }
23
+ }
24
+ return undefined;
25
+ }
13
26
  function normalizeEventName(event) {
14
27
  const trimmed = event.trim();
15
28
  if (trimmed.length === 0) {
@@ -34,6 +47,10 @@ export function parseHookInput(input) {
34
47
  "current_working_directory",
35
48
  "workspace",
36
49
  ]);
50
+ const workspaceRoots = readStringArray(input, [
51
+ "workspace_roots",
52
+ "workspaceRoots",
53
+ ]);
37
54
  const toolName = readString(input, ["toolName", "tool_name", "tool"]);
38
55
  const toolInput = input.toolInput ?? input.tool_input ?? input.input;
39
56
  const conversationId = readString(input, [
@@ -45,6 +62,9 @@ export function parseHookInput(input) {
45
62
  if (cwd !== undefined) {
46
63
  parsed.cwd = cwd;
47
64
  }
65
+ if (workspaceRoots !== undefined) {
66
+ parsed.workspaceRoots = workspaceRoots;
67
+ }
48
68
  if (toolName !== undefined) {
49
69
  parsed.toolName = toolName;
50
70
  }
@@ -5,8 +5,8 @@ import path from "node:path";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { readGuidance, writeGuidance } from "./guidance.js";
7
7
  import { parseHookInput, parseStdinJson, readStdin } from "./hook-input.js";
8
- import { extractKbMcpToolName } from "./kb-mcp-tools.js";
9
8
  import { addDirtyPaths, clearSessionHookState, hasGuidedPath, loadHookState, recordKbMcpTool, rememberGuidedPath, resolveStateDir, } from "./hook-state.js";
9
+ import { extractKbMcpToolName } from "./kb-mcp-tools.js";
10
10
  import { BOOTSTRAP_REMINDER, DIRECT_KB_EDIT_WARNING, stopFollowupMessage, } from "./messages.js";
11
11
  import { extractExplicitPathFields, isDirectKbPath, isMeaningfulTrackedPath, toRepoRelativePath, } from "./path-policy.js";
12
12
  const editableTools = new Set([
@@ -33,7 +33,7 @@ function isReadLikeTool(toolName) {
33
33
  return toolName === undefined || readTools.has(toolName);
34
34
  }
35
35
  function resolveWorkspaceRoot(input) {
36
- return input.cwd ?? process.cwd();
36
+ return input.workspaceRoots?.[0] ?? input.cwd ?? process.cwd();
37
37
  }
38
38
  function resolvePrimaryPath(input) {
39
39
  if (input.filePath) {
@@ -231,7 +231,9 @@ export function recordKbMcpTool(stateDir, toolName) {
231
231
  if (normalized === "kb_upsert" || normalized === "kb_delete") {
232
232
  return {
233
233
  ...state,
234
- kbMutationTools: mergeStringPaths(state.kbMutationTools, [normalized]).slice(-maxKbMutationTools),
234
+ kbMutationTools: mergeStringPaths(state.kbMutationTools, [
235
+ normalized,
236
+ ]).slice(-maxKbMutationTools),
235
237
  };
236
238
  }
237
239
  return state;
@@ -27,7 +27,11 @@ export function extractKbMcpToolName(toolName, toolInput) {
27
27
  }
28
28
  const nestedArgs = toolInput.arguments ?? toolInput.args;
29
29
  if (isRecord(nestedArgs)) {
30
- const nestedTool = readString(nestedArgs, ["toolName", "tool_name", "name"]);
30
+ const nestedTool = readString(nestedArgs, [
31
+ "toolName",
32
+ "tool_name",
33
+ "name",
34
+ ]);
31
35
  if (nestedTool?.startsWith("kb_")) {
32
36
  return nestedTool;
33
37
  }
@@ -1,5 +1,5 @@
1
1
  import type { HookState } from "./hook-state.js";
2
- export declare const BOOTSTRAP_REMINDER = "Kibi is not initialized for this workspace. Use the Kibi MCP workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
2
+ export declare const BOOTSTRAP_REMINDER = "Kibi config was not found at the Cursor workspace root. Use the Kibi MCP /init-kibi workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
3
3
  export declare const DIRECT_KB_EDIT_WARNING = "Avoid direct edits to .kb/. Use Kibi MCP tools for KB discovery and mutations so project memory stays valid.";
4
4
  export declare function stopFollowupMessage(state: HookState): string | undefined;
5
5
  /** @deprecated Use stopFollowupMessage */
package/dist/messages.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isKbFreshnessRelevantPath } from "./path-policy.js";
2
- export const BOOTSTRAP_REMINDER = "Kibi is not initialized for this workspace. Use the Kibi MCP workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
2
+ export const BOOTSTRAP_REMINDER = "Kibi config was not found at the Cursor workspace root. Use the Kibi MCP /init-kibi workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
3
3
  export const DIRECT_KB_EDIT_WARNING = "Avoid direct edits to .kb/. Use Kibi MCP tools for KB discovery and mutations so project memory stays valid.";
4
4
  export function stopFollowupMessage(state) {
5
5
  if (state.kbMutationTools.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Kibi Cursor plugin - thin adapter for Cursor MCP integration and editor hooks",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",