thoth-plugin 1.1.2 → 1.2.0
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/config/schema.d.ts +4 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/read-confirmation.d.ts +34 -0
- package/dist/hooks/write-confirmation.d.ts +34 -0
- package/dist/index.js +131 -38
- package/package.json +1 -1
package/dist/config/schema.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ declare const HooksConfigSchema: z.ZodObject<{
|
|
|
13
13
|
"knowledge-persistence": z.ZodOptional<z.ZodBoolean>;
|
|
14
14
|
"directory-agents-injector": z.ZodOptional<z.ZodBoolean>;
|
|
15
15
|
"frontmatter-enforcer": z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
"read-confirmation": z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
"write-confirmation": z.ZodOptional<z.ZodBoolean>;
|
|
16
18
|
"todo-continuation": z.ZodOptional<z.ZodBoolean>;
|
|
17
19
|
"session-recovery": z.ZodOptional<z.ZodBoolean>;
|
|
18
20
|
"context-window-monitor": z.ZodOptional<z.ZodBoolean>;
|
|
@@ -67,6 +69,8 @@ export declare const ThothPluginConfigSchema: z.ZodObject<{
|
|
|
67
69
|
"knowledge-persistence": z.ZodOptional<z.ZodBoolean>;
|
|
68
70
|
"directory-agents-injector": z.ZodOptional<z.ZodBoolean>;
|
|
69
71
|
"frontmatter-enforcer": z.ZodOptional<z.ZodBoolean>;
|
|
72
|
+
"read-confirmation": z.ZodOptional<z.ZodBoolean>;
|
|
73
|
+
"write-confirmation": z.ZodOptional<z.ZodBoolean>;
|
|
70
74
|
"todo-continuation": z.ZodOptional<z.ZodBoolean>;
|
|
71
75
|
"session-recovery": z.ZodOptional<z.ZodBoolean>;
|
|
72
76
|
"context-window-monitor": z.ZodOptional<z.ZodBoolean>;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export { createTrustLevelTrackerHook, type TrustLevelTrackerHook, type TrustLeve
|
|
|
3
3
|
export { createContextApertureHook, type ContextApertureHook, type ContextApertureConfig, } from "./context-aperture";
|
|
4
4
|
export { createTemporalAwarenessHook, type TemporalAwarenessHook, type TemporalAwarenessConfig, } from "./temporal-awareness";
|
|
5
5
|
export { createFrontmatterEnforcerHook, type FrontmatterEnforcerHook, type FrontmatterEnforcerConfig, } from "./frontmatter-enforcer";
|
|
6
|
+
export { createReadConfirmationHook, type ReadConfirmationHook, type ReadConfirmationConfig, } from "./read-confirmation";
|
|
7
|
+
export { createWriteConfirmationHook, type WriteConfirmationHook, type WriteConfirmationConfig, } from "./write-confirmation";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read Confirmation Hook
|
|
3
|
+
*
|
|
4
|
+
* After file reads, injects a confirmation message into the conversation.
|
|
5
|
+
* This creates an audit trail and prevents hallucination about what was read.
|
|
6
|
+
*
|
|
7
|
+
* Value:
|
|
8
|
+
* - Prevents "I read file X" when it wasn't actually read
|
|
9
|
+
* - Creates audit trail of file access
|
|
10
|
+
* - Helps with context management
|
|
11
|
+
*/
|
|
12
|
+
export interface ReadConfirmationConfig {
|
|
13
|
+
knowledgeBasePath: string;
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
/** Only confirm reads within the knowledge base (default: true) */
|
|
16
|
+
kbOnly?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function createReadConfirmationHook(config: ReadConfirmationConfig): {
|
|
19
|
+
"tool.execute.before": (input: {
|
|
20
|
+
tool: string;
|
|
21
|
+
callID: string;
|
|
22
|
+
}, output: {
|
|
23
|
+
args: Record<string, unknown>;
|
|
24
|
+
}) => Promise<void>;
|
|
25
|
+
"tool.execute.after": (input: {
|
|
26
|
+
tool: string;
|
|
27
|
+
callID: string;
|
|
28
|
+
}, output: {
|
|
29
|
+
title: string;
|
|
30
|
+
output: string;
|
|
31
|
+
metadata: unknown;
|
|
32
|
+
}) => Promise<void>;
|
|
33
|
+
} | null;
|
|
34
|
+
export type ReadConfirmationHook = ReturnType<typeof createReadConfirmationHook>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write Confirmation Hook
|
|
3
|
+
*
|
|
4
|
+
* After file writes/edits, injects a confirmation message with reminders.
|
|
5
|
+
* This creates an audit trail and reinforces the Smart Merge protocol.
|
|
6
|
+
*
|
|
7
|
+
* Value:
|
|
8
|
+
* - Reminds about _index.md updates for new files
|
|
9
|
+
* - Creates audit trail of file modifications
|
|
10
|
+
* - Reinforces Smart Merge protocol
|
|
11
|
+
*/
|
|
12
|
+
export interface WriteConfirmationConfig {
|
|
13
|
+
knowledgeBasePath: string;
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
/** Only confirm writes within the knowledge base (default: true) */
|
|
16
|
+
kbOnly?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function createWriteConfirmationHook(config: WriteConfirmationConfig): {
|
|
19
|
+
"tool.execute.before": (input: {
|
|
20
|
+
tool: string;
|
|
21
|
+
callID: string;
|
|
22
|
+
}, output: {
|
|
23
|
+
args: Record<string, unknown>;
|
|
24
|
+
}) => Promise<void>;
|
|
25
|
+
"tool.execute.after": (input: {
|
|
26
|
+
tool: string;
|
|
27
|
+
callID: string;
|
|
28
|
+
}, output: {
|
|
29
|
+
title: string;
|
|
30
|
+
output: string;
|
|
31
|
+
metadata: unknown;
|
|
32
|
+
}) => Promise<void>;
|
|
33
|
+
} | null;
|
|
34
|
+
export type WriteConfirmationHook = ReturnType<typeof createWriteConfirmationHook>;
|
package/dist/index.js
CHANGED
|
@@ -3554,6 +3554,91 @@ function createFrontmatterEnforcerHook(config) {
|
|
|
3554
3554
|
}
|
|
3555
3555
|
};
|
|
3556
3556
|
}
|
|
3557
|
+
// src/hooks/read-confirmation.ts
|
|
3558
|
+
import * as path6 from "path";
|
|
3559
|
+
function createReadConfirmationHook(config) {
|
|
3560
|
+
const { knowledgeBasePath, enabled = true, kbOnly = true } = config;
|
|
3561
|
+
if (!enabled) {
|
|
3562
|
+
return null;
|
|
3563
|
+
}
|
|
3564
|
+
const kbPath = expandPath(knowledgeBasePath);
|
|
3565
|
+
const tracker = {
|
|
3566
|
+
pendingReadPaths: new Map
|
|
3567
|
+
};
|
|
3568
|
+
return {
|
|
3569
|
+
"tool.execute.before": async (input, output) => {
|
|
3570
|
+
if (input.tool !== "read")
|
|
3571
|
+
return;
|
|
3572
|
+
const filePath = output.args?.filePath;
|
|
3573
|
+
if (filePath && input.callID) {
|
|
3574
|
+
tracker.pendingReadPaths.set(input.callID, filePath);
|
|
3575
|
+
}
|
|
3576
|
+
},
|
|
3577
|
+
"tool.execute.after": async (input, output) => {
|
|
3578
|
+
if (input.tool !== "read")
|
|
3579
|
+
return;
|
|
3580
|
+
const filePath = tracker.pendingReadPaths.get(input.callID);
|
|
3581
|
+
tracker.pendingReadPaths.delete(input.callID);
|
|
3582
|
+
if (!filePath)
|
|
3583
|
+
return;
|
|
3584
|
+
if (kbOnly && !filePath.startsWith(kbPath)) {
|
|
3585
|
+
return;
|
|
3586
|
+
}
|
|
3587
|
+
const lineCount = output.output?.split(`
|
|
3588
|
+
`).length || 0;
|
|
3589
|
+
const relativePath = filePath.startsWith(kbPath) ? filePath.slice(kbPath.length + 1) : path6.basename(filePath);
|
|
3590
|
+
log(`[Read confirmed: ${relativePath} (${lineCount} lines)]`);
|
|
3591
|
+
}
|
|
3592
|
+
};
|
|
3593
|
+
}
|
|
3594
|
+
// src/hooks/write-confirmation.ts
|
|
3595
|
+
import * as path7 from "path";
|
|
3596
|
+
function createWriteConfirmationHook(config) {
|
|
3597
|
+
const { knowledgeBasePath, enabled = true, kbOnly = true } = config;
|
|
3598
|
+
if (!enabled) {
|
|
3599
|
+
return null;
|
|
3600
|
+
}
|
|
3601
|
+
const kbPath = expandPath(knowledgeBasePath);
|
|
3602
|
+
const tracker = {
|
|
3603
|
+
pendingWritePaths: new Map
|
|
3604
|
+
};
|
|
3605
|
+
return {
|
|
3606
|
+
"tool.execute.before": async (input, output) => {
|
|
3607
|
+
if (input.tool !== "write" && input.tool !== "edit")
|
|
3608
|
+
return;
|
|
3609
|
+
const filePath = output.args?.filePath;
|
|
3610
|
+
if (filePath && input.callID) {
|
|
3611
|
+
tracker.pendingWritePaths.set(input.callID, {
|
|
3612
|
+
filePath,
|
|
3613
|
+
action: input.tool
|
|
3614
|
+
});
|
|
3615
|
+
}
|
|
3616
|
+
},
|
|
3617
|
+
"tool.execute.after": async (input, output) => {
|
|
3618
|
+
if (input.tool !== "write" && input.tool !== "edit")
|
|
3619
|
+
return;
|
|
3620
|
+
const pending = tracker.pendingWritePaths.get(input.callID);
|
|
3621
|
+
tracker.pendingWritePaths.delete(input.callID);
|
|
3622
|
+
if (!pending)
|
|
3623
|
+
return;
|
|
3624
|
+
const { filePath, action } = pending;
|
|
3625
|
+
if (kbOnly && !filePath.startsWith(kbPath)) {
|
|
3626
|
+
return;
|
|
3627
|
+
}
|
|
3628
|
+
const relativePath = filePath.startsWith(kbPath) ? filePath.slice(kbPath.length + 1) : path7.basename(filePath);
|
|
3629
|
+
const actionLabel = action === "write" ? "Created/Overwrote" : "Edited";
|
|
3630
|
+
const isNewFile = action === "write";
|
|
3631
|
+
const isMarkdownFile = filePath.endsWith(".md");
|
|
3632
|
+
const isIndexFile = relativePath.includes("_index.md") || relativePath.includes("registry.md");
|
|
3633
|
+
let message = `[${actionLabel}: ${relativePath}]`;
|
|
3634
|
+
if (isNewFile && isMarkdownFile && !isIndexFile) {
|
|
3635
|
+
message += `
|
|
3636
|
+
Reminder: Update _index.md if this is a new file. Check bidirectional links.`;
|
|
3637
|
+
}
|
|
3638
|
+
log(message);
|
|
3639
|
+
}
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3557
3642
|
// src/hooks/directory-agents-injector/index.ts
|
|
3558
3643
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
3559
3644
|
import { dirname as dirname4, join as join9, resolve as resolve2 } from "path";
|
|
@@ -3678,8 +3763,8 @@ function createDirectoryAgentsInjectorHook(options) {
|
|
|
3678
3763
|
}
|
|
3679
3764
|
if (toInject.length === 0)
|
|
3680
3765
|
return;
|
|
3681
|
-
for (const { path:
|
|
3682
|
-
const relativePath =
|
|
3766
|
+
for (const { path: path8, content } of toInject) {
|
|
3767
|
+
const relativePath = path8.replace(knowledgeBasePath, "").replace(/^\//, "");
|
|
3683
3768
|
output.output += `
|
|
3684
3769
|
|
|
3685
3770
|
[Directory Context: ${relativePath}]
|
|
@@ -3766,8 +3851,8 @@ function findNearestMessageWithFields(messageDir) {
|
|
|
3766
3851
|
// src/shared-hooks/utils/logger.ts
|
|
3767
3852
|
import * as fs2 from "fs";
|
|
3768
3853
|
import * as os2 from "os";
|
|
3769
|
-
import * as
|
|
3770
|
-
var logFile =
|
|
3854
|
+
import * as path8 from "path";
|
|
3855
|
+
var logFile = path8.join(os2.tmpdir(), "thoth-plugin.log");
|
|
3771
3856
|
function log2(message, data) {
|
|
3772
3857
|
try {
|
|
3773
3858
|
const timestamp = new Date().toISOString();
|
|
@@ -5567,10 +5652,10 @@ function mergeDefs(...defs) {
|
|
|
5567
5652
|
function cloneDef(schema) {
|
|
5568
5653
|
return mergeDefs(schema._zod.def);
|
|
5569
5654
|
}
|
|
5570
|
-
function getElementAtPath(obj,
|
|
5571
|
-
if (!
|
|
5655
|
+
function getElementAtPath(obj, path9) {
|
|
5656
|
+
if (!path9)
|
|
5572
5657
|
return obj;
|
|
5573
|
-
return
|
|
5658
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
5574
5659
|
}
|
|
5575
5660
|
function promiseAllObject(promisesObj) {
|
|
5576
5661
|
const keys = Object.keys(promisesObj);
|
|
@@ -5929,11 +6014,11 @@ function aborted(x, startIndex = 0) {
|
|
|
5929
6014
|
}
|
|
5930
6015
|
return false;
|
|
5931
6016
|
}
|
|
5932
|
-
function prefixIssues(
|
|
6017
|
+
function prefixIssues(path9, issues) {
|
|
5933
6018
|
return issues.map((iss) => {
|
|
5934
6019
|
var _a;
|
|
5935
6020
|
(_a = iss).path ?? (_a.path = []);
|
|
5936
|
-
iss.path.unshift(
|
|
6021
|
+
iss.path.unshift(path9);
|
|
5937
6022
|
return iss;
|
|
5938
6023
|
});
|
|
5939
6024
|
}
|
|
@@ -6101,7 +6186,7 @@ function treeifyError(error, _mapper) {
|
|
|
6101
6186
|
return issue2.message;
|
|
6102
6187
|
};
|
|
6103
6188
|
const result = { errors: [] };
|
|
6104
|
-
const processError = (error2,
|
|
6189
|
+
const processError = (error2, path9 = []) => {
|
|
6105
6190
|
var _a, _b;
|
|
6106
6191
|
for (const issue2 of error2.issues) {
|
|
6107
6192
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -6111,7 +6196,7 @@ function treeifyError(error, _mapper) {
|
|
|
6111
6196
|
} else if (issue2.code === "invalid_element") {
|
|
6112
6197
|
processError({ issues: issue2.issues }, issue2.path);
|
|
6113
6198
|
} else {
|
|
6114
|
-
const fullpath = [...
|
|
6199
|
+
const fullpath = [...path9, ...issue2.path];
|
|
6115
6200
|
if (fullpath.length === 0) {
|
|
6116
6201
|
result.errors.push(mapper(issue2));
|
|
6117
6202
|
continue;
|
|
@@ -6143,8 +6228,8 @@ function treeifyError(error, _mapper) {
|
|
|
6143
6228
|
}
|
|
6144
6229
|
function toDotPath(_path) {
|
|
6145
6230
|
const segs = [];
|
|
6146
|
-
const
|
|
6147
|
-
for (const seg of
|
|
6231
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6232
|
+
for (const seg of path9) {
|
|
6148
6233
|
if (typeof seg === "number")
|
|
6149
6234
|
segs.push(`[${seg}]`);
|
|
6150
6235
|
else if (typeof seg === "symbol")
|
|
@@ -17435,7 +17520,7 @@ Status: ${task.status}`;
|
|
|
17435
17520
|
// src/tools/skill/tools.ts
|
|
17436
17521
|
import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync9, lstatSync, readlinkSync } from "fs";
|
|
17437
17522
|
import { homedir as homedir5 } from "os";
|
|
17438
|
-
import { join as join17, basename as
|
|
17523
|
+
import { join as join17, basename as basename5, resolve as resolve3, dirname as dirname5 } from "path";
|
|
17439
17524
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17440
17525
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
17441
17526
|
var __dirname3 = dirname5(__filename3);
|
|
@@ -17585,7 +17670,7 @@ async function parseSkillMd(skillPath) {
|
|
|
17585
17670
|
const { data, body } = parseFrontmatter(content);
|
|
17586
17671
|
const frontmatter = parseSkillFrontmatter(data);
|
|
17587
17672
|
const metadata = {
|
|
17588
|
-
name: frontmatter.name ||
|
|
17673
|
+
name: frontmatter.name || basename5(skillPath),
|
|
17589
17674
|
description: frontmatter.description,
|
|
17590
17675
|
license: frontmatter.license,
|
|
17591
17676
|
allowedTools: frontmatter["allowed-tools"],
|
|
@@ -18524,10 +18609,10 @@ function mergeDefs2(...defs) {
|
|
|
18524
18609
|
function cloneDef2(schema) {
|
|
18525
18610
|
return mergeDefs2(schema._zod.def);
|
|
18526
18611
|
}
|
|
18527
|
-
function getElementAtPath2(obj,
|
|
18528
|
-
if (!
|
|
18612
|
+
function getElementAtPath2(obj, path9) {
|
|
18613
|
+
if (!path9)
|
|
18529
18614
|
return obj;
|
|
18530
|
-
return
|
|
18615
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
18531
18616
|
}
|
|
18532
18617
|
function promiseAllObject2(promisesObj) {
|
|
18533
18618
|
const keys = Object.keys(promisesObj);
|
|
@@ -18908,11 +18993,11 @@ function aborted2(x, startIndex = 0) {
|
|
|
18908
18993
|
}
|
|
18909
18994
|
return false;
|
|
18910
18995
|
}
|
|
18911
|
-
function prefixIssues2(
|
|
18996
|
+
function prefixIssues2(path9, issues) {
|
|
18912
18997
|
return issues.map((iss) => {
|
|
18913
18998
|
var _a;
|
|
18914
18999
|
(_a = iss).path ?? (_a.path = []);
|
|
18915
|
-
iss.path.unshift(
|
|
19000
|
+
iss.path.unshift(path9);
|
|
18916
19001
|
return iss;
|
|
18917
19002
|
});
|
|
18918
19003
|
}
|
|
@@ -19095,7 +19180,7 @@ function formatError2(error45, mapper = (issue3) => issue3.message) {
|
|
|
19095
19180
|
}
|
|
19096
19181
|
function treeifyError2(error45, mapper = (issue3) => issue3.message) {
|
|
19097
19182
|
const result = { errors: [] };
|
|
19098
|
-
const processError = (error46,
|
|
19183
|
+
const processError = (error46, path9 = []) => {
|
|
19099
19184
|
var _a, _b;
|
|
19100
19185
|
for (const issue3 of error46.issues) {
|
|
19101
19186
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
@@ -19105,7 +19190,7 @@ function treeifyError2(error45, mapper = (issue3) => issue3.message) {
|
|
|
19105
19190
|
} else if (issue3.code === "invalid_element") {
|
|
19106
19191
|
processError({ issues: issue3.issues }, issue3.path);
|
|
19107
19192
|
} else {
|
|
19108
|
-
const fullpath = [...
|
|
19193
|
+
const fullpath = [...path9, ...issue3.path];
|
|
19109
19194
|
if (fullpath.length === 0) {
|
|
19110
19195
|
result.errors.push(mapper(issue3));
|
|
19111
19196
|
continue;
|
|
@@ -19137,8 +19222,8 @@ function treeifyError2(error45, mapper = (issue3) => issue3.message) {
|
|
|
19137
19222
|
}
|
|
19138
19223
|
function toDotPath2(_path) {
|
|
19139
19224
|
const segs = [];
|
|
19140
|
-
const
|
|
19141
|
-
for (const seg of
|
|
19225
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
19226
|
+
for (const seg of path9) {
|
|
19142
19227
|
if (typeof seg === "number")
|
|
19143
19228
|
segs.push(`[${seg}]`);
|
|
19144
19229
|
else if (typeof seg === "symbol")
|
|
@@ -30885,13 +30970,13 @@ function resolveRef(ref, ctx) {
|
|
|
30885
30970
|
if (!ref.startsWith("#")) {
|
|
30886
30971
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
30887
30972
|
}
|
|
30888
|
-
const
|
|
30889
|
-
if (
|
|
30973
|
+
const path9 = ref.slice(1).split("/").filter(Boolean);
|
|
30974
|
+
if (path9.length === 0) {
|
|
30890
30975
|
return ctx.rootSchema;
|
|
30891
30976
|
}
|
|
30892
30977
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
30893
|
-
if (
|
|
30894
|
-
const key =
|
|
30978
|
+
if (path9[0] === defsKey) {
|
|
30979
|
+
const key = path9[1];
|
|
30895
30980
|
if (!key || !ctx.defs[key]) {
|
|
30896
30981
|
throw new Error(`Reference not found: ${ref}`);
|
|
30897
30982
|
}
|
|
@@ -31306,6 +31391,8 @@ var HooksConfigSchema = exports_external2.object({
|
|
|
31306
31391
|
"knowledge-persistence": exports_external2.boolean().optional(),
|
|
31307
31392
|
"directory-agents-injector": exports_external2.boolean().optional(),
|
|
31308
31393
|
"frontmatter-enforcer": exports_external2.boolean().optional(),
|
|
31394
|
+
"read-confirmation": exports_external2.boolean().optional(),
|
|
31395
|
+
"write-confirmation": exports_external2.boolean().optional(),
|
|
31309
31396
|
"todo-continuation": exports_external2.boolean().optional(),
|
|
31310
31397
|
"session-recovery": exports_external2.boolean().optional(),
|
|
31311
31398
|
"context-window-monitor": exports_external2.boolean().optional(),
|
|
@@ -31343,7 +31430,7 @@ var ThothPluginConfigSchema = exports_external2.object({
|
|
|
31343
31430
|
}).strict();
|
|
31344
31431
|
// src/index.ts
|
|
31345
31432
|
import * as fs3 from "fs";
|
|
31346
|
-
import * as
|
|
31433
|
+
import * as path9 from "path";
|
|
31347
31434
|
var sessionSpecializations = new Map;
|
|
31348
31435
|
function loadConfigFromPath(configPath) {
|
|
31349
31436
|
try {
|
|
@@ -31375,8 +31462,8 @@ function mergeConfigs(base, override) {
|
|
|
31375
31462
|
};
|
|
31376
31463
|
}
|
|
31377
31464
|
function loadPluginConfig(directory) {
|
|
31378
|
-
const userConfigPath =
|
|
31379
|
-
const projectConfigPath =
|
|
31465
|
+
const userConfigPath = path9.join(getUserConfigDir(), "opencode", "thoth-plugin.json");
|
|
31466
|
+
const projectConfigPath = path9.join(directory, ".opencode", "thoth-plugin.json");
|
|
31380
31467
|
let config3 = loadConfigFromPath(userConfigPath) ?? {};
|
|
31381
31468
|
const projectConfig = loadConfigFromPath(projectConfigPath);
|
|
31382
31469
|
if (projectConfig) {
|
|
@@ -31390,15 +31477,15 @@ function resolveKnowledgeBasePath(config3, directory) {
|
|
|
31390
31477
|
return expandPath(config3.knowledge_base);
|
|
31391
31478
|
}
|
|
31392
31479
|
const commonLocations = [
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31480
|
+
path9.join(process.env.HOME || "", "Repos", "thoth"),
|
|
31481
|
+
path9.join(process.env.HOME || "", "repos", "thoth"),
|
|
31482
|
+
path9.join(process.env.HOME || "", "Projects", "thoth"),
|
|
31483
|
+
path9.join(process.env.HOME || "", "projects", "thoth"),
|
|
31484
|
+
path9.join(process.env.HOME || "", "thoth"),
|
|
31485
|
+
path9.join(directory, "thoth")
|
|
31399
31486
|
];
|
|
31400
31487
|
for (const location of commonLocations) {
|
|
31401
|
-
const kernelPath =
|
|
31488
|
+
const kernelPath = path9.join(location, "kernel");
|
|
31402
31489
|
if (fs3.existsSync(kernelPath)) {
|
|
31403
31490
|
log(`Found knowledge base at: ${location}`);
|
|
31404
31491
|
return location;
|
|
@@ -31420,6 +31507,8 @@ var ThothPlugin = async (ctx) => {
|
|
|
31420
31507
|
const contextAperture = hooksConfig["context-aperture"] !== false ? createContextApertureHook({ knowledgeBasePath }) : null;
|
|
31421
31508
|
const temporalAwareness = hooksConfig["temporal-awareness"] !== false ? createTemporalAwarenessHook() : null;
|
|
31422
31509
|
const frontmatterEnforcer = hooksConfig["frontmatter-enforcer"] !== false ? createFrontmatterEnforcerHook({ knowledgeBasePath }) : null;
|
|
31510
|
+
const readConfirmation = hooksConfig["read-confirmation"] !== false ? createReadConfirmationHook({ knowledgeBasePath }) : null;
|
|
31511
|
+
const writeConfirmation = hooksConfig["write-confirmation"] !== false ? createWriteConfirmationHook({ knowledgeBasePath }) : null;
|
|
31423
31512
|
const todoContinuationEnforcer = hooksConfig["todo-continuation"] !== false ? createTodoContinuationEnforcer(ctx) : null;
|
|
31424
31513
|
const sessionRecoveryHook = hooksConfig["session-recovery"] !== false ? createSessionRecoveryHook(ctx, { experimental: { auto_resume: true } }) : null;
|
|
31425
31514
|
const contextWindowMonitor = hooksConfig["context-window-monitor"] !== false ? createContextWindowMonitorHook(ctx) : null;
|
|
@@ -31525,11 +31614,15 @@ var ThothPlugin = async (ctx) => {
|
|
|
31525
31614
|
await contextAperture?.["tool.execute.before"]?.(input, output);
|
|
31526
31615
|
await trustLevelTracker?.["tool.execute.before"]?.(input, output);
|
|
31527
31616
|
await frontmatterEnforcer?.["tool.execute.before"]?.(input, output);
|
|
31617
|
+
await readConfirmation?.["tool.execute.before"]?.(input, output);
|
|
31618
|
+
await writeConfirmation?.["tool.execute.before"]?.(input, output);
|
|
31528
31619
|
},
|
|
31529
31620
|
"tool.execute.after": async (input, output) => {
|
|
31530
31621
|
await trustLevelTracker?.["tool.execute.after"]?.(input, output);
|
|
31531
31622
|
await contextAperture?.["tool.execute.after"]?.(input, output);
|
|
31532
31623
|
await frontmatterEnforcer?.["tool.execute.after"]?.(input, output);
|
|
31624
|
+
await readConfirmation?.["tool.execute.after"]?.(input, output);
|
|
31625
|
+
await writeConfirmation?.["tool.execute.after"]?.(input, output);
|
|
31533
31626
|
await directoryAgentsInjector?.["tool.execute.after"]?.(input, output);
|
|
31534
31627
|
await contextWindowMonitor?.["tool.execute.after"]?.(input, output);
|
|
31535
31628
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Thoth - Root-level life orchestrator for OpenCode. Unified AI chief of staff combining Sisyphus execution quality, Personal-OS rhythms, and Thoth relationship model.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|