@veewo/claw 0.1.77 → 0.1.79
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/README.md +72 -69
- package/dist/bin.js +8 -2
- package/dist/bin.js.map +1 -1
- package/dist/cli.js +229 -122
- package/dist/cli.js.map +1 -1
- package/dist/codex-driver.js +0 -1
- package/dist/codex-driver.js.map +1 -1
- package/dist/invocation-host.d.ts +6 -0
- package/dist/invocation-host.js +29 -0
- package/dist/invocation-host.js.map +1 -0
- package/dist/knowledge-hook-preflight.d.ts +3 -0
- package/dist/knowledge-hook-preflight.js +112 -0
- package/dist/knowledge-hook-preflight.js.map +1 -0
- package/dist/knowledge-writer-result.d.ts +11 -0
- package/dist/knowledge-writer-result.js +50 -0
- package/dist/knowledge-writer-result.js.map +1 -0
- package/dist/opencode-runner.d.ts +23 -0
- package/dist/opencode-runner.js +105 -0
- package/dist/opencode-runner.js.map +1 -0
- package/package.json +41 -41
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
let bufferedHookInput = null;
|
|
5
|
+
export async function shouldLoadCliForInvocation(args, cwd, env) {
|
|
6
|
+
if (!isKnowledgeHookInvocation(args)) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (env.CLAW_KNOWLEDGE_FINALIZER === "1") {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (!resolveCurrentClawDir(cwd)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const rawInput = await readStdin();
|
|
16
|
+
if (!shouldRunKnowledgeHook(rawInput, cwd, env)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
bufferedHookInput = rawInput;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
export function shouldRunKnowledgeHook(rawInput, cwd, env) {
|
|
23
|
+
const payload = parseHookPayload(rawInput);
|
|
24
|
+
const hookCwd = readHookString(payload, "cwd") ?? cwd.trim();
|
|
25
|
+
const sessionId = resolveSessionId(payload, env);
|
|
26
|
+
if (!hookCwd || !sessionId) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const clawDir = resolveCurrentClawDir(hookCwd);
|
|
30
|
+
if (!clawDir || !hasKnowledgeContext(clawDir, sessionId)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
export function consumeBufferedHookInput() {
|
|
36
|
+
const input = bufferedHookInput;
|
|
37
|
+
bufferedHookInput = null;
|
|
38
|
+
return input;
|
|
39
|
+
}
|
|
40
|
+
function isKnowledgeHookInvocation(args) {
|
|
41
|
+
const positional = [];
|
|
42
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
43
|
+
if (args[index] === "--host") {
|
|
44
|
+
index += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
positional.push(args[index]);
|
|
48
|
+
}
|
|
49
|
+
return positional[0] === "hook" && (positional[1] === "auto-doc" || positional[1] === "Stop");
|
|
50
|
+
}
|
|
51
|
+
async function readStdin() {
|
|
52
|
+
const chunks = [];
|
|
53
|
+
for await (const chunk of process.stdin) {
|
|
54
|
+
chunks.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
|
|
55
|
+
}
|
|
56
|
+
return chunks.join("");
|
|
57
|
+
}
|
|
58
|
+
function parseHookPayload(rawInput) {
|
|
59
|
+
const raw = rawInput.trim();
|
|
60
|
+
if (!raw) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(raw);
|
|
65
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
66
|
+
? parsed
|
|
67
|
+
: null;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function resolveSessionId(payload, env) {
|
|
74
|
+
for (const candidate of [env.CODEX_THREAD_ID, env.CODEX_SESSION_ID, readHookString(payload, "session_id")]) {
|
|
75
|
+
if (candidate?.trim()) {
|
|
76
|
+
return candidate.trim();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function readHookString(payload, key) {
|
|
82
|
+
const value = payload?.[key];
|
|
83
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
84
|
+
}
|
|
85
|
+
function resolveCurrentClawDir(cwd) {
|
|
86
|
+
try {
|
|
87
|
+
const candidate = path.join(path.resolve(cwd), ".claw");
|
|
88
|
+
return fs.statSync(candidate).isDirectory() ? candidate : null;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function hasKnowledgeContext(clawDir, sessionId) {
|
|
95
|
+
const knowledgeKey = createHash("sha256").update(sessionId).digest("hex");
|
|
96
|
+
const knowledgeRegistryPath = path.join(clawDir, "runtime", "knowledge-sessions", `${knowledgeKey}.json`);
|
|
97
|
+
return registryHasKnowledgeTarget(knowledgeRegistryPath, sessionId);
|
|
98
|
+
}
|
|
99
|
+
function registryHasKnowledgeTarget(registryPath, sessionId) {
|
|
100
|
+
try {
|
|
101
|
+
const registry = JSON.parse(fs.readFileSync(registryPath, "utf8"));
|
|
102
|
+
if (registry.sessionId !== sessionId) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return Boolean(registry.pendingTurnOwner
|
|
106
|
+
|| (typeof registry.activePlanPath === "string" && typeof registry.activeReportPath === "string"));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=knowledge-hook-preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge-hook-preflight.js","sourceRoot":"","sources":["../src/knowledge-hook-preflight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type KnowledgeWriterResult = {
|
|
2
|
+
status: "changed" | "no-op";
|
|
3
|
+
updatedPaths: string[];
|
|
4
|
+
coveredFacts: string[];
|
|
5
|
+
coveredDecisions: string[];
|
|
6
|
+
excludedItems: string[];
|
|
7
|
+
conflictsResolved: string[];
|
|
8
|
+
reason?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Parse the structured result required by the built-in knowledge writer. */
|
|
11
|
+
export declare function parseKnowledgeWriterResult(response: string): KnowledgeWriterResult | null;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function stringList(value) {
|
|
2
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
|
|
3
|
+
return null;
|
|
4
|
+
}
|
|
5
|
+
return value.map((item) => String(item).trim());
|
|
6
|
+
}
|
|
7
|
+
/** Parse the structured result required by the built-in knowledge writer. */
|
|
8
|
+
export function parseKnowledgeWriterResult(response) {
|
|
9
|
+
let value;
|
|
10
|
+
try {
|
|
11
|
+
value = JSON.parse(response.trim());
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (!value || typeof value !== "object") {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const record = value;
|
|
20
|
+
if (record.status !== "changed" && record.status !== "no-op") {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const updatedPaths = stringList(record.updatedPaths);
|
|
24
|
+
const coveredFacts = stringList(record.coveredFacts);
|
|
25
|
+
const coveredDecisions = stringList(record.coveredDecisions);
|
|
26
|
+
const excludedItems = stringList(record.excludedItems);
|
|
27
|
+
const conflictsResolved = stringList(record.conflictsResolved);
|
|
28
|
+
if (!updatedPaths || !coveredFacts || !coveredDecisions || !excludedItems || !conflictsResolved) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const reason = typeof record.reason === "string" && record.reason.trim()
|
|
32
|
+
? record.reason.trim()
|
|
33
|
+
: undefined;
|
|
34
|
+
if (record.status === "changed" && updatedPaths.length === 0) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (record.status === "no-op" && (updatedPaths.length > 0 || !reason)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
status: record.status,
|
|
42
|
+
updatedPaths,
|
|
43
|
+
coveredFacts,
|
|
44
|
+
coveredDecisions,
|
|
45
|
+
excludedItems,
|
|
46
|
+
conflictsResolved,
|
|
47
|
+
...(reason ? { reason } : {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=knowledge-writer-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge-writer-result.js","sourceRoot":"","sources":["../src/knowledge-writer-result.ts"],"names":[],"mappings":"AAUA,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IACzD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,IAAI,CAAC,gBAAgB,IAAI,CAAC,aAAa,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChG,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QACtE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QACtB,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,aAAa;QACb,iBAAiB;QACjB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { KnowledgeWriterConfig } from "@veewo/claw-core";
|
|
2
|
+
export type OpencodeRunnerResult = {
|
|
3
|
+
finalResponse: string;
|
|
4
|
+
threadId?: string;
|
|
5
|
+
};
|
|
6
|
+
/** Resolve the opencode CLI binary path. CLAW_OPENCODE_PATH_OVERRIDE supports hermetic tests. */
|
|
7
|
+
export declare function resolveOpencodeBinary(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Finalization runner for the opencode host. The opencode adapter cannot assume a
|
|
10
|
+
* Codex SDK runtime is installed locally, so deposition runs through `opencode run`
|
|
11
|
+
* inside the user's own opencode environment instead of the Codex SDK.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runOpencodeKnowledgeWriter(input: {
|
|
14
|
+
prompt: string;
|
|
15
|
+
projectRoot: string;
|
|
16
|
+
writer?: KnowledgeWriterConfig | null;
|
|
17
|
+
}): OpencodeRunnerResult;
|
|
18
|
+
/**
|
|
19
|
+
* Parse the NDJSON event stream emitted by `opencode run --format json`.
|
|
20
|
+
* The final assistant text is reconstructed from message.part.updated text parts,
|
|
21
|
+
* matched to role via the message.updated events. The last assistant message wins.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseOpencodeRunOutput(stdout: string): OpencodeRunnerResult;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { withoutInvocationHost } from "./invocation-host.js";
|
|
3
|
+
const DEFAULT_OPENCODE_AGENT = "claw-knowledge-writer";
|
|
4
|
+
/** Resolve the opencode CLI binary path. CLAW_OPENCODE_PATH_OVERRIDE supports hermetic tests. */
|
|
5
|
+
export function resolveOpencodeBinary() {
|
|
6
|
+
return process.env.CLAW_OPENCODE_PATH_OVERRIDE ?? "opencode";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Finalization runner for the opencode host. The opencode adapter cannot assume a
|
|
10
|
+
* Codex SDK runtime is installed locally, so deposition runs through `opencode run`
|
|
11
|
+
* inside the user's own opencode environment instead of the Codex SDK.
|
|
12
|
+
*/
|
|
13
|
+
export function runOpencodeKnowledgeWriter(input) {
|
|
14
|
+
const binary = resolveOpencodeBinary();
|
|
15
|
+
const args = [
|
|
16
|
+
"run",
|
|
17
|
+
"--format", "json",
|
|
18
|
+
"--dir", input.projectRoot,
|
|
19
|
+
"--dangerously-skip-permissions",
|
|
20
|
+
"--agent", DEFAULT_OPENCODE_AGENT,
|
|
21
|
+
];
|
|
22
|
+
if (input.writer?.model) {
|
|
23
|
+
args.push("--model", input.writer.model);
|
|
24
|
+
}
|
|
25
|
+
if (input.writer?.reasoningEffort) {
|
|
26
|
+
args.push("--variant", input.writer.reasoningEffort);
|
|
27
|
+
}
|
|
28
|
+
args.push(input.prompt);
|
|
29
|
+
let result;
|
|
30
|
+
try {
|
|
31
|
+
result = spawnSync(binary, args, {
|
|
32
|
+
cwd: input.projectRoot,
|
|
33
|
+
encoding: "utf8",
|
|
34
|
+
maxBuffer: 1024 * 1024 * 64,
|
|
35
|
+
env: { ...withoutInvocationHost(), CLAW_KNOWLEDGE_FINALIZER: "1" },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`Failed to launch opencode runner: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
|
+
}
|
|
41
|
+
if (result.error) {
|
|
42
|
+
throw new Error(`opencode runner failed to start: ${result.error.message}`);
|
|
43
|
+
}
|
|
44
|
+
if (result.status !== 0) {
|
|
45
|
+
throw new Error(`opencode run exited with status ${String(result.status)}: ${result.stderr?.trim() ?? result.stdout?.trim() ?? ""}`);
|
|
46
|
+
}
|
|
47
|
+
return parseOpencodeRunOutput(result.stdout ?? "");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse the NDJSON event stream emitted by `opencode run --format json`.
|
|
51
|
+
* The final assistant text is reconstructed from message.part.updated text parts,
|
|
52
|
+
* matched to role via the message.updated events. The last assistant message wins.
|
|
53
|
+
*/
|
|
54
|
+
export function parseOpencodeRunOutput(stdout) {
|
|
55
|
+
const messageRoles = new Map();
|
|
56
|
+
const messageTexts = new Map();
|
|
57
|
+
let threadId;
|
|
58
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
59
|
+
const trimmed = line.trim();
|
|
60
|
+
if (!trimmed || !trimmed.startsWith("{")) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
let event;
|
|
64
|
+
try {
|
|
65
|
+
event = JSON.parse(trimmed);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const type = event.type ?? "";
|
|
71
|
+
const properties = event.properties ?? {};
|
|
72
|
+
if (type === "session.created" && properties.sessionID) {
|
|
73
|
+
threadId = properties.sessionID;
|
|
74
|
+
}
|
|
75
|
+
if (type === "message.updated" && properties.info?.id && properties.info?.role) {
|
|
76
|
+
messageRoles.set(properties.info.id, properties.info.role);
|
|
77
|
+
}
|
|
78
|
+
if (type === "message.part.updated") {
|
|
79
|
+
const part = properties.part;
|
|
80
|
+
if (part && part.type === "text" && typeof part.text === "string" && part.messageID) {
|
|
81
|
+
const bucket = messageTexts.get(part.messageID) ?? [];
|
|
82
|
+
bucket.push(part.text);
|
|
83
|
+
messageTexts.set(part.messageID, bucket);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
let lastAssistantId;
|
|
88
|
+
for (const [messageId, role] of messageRoles) {
|
|
89
|
+
if (role === "assistant") {
|
|
90
|
+
lastAssistantId = messageId;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
let finalResponse = "";
|
|
94
|
+
if (lastAssistantId) {
|
|
95
|
+
const texts = messageTexts.get(lastAssistantId);
|
|
96
|
+
if (texts && texts.length > 0) {
|
|
97
|
+
finalResponse = texts.join("\n").trim();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
finalResponse,
|
|
102
|
+
...(threadId ? { threadId } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=opencode-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-runner.js","sourceRoot":"","sources":["../src/opencode-runner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@veewo/claw",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "CLI for running the .claw workflow: project planning, recall, truth ingestion, and closeout.",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"claw",
|
|
8
|
-
".claw",
|
|
9
|
-
"agent-workflow",
|
|
10
|
-
"knowledge-capture",
|
|
11
|
-
"project-memory",
|
|
12
|
-
"truth",
|
|
13
|
-
"adr",
|
|
14
|
-
"cli"
|
|
15
|
-
],
|
|
16
|
-
"homepage": "https://github.com/chanyuenpang/claw-kit",
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "https://github.com/chanyuenpang/claw-kit.git",
|
|
20
|
-
"directory": "packages/cli"
|
|
21
|
-
},
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"publishConfig": {
|
|
24
|
-
"access": "public"
|
|
25
|
-
},
|
|
26
|
-
"files": [
|
|
27
|
-
"dist",
|
|
28
|
-
"README.md"
|
|
29
|
-
],
|
|
30
|
-
"bin": {
|
|
31
|
-
"claw": "./dist/bin.js"
|
|
32
|
-
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"@veewo/claw-core": "0.1.
|
|
35
|
-
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "tsc -p tsconfig.json",
|
|
38
|
-
"check": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
39
|
-
"test": "tsc -p tsconfig.test.json && node --test dist-test/**/*.test.js"
|
|
40
|
-
}
|
|
41
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@veewo/claw",
|
|
3
|
+
"version": "0.1.79",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "CLI for running the .claw workflow: project planning, recall, truth ingestion, and closeout.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"claw",
|
|
8
|
+
".claw",
|
|
9
|
+
"agent-workflow",
|
|
10
|
+
"knowledge-capture",
|
|
11
|
+
"project-memory",
|
|
12
|
+
"truth",
|
|
13
|
+
"adr",
|
|
14
|
+
"cli"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/chanyuenpang/claw-kit",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/chanyuenpang/claw-kit.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"bin": {
|
|
31
|
+
"claw": "./dist/bin.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@veewo/claw-core": "0.1.79"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.json",
|
|
38
|
+
"check": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
39
|
+
"test": "tsc -p tsconfig.test.json && node --test dist-test/**/*.test.js"
|
|
40
|
+
}
|
|
41
|
+
}
|