pi-para 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +0 -9
- package/CHANGELOG.md +13 -0
- package/CONFIGURATION.md +0 -23
- package/README.md +1 -29
- package/SETUP.md +1 -1
- package/STRUCTURE.md +0 -9
- package/dist/atomic-write.d.ts +2 -0
- package/dist/atomic-write.d.ts.map +1 -0
- package/dist/atomic-write.js +18 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/capture.d.ts +34 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +461 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli-legacy.d.ts +4 -0
- package/dist/cli-legacy.d.ts.map +1 -0
- package/dist/cli-legacy.js +41 -0
- package/dist/cli-legacy.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +427 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +15 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +719 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +94 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +228 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +63 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +311 -0
- package/dist/context.js.map +1 -0
- package/dist/credentials.d.ts +27 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +85 -0
- package/dist/credentials.js.map +1 -0
- package/dist/daemon.d.ts +49 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +226 -0
- package/dist/daemon.js.map +1 -0
- package/dist/doctor.d.ts +20 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +176 -0
- package/dist/doctor.js.map +1 -0
- package/dist/frontmatter.d.ts +59 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +170 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +342 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest.d.ts +88 -0
- package/dist/ingest.d.ts.map +1 -0
- package/dist/ingest.js +105 -0
- package/dist/ingest.js.map +1 -0
- package/dist/link-discovery.d.ts +40 -0
- package/dist/link-discovery.d.ts.map +1 -0
- package/dist/link-discovery.js +122 -0
- package/dist/link-discovery.js.map +1 -0
- package/dist/link-utils.d.ts +30 -0
- package/dist/link-utils.d.ts.map +1 -0
- package/dist/link-utils.js +145 -0
- package/dist/link-utils.js.map +1 -0
- package/dist/lint.d.ts +39 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +827 -0
- package/dist/lint.js.map +1 -0
- package/dist/maintainer.d.ts +24 -0
- package/dist/maintainer.d.ts.map +1 -0
- package/dist/maintainer.js +358 -0
- package/dist/maintainer.js.map +1 -0
- package/dist/model-resolver.d.ts +30 -0
- package/dist/model-resolver.d.ts.map +1 -0
- package/dist/model-resolver.js +71 -0
- package/dist/model-resolver.js.map +1 -0
- package/dist/paths.d.ts +20 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +33 -0
- package/dist/paths.js.map +1 -0
- package/dist/processor.d.ts +14 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +361 -0
- package/dist/processor.js.map +1 -0
- package/dist/qmd-providers.d.ts +12 -0
- package/dist/qmd-providers.d.ts.map +1 -0
- package/dist/qmd-providers.js +45 -0
- package/dist/qmd-providers.js.map +1 -0
- package/dist/query.d.ts +69 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +120 -0
- package/dist/query.js.map +1 -0
- package/dist/raw.d.ts +57 -0
- package/dist/raw.d.ts.map +1 -0
- package/dist/raw.js +219 -0
- package/dist/raw.js.map +1 -0
- package/dist/redact.d.ts +21 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +143 -0
- package/dist/redact.js.map +1 -0
- package/dist/repair.d.ts +11 -0
- package/dist/repair.d.ts.map +1 -0
- package/dist/repair.js +41 -0
- package/dist/repair.js.map +1 -0
- package/dist/scheduler/controls.d.ts +35 -0
- package/dist/scheduler/controls.d.ts.map +1 -0
- package/dist/scheduler/controls.js +98 -0
- package/dist/scheduler/controls.js.map +1 -0
- package/dist/scheduler/index.d.ts +48 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +193 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/leases.d.ts +22 -0
- package/dist/scheduler/leases.d.ts.map +1 -0
- package/dist/scheduler/leases.js +74 -0
- package/dist/scheduler/leases.js.map +1 -0
- package/dist/scheduler/session-capture.d.ts +33 -0
- package/dist/scheduler/session-capture.d.ts.map +1 -0
- package/dist/scheduler/session-capture.js +108 -0
- package/dist/scheduler/session-capture.js.map +1 -0
- package/dist/scheduler/state.d.ts +56 -0
- package/dist/scheduler/state.d.ts.map +1 -0
- package/dist/scheduler/state.js +210 -0
- package/dist/scheduler/state.js.map +1 -0
- package/dist/scope.d.ts +54 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +161 -0
- package/dist/scope.js.map +1 -0
- package/dist/scripts/bulk-link-fix.d.ts +9 -0
- package/dist/scripts/bulk-link-fix.d.ts.map +1 -0
- package/dist/scripts/bulk-link-fix.js +106 -0
- package/dist/scripts/bulk-link-fix.js.map +1 -0
- package/dist/session-tools.d.ts +33 -0
- package/dist/session-tools.d.ts.map +1 -0
- package/dist/session-tools.js +211 -0
- package/dist/session-tools.js.map +1 -0
- package/dist/settings.d.ts +19 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +106 -0
- package/dist/settings.js.map +1 -0
- package/dist/setup.d.ts +29 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +90 -0
- package/dist/setup.js.map +1 -0
- package/dist/state.d.ts +54 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +176 -0
- package/dist/state.js.map +1 -0
- package/dist/status.d.ts +22 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +93 -0
- package/dist/status.js.map +1 -0
- package/dist/store.d.ts +71 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +282 -0
- package/dist/store.js.map +1 -0
- package/dist/summarize.d.ts +60 -0
- package/dist/summarize.d.ts.map +1 -0
- package/dist/summarize.js +266 -0
- package/dist/summarize.js.map +1 -0
- package/dist/tag-registry.d.ts +56 -0
- package/dist/tag-registry.d.ts.map +1 -0
- package/dist/tag-registry.js +146 -0
- package/dist/tag-registry.js.map +1 -0
- package/dist/templates/prompts.d.ts +51 -0
- package/dist/templates/prompts.d.ts.map +1 -0
- package/dist/templates/prompts.js +203 -0
- package/dist/templates/prompts.js.map +1 -0
- package/dist/tools.d.ts +26 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +1198 -0
- package/dist/tools.js.map +1 -0
- package/dist/watcher.d.ts +25 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +84 -0
- package/dist/watcher.js.map +1 -0
- package/dist/webui/client/dist/index.html +1885 -0
- package/dist/webui/server.d.ts +31 -0
- package/dist/webui/server.d.ts.map +1 -0
- package/dist/webui/server.js +566 -0
- package/dist/webui/server.js.map +1 -0
- package/dist/wiki-tool-guidance.d.ts +6 -0
- package/dist/wiki-tool-guidance.d.ts.map +1 -0
- package/dist/wiki-tool-guidance.js +70 -0
- package/dist/wiki-tool-guidance.js.map +1 -0
- package/dist/wiki.d.ts +108 -0
- package/dist/wiki.d.ts.map +1 -0
- package/dist/wiki.js +497 -0
- package/dist/wiki.js.map +1 -0
- package/package.json +2 -1
- package/scripts/build-assets.mjs +1 -13
- package/skills/setup/SKILL.md +1 -1
- package/src/cli.ts +0 -70
- package/src/config.ts +0 -25
- package/src/index.ts +1 -38
- package/src/templates/prompts.ts +0 -56
- package/scripts/gepa/dataset.py +0 -192
- package/scripts/gepa/lm_providers.py +0 -472
- package/scripts/gepa/metric.py +0 -279
- package/scripts/gepa/optimize.py +0 -367
- package/scripts/gepa/program.py +0 -99
- package/scripts/gepa/pyproject.toml +0 -19
- package/scripts/gepa/run-all.sh +0 -53
- package/scripts/gepa/wiki_reader.py +0 -113
- package/src/gepa/index.ts +0 -287
- package/src/gepa/optimized/capture-prompt.txt +0 -65
package/dist/query.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query pipeline — searches the wiki and returns relevant results.
|
|
3
|
+
*
|
|
4
|
+
* Performs scoped search via qmd and returns results for the LLM
|
|
5
|
+
* to synthesize answers from. This is the reusable library function;
|
|
6
|
+
* the wiki_query tool wraps it with LLM prompt formatting.
|
|
7
|
+
*/
|
|
8
|
+
import { searchWiki } from "./store.js";
|
|
9
|
+
// -- Main pipeline -----------------------------------------------------------
|
|
10
|
+
/**
|
|
11
|
+
* Search the wiki with scope and category filtering.
|
|
12
|
+
*
|
|
13
|
+
* This is the reusable library function. It:
|
|
14
|
+
* 1. Applies scope filtering (unless global flag is set)
|
|
15
|
+
* 2. Filters by PARA category if specified
|
|
16
|
+
* 3. Excludes archives unless explicitly requested
|
|
17
|
+
* 4. Returns results sorted by relevance score
|
|
18
|
+
*
|
|
19
|
+
* The caller (tool or standalone agent) can format the results
|
|
20
|
+
* into an LLM prompt or use them directly.
|
|
21
|
+
*/
|
|
22
|
+
export async function queryWiki(store, options, scope) {
|
|
23
|
+
const limit = options.limit ?? 10;
|
|
24
|
+
const isGlobal = options.global ?? false;
|
|
25
|
+
const includeArchives = options.includeArchives ?? (options.category === "archives");
|
|
26
|
+
// Build scope override if explicit scope tags provided
|
|
27
|
+
let effectiveScope;
|
|
28
|
+
if (isGlobal) {
|
|
29
|
+
effectiveScope = undefined; // no scope filtering
|
|
30
|
+
}
|
|
31
|
+
else if (options.scope && options.scope.length > 0) {
|
|
32
|
+
effectiveScope = {
|
|
33
|
+
...scope,
|
|
34
|
+
name: scope.name,
|
|
35
|
+
include: options.scope,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
effectiveScope = scope;
|
|
40
|
+
}
|
|
41
|
+
let results = await searchWiki(store, options.query, {
|
|
42
|
+
scope: effectiveScope,
|
|
43
|
+
category: options.category,
|
|
44
|
+
limit,
|
|
45
|
+
includeArchives,
|
|
46
|
+
graphBoost: options.graphBoost,
|
|
47
|
+
});
|
|
48
|
+
// If QMD's BM25 index is stale, freshly written/readable pages can return
|
|
49
|
+
// as zero search results. On a miss, refresh the filesystem index once and
|
|
50
|
+
// retry before telling the agent the wiki lacks matching content.
|
|
51
|
+
if (results.length === 0) {
|
|
52
|
+
await store.update();
|
|
53
|
+
results = await searchWiki(store, options.query, {
|
|
54
|
+
scope: effectiveScope,
|
|
55
|
+
category: options.category,
|
|
56
|
+
limit,
|
|
57
|
+
includeArchives,
|
|
58
|
+
graphBoost: options.graphBoost,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
results,
|
|
63
|
+
scopeUsed: effectiveScope ?? scope,
|
|
64
|
+
wasGlobal: isGlobal,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Format query results as a readable text block.
|
|
69
|
+
* Useful for building LLM prompts or display.
|
|
70
|
+
*
|
|
71
|
+
* Includes freshness indicators so the LLM knows which pages to trust
|
|
72
|
+
* vs. which need verification against current code/state.
|
|
73
|
+
*/
|
|
74
|
+
export function formatQueryResults(results) {
|
|
75
|
+
if (results.length === 0)
|
|
76
|
+
return "No results found.";
|
|
77
|
+
const now = Date.now();
|
|
78
|
+
return results
|
|
79
|
+
.map((r, i) => {
|
|
80
|
+
const fm = r.frontmatter;
|
|
81
|
+
const freshness = formatFreshness(fm.updated, now);
|
|
82
|
+
return [
|
|
83
|
+
`### Result ${i + 1}: ${fm.title} (${r.page.path})`,
|
|
84
|
+
`PARA: ${fm.para} | Scope: ${fm.scope.join(", ")} | Tags: ${fm.tags.join(", ")}`,
|
|
85
|
+
`Updated: ${fm.updated} | ${freshness}`,
|
|
86
|
+
`Score: ${r.score.toFixed(3)}`,
|
|
87
|
+
"",
|
|
88
|
+
r.snippet,
|
|
89
|
+
].join("\n");
|
|
90
|
+
})
|
|
91
|
+
.join("\n\n");
|
|
92
|
+
}
|
|
93
|
+
// -- Freshness helpers -------------------------------------------------------
|
|
94
|
+
/**
|
|
95
|
+
* Compute a human-readable freshness indicator from the page's `updated` date.
|
|
96
|
+
*
|
|
97
|
+
* - < 7 days → "✅ FRESH"
|
|
98
|
+
* - 7-14 days → "✅ Recent — N days old"
|
|
99
|
+
* - 14-30 days → "⚠️ AGING — N days old — verify claims about code/configs"
|
|
100
|
+
* - 30-90 days → "⚠️ STALE — N days old — verify before trusting"
|
|
101
|
+
* - > 90 days → "🚨 VERY STALE — N days old — likely outdated, verify everything"
|
|
102
|
+
*/
|
|
103
|
+
export function formatFreshness(updatedISO, nowMs) {
|
|
104
|
+
const updatedMs = Date.parse(updatedISO);
|
|
105
|
+
if (isNaN(updatedMs))
|
|
106
|
+
return "❓ Unknown freshness (no valid date)";
|
|
107
|
+
const ageDays = Math.floor((nowMs - updatedMs) / (1000 * 60 * 60 * 24));
|
|
108
|
+
if (ageDays < 0)
|
|
109
|
+
return "✅ FRESH";
|
|
110
|
+
if (ageDays < 7)
|
|
111
|
+
return "✅ FRESH";
|
|
112
|
+
if (ageDays < 14)
|
|
113
|
+
return `✅ Recent — ${ageDays} days old`;
|
|
114
|
+
if (ageDays < 30)
|
|
115
|
+
return `⚠️ AGING — ${ageDays} days old — verify claims about code/configs`;
|
|
116
|
+
if (ageDays < 90)
|
|
117
|
+
return `⚠️ STALE — ${ageDays} days old — verify before trusting`;
|
|
118
|
+
return `🚨 VERY STALE — ${ageDays} days old — likely outdated, verify everything`;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/raw.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw source vault and session digests.
|
|
3
|
+
*
|
|
4
|
+
* Manages immutable source material in ~/.pi/wiki/raw/ and
|
|
5
|
+
* session digest entries in sessions.md.
|
|
6
|
+
*/
|
|
7
|
+
export interface RawSource {
|
|
8
|
+
type: "url" | "file" | "text";
|
|
9
|
+
originalPath: string;
|
|
10
|
+
savedPath: string;
|
|
11
|
+
ingestedAt: string;
|
|
12
|
+
wikiPages: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface SessionDigest {
|
|
15
|
+
date: string;
|
|
16
|
+
project: string;
|
|
17
|
+
sessionFile: string;
|
|
18
|
+
scope: string;
|
|
19
|
+
capturedPages: string[];
|
|
20
|
+
summary: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Save a raw source to the vault. URL sources go to raw/articles/,
|
|
24
|
+
* file sources to raw/docs/, text sources to raw/notes/.
|
|
25
|
+
*
|
|
26
|
+
* The file is saved as markdown with a metadata header.
|
|
27
|
+
* Returns the path relative to wikiDir (e.g. "raw/articles/example-com-page.md").
|
|
28
|
+
*/
|
|
29
|
+
export declare function saveRawSource(wikiDir: string, source: {
|
|
30
|
+
type: "url" | "file" | "text";
|
|
31
|
+
content: string;
|
|
32
|
+
originalPath: string;
|
|
33
|
+
}): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Append a session digest entry to sessions.md in the documented format:
|
|
36
|
+
*
|
|
37
|
+
* ```
|
|
38
|
+
* ## [2026-04-27] pi-mono | SSL certificate debugging
|
|
39
|
+
* - **Session**: `~/.pi/agent/sessions/.../file.jsonl`
|
|
40
|
+
* - **Scope**: pi-mono
|
|
41
|
+
* - **Captured**: [[ssl-cert-gotchas]]
|
|
42
|
+
* - **Summary**: One-paragraph summary...
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Creates sessions.md if it does not exist.
|
|
46
|
+
*/
|
|
47
|
+
export declare function appendSessionDigest(wikiDir: string, digest: SessionDigest): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Parse sessions.md and return session digest entries.
|
|
50
|
+
* Optionally filter by scope and/or limit the number of results.
|
|
51
|
+
* Results are returned in file order (oldest first).
|
|
52
|
+
*/
|
|
53
|
+
export declare function readSessionDigests(wikiDir: string, options?: {
|
|
54
|
+
limit?: number;
|
|
55
|
+
scope?: string;
|
|
56
|
+
}): Promise<SessionDigest[]>;
|
|
57
|
+
//# sourceMappingURL=raw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../src/raw.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAgFD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;IACN,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,GACA,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,aAAa,EAAE,CAAC,CAiE1B"}
|
package/dist/raw.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw source vault and session digests.
|
|
3
|
+
*
|
|
4
|
+
* Manages immutable source material in ~/.pi/wiki/raw/ and
|
|
5
|
+
* session digest entries in sessions.md.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile, mkdir, access } from "node:fs/promises";
|
|
8
|
+
import { join, basename, extname } from "node:path";
|
|
9
|
+
// -- Helpers -----------------------------------------------------------------
|
|
10
|
+
const RAW_SUBDIRS = {
|
|
11
|
+
url: "articles",
|
|
12
|
+
file: "docs",
|
|
13
|
+
text: "notes",
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Slugify a string for use as a filename. Lowercase, hyphens, no special
|
|
17
|
+
* characters. Collapses multiple hyphens. Trims leading/trailing hyphens.
|
|
18
|
+
*/
|
|
19
|
+
function slugify(input) {
|
|
20
|
+
return input
|
|
21
|
+
.toLowerCase()
|
|
22
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
23
|
+
.replace(/-+/g, "-")
|
|
24
|
+
.replace(/^-|-$/g, "");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Derive a filename slug from the original path based on source type.
|
|
28
|
+
*
|
|
29
|
+
* - URL: extract domain + path components
|
|
30
|
+
* - file: use the filename without extension
|
|
31
|
+
* - text: use a timestamp-based name
|
|
32
|
+
*/
|
|
33
|
+
function deriveSlug(type, originalPath) {
|
|
34
|
+
if (type === "url") {
|
|
35
|
+
try {
|
|
36
|
+
const url = new URL(originalPath);
|
|
37
|
+
const host = url.hostname.replace(/^www\./, "");
|
|
38
|
+
const pathParts = url.pathname
|
|
39
|
+
.split("/")
|
|
40
|
+
.filter((p) => p.length > 0)
|
|
41
|
+
.slice(0, 3);
|
|
42
|
+
const raw = [host, ...pathParts].join("-");
|
|
43
|
+
return slugify(raw) || "untitled";
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return slugify(originalPath) || "untitled";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (type === "file") {
|
|
50
|
+
const name = basename(originalPath, extname(originalPath));
|
|
51
|
+
return slugify(name) || "untitled";
|
|
52
|
+
}
|
|
53
|
+
// text: timestamp-based
|
|
54
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
55
|
+
return `note-${ts}`;
|
|
56
|
+
}
|
|
57
|
+
async function fileExists(path) {
|
|
58
|
+
try {
|
|
59
|
+
await access(path);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Ensure a unique filename by appending -2, -3, etc. if the slug already exists.
|
|
68
|
+
*/
|
|
69
|
+
async function uniquePath(dir, slug, ext) {
|
|
70
|
+
let candidate = join(dir, `${slug}${ext}`);
|
|
71
|
+
if (!(await fileExists(candidate)))
|
|
72
|
+
return candidate;
|
|
73
|
+
let i = 2;
|
|
74
|
+
while (await fileExists(join(dir, `${slug}-${i}${ext}`))) {
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
return join(dir, `${slug}-${i}${ext}`);
|
|
78
|
+
}
|
|
79
|
+
// -- Functions ---------------------------------------------------------------
|
|
80
|
+
/**
|
|
81
|
+
* Save a raw source to the vault. URL sources go to raw/articles/,
|
|
82
|
+
* file sources to raw/docs/, text sources to raw/notes/.
|
|
83
|
+
*
|
|
84
|
+
* The file is saved as markdown with a metadata header.
|
|
85
|
+
* Returns the path relative to wikiDir (e.g. "raw/articles/example-com-page.md").
|
|
86
|
+
*/
|
|
87
|
+
export async function saveRawSource(wikiDir, source) {
|
|
88
|
+
const subdir = RAW_SUBDIRS[source.type];
|
|
89
|
+
const dir = join(wikiDir, "raw", subdir);
|
|
90
|
+
await mkdir(dir, { recursive: true });
|
|
91
|
+
const slug = deriveSlug(source.type, source.originalPath);
|
|
92
|
+
const filePath = await uniquePath(dir, slug, ".md");
|
|
93
|
+
const fileName = basename(filePath);
|
|
94
|
+
const header = [
|
|
95
|
+
"---",
|
|
96
|
+
`source_type: ${source.type}`,
|
|
97
|
+
`original_path: "${source.originalPath}"`,
|
|
98
|
+
`ingested_at: "${new Date().toISOString()}"`,
|
|
99
|
+
"---",
|
|
100
|
+
"",
|
|
101
|
+
].join("\n");
|
|
102
|
+
await writeFile(filePath, header + source.content, "utf-8");
|
|
103
|
+
return `raw/${subdir}/${fileName}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Append a session digest entry to sessions.md in the documented format:
|
|
107
|
+
*
|
|
108
|
+
* ```
|
|
109
|
+
* ## [2026-04-27] pi-mono | SSL certificate debugging
|
|
110
|
+
* - **Session**: `~/.pi/agent/sessions/.../file.jsonl`
|
|
111
|
+
* - **Scope**: pi-mono
|
|
112
|
+
* - **Captured**: [[ssl-cert-gotchas]]
|
|
113
|
+
* - **Summary**: One-paragraph summary...
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* Creates sessions.md if it does not exist.
|
|
117
|
+
*/
|
|
118
|
+
export async function appendSessionDigest(wikiDir, digest) {
|
|
119
|
+
const sessionsPath = join(wikiDir, "sessions.md");
|
|
120
|
+
let existing;
|
|
121
|
+
try {
|
|
122
|
+
existing = await readFile(sessionsPath, "utf-8");
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
if (err.code === "ENOENT") {
|
|
126
|
+
existing = "# Session Digests\n";
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const captured = digest.capturedPages.map((p) => `[[${p}]]`).join(", ");
|
|
133
|
+
const heading = digest.summary.split(/[.!?\n]/)[0].trim() || "Session capture";
|
|
134
|
+
const entry = [
|
|
135
|
+
"",
|
|
136
|
+
`## [${digest.date}] ${digest.project} | ${heading}`,
|
|
137
|
+
`- **Session**: \`${digest.sessionFile}\``,
|
|
138
|
+
`- **Scope**: ${digest.scope}`,
|
|
139
|
+
`- **Captured**: ${captured || "none"}`,
|
|
140
|
+
`- **Summary**: ${digest.summary}`,
|
|
141
|
+
"",
|
|
142
|
+
].join("\n");
|
|
143
|
+
await writeFile(sessionsPath, existing + entry, "utf-8");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Parse sessions.md and return session digest entries.
|
|
147
|
+
* Optionally filter by scope and/or limit the number of results.
|
|
148
|
+
* Results are returned in file order (oldest first).
|
|
149
|
+
*/
|
|
150
|
+
export async function readSessionDigests(wikiDir, options) {
|
|
151
|
+
const sessionsPath = join(wikiDir, "sessions.md");
|
|
152
|
+
let content;
|
|
153
|
+
try {
|
|
154
|
+
content = await readFile(sessionsPath, "utf-8");
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
if (err.code === "ENOENT") {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
const digests = [];
|
|
163
|
+
// Split on ## headings (session entries)
|
|
164
|
+
const entryPattern = /^## \[([^\]]+)\] ([^|]+)\| (.+)$/gm;
|
|
165
|
+
let match;
|
|
166
|
+
while ((match = entryPattern.exec(content)) !== null) {
|
|
167
|
+
const date = match[1].trim();
|
|
168
|
+
const project = match[2].trim();
|
|
169
|
+
// Extract the block after this heading until the next heading or end
|
|
170
|
+
const startIdx = match.index + match[0].length;
|
|
171
|
+
const nextHeading = content.indexOf("\n## ", startIdx);
|
|
172
|
+
const block = nextHeading === -1
|
|
173
|
+
? content.slice(startIdx)
|
|
174
|
+
: content.slice(startIdx, nextHeading);
|
|
175
|
+
const sessionFile = extractField(block, "Session");
|
|
176
|
+
const scope = extractField(block, "Scope");
|
|
177
|
+
const capturedRaw = extractField(block, "Captured");
|
|
178
|
+
const summary = extractField(block, "Summary");
|
|
179
|
+
// Parse captured wikilinks: [[slug1]], [[slug2]]
|
|
180
|
+
const capturedPages = [];
|
|
181
|
+
const linkPattern = /\[\[([^\]]+)\]\]/g;
|
|
182
|
+
let linkMatch;
|
|
183
|
+
while ((linkMatch = linkPattern.exec(capturedRaw)) !== null) {
|
|
184
|
+
capturedPages.push(linkMatch[1]);
|
|
185
|
+
}
|
|
186
|
+
digests.push({
|
|
187
|
+
date,
|
|
188
|
+
project,
|
|
189
|
+
sessionFile,
|
|
190
|
+
scope,
|
|
191
|
+
capturedPages,
|
|
192
|
+
summary,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// Apply scope filter
|
|
196
|
+
let filtered = digests;
|
|
197
|
+
if (options?.scope) {
|
|
198
|
+
const scopeFilter = options.scope;
|
|
199
|
+
filtered = filtered.filter((d) => d.scope === scopeFilter);
|
|
200
|
+
}
|
|
201
|
+
// Apply limit (return the last N entries — most recent)
|
|
202
|
+
if (options?.limit !== undefined && options.limit < filtered.length) {
|
|
203
|
+
filtered = filtered.slice(filtered.length - options.limit);
|
|
204
|
+
}
|
|
205
|
+
return filtered;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Extract a field value from a session digest block.
|
|
209
|
+
* Matches lines like: `- **Field**: value` or `- **Field**: \`value\``
|
|
210
|
+
*/
|
|
211
|
+
function extractField(block, field) {
|
|
212
|
+
const pattern = new RegExp(`^- \\*\\*${field}\\*\\*:\\s*(.+)$`, "m");
|
|
213
|
+
const match = pattern.exec(block);
|
|
214
|
+
if (!match)
|
|
215
|
+
return "";
|
|
216
|
+
// Strip backticks wrapping the value
|
|
217
|
+
return match[1].trim().replace(/^`|`$/g, "");
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=raw.js.map
|
package/dist/raw.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.js","sourceRoot":"","sources":["../src/raw.ts"],"names":[],"mappings":"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"}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction — strips API keys, tokens, passwords, and other
|
|
3
|
+
* sensitive values from wiki page content before writing.
|
|
4
|
+
*
|
|
5
|
+
* Runs automatically on every wiki_write to prevent secrets from
|
|
6
|
+
* being persisted in the knowledge base.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Redact secrets from text content.
|
|
10
|
+
* Returns the redacted text and count of redactions made.
|
|
11
|
+
*/
|
|
12
|
+
export declare function redactSecrets(text: string): {
|
|
13
|
+
text: string;
|
|
14
|
+
redactions: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Check if text contains any detectable secrets.
|
|
18
|
+
* Faster than redactSecrets() — stops at first match.
|
|
19
|
+
*/
|
|
20
|
+
export declare function containsSecrets(text: string): boolean;
|
|
21
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuHH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAiBhF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMrD"}
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction — strips API keys, tokens, passwords, and other
|
|
3
|
+
* sensitive values from wiki page content before writing.
|
|
4
|
+
*
|
|
5
|
+
* Runs automatically on every wiki_write to prevent secrets from
|
|
6
|
+
* being persisted in the knowledge base.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Secret detection patterns — ordered from most specific to most general.
|
|
10
|
+
*
|
|
11
|
+
* Each pattern matches a specific type of secret. The replacement preserves
|
|
12
|
+
* the key type for documentation purposes while removing the actual value.
|
|
13
|
+
*/
|
|
14
|
+
const SECRET_PATTERNS = [
|
|
15
|
+
// --- Provider-specific API key formats ---
|
|
16
|
+
{
|
|
17
|
+
name: "OpenRouter API key",
|
|
18
|
+
pattern: /sk-or-v1-[a-f0-9]{64}/g,
|
|
19
|
+
replacement: "<REDACTED:openrouter-key>",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "OpenAI API key",
|
|
23
|
+
pattern: /sk-[a-zA-Z0-9]{48,}/g,
|
|
24
|
+
replacement: "<REDACTED:openai-key>",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "Anthropic API key",
|
|
28
|
+
pattern: /sk-ant-[a-zA-Z0-9_-]{40,}/g,
|
|
29
|
+
replacement: "<REDACTED:anthropic-key>",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "MiniMax API key",
|
|
33
|
+
pattern: /sk-cp-[a-zA-Z0-9_-]{40,}/g,
|
|
34
|
+
replacement: "<REDACTED:minimax-key>",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "GitHub PAT (fine-grained)",
|
|
38
|
+
pattern: /github_pat_[a-zA-Z0-9_]{60,}/g,
|
|
39
|
+
replacement: "<REDACTED:github-pat>",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "GitHub PAT (classic)",
|
|
43
|
+
pattern: /ghp_[a-zA-Z0-9]{36,}/g,
|
|
44
|
+
replacement: "<REDACTED:github-pat>",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "GitHub OAuth token",
|
|
48
|
+
pattern: /gho_[a-zA-Z0-9]{36,}/g,
|
|
49
|
+
replacement: "<REDACTED:github-oauth>",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "AWS Access Key ID",
|
|
53
|
+
pattern: /AKIA[0-9A-Z]{16}/g,
|
|
54
|
+
replacement: "<REDACTED:aws-key-id>",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "AWS Secret Access Key",
|
|
58
|
+
pattern: /(?<=aws_secret_access_key\s*[=:]\s*)[A-Za-z0-9/+=]{40}/g,
|
|
59
|
+
replacement: "<REDACTED:aws-secret>",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "Jina API key",
|
|
63
|
+
pattern: /jina_[a-zA-Z0-9_-]{30,}/g,
|
|
64
|
+
replacement: "<REDACTED:jina-key>",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "Bearer token",
|
|
68
|
+
pattern: /Bearer [a-zA-Z0-9._-]{30,}/g,
|
|
69
|
+
replacement: "Bearer <REDACTED>",
|
|
70
|
+
},
|
|
71
|
+
// --- Generic key/value patterns in YAML/config context ---
|
|
72
|
+
// Match: key: <long-alphanumeric-value> (in YAML blocks)
|
|
73
|
+
{
|
|
74
|
+
name: "YAML key value",
|
|
75
|
+
pattern: /(?<=^\s*key:\s*)[a-zA-Z0-9_-]{32,}/gm,
|
|
76
|
+
replacement: "<REDACTED>",
|
|
77
|
+
},
|
|
78
|
+
// Match: token: <long-alphanumeric-value>
|
|
79
|
+
{
|
|
80
|
+
name: "YAML token value",
|
|
81
|
+
pattern: /(?<=^\s*token:\s*)[a-zA-Z0-9_-]{32,}/gm,
|
|
82
|
+
replacement: "<REDACTED>",
|
|
83
|
+
},
|
|
84
|
+
// Match: secret: <long-alphanumeric-value>
|
|
85
|
+
{
|
|
86
|
+
name: "YAML secret value",
|
|
87
|
+
pattern: /(?<=^\s*secret:\s*)[a-zA-Z0-9_-]{32,}/gm,
|
|
88
|
+
replacement: "<REDACTED>",
|
|
89
|
+
},
|
|
90
|
+
// Match: password: <value> (any length, in YAML)
|
|
91
|
+
{
|
|
92
|
+
name: "YAML password value",
|
|
93
|
+
pattern: /(?<=^\s*password:\s*)\S+/gm,
|
|
94
|
+
replacement: "<REDACTED>",
|
|
95
|
+
},
|
|
96
|
+
// Match: api_key: / apiKey: <long-alphanumeric-value>
|
|
97
|
+
{
|
|
98
|
+
name: "YAML api_key value",
|
|
99
|
+
pattern: /(?<=^\s*(?:api_key|apiKey|api-key):\s*)[a-zA-Z0-9_-]{20,}/gm,
|
|
100
|
+
replacement: "<REDACTED>",
|
|
101
|
+
},
|
|
102
|
+
// --- Environment variable patterns ---
|
|
103
|
+
// Match: export SECRET_NAME=value or SECRET_NAME="value"
|
|
104
|
+
{
|
|
105
|
+
name: "Env var secret",
|
|
106
|
+
pattern: /(?<=(?:export\s+)?(?:API_KEY|SECRET|TOKEN|PASSWORD|PRIVATE_KEY|ACCESS_KEY)[A-Z_]*\s*=\s*["']?)[^\s"']{16,}/g,
|
|
107
|
+
replacement: "<REDACTED>",
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
// -- Public API --------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Redact secrets from text content.
|
|
113
|
+
* Returns the redacted text and count of redactions made.
|
|
114
|
+
*/
|
|
115
|
+
export function redactSecrets(text) {
|
|
116
|
+
let result = text;
|
|
117
|
+
let redactions = 0;
|
|
118
|
+
for (const { pattern, replacement } of SECRET_PATTERNS) {
|
|
119
|
+
// Reset regex state for global patterns
|
|
120
|
+
const re = new RegExp(pattern.source, pattern.flags);
|
|
121
|
+
const before = result;
|
|
122
|
+
result = result.replace(re, replacement);
|
|
123
|
+
if (result !== before) {
|
|
124
|
+
// Count how many replacements were made
|
|
125
|
+
const matches = before.match(new RegExp(pattern.source, pattern.flags));
|
|
126
|
+
redactions += matches?.length ?? 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { text: result, redactions };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if text contains any detectable secrets.
|
|
133
|
+
* Faster than redactSecrets() — stops at first match.
|
|
134
|
+
*/
|
|
135
|
+
export function containsSecrets(text) {
|
|
136
|
+
for (const { pattern } of SECRET_PATTERNS) {
|
|
137
|
+
const re = new RegExp(pattern.source, pattern.flags);
|
|
138
|
+
if (re.test(text))
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"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"}
|
package/dist/repair.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const GENERATED_STATE_GITIGNORE_PATTERNS: string[];
|
|
2
|
+
export interface GitignoreRepairResult {
|
|
3
|
+
path: string;
|
|
4
|
+
changed: boolean;
|
|
5
|
+
added: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function missingGeneratedStateGitignorePatterns(wikiDir: string): string[];
|
|
8
|
+
export declare function ensureGeneratedStateGitignore(wikiDir: string): Promise<GitignoreRepairResult>;
|
|
9
|
+
export declare function fixSecretPermissions(secretsPath: string): boolean;
|
|
10
|
+
export declare function readMode(path: string): number;
|
|
11
|
+
//# sourceMappingURL=repair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.d.ts","sourceRoot":"","sources":["../src/repair.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kCAAkC,UAM9C,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,sCAAsC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAKhF;AAED,wBAAsB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAWnG;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAMjE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C"}
|
package/dist/repair.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync, chmodSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export const GENERATED_STATE_GITIGNORE_PATTERNS = [
|
|
5
|
+
".qmd.sqlite*",
|
|
6
|
+
".daemon.sqlite*",
|
|
7
|
+
".pi-para.sqlite*",
|
|
8
|
+
"gepa/input/",
|
|
9
|
+
"gepa/output/",
|
|
10
|
+
];
|
|
11
|
+
export function missingGeneratedStateGitignorePatterns(wikiDir) {
|
|
12
|
+
const path = join(wikiDir, ".gitignore");
|
|
13
|
+
const existing = existsSync(path) ? readFileSync(path, "utf-8") : "";
|
|
14
|
+
const lines = existing.split(/\r?\n/);
|
|
15
|
+
return GENERATED_STATE_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
|
|
16
|
+
}
|
|
17
|
+
export async function ensureGeneratedStateGitignore(wikiDir) {
|
|
18
|
+
const path = join(wikiDir, ".gitignore");
|
|
19
|
+
await mkdir(dirname(path), { recursive: true });
|
|
20
|
+
const existing = existsSync(path) ? readFileSync(path, "utf-8") : "";
|
|
21
|
+
const added = missingGeneratedStateGitignorePatterns(wikiDir);
|
|
22
|
+
if (added.length === 0)
|
|
23
|
+
return { path, changed: false, added: [] };
|
|
24
|
+
const prefix = existing.trimEnd().length > 0 ? `${existing.trimEnd()}\n` : "";
|
|
25
|
+
const block = `${prefix}${prefix ? "\n" : ""}# pi-para generated state (do not version)\n${added.join("\n")}\n`;
|
|
26
|
+
await writeFile(path, block, "utf-8");
|
|
27
|
+
return { path, changed: true, added };
|
|
28
|
+
}
|
|
29
|
+
export function fixSecretPermissions(secretsPath) {
|
|
30
|
+
if (!existsSync(secretsPath))
|
|
31
|
+
return false;
|
|
32
|
+
const before = readMode(secretsPath);
|
|
33
|
+
if ((before & 0o077) === 0)
|
|
34
|
+
return false;
|
|
35
|
+
chmodSync(secretsPath, 0o600);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
export function readMode(path) {
|
|
39
|
+
return existsSync(path) ? (statSync(path).mode & 0o777) : 0;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.js","sourceRoot":"","sources":["../src/repair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,kCAAkC,GAAG;IAChD,cAAc;IACd,iBAAiB;IACjB,kBAAkB;IAClB,aAAa;IACb,cAAc;CACf,CAAC;AAQF,MAAM,UAAU,sCAAsC,CAAC,OAAe;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,kCAAkC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,OAAe;IACjE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,sCAAsC,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAEnE,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,MAAM,KAAK,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,+CAA+C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAChH,MAAM,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC9B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC"}
|