@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/dsh.js
CHANGED
|
@@ -142,12 +142,10 @@ function requireBank(access, bank, operation) {
|
|
|
142
142
|
}
|
|
143
143
|
function classifyOperation(method, suffix) {
|
|
144
144
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
145
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
146
|
-
suffix
|
|
147
|
-
))
|
|
145
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
148
146
|
return "read";
|
|
149
147
|
if (method === "GET" && suffix === "") return "read";
|
|
150
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
148
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
151
149
|
suffix
|
|
152
150
|
))
|
|
153
151
|
return "write";
|
|
@@ -442,6 +440,54 @@ var RouterTransport = class {
|
|
|
442
440
|
// ../../coding-agents/human-session.ts
|
|
443
441
|
import { createHash as createHash2 } from "crypto";
|
|
444
442
|
import { createRequire } from "module";
|
|
443
|
+
|
|
444
|
+
// src/harness/names.ts
|
|
445
|
+
var HARNESS_NAMES = [
|
|
446
|
+
"opencode",
|
|
447
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
448
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
449
|
+
"opencode2",
|
|
450
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
451
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
452
|
+
"kilo",
|
|
453
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
454
|
+
"cline-cli",
|
|
455
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
456
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
457
|
+
"dsh",
|
|
458
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
459
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
460
|
+
"pi",
|
|
461
|
+
"prime-agent",
|
|
462
|
+
"claude-code",
|
|
463
|
+
"cursor-cli",
|
|
464
|
+
"codex",
|
|
465
|
+
"dcode",
|
|
466
|
+
"antigravity-cli",
|
|
467
|
+
"devin-cli",
|
|
468
|
+
"copilot-cli",
|
|
469
|
+
"grok-build",
|
|
470
|
+
"qwen-code",
|
|
471
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
472
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
473
|
+
"factory-droid",
|
|
474
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
475
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
476
|
+
"zcode",
|
|
477
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
478
|
+
"traecode",
|
|
479
|
+
"kimi-code",
|
|
480
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
481
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
482
|
+
"workbuddy",
|
|
483
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
484
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
485
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
486
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
487
|
+
"codebuddy"
|
|
488
|
+
];
|
|
489
|
+
|
|
490
|
+
// ../../coding-agents/human-session.ts
|
|
445
491
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
446
492
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
447
493
|
constructor() {
|
|
@@ -467,14 +513,14 @@ function humanRouterUrl(value) {
|
|
|
467
513
|
if (url2.search || url2.hash) throw new HumanLoginRequiredError();
|
|
468
514
|
return canonical2;
|
|
469
515
|
}
|
|
470
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
516
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
471
517
|
try {
|
|
472
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
518
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
473
519
|
throw new HumanLoginRequiredError();
|
|
474
520
|
}
|
|
475
521
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
476
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
477
|
-
return new NativeEntry(service, credentialRef
|
|
522
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
523
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
478
524
|
} catch {
|
|
479
525
|
throw new HumanLoginRequiredError();
|
|
480
526
|
}
|
|
@@ -492,9 +538,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
492
538
|
routerUrl: session.routerUrl
|
|
493
539
|
};
|
|
494
540
|
}
|
|
495
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
541
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
496
542
|
try {
|
|
497
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
543
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
498
544
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
499
545
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
500
546
|
} catch {
|
|
@@ -506,11 +552,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
506
552
|
function harnessTransport(harness) {
|
|
507
553
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
508
554
|
}
|
|
509
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
555
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
510
556
|
if (principal.human) {
|
|
511
557
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
512
558
|
const reference = principal.human.credentialRef;
|
|
513
|
-
let session = readHumanSession(routerUrl, reference);
|
|
559
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
514
560
|
return new RouterTransport({
|
|
515
561
|
routerUrl,
|
|
516
562
|
access: principal,
|
|
@@ -518,7 +564,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
518
564
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
519
565
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
520
566
|
token: () => {
|
|
521
|
-
session = readHumanSession(routerUrl, reference);
|
|
567
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
522
568
|
return session.token;
|
|
523
569
|
}
|
|
524
570
|
});
|
|
@@ -1325,7 +1371,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
1325
1371
|
];
|
|
1326
1372
|
|
|
1327
1373
|
// package.json
|
|
1328
|
-
var version = "0.8.
|
|
1374
|
+
var version = "0.8.14";
|
|
1329
1375
|
|
|
1330
1376
|
// src/core/util.ts
|
|
1331
1377
|
import { accessSync, constants } from "fs";
|
|
@@ -1858,7 +1904,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1858
1904
|
*/
|
|
1859
1905
|
async tree() {
|
|
1860
1906
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1861
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
1907
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
1862
1908
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
1863
1909
|
if (r.status === 404) return [];
|
|
1864
1910
|
this.knowledgePagesSupported = true;
|
|
@@ -1906,7 +1952,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1906
1952
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1907
1953
|
const r = await this.req(
|
|
1908
1954
|
"GET",
|
|
1909
|
-
this.bankUrl(`/
|
|
1955
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
1910
1956
|
);
|
|
1911
1957
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
1912
1958
|
return shapePage(await r.json());
|
|
@@ -1919,7 +1965,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1919
1965
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
1920
1966
|
const r = await this.req(
|
|
1921
1967
|
"GET",
|
|
1922
|
-
this.bankUrl(`/
|
|
1968
|
+
this.bankUrl(`/pages/search${q}`),
|
|
1923
1969
|
void 0,
|
|
1924
1970
|
[],
|
|
1925
1971
|
opts.timeoutMs
|
|
@@ -1938,7 +1984,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1938
1984
|
/**
|
|
1939
1985
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
1940
1986
|
*
|
|
1941
|
-
* Matched by NAME, not id: `/
|
|
1987
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
1942
1988
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
1943
1989
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
1944
1990
|
*
|
|
@@ -1977,7 +2023,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1977
2023
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
1978
2024
|
};
|
|
1979
2025
|
if (!hit) {
|
|
1980
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2026
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
1981
2027
|
if (await this.pagesUnsupported(r)) {
|
|
1982
2028
|
this.log(
|
|
1983
2029
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -2004,7 +2050,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2004
2050
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
2005
2051
|
const r = await this.req(
|
|
2006
2052
|
"PATCH",
|
|
2007
|
-
this.bankUrl(`/
|
|
2053
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
2008
2054
|
patch
|
|
2009
2055
|
);
|
|
2010
2056
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -2058,7 +2104,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2058
2104
|
if (!patch.trigger && !patch.source_query) continue;
|
|
2059
2105
|
const r = await this.req(
|
|
2060
2106
|
"PATCH",
|
|
2061
|
-
this.bankUrl(`/
|
|
2107
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
2062
2108
|
patch
|
|
2063
2109
|
);
|
|
2064
2110
|
if (r.status === 404) continue;
|
|
@@ -2087,7 +2133,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2087
2133
|
let pageId = args.relatesToPageId;
|
|
2088
2134
|
if (!pageId) {
|
|
2089
2135
|
const folderId = await this.ensureFolder("Initiatives");
|
|
2090
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2136
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
2091
2137
|
name: args.title,
|
|
2092
2138
|
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),
|
|
2093
2139
|
parent_id: folderId,
|
|
@@ -2115,7 +2161,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2115
2161
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
2116
2162
|
async ensureFolder(name2) {
|
|
2117
2163
|
try {
|
|
2118
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
2164
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
2119
2165
|
const hit = (tree.roots || []).find(
|
|
2120
2166
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name2.toLowerCase()
|
|
2121
2167
|
);
|
|
@@ -2124,7 +2170,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2124
2170
|
if (error62 instanceof AccessDeniedError) throw error62;
|
|
2125
2171
|
}
|
|
2126
2172
|
try {
|
|
2127
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2173
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name: name2 });
|
|
2128
2174
|
return (await r.json()).id;
|
|
2129
2175
|
} catch (error62) {
|
|
2130
2176
|
if (error62 instanceof AccessDeniedError) throw error62;
|
package/dist/grok-hook.js
CHANGED
|
@@ -36,12 +36,10 @@ function requireBank(access, bank, operation) {
|
|
|
36
36
|
}
|
|
37
37
|
function classifyOperation(method, suffix) {
|
|
38
38
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
39
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
40
|
-
suffix
|
|
41
|
-
))
|
|
39
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
42
40
|
return "read";
|
|
43
41
|
if (method === "GET" && suffix === "") return "read";
|
|
44
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
42
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
45
43
|
suffix
|
|
46
44
|
))
|
|
47
45
|
return "write";
|
|
@@ -393,6 +391,54 @@ var RouterTransport = class {
|
|
|
393
391
|
// ../../coding-agents/human-session.ts
|
|
394
392
|
import { createHash as createHash2 } from "crypto";
|
|
395
393
|
import { createRequire } from "module";
|
|
394
|
+
|
|
395
|
+
// src/harness/names.ts
|
|
396
|
+
var HARNESS_NAMES = [
|
|
397
|
+
"opencode",
|
|
398
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
399
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
400
|
+
"opencode2",
|
|
401
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
402
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
403
|
+
"kilo",
|
|
404
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
405
|
+
"cline-cli",
|
|
406
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
407
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
408
|
+
"dsh",
|
|
409
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
410
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
411
|
+
"pi",
|
|
412
|
+
"prime-agent",
|
|
413
|
+
"claude-code",
|
|
414
|
+
"cursor-cli",
|
|
415
|
+
"codex",
|
|
416
|
+
"dcode",
|
|
417
|
+
"antigravity-cli",
|
|
418
|
+
"devin-cli",
|
|
419
|
+
"copilot-cli",
|
|
420
|
+
"grok-build",
|
|
421
|
+
"qwen-code",
|
|
422
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
423
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
424
|
+
"factory-droid",
|
|
425
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
426
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
427
|
+
"zcode",
|
|
428
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
429
|
+
"traecode",
|
|
430
|
+
"kimi-code",
|
|
431
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
432
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
433
|
+
"workbuddy",
|
|
434
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
435
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
436
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
437
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
438
|
+
"codebuddy"
|
|
439
|
+
];
|
|
440
|
+
|
|
441
|
+
// ../../coding-agents/human-session.ts
|
|
396
442
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
397
443
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
398
444
|
constructor() {
|
|
@@ -418,14 +464,14 @@ function humanRouterUrl(value) {
|
|
|
418
464
|
if (url.search || url.hash) throw new HumanLoginRequiredError();
|
|
419
465
|
return canonical2;
|
|
420
466
|
}
|
|
421
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
467
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
422
468
|
try {
|
|
423
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
469
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
424
470
|
throw new HumanLoginRequiredError();
|
|
425
471
|
}
|
|
426
472
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
427
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
428
|
-
return new NativeEntry(service, credentialRef
|
|
473
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
474
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
429
475
|
} catch {
|
|
430
476
|
throw new HumanLoginRequiredError();
|
|
431
477
|
}
|
|
@@ -443,9 +489,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
443
489
|
routerUrl: session.routerUrl
|
|
444
490
|
};
|
|
445
491
|
}
|
|
446
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
492
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
447
493
|
try {
|
|
448
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
494
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
449
495
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
450
496
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
451
497
|
} catch {
|
|
@@ -457,11 +503,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
457
503
|
function harnessTransport(harness) {
|
|
458
504
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
459
505
|
}
|
|
460
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
506
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
461
507
|
if (principal.human) {
|
|
462
508
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
463
509
|
const reference = principal.human.credentialRef;
|
|
464
|
-
let session = readHumanSession(routerUrl, reference);
|
|
510
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
465
511
|
return new RouterTransport({
|
|
466
512
|
routerUrl,
|
|
467
513
|
access: principal,
|
|
@@ -469,7 +515,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
469
515
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
470
516
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
471
517
|
token: () => {
|
|
472
|
-
session = readHumanSession(routerUrl, reference);
|
|
518
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
473
519
|
return session.token;
|
|
474
520
|
}
|
|
475
521
|
});
|
|
@@ -1277,7 +1323,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
1277
1323
|
];
|
|
1278
1324
|
|
|
1279
1325
|
// package.json
|
|
1280
|
-
var version = "0.8.
|
|
1326
|
+
var version = "0.8.14";
|
|
1281
1327
|
|
|
1282
1328
|
// src/core/util.ts
|
|
1283
1329
|
import { accessSync, constants } from "fs";
|
|
@@ -1791,7 +1837,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1791
1837
|
*/
|
|
1792
1838
|
async tree() {
|
|
1793
1839
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1794
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
1840
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
1795
1841
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
1796
1842
|
if (r.status === 404) return [];
|
|
1797
1843
|
this.knowledgePagesSupported = true;
|
|
@@ -1839,7 +1885,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1839
1885
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1840
1886
|
const r = await this.req(
|
|
1841
1887
|
"GET",
|
|
1842
|
-
this.bankUrl(`/
|
|
1888
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
1843
1889
|
);
|
|
1844
1890
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
1845
1891
|
return shapePage(await r.json());
|
|
@@ -1852,7 +1898,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1852
1898
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
1853
1899
|
const r = await this.req(
|
|
1854
1900
|
"GET",
|
|
1855
|
-
this.bankUrl(`/
|
|
1901
|
+
this.bankUrl(`/pages/search${q}`),
|
|
1856
1902
|
void 0,
|
|
1857
1903
|
[],
|
|
1858
1904
|
opts.timeoutMs
|
|
@@ -1871,7 +1917,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1871
1917
|
/**
|
|
1872
1918
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
1873
1919
|
*
|
|
1874
|
-
* Matched by NAME, not id: `/
|
|
1920
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
1875
1921
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
1876
1922
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
1877
1923
|
*
|
|
@@ -1910,7 +1956,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1910
1956
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
1911
1957
|
};
|
|
1912
1958
|
if (!hit) {
|
|
1913
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
1959
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
1914
1960
|
if (await this.pagesUnsupported(r)) {
|
|
1915
1961
|
this.log(
|
|
1916
1962
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -1937,7 +1983,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1937
1983
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
1938
1984
|
const r = await this.req(
|
|
1939
1985
|
"PATCH",
|
|
1940
|
-
this.bankUrl(`/
|
|
1986
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
1941
1987
|
patch
|
|
1942
1988
|
);
|
|
1943
1989
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -1991,7 +2037,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1991
2037
|
if (!patch.trigger && !patch.source_query) continue;
|
|
1992
2038
|
const r = await this.req(
|
|
1993
2039
|
"PATCH",
|
|
1994
|
-
this.bankUrl(`/
|
|
2040
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
1995
2041
|
patch
|
|
1996
2042
|
);
|
|
1997
2043
|
if (r.status === 404) continue;
|
|
@@ -2020,7 +2066,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2020
2066
|
let pageId = args.relatesToPageId;
|
|
2021
2067
|
if (!pageId) {
|
|
2022
2068
|
const folderId = await this.ensureFolder("Initiatives");
|
|
2023
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2069
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
2024
2070
|
name: args.title,
|
|
2025
2071
|
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),
|
|
2026
2072
|
parent_id: folderId,
|
|
@@ -2048,7 +2094,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2048
2094
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
2049
2095
|
async ensureFolder(name) {
|
|
2050
2096
|
try {
|
|
2051
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
2097
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
2052
2098
|
const hit = (tree.roots || []).find(
|
|
2053
2099
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
2054
2100
|
);
|
|
@@ -2057,7 +2103,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2057
2103
|
if (error instanceof AccessDeniedError) throw error;
|
|
2058
2104
|
}
|
|
2059
2105
|
try {
|
|
2060
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2106
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
2061
2107
|
return (await r.json()).id;
|
|
2062
2108
|
} catch (error) {
|
|
2063
2109
|
if (error instanceof AccessDeniedError) throw error;
|
|
@@ -36,12 +36,10 @@ function requireBank(access, bank, operation) {
|
|
|
36
36
|
}
|
|
37
37
|
function classifyOperation(method, suffix) {
|
|
38
38
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
39
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
40
|
-
suffix
|
|
41
|
-
))
|
|
39
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
42
40
|
return "read";
|
|
43
41
|
if (method === "GET" && suffix === "") return "read";
|
|
44
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
42
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
45
43
|
suffix
|
|
46
44
|
))
|
|
47
45
|
return "write";
|
|
@@ -427,6 +425,54 @@ var RouterTransport = class {
|
|
|
427
425
|
// ../../coding-agents/human-session.ts
|
|
428
426
|
import { createHash as createHash2 } from "crypto";
|
|
429
427
|
import { createRequire } from "module";
|
|
428
|
+
|
|
429
|
+
// src/harness/names.ts
|
|
430
|
+
var HARNESS_NAMES = [
|
|
431
|
+
"opencode",
|
|
432
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
433
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
434
|
+
"opencode2",
|
|
435
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
436
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
437
|
+
"kilo",
|
|
438
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
439
|
+
"cline-cli",
|
|
440
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
441
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
442
|
+
"dsh",
|
|
443
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
444
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
445
|
+
"pi",
|
|
446
|
+
"prime-agent",
|
|
447
|
+
"claude-code",
|
|
448
|
+
"cursor-cli",
|
|
449
|
+
"codex",
|
|
450
|
+
"dcode",
|
|
451
|
+
"antigravity-cli",
|
|
452
|
+
"devin-cli",
|
|
453
|
+
"copilot-cli",
|
|
454
|
+
"grok-build",
|
|
455
|
+
"qwen-code",
|
|
456
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
457
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
458
|
+
"factory-droid",
|
|
459
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
460
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
461
|
+
"zcode",
|
|
462
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
463
|
+
"traecode",
|
|
464
|
+
"kimi-code",
|
|
465
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
466
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
467
|
+
"workbuddy",
|
|
468
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
469
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
470
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
471
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
472
|
+
"codebuddy"
|
|
473
|
+
];
|
|
474
|
+
|
|
475
|
+
// ../../coding-agents/human-session.ts
|
|
430
476
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
431
477
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
432
478
|
constructor() {
|
|
@@ -452,14 +498,14 @@ function humanRouterUrl(value) {
|
|
|
452
498
|
if (url.search || url.hash) throw new HumanLoginRequiredError();
|
|
453
499
|
return canonical2;
|
|
454
500
|
}
|
|
455
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
501
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
456
502
|
try {
|
|
457
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
503
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
458
504
|
throw new HumanLoginRequiredError();
|
|
459
505
|
}
|
|
460
506
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
461
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
462
|
-
return new NativeEntry(service, credentialRef
|
|
507
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
508
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
463
509
|
} catch {
|
|
464
510
|
throw new HumanLoginRequiredError();
|
|
465
511
|
}
|
|
@@ -477,9 +523,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
477
523
|
routerUrl: session.routerUrl
|
|
478
524
|
};
|
|
479
525
|
}
|
|
480
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
526
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
481
527
|
try {
|
|
482
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
528
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
483
529
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
484
530
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
485
531
|
} catch {
|
|
@@ -491,11 +537,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
491
537
|
function harnessTransport(harness) {
|
|
492
538
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
493
539
|
}
|
|
494
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
540
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
495
541
|
if (principal.human) {
|
|
496
542
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
497
543
|
const reference = principal.human.credentialRef;
|
|
498
|
-
let session = readHumanSession(routerUrl, reference);
|
|
544
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
499
545
|
return new RouterTransport({
|
|
500
546
|
routerUrl,
|
|
501
547
|
access: principal,
|
|
@@ -503,7 +549,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
503
549
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
504
550
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
505
551
|
token: () => {
|
|
506
|
-
session = readHumanSession(routerUrl, reference);
|
|
552
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
507
553
|
return session.token;
|
|
508
554
|
}
|
|
509
555
|
});
|
|
@@ -1348,7 +1394,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
1348
1394
|
];
|
|
1349
1395
|
|
|
1350
1396
|
// package.json
|
|
1351
|
-
var version = "0.8.
|
|
1397
|
+
var version = "0.8.14";
|
|
1352
1398
|
|
|
1353
1399
|
// src/core/util.ts
|
|
1354
1400
|
import { accessSync, constants } from "fs";
|
|
@@ -1881,7 +1927,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1881
1927
|
*/
|
|
1882
1928
|
async tree() {
|
|
1883
1929
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1884
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
1930
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
1885
1931
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
1886
1932
|
if (r.status === 404) return [];
|
|
1887
1933
|
this.knowledgePagesSupported = true;
|
|
@@ -1929,7 +1975,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1929
1975
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
1930
1976
|
const r = await this.req(
|
|
1931
1977
|
"GET",
|
|
1932
|
-
this.bankUrl(`/
|
|
1978
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
1933
1979
|
);
|
|
1934
1980
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
1935
1981
|
return shapePage(await r.json());
|
|
@@ -1942,7 +1988,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1942
1988
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
1943
1989
|
const r = await this.req(
|
|
1944
1990
|
"GET",
|
|
1945
|
-
this.bankUrl(`/
|
|
1991
|
+
this.bankUrl(`/pages/search${q}`),
|
|
1946
1992
|
void 0,
|
|
1947
1993
|
[],
|
|
1948
1994
|
opts.timeoutMs
|
|
@@ -1961,7 +2007,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
1961
2007
|
/**
|
|
1962
2008
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
1963
2009
|
*
|
|
1964
|
-
* Matched by NAME, not id: `/
|
|
2010
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
1965
2011
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
1966
2012
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
1967
2013
|
*
|
|
@@ -2000,7 +2046,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2000
2046
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
2001
2047
|
};
|
|
2002
2048
|
if (!hit) {
|
|
2003
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2049
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
2004
2050
|
if (await this.pagesUnsupported(r)) {
|
|
2005
2051
|
this.log(
|
|
2006
2052
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -2027,7 +2073,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2027
2073
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
2028
2074
|
const r = await this.req(
|
|
2029
2075
|
"PATCH",
|
|
2030
|
-
this.bankUrl(`/
|
|
2076
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
2031
2077
|
patch
|
|
2032
2078
|
);
|
|
2033
2079
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -2081,7 +2127,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2081
2127
|
if (!patch.trigger && !patch.source_query) continue;
|
|
2082
2128
|
const r = await this.req(
|
|
2083
2129
|
"PATCH",
|
|
2084
|
-
this.bankUrl(`/
|
|
2130
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
2085
2131
|
patch
|
|
2086
2132
|
);
|
|
2087
2133
|
if (r.status === 404) continue;
|
|
@@ -2110,7 +2156,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2110
2156
|
let pageId = args.relatesToPageId;
|
|
2111
2157
|
if (!pageId) {
|
|
2112
2158
|
const folderId = await this.ensureFolder("Initiatives");
|
|
2113
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2159
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
2114
2160
|
name: args.title,
|
|
2115
2161
|
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),
|
|
2116
2162
|
parent_id: folderId,
|
|
@@ -2138,7 +2184,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2138
2184
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
2139
2185
|
async ensureFolder(name) {
|
|
2140
2186
|
try {
|
|
2141
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
2187
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
2142
2188
|
const hit = (tree.roots || []).find(
|
|
2143
2189
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
2144
2190
|
);
|
|
@@ -2147,7 +2193,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
2147
2193
|
if (error instanceof AccessDeniedError) throw error;
|
|
2148
2194
|
}
|
|
2149
2195
|
try {
|
|
2150
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
2196
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
2151
2197
|
return (await r.json()).id;
|
|
2152
2198
|
} catch (error) {
|
|
2153
2199
|
if (error instanceof AccessDeniedError) throw error;
|