@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/pi.js
CHANGED
|
@@ -19748,12 +19748,10 @@ function requireBank(access, bank, operation) {
|
|
|
19748
19748
|
}
|
|
19749
19749
|
function classifyOperation(method, suffix) {
|
|
19750
19750
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
19751
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
19752
|
-
suffix
|
|
19753
|
-
))
|
|
19751
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
19754
19752
|
return "read";
|
|
19755
19753
|
if (method === "GET" && suffix === "") return "read";
|
|
19756
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
19754
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
19757
19755
|
suffix
|
|
19758
19756
|
))
|
|
19759
19757
|
return "write";
|
|
@@ -20158,6 +20156,54 @@ var RouterTransport = class {
|
|
|
20158
20156
|
// ../../coding-agents/human-session.ts
|
|
20159
20157
|
import { createHash as createHash2 } from "crypto";
|
|
20160
20158
|
import { createRequire } from "module";
|
|
20159
|
+
|
|
20160
|
+
// src/harness/names.ts
|
|
20161
|
+
var HARNESS_NAMES = [
|
|
20162
|
+
"opencode",
|
|
20163
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
20164
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
20165
|
+
"opencode2",
|
|
20166
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
20167
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
20168
|
+
"kilo",
|
|
20169
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
20170
|
+
"cline-cli",
|
|
20171
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
20172
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
20173
|
+
"dsh",
|
|
20174
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
20175
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
20176
|
+
"pi",
|
|
20177
|
+
"prime-agent",
|
|
20178
|
+
"claude-code",
|
|
20179
|
+
"cursor-cli",
|
|
20180
|
+
"codex",
|
|
20181
|
+
"dcode",
|
|
20182
|
+
"antigravity-cli",
|
|
20183
|
+
"devin-cli",
|
|
20184
|
+
"copilot-cli",
|
|
20185
|
+
"grok-build",
|
|
20186
|
+
"qwen-code",
|
|
20187
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
20188
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
20189
|
+
"factory-droid",
|
|
20190
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
20191
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
20192
|
+
"zcode",
|
|
20193
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
20194
|
+
"traecode",
|
|
20195
|
+
"kimi-code",
|
|
20196
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
20197
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
20198
|
+
"workbuddy",
|
|
20199
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
20200
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
20201
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
20202
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
20203
|
+
"codebuddy"
|
|
20204
|
+
];
|
|
20205
|
+
|
|
20206
|
+
// ../../coding-agents/human-session.ts
|
|
20161
20207
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
20162
20208
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
20163
20209
|
constructor() {
|
|
@@ -20183,14 +20229,14 @@ function humanRouterUrl(value) {
|
|
|
20183
20229
|
if (url2.search || url2.hash) throw new HumanLoginRequiredError();
|
|
20184
20230
|
return canonical2;
|
|
20185
20231
|
}
|
|
20186
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
20232
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
20187
20233
|
try {
|
|
20188
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
20234
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
20189
20235
|
throw new HumanLoginRequiredError();
|
|
20190
20236
|
}
|
|
20191
20237
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
20192
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
20193
|
-
return new NativeEntry(service, credentialRef
|
|
20238
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
20239
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
20194
20240
|
} catch {
|
|
20195
20241
|
throw new HumanLoginRequiredError();
|
|
20196
20242
|
}
|
|
@@ -20208,9 +20254,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
20208
20254
|
routerUrl: session.routerUrl
|
|
20209
20255
|
};
|
|
20210
20256
|
}
|
|
20211
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
20257
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
20212
20258
|
try {
|
|
20213
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
20259
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
20214
20260
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
20215
20261
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
20216
20262
|
} catch {
|
|
@@ -20222,11 +20268,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
20222
20268
|
function harnessTransport(harness) {
|
|
20223
20269
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
20224
20270
|
}
|
|
20225
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
20271
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
20226
20272
|
if (principal.human) {
|
|
20227
20273
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
20228
20274
|
const reference = principal.human.credentialRef;
|
|
20229
|
-
let session = readHumanSession(routerUrl, reference);
|
|
20275
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
20230
20276
|
return new RouterTransport({
|
|
20231
20277
|
routerUrl,
|
|
20232
20278
|
access: principal,
|
|
@@ -20234,7 +20280,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
20234
20280
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
20235
20281
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
20236
20282
|
token: () => {
|
|
20237
|
-
session = readHumanSession(routerUrl, reference);
|
|
20283
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
20238
20284
|
return session.token;
|
|
20239
20285
|
}
|
|
20240
20286
|
});
|
|
@@ -21041,7 +21087,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
21041
21087
|
];
|
|
21042
21088
|
|
|
21043
21089
|
// package.json
|
|
21044
|
-
var version2 = "0.8.
|
|
21090
|
+
var version2 = "0.8.14";
|
|
21045
21091
|
|
|
21046
21092
|
// src/core/util.ts
|
|
21047
21093
|
import { accessSync, constants } from "fs";
|
|
@@ -21574,7 +21620,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21574
21620
|
*/
|
|
21575
21621
|
async tree() {
|
|
21576
21622
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21577
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
21623
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
21578
21624
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
21579
21625
|
if (r.status === 404) return [];
|
|
21580
21626
|
this.knowledgePagesSupported = true;
|
|
@@ -21622,7 +21668,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21622
21668
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21623
21669
|
const r = await this.req(
|
|
21624
21670
|
"GET",
|
|
21625
|
-
this.bankUrl(`/
|
|
21671
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
21626
21672
|
);
|
|
21627
21673
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
21628
21674
|
return shapePage(await r.json());
|
|
@@ -21635,7 +21681,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21635
21681
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
21636
21682
|
const r = await this.req(
|
|
21637
21683
|
"GET",
|
|
21638
|
-
this.bankUrl(`/
|
|
21684
|
+
this.bankUrl(`/pages/search${q}`),
|
|
21639
21685
|
void 0,
|
|
21640
21686
|
[],
|
|
21641
21687
|
opts.timeoutMs
|
|
@@ -21654,7 +21700,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21654
21700
|
/**
|
|
21655
21701
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
21656
21702
|
*
|
|
21657
|
-
* Matched by NAME, not id: `/
|
|
21703
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
21658
21704
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
21659
21705
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
21660
21706
|
*
|
|
@@ -21693,7 +21739,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21693
21739
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
21694
21740
|
};
|
|
21695
21741
|
if (!hit) {
|
|
21696
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21742
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
21697
21743
|
if (await this.pagesUnsupported(r)) {
|
|
21698
21744
|
this.log(
|
|
21699
21745
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -21720,7 +21766,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21720
21766
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
21721
21767
|
const r = await this.req(
|
|
21722
21768
|
"PATCH",
|
|
21723
|
-
this.bankUrl(`/
|
|
21769
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
21724
21770
|
patch
|
|
21725
21771
|
);
|
|
21726
21772
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -21774,7 +21820,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21774
21820
|
if (!patch.trigger && !patch.source_query) continue;
|
|
21775
21821
|
const r = await this.req(
|
|
21776
21822
|
"PATCH",
|
|
21777
|
-
this.bankUrl(`/
|
|
21823
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
21778
21824
|
patch
|
|
21779
21825
|
);
|
|
21780
21826
|
if (r.status === 404) continue;
|
|
@@ -21803,7 +21849,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21803
21849
|
let pageId = args.relatesToPageId;
|
|
21804
21850
|
if (!pageId) {
|
|
21805
21851
|
const folderId = await this.ensureFolder("Initiatives");
|
|
21806
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21852
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
21807
21853
|
name: args.title,
|
|
21808
21854
|
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),
|
|
21809
21855
|
parent_id: folderId,
|
|
@@ -21831,7 +21877,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21831
21877
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
21832
21878
|
async ensureFolder(name) {
|
|
21833
21879
|
try {
|
|
21834
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
21880
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
21835
21881
|
const hit = (tree.roots || []).find(
|
|
21836
21882
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
21837
21883
|
);
|
|
@@ -21840,7 +21886,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21840
21886
|
if (error62 instanceof AccessDeniedError) throw error62;
|
|
21841
21887
|
}
|
|
21842
21888
|
try {
|
|
21843
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21889
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
21844
21890
|
return (await r.json()).id;
|
|
21845
21891
|
} catch (error62) {
|
|
21846
21892
|
if (error62 instanceof AccessDeniedError) throw error62;
|
package/dist/prime-agent.js
CHANGED
|
@@ -19748,12 +19748,10 @@ function requireBank(access, bank, operation) {
|
|
|
19748
19748
|
}
|
|
19749
19749
|
function classifyOperation(method, suffix) {
|
|
19750
19750
|
if (method === "POST" && ["/memories/recall", "/reflect"].includes(suffix)) return "read";
|
|
19751
|
-
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|
|
|
19752
|
-
suffix
|
|
19753
|
-
))
|
|
19751
|
+
if (method === "GET" && /^\/(?:config|stats|tags|graph|documents|operations|memories|mental-models|pages)(?:\/[^/]+)*$/.test(suffix))
|
|
19754
19752
|
return "read";
|
|
19755
19753
|
if (method === "GET" && suffix === "") return "read";
|
|
19756
|
-
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|
|
|
19754
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method) && /^(?:\/(?:config|import|memories|documents|mental-models|pages|consolidate|consolidation)(?:\/[^/]+)*)?$/.test(
|
|
19757
19755
|
suffix
|
|
19758
19756
|
))
|
|
19759
19757
|
return "write";
|
|
@@ -20158,6 +20156,54 @@ var RouterTransport = class {
|
|
|
20158
20156
|
// ../../coding-agents/human-session.ts
|
|
20159
20157
|
import { createHash as createHash2 } from "crypto";
|
|
20160
20158
|
import { createRequire } from "module";
|
|
20159
|
+
|
|
20160
|
+
// src/harness/names.ts
|
|
20161
|
+
var HARNESS_NAMES = [
|
|
20162
|
+
"opencode",
|
|
20163
|
+
// opencode v2 (binary `opencode2`) — a ground-up rewrite of the plugin API, loaded from the
|
|
20164
|
+
// package's root index.js (src/opencode2.ts). Like opencode it has NO hook binary.
|
|
20165
|
+
"opencode2",
|
|
20166
|
+
// Kilo CLI is an opencode fork loaded as a persistent plugin (src/kilo.ts), so like opencode it
|
|
20167
|
+
// has NO hook binary — deliberately absent from HOOK_BINS below.
|
|
20168
|
+
"kilo",
|
|
20169
|
+
// Cline CLI loads dist/cline.js through its native plugin manager; file hooks cannot inject.
|
|
20170
|
+
"cline-cli",
|
|
20171
|
+
// DeepSeek Harness loads dist/dsh.js as a native Cordis plugin (src/dsh.ts). Its Claude Code /
|
|
20172
|
+
// Codex hook bridges are optional packages, so there is no hook binary to install either.
|
|
20173
|
+
"dsh",
|
|
20174
|
+
// pi loads dist/pi.js as an extension (src/pi.ts), and Prime Agent — a fork of pi — loads
|
|
20175
|
+
// dist/prime-agent.js the same way (src/prime-agent.ts). Neither has a hook binary.
|
|
20176
|
+
"pi",
|
|
20177
|
+
"prime-agent",
|
|
20178
|
+
"claude-code",
|
|
20179
|
+
"cursor-cli",
|
|
20180
|
+
"codex",
|
|
20181
|
+
"dcode",
|
|
20182
|
+
"antigravity-cli",
|
|
20183
|
+
"devin-cli",
|
|
20184
|
+
"copilot-cli",
|
|
20185
|
+
"grok-build",
|
|
20186
|
+
"qwen-code",
|
|
20187
|
+
// Factory Droid is a per-prompt HOOK host: the installer wires ~/.factory/hooks.json and the
|
|
20188
|
+
// stdio MCP registration in ~/.factory/mcp.json (see src/installer.ts).
|
|
20189
|
+
"factory-droid",
|
|
20190
|
+
// ZCode is a per-prompt HOOK host too, registered in its own CLI config
|
|
20191
|
+
// (~/.zcode/cli/config.json) under `hooks.events` — never the user's real Claude Code settings.
|
|
20192
|
+
"zcode",
|
|
20193
|
+
// TraeCode is a per-prompt HOOK host registered in ~/.trae-cn/hooks.json (see src/installer.ts).
|
|
20194
|
+
"traecode",
|
|
20195
|
+
"kimi-code",
|
|
20196
|
+
// WorkBuddy is a per-prompt HOOK host too: the installer wires ~/.workbuddy/settings.json and
|
|
20197
|
+
// the stdio MCP registration in ~/.workbuddy/mcp.json (see src/installer.ts).
|
|
20198
|
+
"workbuddy",
|
|
20199
|
+
// CodeBuddy Code is the SAME @genie/agent-cli HOOK host, one product config apart (WorkBuddy only
|
|
20200
|
+
// renames the home folder): the installer wires ~/.codebuddy/settings.json and the stdio MCP
|
|
20201
|
+
// registration in CodeBuddy's priority-chained MCP file (see src/installer.ts). The CLI
|
|
20202
|
+
// writes WorkBuddy's transcript format; the CodeBuddy IDE has a reader of its own.
|
|
20203
|
+
"codebuddy"
|
|
20204
|
+
];
|
|
20205
|
+
|
|
20206
|
+
// ../../coding-agents/human-session.ts
|
|
20161
20207
|
var HUMAN_TOKEN_PATTERN = /^mrh_[0-9a-f]{32}_[0-9a-f]{64}$/;
|
|
20162
20208
|
var HumanLoginRequiredError = class extends AccessDeniedError {
|
|
20163
20209
|
constructor() {
|
|
@@ -20183,14 +20229,14 @@ function humanRouterUrl(value) {
|
|
|
20183
20229
|
if (url2.search || url2.hash) throw new HumanLoginRequiredError();
|
|
20184
20230
|
return canonical2;
|
|
20185
20231
|
}
|
|
20186
|
-
function secureEntry(routerUrl, credentialRef) {
|
|
20232
|
+
function secureEntry(routerUrl, credentialRef, harness) {
|
|
20187
20233
|
try {
|
|
20188
|
-
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef)) {
|
|
20234
|
+
if (!["darwin", "win32", "linux"].includes(process.platform) || !/^[A-Za-z0-9._-]{1,64}$/.test(credentialRef) || !HARNESS_NAMES.includes(harness)) {
|
|
20189
20235
|
throw new HumanLoginRequiredError();
|
|
20190
20236
|
}
|
|
20191
20237
|
const { Entry: NativeEntry } = createRequire(import.meta.url)("@napi-rs/keyring");
|
|
20192
|
-
const service = `hindsight-memory-router:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
20193
|
-
return new NativeEntry(service, credentialRef
|
|
20238
|
+
const service = `hindsight-memory-router:human-v2:${createHash2("sha256").update(humanRouterUrl(routerUrl)).digest("hex")}`;
|
|
20239
|
+
return new NativeEntry(service, `${harness}:${credentialRef}`, { linux: { store: "secret-service" } });
|
|
20194
20240
|
} catch {
|
|
20195
20241
|
throw new HumanLoginRequiredError();
|
|
20196
20242
|
}
|
|
@@ -20208,9 +20254,9 @@ function validateHumanSession(value, routerUrl, allowExpired = false) {
|
|
|
20208
20254
|
routerUrl: session.routerUrl
|
|
20209
20255
|
};
|
|
20210
20256
|
}
|
|
20211
|
-
function readHumanSession(routerUrl, credentialRef) {
|
|
20257
|
+
function readHumanSession(routerUrl, credentialRef, harness) {
|
|
20212
20258
|
try {
|
|
20213
|
-
const password = secureEntry(routerUrl, credentialRef).getPassword();
|
|
20259
|
+
const password = secureEntry(routerUrl, credentialRef, harness).getPassword();
|
|
20214
20260
|
if (!password || password.length > 4096) throw new HumanLoginRequiredError();
|
|
20215
20261
|
return validateHumanSession(JSON.parse(password), routerUrl);
|
|
20216
20262
|
} catch {
|
|
@@ -20222,11 +20268,11 @@ function readHumanSession(routerUrl, credentialRef) {
|
|
|
20222
20268
|
function harnessTransport(harness) {
|
|
20223
20269
|
return transportForConfig(harness, loadManagedConfig(process.env, harness));
|
|
20224
20270
|
}
|
|
20225
|
-
function transportForConfig(harness, { config: config2, principal }) {
|
|
20271
|
+
function transportForConfig(harness, { config: config2, principal, principalId }) {
|
|
20226
20272
|
if (principal.human) {
|
|
20227
20273
|
const routerUrl = humanRouterUrl(config2.routerUrl);
|
|
20228
20274
|
const reference = principal.human.credentialRef;
|
|
20229
|
-
let session = readHumanSession(routerUrl, reference);
|
|
20275
|
+
let session = readHumanSession(routerUrl, reference, principalId);
|
|
20230
20276
|
return new RouterTransport({
|
|
20231
20277
|
routerUrl,
|
|
20232
20278
|
access: principal,
|
|
@@ -20234,7 +20280,7 @@ function transportForConfig(harness, { config: config2, principal }) {
|
|
|
20234
20280
|
tokenPattern: HUMAN_TOKEN_PATTERN,
|
|
20235
20281
|
unauthorizedError: () => new HumanLoginRequiredError(),
|
|
20236
20282
|
token: () => {
|
|
20237
|
-
session = readHumanSession(routerUrl, reference);
|
|
20283
|
+
session = readHumanSession(routerUrl, reference, principalId);
|
|
20238
20284
|
return session.token;
|
|
20239
20285
|
}
|
|
20240
20286
|
});
|
|
@@ -21041,7 +21087,7 @@ var PLUGIN_GOVERNED_BANK_FIELDS = [
|
|
|
21041
21087
|
];
|
|
21042
21088
|
|
|
21043
21089
|
// package.json
|
|
21044
|
-
var version2 = "0.8.
|
|
21090
|
+
var version2 = "0.8.14";
|
|
21045
21091
|
|
|
21046
21092
|
// src/core/util.ts
|
|
21047
21093
|
import { accessSync, constants } from "fs";
|
|
@@ -21574,7 +21620,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21574
21620
|
*/
|
|
21575
21621
|
async tree() {
|
|
21576
21622
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21577
|
-
const r = await this.req("GET", this.bankUrl("/
|
|
21623
|
+
const r = await this.req("GET", this.bankUrl("/pages/tree"));
|
|
21578
21624
|
if (await this.pagesUnsupported(r)) throw new KnowledgePagesUnavailableError();
|
|
21579
21625
|
if (r.status === 404) return [];
|
|
21580
21626
|
this.knowledgePagesSupported = true;
|
|
@@ -21622,7 +21668,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21622
21668
|
if (this.knowledgePagesSupported === false) throw new KnowledgePagesUnavailableError();
|
|
21623
21669
|
const r = await this.req(
|
|
21624
21670
|
"GET",
|
|
21625
|
-
this.bankUrl(`/
|
|
21671
|
+
this.bankUrl(`/pages/${encodeURIComponent(pageId)}`)
|
|
21626
21672
|
);
|
|
21627
21673
|
if (r.status === 404) throw new Error(`knowledge page not found: ${pageId}`);
|
|
21628
21674
|
return shapePage(await r.json());
|
|
@@ -21635,7 +21681,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21635
21681
|
const q = `?q=${encodeURIComponent(query)}&limit=${opts.limit ?? this.pageSearchLimit}`;
|
|
21636
21682
|
const r = await this.req(
|
|
21637
21683
|
"GET",
|
|
21638
|
-
this.bankUrl(`/
|
|
21684
|
+
this.bankUrl(`/pages/search${q}`),
|
|
21639
21685
|
void 0,
|
|
21640
21686
|
[],
|
|
21641
21687
|
opts.timeoutMs
|
|
@@ -21654,7 +21700,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21654
21700
|
/**
|
|
21655
21701
|
* Seed the fixed page taxonomy as knowledge-base pages at the tree root, idempotently.
|
|
21656
21702
|
*
|
|
21657
|
-
* Matched by NAME, not id: `/
|
|
21703
|
+
* Matched by NAME, not id: `/pages` mints its own `kp-…` id, so a stable
|
|
21658
21704
|
* client-chosen id isn't available to match on (unlike the old mental-model path, which keyed
|
|
21659
21705
|
* off a slug). Names are unique per folder server-side, which makes them a sound key.
|
|
21660
21706
|
*
|
|
@@ -21693,7 +21739,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21693
21739
|
trigger: pageTriggerFor(pageTrigger, this.bank, page.name)
|
|
21694
21740
|
};
|
|
21695
21741
|
if (!hit) {
|
|
21696
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21742
|
+
const r = await this.req("POST", this.bankUrl("/pages"), body, [409]);
|
|
21697
21743
|
if (await this.pagesUnsupported(r)) {
|
|
21698
21744
|
this.log(
|
|
21699
21745
|
`[bank] knowledge pages unavailable on ${this.apiUrl}; continuing without pages`
|
|
@@ -21720,7 +21766,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21720
21766
|
if (triggerDrift) patch.trigger = pageTriggerPatch(body.trigger);
|
|
21721
21767
|
const r = await this.req(
|
|
21722
21768
|
"PATCH",
|
|
21723
|
-
this.bankUrl(`/
|
|
21769
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(hit.id)}`),
|
|
21724
21770
|
patch
|
|
21725
21771
|
);
|
|
21726
21772
|
if (await this.pagesUnsupported(r)) {
|
|
@@ -21774,7 +21820,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21774
21820
|
if (!patch.trigger && !patch.source_query) continue;
|
|
21775
21821
|
const r = await this.req(
|
|
21776
21822
|
"PATCH",
|
|
21777
|
-
this.bankUrl(`/
|
|
21823
|
+
this.bankUrl(`/pages/nodes/${encodeURIComponent(page.id)}`),
|
|
21778
21824
|
patch
|
|
21779
21825
|
);
|
|
21780
21826
|
if (r.status === 404) continue;
|
|
@@ -21803,7 +21849,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21803
21849
|
let pageId = args.relatesToPageId;
|
|
21804
21850
|
if (!pageId) {
|
|
21805
21851
|
const folderId = await this.ensureFolder("Initiatives");
|
|
21806
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21852
|
+
const r = await this.req("POST", this.bankUrl("/pages"), {
|
|
21807
21853
|
name: args.title,
|
|
21808
21854
|
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),
|
|
21809
21855
|
parent_id: folderId,
|
|
@@ -21831,7 +21877,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21831
21877
|
/** Find a root folder by name (case-insensitive) or create it; returns its id. Fail-open to undefined. */
|
|
21832
21878
|
async ensureFolder(name) {
|
|
21833
21879
|
try {
|
|
21834
|
-
const tree = await (await this.req("GET", this.bankUrl("/
|
|
21880
|
+
const tree = await (await this.req("GET", this.bankUrl("/pages/tree"))).json();
|
|
21835
21881
|
const hit = (tree.roots || []).find(
|
|
21836
21882
|
(n) => n.kind === "folder" && (n.name || "").toLowerCase() === name.toLowerCase()
|
|
21837
21883
|
);
|
|
@@ -21840,7 +21886,7 @@ var HindsightClient = class _HindsightClient {
|
|
|
21840
21886
|
if (error62 instanceof AccessDeniedError) throw error62;
|
|
21841
21887
|
}
|
|
21842
21888
|
try {
|
|
21843
|
-
const r = await this.req("POST", this.bankUrl("/
|
|
21889
|
+
const r = await this.req("POST", this.bankUrl("/pages/folders"), { name });
|
|
21844
21890
|
return (await r.json()).id;
|
|
21845
21891
|
} catch (error62) {
|
|
21846
21892
|
if (error62 instanceof AccessDeniedError) throw error62;
|
package/dist/qwen-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;
|