@mickey-kras/hindsight-memory-router-coding-agents 0.8.9 → 0.8.14
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/dist/antigravity-hook.js +70 -24
- package/dist/antigravity-statusline.js +60 -14
- package/dist/antigravity-stop-hook.js +70 -24
- package/dist/claude-hook.js +70 -24
- package/dist/claude-sessionstart-hook.js +70 -24
- package/dist/claude-stop-hook.js +70 -24
- package/dist/cline.js +70 -24
- package/dist/codebuddy-hook.js +70 -24
- package/dist/codebuddy-sessionstart-hook.js +70 -24
- package/dist/codebuddy-stop-hook.js +70 -24
- package/dist/codex-hook.js +70 -24
- package/dist/codex-sessionstart-hook.js +70 -24
- package/dist/codex-stop-hook.js +70 -24
- package/dist/copilot-hook.js +70 -24
- package/dist/copilot-sessionstart-hook.js +70 -24
- package/dist/copilot-stop-hook.js +70 -24
- package/dist/cursor-hook.js +70 -24
- package/dist/cursor-sessionstart-hook.js +70 -24
- package/dist/cursor-stop-hook.js +70 -24
- package/dist/dcode-hook.js +70 -24
- package/dist/dcode-sessionstart-hook.js +70 -24
- package/dist/dcode-stop-hook.js +70 -24
- package/dist/deepen.js +70 -68
- package/dist/devin-hook.js +70 -24
- package/dist/devin-sessionstart-hook.js +70 -24
- package/dist/devin-stop-hook.js +70 -24
- package/dist/droid-hook.js +70 -24
- package/dist/droid-sessionstart-hook.js +70 -24
- package/dist/droid-stop-hook.js +70 -24
- package/dist/dsh.js +70 -24
- package/dist/grok-hook.js +70 -24
- package/dist/grok-sessionstart-hook.js +70 -24
- package/dist/grok-stop-hook.js +70 -24
- package/dist/hindsight-seed.js +60 -14
- package/dist/index.js +70 -24
- package/dist/installer.js +70 -21
- package/dist/kilo.js +70 -24
- package/dist/kimi-hook.js +70 -24
- package/dist/kimi-sessionstart-hook.js +70 -24
- package/dist/kimi-stop-hook.js +70 -24
- package/dist/mcp-server.js +79 -24
- package/dist/opencode2.js +70 -24
- package/dist/pi.js +70 -24
- package/dist/prime-agent.js +70 -24
- package/dist/qwen-hook.js +70 -24
- package/dist/qwen-sessionstart-hook.js +70 -24
- package/dist/qwen-stop-hook.js +70 -24
- package/dist/status.js +70 -24
- package/dist/traecode-hook.js +70 -24
- package/dist/traecode-sessionstart-hook.js +70 -24
- package/dist/traecode-stop-hook.js +70 -24
- package/dist/workbuddy-hook.js +70 -24
- package/dist/workbuddy-sessionstart-hook.js +70 -24
- package/dist/workbuddy-stop-hook.js +70 -24
- package/dist/zcode-hook.js +70 -24
- package/dist/zcode-sessionstart-hook.js +70 -24
- package/dist/zcode-stop-hook.js +70 -24
- package/npm-shrinkwrap.json +257 -711
- package/package.json +8 -5
package/dist/mcp-server.js
CHANGED
|
@@ -35873,6 +35873,15 @@ var McpServer = class {
|
|
|
35873
35873
|
this._promptHandlersInitialized = false;
|
|
35874
35874
|
this.server = new Server(serverInfo, options);
|
|
35875
35875
|
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
35876
|
+
if (options?.capabilities?.tools) {
|
|
35877
|
+
this.setToolRequestHandlers();
|
|
35878
|
+
}
|
|
35879
|
+
if (options?.capabilities?.resources) {
|
|
35880
|
+
this.setResourceRequestHandlers();
|
|
35881
|
+
}
|
|
35882
|
+
if (options?.capabilities?.prompts) {
|
|
35883
|
+
this.setPromptRequestHandlers();
|
|
35884
|
+
}
|
|
35876
35885
|
}
|
|
35877
35886
|
/**
|
|
35878
35887
|
* Access experimental features.
|
|
@@ -36790,12 +36799,10 @@ function requireBank(access, bank, operation) {
|
|
|
36790
36799
|
}
|
|
36791
36800
|
function classifyOperation(method, suffix) {
|
|
36792
36801
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
36793
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
36794
|
-
suffix
|
|
36795
|
-
))
|
|
36802
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
36796
36803
|
return "read";
|
|
36797
36804
|
if (method === "GET" && suffix === "") return "read";
|
|
36798
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
36805
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
36799
36806
|
suffix
|
|
36800
36807
|
))
|
|
36801
36808
|
return "write";
|
|
@@ -37090,6 +37097,54 @@ var RouterTransport = class {
|
|
|
37090
37097
|
// ../../coding-agents/human-session.ts
|
|
37091
37098
|
import { createHash as createHash2 } from "crypto";
|
|
37092
37099
|
import { createRequire } from "module";
|
|
37100
|
+
|
|
37101
|
+
// src/harness/names.ts
|
|
37102
|
+
var HARNESS_NAMES = [
|
|
37103
|
+
"opencode",
|
|
37104
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
37105
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
37106
|
+
"opencode2",
|
|
37107
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
37108
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
37109
|
+
"kilo",
|
|
37110
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
37111
|
+
"cline-cli",
|
|
37112
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
37113
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
37114
|
+
"dsh",
|
|
37115
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
37116
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
37117
|
+
"pi",
|
|
37118
|
+
"prime-agent",
|
|
37119
|
+
"claude-code",
|
|
37120
|
+
"cursor-cli",
|
|
37121
|
+
"codex",
|
|
37122
|
+
"dcode",
|
|
37123
|
+
"antigravity-cli",
|
|
37124
|
+
"devin-cli",
|
|
37125
|
+
"copilot-cli",
|
|
37126
|
+
"grok-build",
|
|
37127
|
+
"qwen-code",
|
|
37128
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
37129
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
37130
|
+
"factory-droid",
|
|
37131
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
37132
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
37133
|
+
"zcode",
|
|
37134
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
37135
|
+
"traecode",
|
|
37136
|
+
"kimi-code",
|
|
37137
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
37138
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
37139
|
+
"workbuddy",
|
|
37140
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
37141
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
37142
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
37143
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
37144
|
+
"codebuddy"
|
|
37145
|
+
];
|
|
37146
|
+
|
|
37147
|
+
// ../../coding-agents/human-session.ts
|
|
37093
37148
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
37094
37149
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
37095
37150
|
constructor() {
|
|
@@ -37115,14 +37170,14 @@ function humanRouterUrl(value) {
|
|
|
37115
37170
|
if (url2.search || url2.hash) throw new HumanLoginRequiredError();
|
|
37116
37171
|
return canonical2;
|
|
37117
37172
|
}
|
|
37118
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
37173
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
37119
37174
|
try {
|
|
37120
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
37175
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
37121
37176
|
throw new HumanLoginRequiredError();
|
|
37122
37177
|
}
|
|
37123
37178
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
37124
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
37125
|
-
return new NativeEntry(service, credentialRef
|
|
37179
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
37180
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
37126
37181
|
} catch {
|
|
37127
37182
|
throw new HumanLoginRequiredError();
|
|
37128
37183
|
}
|
|
@@ -37140,9 +37195,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
37140
37195
|
routerUrl: session.routerUrl
|
|
37141
37196
|
};
|
|
37142
37197
|
}
|
|
37143
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
37198
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
37144
37199
|
try {
|
|
37145
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
37200
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
37146
37201
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
37147
37202
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
37148
37203
|
} catch {
|
|
@@ -37154,11 +37209,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
37154
37209
|
function harnessTransport(harness) {
|
|
37155
37210
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
37156
37211
|
}
|
|
37157
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
37212
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
37158
37213
|
if (principal.human) {
|
|
37159
37214
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
37160
37215
|
const reference = principal.human.credentialRef;
|
|
37161
|
-
let session = readHumanSession(routerUrl, reference);
|
|
37216
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
37162
37217
|
return new RouterTransport({
|
|
37163
37218
|
routerUrl,
|
|
37164
37219
|
access: principal,
|
|
@@ -37166,7 +37221,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
37166
37221
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
37167
37222
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
37168
37223
|
token: () => {
|
|
37169
|
-
session = readHumanSession(routerUrl, reference);
|
|
37224
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
37170
37225
|
return session.token;
|
|
37171
37226
|
}
|
|
37172
37227
|
});
|
|
@@ -37931,7 +37986,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
37931
37986
|
];
|
|
37932
37987
|
|
|
37933
37988
|
// package.json
|
|
37934
|
-
var version2 = "0.8.
|
|
37989
|
+
var version2 = "0.8.14";
|
|
37935
37990
|
|
|
37936
37991
|
// src/core/util.ts
|
|
37937
37992
|
import { accessSync, constants } from "fs";
|
|
@@ -38445,7 +38500,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38445
38500
|
*/
|
|
38446
38501
|
async tree() {
|
|
38447
38502
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
38448
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
38503
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
38449
38504
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
38450
38505
|
if (r.status === 404) return [];
|
|
38451
38506
|
this.knowledgePagesSupported = true;
|
|
@@ -38493,7 +38548,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38493
38548
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
38494
38549
|
const r = await this.req(
|
|
38495
38550
|
"GET",
|
|
38496
|
-
this.bankUrl(`/
|
|
38551
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
38497
38552
|
);
|
|
38498
38553
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
38499
38554
|
return shapePage(await r.json());
|
|
@@ -38506,7 +38561,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38506
38561
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
38507
38562
|
const r = await this.req(
|
|
38508
38563
|
"GET",
|
|
38509
|
-
this.bankUrl(`/
|
|
38564
|
+
this.bankUrl(`/pages/search${q}`),
|
|
38510
38565
|
void 0,
|
|
38511
38566
|
[],
|
|
38512
38567
|
opts.timeoutMs
|
|
@@ -38525,7 +38580,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38525
38580
|
/**
|
|
38526
38581
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
38527
38582
|
*
|
|
38528
|
-
* Matched by NAME, not id: `/
|
|
38583
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
38529
38584
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
38530
38585
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
38531
38586
|
*
|
|
@@ -38564,7 +38619,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38564
38619
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
38565
38620
|
};
|
|
38566
38621
|
if (!hit) {
|
|
38567
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
38622
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
38568
38623
|
if (await this.pagesUnsupported(r)) {
|
|
38569
38624
|
this.log(
|
|
38570
38625
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -38591,7 +38646,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38591
38646
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
38592
38647
|
const r = await this.req(
|
|
38593
38648
|
"PATCH",
|
|
38594
|
-
this.bankUrl(`/
|
|
38649
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
38595
38650
|
patch
|
|
38596
38651
|
);
|
|
38597
38652
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -38645,7 +38700,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38645
38700
|
if (!patch.trigger && !patch.source_query) continue;
|
|
38646
38701
|
const r = await this.req(
|
|
38647
38702
|
"PATCH",
|
|
38648
|
-
this.bankUrl(`/
|
|
38703
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
38649
38704
|
patch
|
|
38650
38705
|
);
|
|
38651
38706
|
if (r.status === 404) continue;
|
|
@@ -38674,7 +38729,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38674
38729
|
let pageId = args.relatesToPageId;
|
|
38675
38730
|
if (!pageId) {
|
|
38676
38731
|
const folderId = await this.ensureFolder("Initiatives");
|
|
38677
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
38732
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
38678
38733
|
name: args.title,
|
|
38679
38734
|
source_query: `Summarize the "${args.title}" initiative: what is being built or changed and why, and its current state \u2014 drawn from the project's memory.` + pageScopeRule(this.project),
|
|
38680
38735
|
parent_id: folderId,
|
|
@@ -38702,7 +38757,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38702
38757
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
38703
38758
|
async ensureFolder(name) {
|
|
38704
38759
|
try {
|
|
38705
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
38760
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
38706
38761
|
const hit = (tree.roots || []).find(
|
|
38707
38762
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
38708
38763
|
);
|
|
@@ -38711,7 +38766,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
38711
38766
|
if (error62 instanceof AccessDeniedError) throw error62;
|
|
38712
38767
|
}
|
|
38713
38768
|
try {
|
|
38714
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
38769
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
38715
38770
|
return (await r.json()).id;
|
|
38716
38771
|
} catch (error62) {
|
|
38717
38772
|
if (error62 instanceof AccessDeniedError) throw error62;
|
package/dist/opencode2.js
CHANGED
|
@@ -143,12 +143,10 @@ function requireBank(access, bank, operation) {
|
|
|
143
143
|
}
|
|
144
144
|
function classifyOperation(method, suffix) {
|
|
145
145
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
146
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
147
|
-
suffix
|
|
148
|
-
))
|
|
146
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
149
147
|
return "read";
|
|
150
148
|
if (method === "GET" && suffix === "") return "read";
|
|
151
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
149
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
152
150
|
suffix
|
|
153
151
|
))
|
|
154
152
|
return "write";
|
|
@@ -439,6 +437,54 @@ var RouterTransport = class {
|
|
|
439
437
|
// ../../coding-agents/human-session.ts
|
|
440
438
|
import { createHash as createHash2 } from "crypto";
|
|
441
439
|
import { createRequire } from "module";
|
|
440
|
+
|
|
441
|
+
// src/harness/names.ts
|
|
442
|
+
var HARNESS_NAMES = [
|
|
443
|
+
"opencode",
|
|
444
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
445
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
446
|
+
"opencode2",
|
|
447
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
448
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
449
|
+
"kilo",
|
|
450
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
451
|
+
"cline-cli",
|
|
452
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
453
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
454
|
+
"dsh",
|
|
455
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
456
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
457
|
+
"pi",
|
|
458
|
+
"prime-agent",
|
|
459
|
+
"claude-code",
|
|
460
|
+
"cursor-cli",
|
|
461
|
+
"codex",
|
|
462
|
+
"dcode",
|
|
463
|
+
"antigravity-cli",
|
|
464
|
+
"devin-cli",
|
|
465
|
+
"copilot-cli",
|
|
466
|
+
"grok-build",
|
|
467
|
+
"qwen-code",
|
|
468
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
469
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
470
|
+
"factory-droid",
|
|
471
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
472
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
473
|
+
"zcode",
|
|
474
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
475
|
+
"traecode",
|
|
476
|
+
"kimi-code",
|
|
477
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
478
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
479
|
+
"workbuddy",
|
|
480
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
481
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
482
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
483
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
484
|
+
"codebuddy"
|
|
485
|
+
];
|
|
486
|
+
|
|
487
|
+
// ../../coding-agents/human-session.ts
|
|
442
488
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
443
489
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
444
490
|
constructor() {
|
|
@@ -464,14 +510,14 @@ function humanRouterUrl(value) {
|
|
|
464
510
|
if (url2.search || url2.hash) throw new HumanLoginRequiredError();
|
|
465
511
|
return canonical2;
|
|
466
512
|
}
|
|
467
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
513
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
468
514
|
try {
|
|
469
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
515
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
470
516
|
throw new HumanLoginRequiredError();
|
|
471
517
|
}
|
|
472
518
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
473
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
474
|
-
return new NativeEntry(service, credentialRef
|
|
519
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
520
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
475
521
|
} catch {
|
|
476
522
|
throw new HumanLoginRequiredError();
|
|
477
523
|
}
|
|
@@ -489,9 +535,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
489
535
|
routerUrl: session.routerUrl
|
|
490
536
|
};
|
|
491
537
|
}
|
|
492
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
538
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
493
539
|
try {
|
|
494
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
540
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
495
541
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
496
542
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
497
543
|
} catch {
|
|
@@ -503,11 +549,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
503
549
|
function harnessTransport(harness) {
|
|
504
550
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
505
551
|
}
|
|
506
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
552
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
507
553
|
if (principal.human) {
|
|
508
554
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
509
555
|
const reference = principal.human.credentialRef;
|
|
510
|
-
let session = readHumanSession(routerUrl, reference);
|
|
556
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
511
557
|
return new RouterTransport({
|
|
512
558
|
routerUrl,
|
|
513
559
|
access: principal,
|
|
@@ -515,7 +561,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
515
561
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
516
562
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
517
563
|
token: () => {
|
|
518
|
-
session = readHumanSession(routerUrl, reference);
|
|
564
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
519
565
|
return session.token;
|
|
520
566
|
}
|
|
521
567
|
});
|
|
@@ -21039,7 +21085,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
21039
21085
|
];
|
|
21040
21086
|
|
|
21041
21087
|
// package.json
|
|
21042
|
-
var version2 = "0.8.
|
|
21088
|
+
var version2 = "0.8.14";
|
|
21043
21089
|
|
|
21044
21090
|
// src/core/util.ts
|
|
21045
21091
|
import { accessSync, constants } from "fs";
|
|
@@ -21572,7 +21618,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21572
21618
|
*/
|
|
21573
21619
|
async tree() {
|
|
21574
21620
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21575
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
21621
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
21576
21622
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
21577
21623
|
if (r.status === 404) return [];
|
|
21578
21624
|
this.knowledgePagesSupported = true;
|
|
@@ -21620,7 +21666,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21620
21666
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21621
21667
|
const r = await this.req(
|
|
21622
21668
|
"GET",
|
|
21623
|
-
this.bankUrl(`/
|
|
21669
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
21624
21670
|
);
|
|
21625
21671
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
21626
21672
|
return shapePage(await r.json());
|
|
@@ -21633,7 +21679,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21633
21679
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
21634
21680
|
const r = await this.req(
|
|
21635
21681
|
"GET",
|
|
21636
|
-
this.bankUrl(`/
|
|
21682
|
+
this.bankUrl(`/pages/search${q}`),
|
|
21637
21683
|
void 0,
|
|
21638
21684
|
[],
|
|
21639
21685
|
opts.timeoutMs
|
|
@@ -21652,7 +21698,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21652
21698
|
/**
|
|
21653
21699
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
21654
21700
|
*
|
|
21655
|
-
* Matched by NAME, not id: `/
|
|
21701
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
21656
21702
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
21657
21703
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
21658
21704
|
*
|
|
@@ -21691,7 +21737,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21691
21737
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
21692
21738
|
};
|
|
21693
21739
|
if (!hit) {
|
|
21694
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21740
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
21695
21741
|
if (await this.pagesUnsupported(r)) {
|
|
21696
21742
|
this.log(
|
|
21697
21743
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -21718,7 +21764,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21718
21764
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
21719
21765
|
const r = await this.req(
|
|
21720
21766
|
"PATCH",
|
|
21721
|
-
this.bankUrl(`/
|
|
21767
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
21722
21768
|
patch
|
|
21723
21769
|
);
|
|
21724
21770
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -21772,7 +21818,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21772
21818
|
if (!patch.trigger && !patch.source_query) continue;
|
|
21773
21819
|
const r = await this.req(
|
|
21774
21820
|
"PATCH",
|
|
21775
|
-
this.bankUrl(`/
|
|
21821
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
21776
21822
|
patch
|
|
21777
21823
|
);
|
|
21778
21824
|
if (r.status === 404) continue;
|
|
@@ -21801,7 +21847,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21801
21847
|
let pageId = args.relatesToPageId;
|
|
21802
21848
|
if (!pageId) {
|
|
21803
21849
|
const folderId = await this.ensureFolder("Initiatives");
|
|
21804
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21850
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
21805
21851
|
name: args.title,
|
|
21806
21852
|
source_query: `Summarize the "${args.title}" initiative: what is being built or changed and why, and its current state \u2014 drawn from the project's memory.` + pageScopeRule(this.project),
|
|
21807
21853
|
parent_id: folderId,
|
|
@@ -21829,7 +21875,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21829
21875
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
21830
21876
|
async ensureFolder(name) {
|
|
21831
21877
|
try {
|
|
21832
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
21878
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
21833
21879
|
const hit = (tree.roots || []).find(
|
|
21834
21880
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
21835
21881
|
);
|
|
@@ -21838,7 +21884,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21838
21884
|
if (error62 instanceof AccessDeniedError) throw error62;
|
|
21839
21885
|
}
|
|
21840
21886
|
try {
|
|
21841
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21887
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
21842
21888
|
return (await r.json()).id;
|
|
21843
21889
|
} catch (error62) {
|
|
21844
21890
|
if (error62 instanceof AccessDeniedError) throw error62;
|