deepclause-pi 0.1.3
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/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +59 -0
- package/dist/context.d.ts +3 -0
- package/dist/context.js +38 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +809 -0
- package/dist/planner.d.ts +45 -0
- package/dist/planner.js +223 -0
- package/dist/runtime.d.ts +30 -0
- package/dist/runtime.js +282 -0
- package/dist/workspace.d.ts +12 -0
- package/dist/workspace.js +116 -0
- package/docs/AUTHORING_GUIDE_ANALYSIS.md +172 -0
- package/docs/DC_PLAN_PROPOSAL.md +423 -0
- package/package.json +58 -0
- package/src/assets/AGENTS.md +435 -0
- package/src/assets/deep_research.dml +55 -0
- package/src/config.ts +74 -0
- package/src/context.ts +50 -0
- package/src/index.ts +857 -0
- package/src/planner.ts +265 -0
- package/src/runtime.ts +364 -0
- package/src/workspace.ts +127 -0
package/src/workspace.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { access, mkdir, readFile, realpath, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { DEFAULT_CONFIG } from "./config.js";
|
|
5
|
+
|
|
6
|
+
export interface DeepClausePaths {
|
|
7
|
+
root: string;
|
|
8
|
+
skills: string;
|
|
9
|
+
plans: string;
|
|
10
|
+
config: string;
|
|
11
|
+
agents: string;
|
|
12
|
+
reference: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const EXAMPLE_DML = `% Pi-hosted DeepClause tour.
|
|
16
|
+
% Demonstrates deterministic CLP(FD), read-only and approved bash pi tools,
|
|
17
|
+
% progress events, typed LLM output, and a final answer.
|
|
18
|
+
% Run with: /dc-run example --debug
|
|
19
|
+
:- use_module(library(clpfd)).
|
|
20
|
+
|
|
21
|
+
solve_pair(X, Y) :-
|
|
22
|
+
X in 1..20,
|
|
23
|
+
Y in 1..20,
|
|
24
|
+
X #< Y,
|
|
25
|
+
X + Y #= 14,
|
|
26
|
+
X * Y #= 48,
|
|
27
|
+
labeling([], [X, Y]).
|
|
28
|
+
|
|
29
|
+
agent_main :-
|
|
30
|
+
output("Phase 1/4: solving X + Y = 14 and X * Y = 48 with CLP(FD)..."),
|
|
31
|
+
solve_pair(X, Y),
|
|
32
|
+
format(string(Solved), "The deterministic solution is X=~w and Y=~w.", [X, Y]),
|
|
33
|
+
output(Solved),
|
|
34
|
+
output("Phase 2/4: listing the active workspace through pi_workspace_list..."),
|
|
35
|
+
exec(pi_workspace_list("."), WorkspaceResult),
|
|
36
|
+
get_dict(entries, WorkspaceResult, Entries),
|
|
37
|
+
length(Entries, EntryCount),
|
|
38
|
+
format(string(ToolSummary), "pi.exec returned ~w top-level workspace entries: ~w", [EntryCount, Entries]),
|
|
39
|
+
output(ToolSummary),
|
|
40
|
+
output("Phase 3/4: requesting an approved bash command through pi_bash..."),
|
|
41
|
+
exec(pi_bash("printf 'bash bridge cwd=%s' \\"$PWD\\""), BashResult),
|
|
42
|
+
get_dict(stdout, BashResult, BashStdout),
|
|
43
|
+
normalize_space(string(BashSummary), BashStdout),
|
|
44
|
+
output(BashSummary),
|
|
45
|
+
output("Phase 4/4: asking pi's active model for a concise explanation..."),
|
|
46
|
+
format(string(Request),
|
|
47
|
+
"Explain in two short sentences why X=~w and Y=~w satisfy X + Y = 14 and X * Y = 48. Mention that the pi-hosted workspace tool observed ~w top-level entries and the approved bash bridge returned: ~w. Store only the explanation in Explanation.",
|
|
48
|
+
[X, Y, EntryCount, BashSummary]),
|
|
49
|
+
task(Request, string(Explanation)),
|
|
50
|
+
format(string(Result), "~w\\n~w\\nBash: ~w\\n\\nModel explanation: ~w", [Solved, ToolSummary, BashSummary, Explanation]),
|
|
51
|
+
answer(Result).
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
export function getPaths(cwd: string): DeepClausePaths {
|
|
55
|
+
const root = path.join(cwd, ".pi", "deepclause");
|
|
56
|
+
return {
|
|
57
|
+
root,
|
|
58
|
+
skills: path.join(root, "skills"),
|
|
59
|
+
plans: path.join(root, "plans"),
|
|
60
|
+
config: path.join(root, "config.json"),
|
|
61
|
+
agents: path.join(root, "AGENTS.md"),
|
|
62
|
+
reference: path.join(root, "DML_REFERENCE.md"),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function writeIfMissing(filePath: string, content: string): Promise<void> {
|
|
67
|
+
try {
|
|
68
|
+
await writeFile(filePath, content, { encoding: "utf8", flag: "wx" });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function bundledReference(): Promise<string> {
|
|
75
|
+
const sdkEntry = fileURLToPath(import.meta.resolve("deepclause-sdk"));
|
|
76
|
+
const referencePath = path.join(path.dirname(sdkEntry), "system", "assets", "docs", "DML_REFERENCE.md");
|
|
77
|
+
return readFile(referencePath, "utf8");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function bundledAuthoringGuide(): Promise<string> {
|
|
81
|
+
return readFile(fileURLToPath(new URL("./assets/AGENTS.md", import.meta.url)), "utf8");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function bundledDeepResearch(): Promise<string> {
|
|
85
|
+
return readFile(fileURLToPath(new URL("./assets/deep_research.dml", import.meta.url)), "utf8");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function initializeWorkspace(cwd: string): Promise<DeepClausePaths> {
|
|
89
|
+
const paths = getPaths(cwd);
|
|
90
|
+
await Promise.all([
|
|
91
|
+
mkdir(paths.skills, { recursive: true }),
|
|
92
|
+
mkdir(paths.plans, { recursive: true }),
|
|
93
|
+
]);
|
|
94
|
+
await Promise.all([
|
|
95
|
+
writeIfMissing(paths.config, `${JSON.stringify(DEFAULT_CONFIG, null, 2)}\n`),
|
|
96
|
+
writeIfMissing(paths.agents, await bundledAuthoringGuide()),
|
|
97
|
+
writeIfMissing(paths.reference, await bundledReference()),
|
|
98
|
+
writeIfMissing(path.join(paths.skills, "example.dml"), EXAMPLE_DML),
|
|
99
|
+
writeIfMissing(path.join(paths.skills, "deep_research.dml"), await bundledDeepResearch()),
|
|
100
|
+
]);
|
|
101
|
+
return paths;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isInside(parent: string, child: string): boolean {
|
|
105
|
+
const relative = path.relative(parent, child);
|
|
106
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function resolveDmlPath(paths: DeepClausePaths, request: string): Promise<string> {
|
|
110
|
+
if (!request || path.isAbsolute(request)) throw new Error("A relative skill name or path is required");
|
|
111
|
+
const hasPathSyntax = request.includes("/") || request.includes("\\");
|
|
112
|
+
const candidate = hasPathSyntax
|
|
113
|
+
? path.resolve(paths.root, request)
|
|
114
|
+
: path.resolve(paths.skills, request.endsWith(".dml") ? request : `${request}.dml`);
|
|
115
|
+
if (!isInside(path.resolve(paths.root), candidate)) throw new Error("DML path escapes .pi/deepclause");
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
await access(candidate);
|
|
119
|
+
const [realRoot, realCandidate] = await Promise.all([realpath(paths.root), realpath(candidate)]);
|
|
120
|
+
if (!isInside(realRoot, realCandidate)) throw new Error("DML path escapes .pi/deepclause through a symlink");
|
|
121
|
+
if (!realCandidate.endsWith(".dml")) throw new Error("DeepClause programs must use the .dml extension");
|
|
122
|
+
return realCandidate;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") throw new Error(`DML file not found: ${request}`);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|