brainjar 0.3.677 → 0.3.683
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/brainjar.js +311 -87
- package/package.json +1 -1
package/brainjar.js
CHANGED
|
@@ -107,7 +107,7 @@ var CLI_VERSION, CACHE, DAY;
|
|
|
107
107
|
var init_version_check = __esm({
|
|
108
108
|
"packages/cli/src/version-check.ts"() {
|
|
109
109
|
"use strict";
|
|
110
|
-
CLI_VERSION = "0.3.
|
|
110
|
+
CLI_VERSION = "0.3.683";
|
|
111
111
|
CACHE = path.join(os.homedir(), ".brainjar", "version-check.json");
|
|
112
112
|
DAY = 864e5;
|
|
113
113
|
}
|
|
@@ -238,8 +238,8 @@ var init_github = __esm({
|
|
|
238
238
|
if (this.opts.token) h.Authorization = `Bearer ${this.opts.token}`;
|
|
239
239
|
return h;
|
|
240
240
|
}
|
|
241
|
-
async *paginate(
|
|
242
|
-
let url = this.buildUrl(
|
|
241
|
+
async *paginate(path15, params) {
|
|
242
|
+
let url = this.buildUrl(path15, params);
|
|
243
243
|
while (url) {
|
|
244
244
|
const res = await this.fetchImpl(url, { headers: this.headers() });
|
|
245
245
|
if (!res.ok) {
|
|
@@ -250,9 +250,9 @@ var init_github = __esm({
|
|
|
250
250
|
url = parseNextLink(res.headers.get("link"));
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
-
buildUrl(
|
|
253
|
+
buildUrl(path15, params) {
|
|
254
254
|
const url = new URL(
|
|
255
|
-
`${this.baseUrl}/repos/${this.opts.owner}/${this.opts.repo}${
|
|
255
|
+
`${this.baseUrl}/repos/${this.opts.owner}/${this.opts.repo}${path15}`
|
|
256
256
|
);
|
|
257
257
|
url.searchParams.set("per_page", String(this.perPage));
|
|
258
258
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -3735,7 +3735,7 @@ var require_split2 = __commonJS({
|
|
|
3735
3735
|
var require_helper = __commonJS({
|
|
3736
3736
|
"node_modules/pgpass/lib/helper.js"(exports, module) {
|
|
3737
3737
|
"use strict";
|
|
3738
|
-
var
|
|
3738
|
+
var path15 = __require("path");
|
|
3739
3739
|
var Stream2 = __require("stream").Stream;
|
|
3740
3740
|
var split = require_split2();
|
|
3741
3741
|
var util = __require("util");
|
|
@@ -3774,7 +3774,7 @@ var require_helper = __commonJS({
|
|
|
3774
3774
|
};
|
|
3775
3775
|
module.exports.getFileName = function(rawEnv) {
|
|
3776
3776
|
var env = rawEnv || process.env;
|
|
3777
|
-
var file = env.PGPASSFILE || (isWin ?
|
|
3777
|
+
var file = env.PGPASSFILE || (isWin ? path15.join(env.APPDATA || "./", "postgresql", "pgpass.conf") : path15.join(env.HOME || "./", ".pgpass"));
|
|
3778
3778
|
return file;
|
|
3779
3779
|
};
|
|
3780
3780
|
module.exports.usePgPass = function(stats, fname) {
|
|
@@ -3906,7 +3906,7 @@ var require_helper = __commonJS({
|
|
|
3906
3906
|
var require_lib = __commonJS({
|
|
3907
3907
|
"node_modules/pgpass/lib/index.js"(exports, module) {
|
|
3908
3908
|
"use strict";
|
|
3909
|
-
var
|
|
3909
|
+
var path15 = __require("path");
|
|
3910
3910
|
var fs = __require("fs");
|
|
3911
3911
|
var helper = require_helper();
|
|
3912
3912
|
module.exports = function(connInfo, cb) {
|
|
@@ -8850,12 +8850,12 @@ var init_path = __esm({
|
|
|
8850
8850
|
"node_modules/@anthropic-ai/sdk/internal/utils/path.mjs"() {
|
|
8851
8851
|
init_error();
|
|
8852
8852
|
EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
8853
|
-
createPathTagFunction = (pathEncoder = encodeURIPath) => function
|
|
8853
|
+
createPathTagFunction = (pathEncoder = encodeURIPath) => function path15(statics, ...params) {
|
|
8854
8854
|
if (statics.length === 1)
|
|
8855
8855
|
return statics[0];
|
|
8856
8856
|
let postPath = false;
|
|
8857
8857
|
const invalidSegments = [];
|
|
8858
|
-
const
|
|
8858
|
+
const path16 = statics.reduce((previousValue, currentValue, index) => {
|
|
8859
8859
|
if (/[?#]/.test(currentValue)) {
|
|
8860
8860
|
postPath = true;
|
|
8861
8861
|
}
|
|
@@ -8872,7 +8872,7 @@ var init_path = __esm({
|
|
|
8872
8872
|
}
|
|
8873
8873
|
return previousValue + currentValue + (index === params.length ? "" : encoded);
|
|
8874
8874
|
}, "");
|
|
8875
|
-
const pathOnly =
|
|
8875
|
+
const pathOnly = path16.split(/[?#]/, 1)[0];
|
|
8876
8876
|
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
|
8877
8877
|
let match;
|
|
8878
8878
|
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
|
@@ -8893,10 +8893,10 @@ var init_path = __esm({
|
|
|
8893
8893
|
}, "");
|
|
8894
8894
|
throw new AnthropicError(`Path parameters result in path with invalid segments:
|
|
8895
8895
|
${invalidSegments.map((e) => e.error).join("\n")}
|
|
8896
|
-
${
|
|
8896
|
+
${path16}
|
|
8897
8897
|
${underline}`);
|
|
8898
8898
|
}
|
|
8899
|
-
return
|
|
8899
|
+
return path16;
|
|
8900
8900
|
};
|
|
8901
8901
|
path3 = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
|
8902
8902
|
}
|
|
@@ -11882,9 +11882,9 @@ var init_client = __esm({
|
|
|
11882
11882
|
makeStatusError(status, error, message, headers) {
|
|
11883
11883
|
return APIError.generate(status, error, message, headers);
|
|
11884
11884
|
}
|
|
11885
|
-
buildURL(
|
|
11885
|
+
buildURL(path15, query, defaultBaseURL) {
|
|
11886
11886
|
const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
11887
|
-
const url = isAbsoluteURL(
|
|
11887
|
+
const url = isAbsoluteURL(path15) ? new URL(path15) : new URL(baseURL + (baseURL.endsWith("/") && path15.startsWith("/") ? path15.slice(1) : path15));
|
|
11888
11888
|
const defaultQuery = this.defaultQuery();
|
|
11889
11889
|
if (!isEmptyObj(defaultQuery)) {
|
|
11890
11890
|
query = { ...defaultQuery, ...query };
|
|
@@ -11915,24 +11915,24 @@ var init_client = __esm({
|
|
|
11915
11915
|
*/
|
|
11916
11916
|
async prepareRequest(request, { url, options }) {
|
|
11917
11917
|
}
|
|
11918
|
-
get(
|
|
11919
|
-
return this.methodRequest("get",
|
|
11918
|
+
get(path15, opts) {
|
|
11919
|
+
return this.methodRequest("get", path15, opts);
|
|
11920
11920
|
}
|
|
11921
|
-
post(
|
|
11922
|
-
return this.methodRequest("post",
|
|
11921
|
+
post(path15, opts) {
|
|
11922
|
+
return this.methodRequest("post", path15, opts);
|
|
11923
11923
|
}
|
|
11924
|
-
patch(
|
|
11925
|
-
return this.methodRequest("patch",
|
|
11924
|
+
patch(path15, opts) {
|
|
11925
|
+
return this.methodRequest("patch", path15, opts);
|
|
11926
11926
|
}
|
|
11927
|
-
put(
|
|
11928
|
-
return this.methodRequest("put",
|
|
11927
|
+
put(path15, opts) {
|
|
11928
|
+
return this.methodRequest("put", path15, opts);
|
|
11929
11929
|
}
|
|
11930
|
-
delete(
|
|
11931
|
-
return this.methodRequest("delete",
|
|
11930
|
+
delete(path15, opts) {
|
|
11931
|
+
return this.methodRequest("delete", path15, opts);
|
|
11932
11932
|
}
|
|
11933
|
-
methodRequest(method,
|
|
11933
|
+
methodRequest(method, path15, opts) {
|
|
11934
11934
|
return this.request(Promise.resolve(opts).then((opts2) => {
|
|
11935
|
-
return { method, path:
|
|
11935
|
+
return { method, path: path15, ...opts2 };
|
|
11936
11936
|
}));
|
|
11937
11937
|
}
|
|
11938
11938
|
request(options, remainingRetries = null) {
|
|
@@ -12036,8 +12036,8 @@ var init_client = __esm({
|
|
|
12036
12036
|
}));
|
|
12037
12037
|
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
|
12038
12038
|
}
|
|
12039
|
-
getAPIList(
|
|
12040
|
-
return this.requestAPIList(Page2, { method: "get", path:
|
|
12039
|
+
getAPIList(path15, Page2, opts) {
|
|
12040
|
+
return this.requestAPIList(Page2, { method: "get", path: path15, ...opts });
|
|
12041
12041
|
}
|
|
12042
12042
|
requestAPIList(Page2, options) {
|
|
12043
12043
|
const request = this.makeRequest(options, null, void 0);
|
|
@@ -12124,8 +12124,8 @@ var init_client = __esm({
|
|
|
12124
12124
|
}
|
|
12125
12125
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
12126
12126
|
const options = { ...inputOptions };
|
|
12127
|
-
const { method, path:
|
|
12128
|
-
const url = this.buildURL(
|
|
12127
|
+
const { method, path: path15, query, defaultBaseURL } = options;
|
|
12128
|
+
const url = this.buildURL(path15, query, defaultBaseURL);
|
|
12129
12129
|
if ("timeout" in options)
|
|
12130
12130
|
validatePositiveInteger("timeout", options.timeout);
|
|
12131
12131
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -13050,24 +13050,90 @@ var init_codex_hooks = __esm({
|
|
|
13050
13050
|
}
|
|
13051
13051
|
});
|
|
13052
13052
|
|
|
13053
|
+
// packages/ingest/src/copilot-hooks.ts
|
|
13054
|
+
import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4, rm as rm2 } from "node:fs/promises";
|
|
13055
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "node:fs";
|
|
13056
|
+
import path8 from "node:path";
|
|
13057
|
+
function render() {
|
|
13058
|
+
const hooks = {
|
|
13059
|
+
sessionStart: [
|
|
13060
|
+
{
|
|
13061
|
+
type: "command",
|
|
13062
|
+
command: `${captureHookCommand("constraints")} --copilot`,
|
|
13063
|
+
timeoutSec: 15
|
|
13064
|
+
}
|
|
13065
|
+
]
|
|
13066
|
+
};
|
|
13067
|
+
for (const { event, timeoutSec } of EVENTS3) {
|
|
13068
|
+
hooks[event] = [
|
|
13069
|
+
{
|
|
13070
|
+
type: "command",
|
|
13071
|
+
command: `${captureHookCommand("hook copilot")} --event ${event}`,
|
|
13072
|
+
timeoutSec
|
|
13073
|
+
}
|
|
13074
|
+
];
|
|
13075
|
+
}
|
|
13076
|
+
return JSON.stringify({ version: 1, hooks }, null, 2) + "\n";
|
|
13077
|
+
}
|
|
13078
|
+
async function installCopilotHooks(root) {
|
|
13079
|
+
const file = hooksFile3(root);
|
|
13080
|
+
const next = render();
|
|
13081
|
+
if (existsSync5(file) && await readFile5(file, "utf8") === next) return false;
|
|
13082
|
+
await mkdir4(path8.dirname(file), { recursive: true });
|
|
13083
|
+
await writeFile4(file, next, "utf8");
|
|
13084
|
+
return true;
|
|
13085
|
+
}
|
|
13086
|
+
function copilotHooksInstalled(root) {
|
|
13087
|
+
const file = hooksFile3(root);
|
|
13088
|
+
if (!existsSync5(file)) return false;
|
|
13089
|
+
try {
|
|
13090
|
+
return readFileSync6(file, "utf8").includes(PROBE2);
|
|
13091
|
+
} catch {
|
|
13092
|
+
return false;
|
|
13093
|
+
}
|
|
13094
|
+
}
|
|
13095
|
+
async function removeCopilotHooks(root) {
|
|
13096
|
+
const file = hooksFile3(root);
|
|
13097
|
+
if (!copilotHooksInstalled(root)) return false;
|
|
13098
|
+
await rm2(file, { force: true });
|
|
13099
|
+
return true;
|
|
13100
|
+
}
|
|
13101
|
+
var PROBE2, EVENTS3, hooksFile3;
|
|
13102
|
+
var init_copilot_hooks = __esm({
|
|
13103
|
+
"packages/ingest/src/copilot-hooks.ts"() {
|
|
13104
|
+
"use strict";
|
|
13105
|
+
init_bootstrap();
|
|
13106
|
+
PROBE2 = "hook copilot";
|
|
13107
|
+
EVENTS3 = [
|
|
13108
|
+
{ event: "userPromptSubmitted", timeoutSec: 30 },
|
|
13109
|
+
{ event: "postToolUse", timeoutSec: 30 },
|
|
13110
|
+
{ event: "postToolUseFailure", timeoutSec: 30 },
|
|
13111
|
+
{ event: "agentStop", timeoutSec: 120 },
|
|
13112
|
+
{ event: "sessionEnd", timeoutSec: 120 }
|
|
13113
|
+
];
|
|
13114
|
+
hooksFile3 = (root) => path8.join(root, ".github", "hooks", "brainjar.json");
|
|
13115
|
+
}
|
|
13116
|
+
});
|
|
13117
|
+
|
|
13053
13118
|
// packages/ingest/src/tools.ts
|
|
13054
|
-
import { existsSync as
|
|
13119
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
13055
13120
|
import os4 from "node:os";
|
|
13056
|
-
import
|
|
13121
|
+
import path9 from "node:path";
|
|
13057
13122
|
function detectedTools(root) {
|
|
13058
13123
|
return CAPTURE_TOOLS.filter((t) => t.detect(root));
|
|
13059
13124
|
}
|
|
13060
|
-
var claudeCode, cursor, codex, CAPTURE_TOOLS;
|
|
13125
|
+
var claudeCode, cursor, codex, copilot, CAPTURE_TOOLS;
|
|
13061
13126
|
var init_tools = __esm({
|
|
13062
13127
|
"packages/ingest/src/tools.ts"() {
|
|
13063
13128
|
"use strict";
|
|
13064
13129
|
init_bootstrap();
|
|
13065
13130
|
init_cursor_hooks();
|
|
13066
13131
|
init_codex_hooks();
|
|
13132
|
+
init_copilot_hooks();
|
|
13067
13133
|
claudeCode = {
|
|
13068
13134
|
id: "claude-code",
|
|
13069
13135
|
name: "Claude Code",
|
|
13070
|
-
detect: (root) =>
|
|
13136
|
+
detect: (root) => existsSync6(path9.join(os4.homedir(), ".claude")) || existsSync6(path9.join(root, ".claude")),
|
|
13071
13137
|
install: installCaptureHook,
|
|
13072
13138
|
installed: captureHookInstalled,
|
|
13073
13139
|
remove: removeCaptureHook
|
|
@@ -13075,7 +13141,7 @@ var init_tools = __esm({
|
|
|
13075
13141
|
cursor = {
|
|
13076
13142
|
id: "cursor",
|
|
13077
13143
|
name: "Cursor",
|
|
13078
|
-
detect: (root) =>
|
|
13144
|
+
detect: (root) => existsSync6(path9.join(os4.homedir(), ".cursor")) || existsSync6(path9.join(root, ".cursor")),
|
|
13079
13145
|
install: installCursorHooks,
|
|
13080
13146
|
installed: cursorHooksInstalled,
|
|
13081
13147
|
remove: removeCursorHooks
|
|
@@ -13083,15 +13149,24 @@ var init_tools = __esm({
|
|
|
13083
13149
|
codex = {
|
|
13084
13150
|
id: "codex",
|
|
13085
13151
|
name: "Codex",
|
|
13086
|
-
detect: (root) =>
|
|
13152
|
+
detect: (root) => existsSync6(path9.join(os4.homedir(), ".codex")) || existsSync6(path9.join(root, ".codex")),
|
|
13087
13153
|
install: installCodexHooks,
|
|
13088
13154
|
installed: codexHooksInstalled,
|
|
13089
13155
|
remove: removeCodexHooks
|
|
13090
13156
|
};
|
|
13157
|
+
copilot = {
|
|
13158
|
+
id: "copilot",
|
|
13159
|
+
name: "GitHub Copilot",
|
|
13160
|
+
detect: (root) => existsSync6(path9.join(os4.homedir(), ".copilot")) || existsSync6(path9.join(root, ".github", "hooks")),
|
|
13161
|
+
install: installCopilotHooks,
|
|
13162
|
+
installed: copilotHooksInstalled,
|
|
13163
|
+
remove: removeCopilotHooks
|
|
13164
|
+
};
|
|
13091
13165
|
CAPTURE_TOOLS = [
|
|
13092
13166
|
claudeCode,
|
|
13093
13167
|
cursor,
|
|
13094
|
-
codex
|
|
13168
|
+
codex,
|
|
13169
|
+
copilot
|
|
13095
13170
|
];
|
|
13096
13171
|
}
|
|
13097
13172
|
});
|
|
@@ -13568,8 +13643,8 @@ var init_doku_model = __esm({
|
|
|
13568
13643
|
|
|
13569
13644
|
// packages/ingest/src/doku.ts
|
|
13570
13645
|
import { createHash as createHash2 } from "node:crypto";
|
|
13571
|
-
import { mkdir as
|
|
13572
|
-
import
|
|
13646
|
+
import { mkdir as mkdir5, readFile as readFile6, rm as rm3, stat, writeFile as writeFile5 } from "node:fs/promises";
|
|
13647
|
+
import path10 from "node:path";
|
|
13573
13648
|
function bodyLocations(o) {
|
|
13574
13649
|
return Array.isArray(o.body.location) ? o.body.location.map(String) : [];
|
|
13575
13650
|
}
|
|
@@ -13635,7 +13710,7 @@ async function loadDokuData(brainId, root) {
|
|
|
13635
13710
|
if (root) {
|
|
13636
13711
|
try {
|
|
13637
13712
|
const pkg = JSON.parse(
|
|
13638
|
-
await
|
|
13713
|
+
await readFile6(path10.join(root, "package.json"), "utf8")
|
|
13639
13714
|
);
|
|
13640
13715
|
description = pkg.description ?? null;
|
|
13641
13716
|
scripts = pkg.scripts ?? null;
|
|
@@ -14218,11 +14293,11 @@ function dokuFilePath(kind, slug) {
|
|
|
14218
14293
|
return `${DOKU_DIR}/${slug}.md`;
|
|
14219
14294
|
}
|
|
14220
14295
|
async function writeDokuTree(root, files) {
|
|
14221
|
-
const dir =
|
|
14222
|
-
const manifestPath =
|
|
14296
|
+
const dir = path10.join(root, DOKU_DIR);
|
|
14297
|
+
const manifestPath = path10.join(dir, MANIFEST);
|
|
14223
14298
|
let old = { files: {} };
|
|
14224
14299
|
try {
|
|
14225
|
-
old = JSON.parse(await
|
|
14300
|
+
old = JSON.parse(await readFile6(manifestPath, "utf8"));
|
|
14226
14301
|
if (typeof old.files !== "object" || old.files === null)
|
|
14227
14302
|
old = { files: {} };
|
|
14228
14303
|
} catch {
|
|
@@ -14232,21 +14307,21 @@ async function writeDokuTree(root, files) {
|
|
|
14232
14307
|
for (const file of files) {
|
|
14233
14308
|
const hash = sha1(file.markdown);
|
|
14234
14309
|
next[file.relPath] = { hash };
|
|
14235
|
-
const abs =
|
|
14310
|
+
const abs = path10.join(root, file.relPath);
|
|
14236
14311
|
if (old.files[file.relPath]?.hash === hash && await exists(abs)) continue;
|
|
14237
|
-
await
|
|
14238
|
-
await
|
|
14312
|
+
await mkdir5(path10.dirname(abs), { recursive: true });
|
|
14313
|
+
await writeFile5(abs, file.markdown, "utf8");
|
|
14239
14314
|
written++;
|
|
14240
14315
|
}
|
|
14241
14316
|
let deleted = 0;
|
|
14242
14317
|
for (const rel of Object.keys(old.files)) {
|
|
14243
14318
|
if (next[rel]) continue;
|
|
14244
14319
|
if (rel !== DOKU_FILENAME && !rel.startsWith(`${DOKU_DIR}/`)) continue;
|
|
14245
|
-
await
|
|
14320
|
+
await rm3(path10.join(root, rel), { force: true });
|
|
14246
14321
|
deleted++;
|
|
14247
14322
|
}
|
|
14248
|
-
await
|
|
14249
|
-
await
|
|
14323
|
+
await mkdir5(dir, { recursive: true });
|
|
14324
|
+
await writeFile5(
|
|
14250
14325
|
manifestPath,
|
|
14251
14326
|
JSON.stringify({ files: next }, null, 2),
|
|
14252
14327
|
"utf8"
|
|
@@ -14399,8 +14474,8 @@ var init_ponytail_brief = __esm({
|
|
|
14399
14474
|
});
|
|
14400
14475
|
|
|
14401
14476
|
// packages/ingest/src/ponytail-debt.ts
|
|
14402
|
-
function isDebtScannable(
|
|
14403
|
-
return !/\.(md|mdx|markdown|txt|jsonl|log|lock)$/i.test(
|
|
14477
|
+
function isDebtScannable(path15) {
|
|
14478
|
+
return !/\.(md|mdx|markdown|txt|jsonl|log|lock)$/i.test(path15);
|
|
14404
14479
|
}
|
|
14405
14480
|
function scanPonytailComments(files) {
|
|
14406
14481
|
const out = [];
|
|
@@ -14566,6 +14641,7 @@ var init_src3 = __esm({
|
|
|
14566
14641
|
init_tools();
|
|
14567
14642
|
init_cursor_hooks();
|
|
14568
14643
|
init_codex_hooks();
|
|
14644
|
+
init_copilot_hooks();
|
|
14569
14645
|
init_commit_links();
|
|
14570
14646
|
init_tool_failure();
|
|
14571
14647
|
init_bootstrap();
|
|
@@ -14651,8 +14727,8 @@ __export(brief_exports, {
|
|
|
14651
14727
|
refreshBrief: () => refreshBrief,
|
|
14652
14728
|
upsertBriefBlock: () => upsertBriefBlock
|
|
14653
14729
|
});
|
|
14654
|
-
import { readFileSync as
|
|
14655
|
-
import
|
|
14730
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync7 } from "node:fs";
|
|
14731
|
+
import path11 from "node:path";
|
|
14656
14732
|
function claudeMdWithImport(existing) {
|
|
14657
14733
|
let text = existing;
|
|
14658
14734
|
const start = text.indexOf(BRIEF_START);
|
|
@@ -14706,12 +14782,12 @@ async function refreshBrief(cwd) {
|
|
|
14706
14782
|
`/capture/brief?brain=${project.brainId}`
|
|
14707
14783
|
);
|
|
14708
14784
|
if (!text) return "skipped";
|
|
14709
|
-
const file =
|
|
14710
|
-
const existing =
|
|
14785
|
+
const file = path11.join(root, BRIEF_FILE);
|
|
14786
|
+
const existing = existsSync7(file) ? readFileSync7(file, "utf8") : "";
|
|
14711
14787
|
const next = upsertBriefBlock(existing, text);
|
|
14712
14788
|
if (next !== null) writeFileSync3(file, next);
|
|
14713
|
-
const claudeFile =
|
|
14714
|
-
const claude =
|
|
14789
|
+
const claudeFile = path11.join(root, "CLAUDE.md");
|
|
14790
|
+
const claude = existsSync7(claudeFile) ? readFileSync7(claudeFile, "utf8") : "";
|
|
14715
14791
|
const claudeNext = claudeMdWithImport(claude);
|
|
14716
14792
|
if (claudeNext !== null) writeFileSync3(claudeFile, claudeNext);
|
|
14717
14793
|
return next !== null || claudeNext !== null ? "updated" : "unchanged";
|
|
@@ -14748,9 +14824,9 @@ __export(debt_exports, {
|
|
|
14748
14824
|
scanDebtInRepo: () => scanDebtInRepo
|
|
14749
14825
|
});
|
|
14750
14826
|
import { execFile as execFile3 } from "node:child_process";
|
|
14751
|
-
import { readFile as
|
|
14827
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
14752
14828
|
import { promisify as promisify3 } from "node:util";
|
|
14753
|
-
import
|
|
14829
|
+
import path12 from "node:path";
|
|
14754
14830
|
async function scanDebtInRepo(root) {
|
|
14755
14831
|
const { stdout } = await run3("git", ["-C", root, "ls-files"], {
|
|
14756
14832
|
maxBuffer: 16 * 1048576
|
|
@@ -14760,7 +14836,7 @@ async function scanDebtInRepo(root) {
|
|
|
14760
14836
|
const p = rel.trim();
|
|
14761
14837
|
if (!p || !isDebtScannable(p)) continue;
|
|
14762
14838
|
try {
|
|
14763
|
-
const buf = await
|
|
14839
|
+
const buf = await readFile7(path12.join(root, p));
|
|
14764
14840
|
if (buf.length > 512 * 1024 || buf.includes(0)) continue;
|
|
14765
14841
|
files.push({ path: p, content: buf.toString("utf8") });
|
|
14766
14842
|
} catch {
|
|
@@ -15186,11 +15262,11 @@ var init_codex = __esm({
|
|
|
15186
15262
|
...commits.length ? { commits } : {}
|
|
15187
15263
|
});
|
|
15188
15264
|
files.forEach(
|
|
15189
|
-
(
|
|
15265
|
+
(path15, i) => events.push({
|
|
15190
15266
|
...base,
|
|
15191
15267
|
event_id: `file:${id}:${i}`,
|
|
15192
15268
|
kind: "file_changed",
|
|
15193
|
-
path:
|
|
15269
|
+
path: path15
|
|
15194
15270
|
})
|
|
15195
15271
|
);
|
|
15196
15272
|
}
|
|
@@ -15218,6 +15294,148 @@ var init_codex = __esm({
|
|
|
15218
15294
|
}
|
|
15219
15295
|
});
|
|
15220
15296
|
|
|
15297
|
+
// packages/cli/src/adapters/copilot.ts
|
|
15298
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
15299
|
+
function targetOf3(args) {
|
|
15300
|
+
if (!args || typeof args !== "object") return "";
|
|
15301
|
+
const a = args;
|
|
15302
|
+
for (const k of ["command", "path", "file_path", "filePath", "file"]) {
|
|
15303
|
+
if (typeof a[k] === "string") return a[k];
|
|
15304
|
+
}
|
|
15305
|
+
return "";
|
|
15306
|
+
}
|
|
15307
|
+
function commitShas4(text) {
|
|
15308
|
+
const s = typeof text === "string" ? text : JSON.stringify(text ?? "");
|
|
15309
|
+
const out = /* @__PURE__ */ new Set();
|
|
15310
|
+
for (const m of s.matchAll(/\[[^\]\n]* ([0-9a-f]{7,40})\]/g)) {
|
|
15311
|
+
out.add(m[1].toLowerCase());
|
|
15312
|
+
}
|
|
15313
|
+
return [...out];
|
|
15314
|
+
}
|
|
15315
|
+
function stamp(ts, now) {
|
|
15316
|
+
if (typeof ts === "number" && Number.isFinite(ts))
|
|
15317
|
+
return new Date(ts).toISOString();
|
|
15318
|
+
if (typeof ts === "string" && !Number.isNaN(Date.parse(ts)))
|
|
15319
|
+
return new Date(ts).toISOString();
|
|
15320
|
+
return now;
|
|
15321
|
+
}
|
|
15322
|
+
function copilotContextEnvelope(text) {
|
|
15323
|
+
return JSON.stringify({ additionalContext: text });
|
|
15324
|
+
}
|
|
15325
|
+
var EDIT_TOOLS2, short5, EVENT_ALIASES, copilot2;
|
|
15326
|
+
var init_copilot = __esm({
|
|
15327
|
+
"packages/cli/src/adapters/copilot.ts"() {
|
|
15328
|
+
"use strict";
|
|
15329
|
+
init_src();
|
|
15330
|
+
EDIT_TOOLS2 = /* @__PURE__ */ new Set(["edit", "create"]);
|
|
15331
|
+
short5 = (s) => createHash6("sha256").update(s).digest("hex").slice(0, 16);
|
|
15332
|
+
EVENT_ALIASES = {
|
|
15333
|
+
SessionStart: "sessionStart",
|
|
15334
|
+
SessionEnd: "sessionEnd",
|
|
15335
|
+
UserPromptSubmit: "userPromptSubmitted",
|
|
15336
|
+
PostToolUse: "postToolUse",
|
|
15337
|
+
PostToolUseFailure: "postToolUseFailure",
|
|
15338
|
+
Stop: "agentStop"
|
|
15339
|
+
};
|
|
15340
|
+
copilot2 = {
|
|
15341
|
+
id: "copilot",
|
|
15342
|
+
map(payload, now, opts) {
|
|
15343
|
+
const p = payload;
|
|
15344
|
+
const sessionId = p?.sessionId ?? p?.session_id;
|
|
15345
|
+
if (!p || typeof p !== "object" || typeof sessionId !== "string") {
|
|
15346
|
+
return null;
|
|
15347
|
+
}
|
|
15348
|
+
const raw = opts?.event ?? p.hook_event_name ?? "";
|
|
15349
|
+
const event = EVENT_ALIASES[raw] ?? raw;
|
|
15350
|
+
const at = stamp(p.timestamp, now);
|
|
15351
|
+
const base = {
|
|
15352
|
+
v: CAPTURE_EVENT_VERSION,
|
|
15353
|
+
tool: "copilot",
|
|
15354
|
+
session_id: sessionId,
|
|
15355
|
+
at,
|
|
15356
|
+
cwd: p.cwd ?? null
|
|
15357
|
+
};
|
|
15358
|
+
const events = [];
|
|
15359
|
+
let flush = false;
|
|
15360
|
+
let end = false;
|
|
15361
|
+
const toolName = p.toolName ?? p.tool_name ?? "tool";
|
|
15362
|
+
const args = p.toolArgs ?? p.tool_args;
|
|
15363
|
+
switch (event) {
|
|
15364
|
+
case "sessionStart":
|
|
15365
|
+
events.push({
|
|
15366
|
+
...base,
|
|
15367
|
+
event_id: `start:${sessionId}`,
|
|
15368
|
+
kind: "session_started"
|
|
15369
|
+
});
|
|
15370
|
+
break;
|
|
15371
|
+
case "userPromptSubmitted":
|
|
15372
|
+
if (typeof p.prompt === "string" && p.prompt.trim()) {
|
|
15373
|
+
events.push({
|
|
15374
|
+
...base,
|
|
15375
|
+
event_id: `prompt:${short5(at + p.prompt)}`,
|
|
15376
|
+
kind: "prompt",
|
|
15377
|
+
text: p.prompt
|
|
15378
|
+
});
|
|
15379
|
+
}
|
|
15380
|
+
break;
|
|
15381
|
+
case "postToolUse": {
|
|
15382
|
+
const target = targetOf3(args);
|
|
15383
|
+
const id = short5(at + toolName + target);
|
|
15384
|
+
const commits = commitShas4(p.toolResult?.textResultForLlm);
|
|
15385
|
+
events.push({
|
|
15386
|
+
...base,
|
|
15387
|
+
event_id: `use:${id}`,
|
|
15388
|
+
kind: "tool_used",
|
|
15389
|
+
tool_name: toolName,
|
|
15390
|
+
...target ? { target } : {},
|
|
15391
|
+
...commits.length ? { commits } : {}
|
|
15392
|
+
});
|
|
15393
|
+
if (EDIT_TOOLS2.has(toolName) && target) {
|
|
15394
|
+
events.push({
|
|
15395
|
+
...base,
|
|
15396
|
+
event_id: `file:${id}`,
|
|
15397
|
+
kind: "file_changed",
|
|
15398
|
+
path: target
|
|
15399
|
+
});
|
|
15400
|
+
}
|
|
15401
|
+
break;
|
|
15402
|
+
}
|
|
15403
|
+
case "postToolUseFailure": {
|
|
15404
|
+
const error = typeof p.error === "string" ? p.error : p.error && typeof p.error === "object" ? String(p.error.message ?? "") : "";
|
|
15405
|
+
if (!error.trim()) break;
|
|
15406
|
+
const target = targetOf3(args);
|
|
15407
|
+
events.push({
|
|
15408
|
+
...base,
|
|
15409
|
+
event_id: `fail:${short5(at + toolName + target + error)}`,
|
|
15410
|
+
kind: "tool_failed",
|
|
15411
|
+
tool_name: toolName,
|
|
15412
|
+
...target ? { target } : {},
|
|
15413
|
+
error
|
|
15414
|
+
});
|
|
15415
|
+
break;
|
|
15416
|
+
}
|
|
15417
|
+
case "agentStop":
|
|
15418
|
+
flush = true;
|
|
15419
|
+
break;
|
|
15420
|
+
case "sessionEnd":
|
|
15421
|
+
events.push({
|
|
15422
|
+
...base,
|
|
15423
|
+
event_id: `end:${sessionId}`,
|
|
15424
|
+
kind: "session_ended",
|
|
15425
|
+
...p.reason ? { reason: p.reason } : {}
|
|
15426
|
+
});
|
|
15427
|
+
flush = true;
|
|
15428
|
+
end = true;
|
|
15429
|
+
break;
|
|
15430
|
+
default:
|
|
15431
|
+
return null;
|
|
15432
|
+
}
|
|
15433
|
+
return { sessionId, cwd: p.cwd ?? null, events, flush, end };
|
|
15434
|
+
}
|
|
15435
|
+
};
|
|
15436
|
+
}
|
|
15437
|
+
});
|
|
15438
|
+
|
|
15221
15439
|
// packages/cli/src/adapters/index.ts
|
|
15222
15440
|
var ADAPTERS;
|
|
15223
15441
|
var init_adapters = __esm({
|
|
@@ -15226,10 +15444,12 @@ var init_adapters = __esm({
|
|
|
15226
15444
|
init_claude_code();
|
|
15227
15445
|
init_cursor();
|
|
15228
15446
|
init_codex();
|
|
15447
|
+
init_copilot();
|
|
15229
15448
|
ADAPTERS = {
|
|
15230
15449
|
[claudeCode2.id]: claudeCode2,
|
|
15231
15450
|
[cursor2.id]: cursor2,
|
|
15232
|
-
[codex2.id]: codex2
|
|
15451
|
+
[codex2.id]: codex2,
|
|
15452
|
+
[copilot2.id]: copilot2
|
|
15233
15453
|
};
|
|
15234
15454
|
}
|
|
15235
15455
|
});
|
|
@@ -15243,17 +15463,17 @@ __export(hook_exports, {
|
|
|
15243
15463
|
});
|
|
15244
15464
|
import {
|
|
15245
15465
|
appendFileSync,
|
|
15246
|
-
existsSync as
|
|
15466
|
+
existsSync as existsSync8,
|
|
15247
15467
|
mkdirSync as mkdirSync3,
|
|
15248
15468
|
readdirSync,
|
|
15249
|
-
readFileSync as
|
|
15469
|
+
readFileSync as readFileSync8,
|
|
15250
15470
|
rmSync,
|
|
15251
15471
|
statSync as statSync2
|
|
15252
15472
|
} from "node:fs";
|
|
15253
15473
|
import os5 from "node:os";
|
|
15254
|
-
import
|
|
15474
|
+
import path13 from "node:path";
|
|
15255
15475
|
function spoolPath(tool, sessionId) {
|
|
15256
|
-
return
|
|
15476
|
+
return path13.join(
|
|
15257
15477
|
os5.homedir(),
|
|
15258
15478
|
".brainjar",
|
|
15259
15479
|
"spool",
|
|
@@ -15263,7 +15483,7 @@ function spoolPath(tool, sessionId) {
|
|
|
15263
15483
|
}
|
|
15264
15484
|
function readSpool(file) {
|
|
15265
15485
|
const out = [];
|
|
15266
|
-
for (const line of
|
|
15486
|
+
for (const line of readFileSync8(file, "utf8").split("\n")) {
|
|
15267
15487
|
if (!line.trim()) continue;
|
|
15268
15488
|
try {
|
|
15269
15489
|
out.push(clampCaptureEvent(JSON.parse(line)));
|
|
@@ -15275,7 +15495,7 @@ function readSpool(file) {
|
|
|
15275
15495
|
function pruneSpool(dir, keep, maxAgeMs = 7 * 864e5) {
|
|
15276
15496
|
try {
|
|
15277
15497
|
for (const f of readdirSync(dir)) {
|
|
15278
|
-
const file =
|
|
15498
|
+
const file = path13.join(dir, f);
|
|
15279
15499
|
if (file === keep) continue;
|
|
15280
15500
|
if (Date.now() - statSync2(file).mtimeMs > maxAgeMs)
|
|
15281
15501
|
rmSync(file, { force: true });
|
|
@@ -15284,7 +15504,9 @@ function pruneSpool(dir, keep, maxAgeMs = 7 * 864e5) {
|
|
|
15284
15504
|
}
|
|
15285
15505
|
}
|
|
15286
15506
|
async function hookMain(argv) {
|
|
15287
|
-
const
|
|
15507
|
+
const eventFlag = argv.indexOf("--event");
|
|
15508
|
+
const event = eventFlag >= 0 ? argv[eventFlag + 1] : void 0;
|
|
15509
|
+
const tool = argv.find((a, i) => !a.startsWith("--") && i !== eventFlag + 1);
|
|
15288
15510
|
const adapter = tool ? ADAPTERS[tool] : void 0;
|
|
15289
15511
|
try {
|
|
15290
15512
|
if (!adapter) {
|
|
@@ -15295,16 +15517,16 @@ async function hookMain(argv) {
|
|
|
15295
15517
|
}
|
|
15296
15518
|
let payload = null;
|
|
15297
15519
|
try {
|
|
15298
|
-
payload = JSON.parse(
|
|
15520
|
+
payload = JSON.parse(readFileSync8(0, "utf8"));
|
|
15299
15521
|
} catch {
|
|
15300
15522
|
return;
|
|
15301
15523
|
}
|
|
15302
|
-
const out = adapter.map(payload, (/* @__PURE__ */ new Date()).toISOString());
|
|
15524
|
+
const out = adapter.map(payload, (/* @__PURE__ */ new Date()).toISOString(), { event });
|
|
15303
15525
|
if (!out) return;
|
|
15304
15526
|
if (out.reply) process.stdout.write(out.reply);
|
|
15305
15527
|
const file = spoolPath(adapter.id, out.sessionId);
|
|
15306
15528
|
if (out.events.length) {
|
|
15307
|
-
mkdirSync3(
|
|
15529
|
+
mkdirSync3(path13.dirname(file), { recursive: true });
|
|
15308
15530
|
appendFileSync(
|
|
15309
15531
|
file,
|
|
15310
15532
|
out.events.map((e) => JSON.stringify(clampCaptureEvent(e))).join("\n") + "\n"
|
|
@@ -15312,7 +15534,7 @@ async function hookMain(argv) {
|
|
|
15312
15534
|
}
|
|
15313
15535
|
if (!out.flush) return;
|
|
15314
15536
|
const root = await repoRoot(out.cwd ?? process.cwd());
|
|
15315
|
-
const events =
|
|
15537
|
+
const events = existsSync8(file) ? readSpool(file) : [];
|
|
15316
15538
|
if (events.length) {
|
|
15317
15539
|
const r = await captureApi("/capture/events", {
|
|
15318
15540
|
method: "POST",
|
|
@@ -15333,7 +15555,7 @@ async function hookMain(argv) {
|
|
|
15333
15555
|
}
|
|
15334
15556
|
}
|
|
15335
15557
|
if (out.end) rmSync(file, { force: true });
|
|
15336
|
-
pruneSpool(
|
|
15558
|
+
pruneSpool(path13.dirname(file), file);
|
|
15337
15559
|
await syncRepo(root);
|
|
15338
15560
|
} catch (e) {
|
|
15339
15561
|
console.error("brainjar hook:", e instanceof Error ? e.message : e);
|
|
@@ -15456,7 +15678,7 @@ __export(init_exports, {
|
|
|
15456
15678
|
init: () => init,
|
|
15457
15679
|
initMain: () => initMain
|
|
15458
15680
|
});
|
|
15459
|
-
import { readFile as
|
|
15681
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
15460
15682
|
async function init(argv) {
|
|
15461
15683
|
const skipTranscripts = argv.includes("--no-transcripts");
|
|
15462
15684
|
const flag = (f) => argv.includes(f) ? argv[argv.indexOf(f) + 1] ?? null : null;
|
|
@@ -15541,7 +15763,7 @@ async function init(argv) {
|
|
|
15541
15763
|
let skipped = 0;
|
|
15542
15764
|
for (const f of files) {
|
|
15543
15765
|
try {
|
|
15544
|
-
const { text, truncated } = capTranscript(await
|
|
15766
|
+
const { text, truncated } = capTranscript(await readFile8(f, "utf8"));
|
|
15545
15767
|
if (truncated) truncatedCount++;
|
|
15546
15768
|
const r = await captureApi("/capture/transcript", {
|
|
15547
15769
|
method: "POST",
|
|
@@ -15564,7 +15786,7 @@ async function init(argv) {
|
|
|
15564
15786
|
const tools = detectedTools(root);
|
|
15565
15787
|
if (tools.length === 0) {
|
|
15566
15788
|
ok(
|
|
15567
|
-
"no coding agent detected (looked for Claude Code, Cursor, Codex); rerun init after installing one"
|
|
15789
|
+
"no coding agent detected (looked for Claude Code, Cursor, Codex, GitHub Copilot); rerun init after installing one"
|
|
15568
15790
|
);
|
|
15569
15791
|
}
|
|
15570
15792
|
for (const tool of tools) {
|
|
@@ -15631,7 +15853,7 @@ __export(constraints_exports, {
|
|
|
15631
15853
|
constraintsMain: () => constraintsMain,
|
|
15632
15854
|
sessionStartEnvelope: () => sessionStartEnvelope
|
|
15633
15855
|
});
|
|
15634
|
-
import { readFileSync as
|
|
15856
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
15635
15857
|
function sessionStartEnvelope(text) {
|
|
15636
15858
|
return JSON.stringify({
|
|
15637
15859
|
hookSpecificOutput: {
|
|
@@ -15649,7 +15871,7 @@ async function constraintsMain(argv) {
|
|
|
15649
15871
|
if (hook) {
|
|
15650
15872
|
let cwd;
|
|
15651
15873
|
try {
|
|
15652
|
-
const payload = JSON.parse(
|
|
15874
|
+
const payload = JSON.parse(readFileSync9(0, "utf8"));
|
|
15653
15875
|
cwd = payload.cwd;
|
|
15654
15876
|
} catch {
|
|
15655
15877
|
}
|
|
@@ -15671,7 +15893,8 @@ async function constraintsMain(argv) {
|
|
|
15671
15893
|
}
|
|
15672
15894
|
return;
|
|
15673
15895
|
}
|
|
15674
|
-
|
|
15896
|
+
const envelope = argv.includes("--copilot") ? copilotContextEnvelope : sessionStartEnvelope;
|
|
15897
|
+
if (r.text) console.log(hook ? envelope(r.text) : r.text);
|
|
15675
15898
|
else if (!hook)
|
|
15676
15899
|
console.log("No recorded failed approaches or rules for this Brain.");
|
|
15677
15900
|
if (hook) {
|
|
@@ -15691,6 +15914,7 @@ var init_constraints = __esm({
|
|
|
15691
15914
|
"use strict";
|
|
15692
15915
|
init_src3();
|
|
15693
15916
|
init_api_client();
|
|
15917
|
+
init_copilot();
|
|
15694
15918
|
}
|
|
15695
15919
|
});
|
|
15696
15920
|
|
|
@@ -15842,8 +16066,8 @@ __export(deepscan_exports, {
|
|
|
15842
16066
|
deepscanMain: () => deepscanMain,
|
|
15843
16067
|
selectDeepScanFiles: () => selectDeepScanFiles
|
|
15844
16068
|
});
|
|
15845
|
-
import { readdir as readdir3, readFile as
|
|
15846
|
-
import
|
|
16069
|
+
import { readdir as readdir3, readFile as readFile9, stat as stat2 } from "node:fs/promises";
|
|
16070
|
+
import path14 from "node:path";
|
|
15847
16071
|
function selectDeepScanFiles(candidates, graph, maxFiles = MAX_FILES) {
|
|
15848
16072
|
const picked = [];
|
|
15849
16073
|
const has = /* @__PURE__ */ new Set();
|
|
@@ -15880,7 +16104,7 @@ async function walkCandidates(root) {
|
|
|
15880
16104
|
for (const e of entries) {
|
|
15881
16105
|
if (!e.isFile()) continue;
|
|
15882
16106
|
const parent = e.parentPath ?? e.path ?? root;
|
|
15883
|
-
const rel =
|
|
16107
|
+
const rel = path14.relative(root, path14.join(parent, e.name)).split(path14.sep).join("/");
|
|
15884
16108
|
if (rel.split("/").some((seg) => SKIP_DIRS.has(seg))) continue;
|
|
15885
16109
|
out.push(rel);
|
|
15886
16110
|
}
|
|
@@ -15905,10 +16129,10 @@ async function deepscanMain() {
|
|
|
15905
16129
|
const artifacts = [];
|
|
15906
16130
|
for (const rel of files) {
|
|
15907
16131
|
try {
|
|
15908
|
-
const abs =
|
|
16132
|
+
const abs = path14.join(root, rel);
|
|
15909
16133
|
const info = await stat2(abs);
|
|
15910
16134
|
if (info.size > RAW_SKIP_BYTES) continue;
|
|
15911
|
-
const content = await
|
|
16135
|
+
const content = await readFile9(abs, "utf8");
|
|
15912
16136
|
artifacts.push({
|
|
15913
16137
|
source: "deepscan",
|
|
15914
16138
|
kind: "source_file",
|