@aipper/aiws 0.0.28 → 0.0.30
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 +18 -2
- package/bin/aiws.js +2 -2
- package/dist/aiws-package.d.ts +4 -0
- package/dist/aiws-package.js +11 -0
- package/dist/aiws-package.js.map +1 -0
- package/dist/aiws-paths.d.ts +48 -0
- package/dist/aiws-paths.js +129 -0
- package/dist/aiws-paths.js.map +1 -0
- package/dist/backup.d.ts +27 -0
- package/dist/backup.js +125 -0
- package/dist/backup.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +773 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-prompts.d.ts +17 -0
- package/dist/codex-prompts.js +49 -0
- package/dist/codex-prompts.js.map +1 -0
- package/dist/codex-skills.d.ts +17 -0
- package/dist/codex-skills.js +75 -0
- package/dist/codex-skills.js.map +1 -0
- package/dist/commands/change-advice.d.ts +25 -0
- package/dist/commands/change-advice.js +197 -0
- package/dist/commands/change-advice.js.map +1 -0
- package/dist/commands/change-evidence-command.d.ts +29 -0
- package/dist/commands/change-evidence-command.js +213 -0
- package/dist/commands/change-evidence-command.js.map +1 -0
- package/dist/commands/change-evidence-entry.d.ts +16 -0
- package/dist/commands/change-evidence-entry.js +35 -0
- package/dist/commands/change-evidence-entry.js.map +1 -0
- package/dist/commands/change-evidence.d.ts +108 -0
- package/dist/commands/change-evidence.js +341 -0
- package/dist/commands/change-evidence.js.map +1 -0
- package/dist/commands/change-finish.d.ts +71 -0
- package/dist/commands/change-finish.js +387 -0
- package/dist/commands/change-finish.js.map +1 -0
- package/dist/commands/change-git-status.d.ts +22 -0
- package/dist/commands/change-git-status.js +50 -0
- package/dist/commands/change-git-status.js.map +1 -0
- package/dist/commands/change-lifecycle-entry.d.ts +29 -0
- package/{src → dist}/commands/change-lifecycle-entry.js +21 -28
- package/dist/commands/change-lifecycle-entry.js.map +1 -0
- package/dist/commands/change-lifecycle.d.ts +56 -0
- package/dist/commands/change-lifecycle.js +211 -0
- package/dist/commands/change-lifecycle.js.map +1 -0
- package/dist/commands/change-metrics-command.d.ts +12 -0
- package/dist/commands/change-metrics-command.js +110 -0
- package/dist/commands/change-metrics-command.js.map +1 -0
- package/dist/commands/change-next-command.d.ts +18 -0
- package/dist/commands/change-next-command.js +138 -0
- package/dist/commands/change-next-command.js.map +1 -0
- package/dist/commands/change-review-gates.d.ts +107 -0
- package/dist/commands/change-review-gates.js +329 -0
- package/dist/commands/change-review-gates.js.map +1 -0
- package/dist/commands/change-scope-gate.d.ts +21 -0
- package/dist/commands/change-scope-gate.js +32 -0
- package/dist/commands/change-scope-gate.js.map +1 -0
- package/dist/commands/change-start.d.ts +30 -0
- package/dist/commands/change-start.js +91 -0
- package/dist/commands/change-start.js.map +1 -0
- package/dist/commands/change-state-command.d.ts +3 -0
- package/dist/commands/change-state-command.js +32 -0
- package/dist/commands/change-state-command.js.map +1 -0
- package/dist/commands/change-status-command.d.ts +13 -0
- package/dist/commands/change-status-command.js +126 -0
- package/dist/commands/change-status-command.js.map +1 -0
- package/dist/commands/change-status-context.d.ts +58 -0
- package/dist/commands/change-status-context.js +166 -0
- package/dist/commands/change-status-context.js.map +1 -0
- package/dist/commands/change-task-stats.d.ts +24 -0
- package/dist/commands/change-task-stats.js +66 -0
- package/dist/commands/change-task-stats.js.map +1 -0
- package/dist/commands/change-validate-entry.d.ts +17 -0
- package/dist/commands/change-validate-entry.js +44 -0
- package/dist/commands/change-validate-entry.js.map +1 -0
- package/dist/commands/change-validate.d.ts +32 -0
- package/dist/commands/change-validate.js +128 -0
- package/dist/commands/change-validate.js.map +1 -0
- package/dist/commands/change.d.ts +322 -0
- package/dist/commands/change.js +1731 -0
- package/dist/commands/change.js.map +1 -0
- package/dist/commands/codex-install-prompts.d.ts +4 -0
- package/dist/commands/codex-install-prompts.js +68 -0
- package/dist/commands/codex-install-prompts.js.map +1 -0
- package/dist/commands/codex-install-skills.d.ts +4 -0
- package/dist/commands/codex-install-skills.js +74 -0
- package/dist/commands/codex-install-skills.js.map +1 -0
- package/dist/commands/codex-status-prompts.d.ts +4 -0
- package/dist/commands/codex-status-prompts.js +44 -0
- package/dist/commands/codex-status-prompts.js.map +1 -0
- package/dist/commands/codex-status-skills.d.ts +4 -0
- package/dist/commands/codex-status-skills.js +54 -0
- package/dist/commands/codex-status-skills.js.map +1 -0
- package/dist/commands/codex-uninstall-prompts.d.ts +4 -0
- package/dist/commands/codex-uninstall-prompts.js +51 -0
- package/dist/commands/codex-uninstall-prompts.js.map +1 -0
- package/dist/commands/codex-uninstall-skills.d.ts +4 -0
- package/dist/commands/codex-uninstall-skills.js +59 -0
- package/dist/commands/codex-uninstall-skills.js.map +1 -0
- package/dist/commands/dashboard.d.ts +222 -0
- package/dist/commands/dashboard.js +193 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/hooks-install.d.ts +4 -0
- package/dist/commands/hooks-install.js +90 -0
- package/dist/commands/hooks-install.js.map +1 -0
- package/dist/commands/hooks-status.d.ts +4 -0
- package/dist/commands/hooks-status.js +89 -0
- package/dist/commands/hooks-status.js.map +1 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +100 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/opencode-auto.d.ts +11 -0
- package/dist/commands/opencode-auto.js +158 -0
- package/dist/commands/opencode-auto.js.map +1 -0
- package/dist/commands/opencode-status.d.ts +4 -0
- package/dist/commands/opencode-status.js +75 -0
- package/dist/commands/opencode-status.js.map +1 -0
- package/dist/commands/opencode-supervise.d.ts +24 -0
- package/dist/commands/opencode-supervise.js +188 -0
- package/dist/commands/opencode-supervise.js.map +1 -0
- package/dist/commands/rollback.d.ts +4 -0
- package/dist/commands/rollback.js +12 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/update.d.ts +4 -0
- package/dist/commands/update.js +212 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.js +222 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/ws-commit.d.ts +5 -0
- package/dist/commands/ws-commit.js +39 -0
- package/dist/commands/ws-commit.js.map +1 -0
- package/dist/commands/ws-deliver.d.ts +5 -0
- package/dist/commands/ws-deliver.js +59 -0
- package/dist/commands/ws-deliver.js.map +1 -0
- package/dist/commands/ws-finish.d.ts +5 -0
- package/dist/commands/ws-finish.js +142 -0
- package/dist/commands/ws-finish.js.map +1 -0
- package/dist/commands/ws-handoff.d.ts +5 -0
- package/dist/commands/ws-handoff.js +35 -0
- package/dist/commands/ws-handoff.js.map +1 -0
- package/dist/commands/ws-migrate.d.ts +5 -0
- package/dist/commands/ws-migrate.js +41 -0
- package/dist/commands/ws-migrate.js.map +1 -0
- package/dist/commands/ws-plan-verify.d.ts +5 -0
- package/dist/commands/ws-plan-verify.js +38 -0
- package/dist/commands/ws-plan-verify.js.map +1 -0
- package/dist/commands/ws-pull.d.ts +5 -0
- package/dist/commands/ws-pull.js +26 -0
- package/dist/commands/ws-pull.js.map +1 -0
- package/dist/commands/ws-push.d.ts +5 -0
- package/dist/commands/ws-push.js +68 -0
- package/dist/commands/ws-push.js.map +1 -0
- package/dist/commands/ws-submodule-setup.d.ts +5 -0
- package/dist/commands/ws-submodule-setup.js +55 -0
- package/dist/commands/ws-submodule-setup.js.map +1 -0
- package/dist/commands/ws-verify-before-complete.d.ts +5 -0
- package/dist/commands/ws-verify-before-complete.js +35 -0
- package/dist/commands/ws-verify-before-complete.js.map +1 -0
- package/dist/dashboard/app.d.ts +1 -0
- package/dist/dashboard/app.js +370 -0
- package/dist/dashboard/app.js.map +1 -0
- package/dist/delegation/cli.d.ts +6 -0
- package/dist/delegation/cli.js +14 -0
- package/dist/delegation/cli.js.map +1 -0
- package/dist/delegation/index.d.ts +35 -0
- package/dist/delegation/index.js +118 -0
- package/dist/delegation/index.js.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/exec.d.ts +9 -0
- package/dist/exec.js +22 -0
- package/dist/exec.js.map +1 -0
- package/dist/fs.d.ts +9 -0
- package/dist/fs.js +62 -0
- package/dist/fs.js.map +1 -0
- package/dist/governance.d.ts +10 -0
- package/dist/governance.js +135 -0
- package/dist/governance.js.map +1 -0
- package/dist/hash.d.ts +3 -0
- package/dist/hash.js +13 -0
- package/dist/hash.js.map +1 -0
- package/dist/hooks/deploy-claude.d.ts +13 -0
- package/dist/hooks/deploy-claude.js +67 -0
- package/dist/hooks/deploy-claude.js.map +1 -0
- package/dist/journal.d.ts +22 -0
- package/dist/journal.js +112 -0
- package/dist/journal.js.map +1 -0
- package/dist/json-schema-lite.d.ts +22 -0
- package/dist/json-schema-lite.js +148 -0
- package/dist/json-schema-lite.js.map +1 -0
- package/dist/managed-blocks.d.ts +24 -0
- package/dist/managed-blocks.js +84 -0
- package/dist/managed-blocks.js.map +1 -0
- package/dist/manifest.d.ts +24 -0
- package/dist/manifest.js +145 -0
- package/dist/manifest.js.map +1 -0
- package/dist/opencode-env.d.ts +62 -0
- package/dist/opencode-env.js +178 -0
- package/dist/opencode-env.js.map +1 -0
- package/dist/path-utils.d.ts +2 -0
- package/dist/path-utils.js +8 -0
- package/dist/path-utils.js.map +1 -0
- package/dist/spec.d.ts +17 -0
- package/dist/spec.js +174 -0
- package/dist/spec.js.map +1 -0
- package/dist/template.d.ts +20 -0
- package/dist/template.js +123 -0
- package/dist/template.js.map +1 -0
- package/dist/workspace.d.ts +4 -0
- package/dist/workspace.js +19 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +11 -3
- package/src/aiws-package.js +0 -15
- package/src/backup.js +0 -149
- package/src/cli.js +0 -647
- package/src/codex-prompts.js +0 -74
- package/src/codex-skills.js +0 -111
- package/src/commands/change-advice.js +0 -200
- package/src/commands/change-evidence-command.js +0 -242
- package/src/commands/change-evidence-entry.js +0 -40
- package/src/commands/change-evidence.js +0 -340
- package/src/commands/change-finish.js +0 -484
- package/src/commands/change-git-status.js +0 -53
- package/src/commands/change-lifecycle.js +0 -236
- package/src/commands/change-metrics-command.js +0 -110
- package/src/commands/change-next-command.js +0 -129
- package/src/commands/change-review-gates.js +0 -315
- package/src/commands/change-scope-gate.js +0 -34
- package/src/commands/change-start.js +0 -120
- package/src/commands/change-state-command.js +0 -40
- package/src/commands/change-status-command.js +0 -134
- package/src/commands/change-status-context.js +0 -202
- package/src/commands/change-task-stats.js +0 -64
- package/src/commands/change-validate-entry.js +0 -45
- package/src/commands/change-validate.js +0 -127
- package/src/commands/change.js +0 -2087
- package/src/commands/codex-install-prompts.js +0 -68
- package/src/commands/codex-install-skills.js +0 -74
- package/src/commands/codex-status-prompts.js +0 -55
- package/src/commands/codex-status-skills.js +0 -63
- package/src/commands/codex-uninstall-prompts.js +0 -55
- package/src/commands/codex-uninstall-skills.js +0 -62
- package/src/commands/dashboard.js +0 -205
- package/src/commands/hooks-install.js +0 -92
- package/src/commands/hooks-status.js +0 -95
- package/src/commands/init.js +0 -93
- package/src/commands/opencode-status.js +0 -61
- package/src/commands/rollback.js +0 -13
- package/src/commands/update.js +0 -133
- package/src/commands/validate.js +0 -222
- package/src/dashboard/app.js +0 -371
- package/src/errors.js +0 -15
- package/src/exec.js +0 -34
- package/src/fs.js +0 -91
- package/src/governance.js +0 -159
- package/src/hash.js +0 -25
- package/src/json-schema-lite.js +0 -164
- package/src/managed-blocks.js +0 -131
- package/src/manifest.js +0 -153
- package/src/opencode-env.js +0 -76
- package/src/path-utils.js +0 -20
- package/src/spec.js +0 -195
- package/src/template.js +0 -187
- package/src/workspace.js +0 -23
- /package/{src → dist}/dashboard/index.html +0 -0
- /package/{src → dist}/dashboard/style.css +0 -0
package/src/hash.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
import { readText } from "./fs.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {string} s
|
|
6
|
-
*/
|
|
7
|
-
export function normalizeNewlines(s) {
|
|
8
|
-
return s.replaceAll("\r\n", "\n");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} text
|
|
13
|
-
*/
|
|
14
|
-
export function sha256Text(text) {
|
|
15
|
-
return crypto.createHash("sha256").update(text, "utf8").digest("hex");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {string} filePath
|
|
20
|
-
*/
|
|
21
|
-
export async function sha256FileText(filePath) {
|
|
22
|
-
const content = normalizeNewlines(await readText(filePath));
|
|
23
|
-
return sha256Text(content);
|
|
24
|
-
}
|
|
25
|
-
|
package/src/json-schema-lite.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { UserError } from "./errors.js";
|
|
2
|
-
|
|
3
|
-
function isPlainObject(value) {
|
|
4
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function joinPath(base, segment) {
|
|
8
|
-
if (!base || base === "$") return `$${segment}`;
|
|
9
|
-
return `${base}${segment}`;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function resolvePointer(rootSchema, ref) {
|
|
13
|
-
if (typeof ref !== "string" || !ref.startsWith("#/")) {
|
|
14
|
-
throw new UserError("Unsupported schema $ref.", { details: String(ref || "") });
|
|
15
|
-
}
|
|
16
|
-
const parts = ref
|
|
17
|
-
.slice(2)
|
|
18
|
-
.split("/")
|
|
19
|
-
.map((part) => part.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
20
|
-
let cur = rootSchema;
|
|
21
|
-
for (const part of parts) {
|
|
22
|
-
if (!isPlainObject(cur) && !Array.isArray(cur)) return undefined;
|
|
23
|
-
cur = cur[part];
|
|
24
|
-
}
|
|
25
|
-
return cur;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function typeMatches(value, type) {
|
|
29
|
-
switch (type) {
|
|
30
|
-
case "object":
|
|
31
|
-
return isPlainObject(value);
|
|
32
|
-
case "array":
|
|
33
|
-
return Array.isArray(value);
|
|
34
|
-
case "string":
|
|
35
|
-
return typeof value === "string";
|
|
36
|
-
case "number":
|
|
37
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
38
|
-
case "integer":
|
|
39
|
-
return typeof value === "number" && Number.isInteger(value);
|
|
40
|
-
case "boolean":
|
|
41
|
-
return typeof value === "boolean";
|
|
42
|
-
case "null":
|
|
43
|
-
return value === null;
|
|
44
|
-
default:
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @param {any} value
|
|
51
|
-
* @param {any} schema
|
|
52
|
-
* @param {any} rootSchema
|
|
53
|
-
* @param {string} curPath
|
|
54
|
-
* @param {string[]} errors
|
|
55
|
-
*/
|
|
56
|
-
function validateNode(value, schema, rootSchema, curPath, errors) {
|
|
57
|
-
if (!isPlainObject(schema)) return;
|
|
58
|
-
|
|
59
|
-
if (schema.$ref) {
|
|
60
|
-
const target = resolvePointer(rootSchema, schema.$ref);
|
|
61
|
-
if (!target) {
|
|
62
|
-
errors.push(`${curPath}: unresolved $ref ${schema.$ref}`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
validateNode(value, target, rootSchema, curPath, errors);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
|
|
70
|
-
const matched = schema.anyOf.some((candidate) => {
|
|
71
|
-
const branchErrors = [];
|
|
72
|
-
validateNode(value, candidate, rootSchema, curPath, branchErrors);
|
|
73
|
-
return branchErrors.length === 0;
|
|
74
|
-
});
|
|
75
|
-
if (!matched) errors.push(`${curPath}: does not match anyOf`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
|
|
79
|
-
for (const candidate of schema.allOf) validateNode(value, candidate, rootSchema, curPath, errors);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
|
|
83
|
-
let matches = 0;
|
|
84
|
-
for (const candidate of schema.oneOf) {
|
|
85
|
-
const branchErrors = [];
|
|
86
|
-
validateNode(value, candidate, rootSchema, curPath, branchErrors);
|
|
87
|
-
if (branchErrors.length === 0) matches += 1;
|
|
88
|
-
}
|
|
89
|
-
if (matches !== 1) errors.push(`${curPath}: does not match exactly one schema`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (schema.type && !typeMatches(value, schema.type)) {
|
|
93
|
-
errors.push(`${curPath}: expected ${schema.type}`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (Object.prototype.hasOwnProperty.call(schema, "const") && value !== schema.const) {
|
|
98
|
-
errors.push(`${curPath}: expected const ${JSON.stringify(schema.const)}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
102
|
-
errors.push(`${curPath}: expected one of ${schema.enum.map((item) => JSON.stringify(item)).join(", ")}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (typeof value === "string") {
|
|
106
|
-
if (typeof schema.minLength === "number" && value.length < schema.minLength) {
|
|
107
|
-
errors.push(`${curPath}: expected minLength ${schema.minLength}`);
|
|
108
|
-
}
|
|
109
|
-
if (typeof schema.pattern === "string") {
|
|
110
|
-
const re = new RegExp(schema.pattern);
|
|
111
|
-
if (!re.test(value)) errors.push(`${curPath}: does not match pattern ${schema.pattern}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (Array.isArray(value)) {
|
|
116
|
-
if (typeof schema.minItems === "number" && value.length < schema.minItems) {
|
|
117
|
-
errors.push(`${curPath}: expected minItems ${schema.minItems}`);
|
|
118
|
-
}
|
|
119
|
-
if (schema.items) {
|
|
120
|
-
value.forEach((item, index) => validateNode(item, schema.items, rootSchema, joinPath(curPath, `[${index}]`), errors));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (isPlainObject(value)) {
|
|
125
|
-
const entries = Object.keys(value);
|
|
126
|
-
if (typeof schema.minProperties === "number" && entries.length < schema.minProperties) {
|
|
127
|
-
errors.push(`${curPath}: expected minProperties ${schema.minProperties}`);
|
|
128
|
-
}
|
|
129
|
-
if (typeof schema.maxProperties === "number" && entries.length > schema.maxProperties) {
|
|
130
|
-
errors.push(`${curPath}: expected maxProperties ${schema.maxProperties}`);
|
|
131
|
-
}
|
|
132
|
-
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
133
|
-
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
134
|
-
for (const key of required) {
|
|
135
|
-
if (!Object.prototype.hasOwnProperty.call(value, key)) errors.push(`${curPath}: missing required property ${key}`);
|
|
136
|
-
}
|
|
137
|
-
for (const [key, childSchema] of Object.entries(properties)) {
|
|
138
|
-
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
139
|
-
validateNode(value[key], childSchema, rootSchema, joinPath(curPath, `.${key}`), errors);
|
|
140
|
-
}
|
|
141
|
-
if (schema.additionalProperties === false) {
|
|
142
|
-
for (const key of entries) {
|
|
143
|
-
if (!Object.prototype.hasOwnProperty.call(properties, key)) {
|
|
144
|
-
errors.push(`${curPath}: unexpected property ${key}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @param {any} value
|
|
153
|
-
* @param {any} schema
|
|
154
|
-
* @param {{ source: string }} options
|
|
155
|
-
*/
|
|
156
|
-
export function validateJsonSchemaLite(value, schema, options) {
|
|
157
|
-
const errors = [];
|
|
158
|
-
validateNode(value, schema, schema, "$", errors);
|
|
159
|
-
if (errors.length > 0) {
|
|
160
|
-
throw new UserError("Spec doc schema validation failed.", {
|
|
161
|
-
details: [options?.source || "", ...errors].filter(Boolean).join("\n"),
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
package/src/managed-blocks.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { normalizeNewlines, sha256Text } from "./hash.js";
|
|
2
|
-
import { UserError } from "./errors.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {string} s
|
|
6
|
-
* @returns {string}
|
|
7
|
-
*/
|
|
8
|
-
function escapeRegExp(s) {
|
|
9
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {string} text
|
|
14
|
-
* @param {string} blockId
|
|
15
|
-
* @returns {{ beginLineIndex: number, endLineIndex: number, innerText: string, beginLine: string, endLine: string } | null}
|
|
16
|
-
*/
|
|
17
|
-
export function findManagedBlock(text, blockId) {
|
|
18
|
-
const t = normalizeNewlines(text);
|
|
19
|
-
const lines = t.split("\n");
|
|
20
|
-
const beginRe = new RegExp(`AIWS_MANAGED_BEGIN:${escapeRegExp(blockId)}(?:\\s|$|-->)`);
|
|
21
|
-
const endRe = new RegExp(`AIWS_MANAGED_END:${escapeRegExp(blockId)}(?:\\s|$|-->)`);
|
|
22
|
-
|
|
23
|
-
let beginLineIndex = -1;
|
|
24
|
-
let endLineIndex = -1;
|
|
25
|
-
|
|
26
|
-
for (let i = 0; i < lines.length; i++) {
|
|
27
|
-
if (beginLineIndex === -1 && beginRe.test(lines[i] ?? "")) {
|
|
28
|
-
beginLineIndex = i;
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
if (beginLineIndex !== -1 && endRe.test(lines[i] ?? "")) {
|
|
32
|
-
endLineIndex = i;
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (beginLineIndex === -1 || endLineIndex === -1 || endLineIndex <= beginLineIndex) return null;
|
|
38
|
-
|
|
39
|
-
const innerLines = lines.slice(beginLineIndex + 1, endLineIndex);
|
|
40
|
-
let innerText = innerLines.join("\n");
|
|
41
|
-
if (innerLines.length > 0) innerText += "\n";
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
beginLineIndex,
|
|
45
|
-
endLineIndex,
|
|
46
|
-
innerText,
|
|
47
|
-
beginLine: lines[beginLineIndex] ?? "",
|
|
48
|
-
endLine: lines[endLineIndex] ?? "",
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Extract the canonical block chunk (begin+inner+end) from a template file.
|
|
54
|
-
*
|
|
55
|
-
* @param {string} templateText
|
|
56
|
-
* @param {string} blockId
|
|
57
|
-
* @returns {{ blockChunk: string, innerText: string }}
|
|
58
|
-
*/
|
|
59
|
-
export function extractTemplateBlock(templateText, blockId) {
|
|
60
|
-
const t = normalizeNewlines(templateText);
|
|
61
|
-
const block = findManagedBlock(t, blockId);
|
|
62
|
-
if (!block) {
|
|
63
|
-
throw new UserError(`Template is missing managed block: ${blockId}`, { exitCode: 1 });
|
|
64
|
-
}
|
|
65
|
-
const blockChunk = `${block.beginLine}\n${block.innerText}${block.endLine}\n`;
|
|
66
|
-
return { blockChunk, innerText: block.innerText };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @param {string} targetText
|
|
71
|
-
* @param {string} blockId
|
|
72
|
-
* @param {string} newInnerText normalized; may end with "\n"
|
|
73
|
-
* @param {{ insertIfMissing: boolean, templateBlockChunk?: string } } options
|
|
74
|
-
* @returns {{ nextText: string, changed: boolean, inserted: boolean }}
|
|
75
|
-
*/
|
|
76
|
-
export function upsertManagedBlock(targetText, blockId, newInnerText, options) {
|
|
77
|
-
const original = normalizeNewlines(targetText);
|
|
78
|
-
const block = findManagedBlock(original, blockId);
|
|
79
|
-
if (!block) {
|
|
80
|
-
if (!options.insertIfMissing) {
|
|
81
|
-
throw new UserError(`Missing managed block: ${blockId}`);
|
|
82
|
-
}
|
|
83
|
-
if (!options.templateBlockChunk) {
|
|
84
|
-
throw new UserError(`Cannot insert managed block without template chunk: ${blockId}`, { exitCode: 1 });
|
|
85
|
-
}
|
|
86
|
-
const nextText = insertBlockAtTop(original, options.templateBlockChunk);
|
|
87
|
-
return { nextText, changed: true, inserted: true };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const lines = original.split("\n");
|
|
91
|
-
const begin = lines.slice(0, block.beginLineIndex + 1);
|
|
92
|
-
const end = lines.slice(block.endLineIndex);
|
|
93
|
-
|
|
94
|
-
const innerLines = newInnerText.endsWith("\n") ? newInnerText.slice(0, -1).split("\n") : newInnerText.split("\n");
|
|
95
|
-
const rebuilt = [...begin, ...innerLines, ...end].join("\n");
|
|
96
|
-
|
|
97
|
-
return { nextText: rebuilt, changed: rebuilt !== original, inserted: false };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Insert block chunk near the top with minimal disruption:
|
|
102
|
-
* - If the file starts with a Markdown heading (`# ...`), insert after the first line.
|
|
103
|
-
* - Otherwise, insert at the very top.
|
|
104
|
-
*
|
|
105
|
-
* @param {string} text normalized
|
|
106
|
-
* @param {string} blockChunk normalized; should end with "\n"
|
|
107
|
-
*/
|
|
108
|
-
function insertBlockAtTop(text, blockChunk) {
|
|
109
|
-
const t = normalizeNewlines(text);
|
|
110
|
-
const chunk = normalizeNewlines(blockChunk).endsWith("\n") ? normalizeNewlines(blockChunk) : `${normalizeNewlines(blockChunk)}\n`;
|
|
111
|
-
|
|
112
|
-
const lines = t.split("\n");
|
|
113
|
-
if (lines.length > 0 && (lines[0] ?? "").startsWith("# ")) {
|
|
114
|
-
const after = lines.slice(1).join("\n");
|
|
115
|
-
const head = `${lines[0]}\n`;
|
|
116
|
-
return `${head}\n${chunk}\n${after}`.replace(/\n{3,}/g, "\n\n");
|
|
117
|
-
}
|
|
118
|
-
return `${chunk}\n${t}`.replace(/\n{3,}/g, "\n\n");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* @param {string} text
|
|
123
|
-
* @param {string} blockId
|
|
124
|
-
*/
|
|
125
|
-
export function hashManagedBlockInner(text, blockId) {
|
|
126
|
-
const block = findManagedBlock(text, blockId);
|
|
127
|
-
if (!block) {
|
|
128
|
-
throw new UserError(`Missing managed block: ${blockId}`);
|
|
129
|
-
}
|
|
130
|
-
return sha256Text(block.innerText);
|
|
131
|
-
}
|
package/src/manifest.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { normalizeNewlines, sha256FileText, sha256Text } from "./hash.js";
|
|
3
|
-
import { joinRel, normalizeRel } from "./path-utils.js";
|
|
4
|
-
import { pathExists, readText, writeText } from "./fs.js";
|
|
5
|
-
import { findManagedBlock } from "./managed-blocks.js";
|
|
6
|
-
import { UserError } from "./errors.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {any} manifest
|
|
10
|
-
*/
|
|
11
|
-
export function isPlaceholderManifest(manifest) {
|
|
12
|
-
if (!manifest || typeof manifest !== "object") return true;
|
|
13
|
-
if (manifest.installed_at === "1970-01-01T00:00:00Z" || manifest.updated_at === "1970-01-01T00:00:00Z") return true;
|
|
14
|
-
|
|
15
|
-
const managed = Array.isArray(manifest.managed) ? manifest.managed : [];
|
|
16
|
-
for (const m of managed) {
|
|
17
|
-
if (!m || typeof m !== "object") continue;
|
|
18
|
-
if (typeof m.sha256 === "string" && m.sha256.includes("<sha256>")) return true;
|
|
19
|
-
if (m.blocks && typeof m.blocks === "object") {
|
|
20
|
-
for (const v of Object.values(m.blocks)) {
|
|
21
|
-
if (typeof v === "string" && v.includes("<sha256>")) return true;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @param {{ workspaceRoot: string, templateId: string, specVersion: string, aiwsVersion: string, installedAt: string, updatedAt: string, tools: string[], templateManifest: any }} options
|
|
30
|
-
*/
|
|
31
|
-
export async function writeWorkspaceManifest(options) {
|
|
32
|
-
const managed = await computeManagedState({
|
|
33
|
-
workspaceRoot: options.workspaceRoot,
|
|
34
|
-
templateManifest: options.templateManifest,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const obj = {
|
|
38
|
-
manifest_version: 1,
|
|
39
|
-
template_id: options.templateId,
|
|
40
|
-
spec_version: options.specVersion,
|
|
41
|
-
aiws_version: options.aiwsVersion,
|
|
42
|
-
installed_at: options.installedAt,
|
|
43
|
-
updated_at: options.updatedAt,
|
|
44
|
-
tools: options.tools,
|
|
45
|
-
managed,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const outPath = path.join(options.workspaceRoot, ".aiws", "manifest.json");
|
|
49
|
-
await writeText(outPath, JSON.stringify(obj, null, 2) + "\n");
|
|
50
|
-
return obj;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Compute managed hashes for the current workspace.
|
|
55
|
-
*
|
|
56
|
-
* Note: `.aiws/manifest.json` is intentionally excluded from `managed` to avoid self-hashing.
|
|
57
|
-
*
|
|
58
|
-
* @param {{ workspaceRoot: string, templateManifest: any }} options
|
|
59
|
-
*/
|
|
60
|
-
export async function computeManagedState(options) {
|
|
61
|
-
const update = options.templateManifest?.update || {};
|
|
62
|
-
const replaceFiles = Array.isArray(update.replace_file) ? update.replace_file : [];
|
|
63
|
-
const managedBlocks = update.managed_blocks && typeof update.managed_blocks === "object" ? update.managed_blocks : {};
|
|
64
|
-
|
|
65
|
-
/** @type {any[]} */
|
|
66
|
-
const out = [];
|
|
67
|
-
|
|
68
|
-
for (const relRaw of replaceFiles) {
|
|
69
|
-
const rel = normalizeRel(relRaw);
|
|
70
|
-
if (!rel || rel === ".aiws/manifest.json") continue;
|
|
71
|
-
const abs = joinRel(options.workspaceRoot, rel);
|
|
72
|
-
if (!(await pathExists(abs))) throw new UserError(`Missing required managed file: ${rel}`);
|
|
73
|
-
out.push({ path: rel, mode: "replace_file", sha256: await sha256FileText(abs) });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
for (const [fileRelRaw, blockIdsRaw] of Object.entries(managedBlocks)) {
|
|
77
|
-
const fileRel = normalizeRel(fileRelRaw);
|
|
78
|
-
if (!fileRel) continue;
|
|
79
|
-
const abs = joinRel(options.workspaceRoot, fileRel);
|
|
80
|
-
if (!(await pathExists(abs))) throw new UserError(`Missing required managed file: ${fileRel}`);
|
|
81
|
-
const text = normalizeNewlines(await readText(abs));
|
|
82
|
-
/** @type {Record<string, string>} */
|
|
83
|
-
const blocks = {};
|
|
84
|
-
const ids = Array.isArray(blockIdsRaw) ? blockIdsRaw : [];
|
|
85
|
-
for (const idRaw of ids) {
|
|
86
|
-
const id = String(idRaw);
|
|
87
|
-
const found = findManagedBlock(text, id);
|
|
88
|
-
if (!found) throw new UserError(`Missing managed block: ${id}`, { details: `File: ${fileRel}` });
|
|
89
|
-
blocks[id] = sha256Text(found.innerText);
|
|
90
|
-
}
|
|
91
|
-
out.push({ path: fileRel, mode: "managed_blocks", blocks });
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
out.sort((a, b) => String(a.path).localeCompare(String(b.path)));
|
|
95
|
-
return out;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Validate current workspace against the stored `.aiws/manifest.json` and template contract.
|
|
100
|
-
*
|
|
101
|
-
* @param {{ workspaceRoot: string, storedManifest: any, templateManifest: any }} options
|
|
102
|
-
*/
|
|
103
|
-
export async function validateDrift(options) {
|
|
104
|
-
const stored = options.storedManifest;
|
|
105
|
-
if (isPlaceholderManifest(stored)) {
|
|
106
|
-
throw new UserError("Workspace manifest is placeholder/uninitialized.", {
|
|
107
|
-
details: "Run `aiws init` to generate a real .aiws/manifest.json.",
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const expected = await computeManagedState({ workspaceRoot: options.workspaceRoot, templateManifest: options.templateManifest });
|
|
112
|
-
const currentByPath = new Map(expected.map((e) => [e.path, e]));
|
|
113
|
-
|
|
114
|
-
const managed = Array.isArray(stored.managed) ? stored.managed : [];
|
|
115
|
-
const storedByPath = new Map(managed.map((e) => [String(e.path || ""), e]));
|
|
116
|
-
|
|
117
|
-
/** @type {string[]} */
|
|
118
|
-
const problems = [];
|
|
119
|
-
|
|
120
|
-
for (const [p, cur] of currentByPath.entries()) {
|
|
121
|
-
const s = storedByPath.get(p);
|
|
122
|
-
if (!s) {
|
|
123
|
-
problems.push(`missing manifest entry: ${p}`);
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (cur.mode !== s.mode) {
|
|
127
|
-
problems.push(`mode mismatch: ${p} (expected ${cur.mode}, got ${s.mode})`);
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
if (cur.mode === "replace_file") {
|
|
131
|
-
if (cur.sha256 !== s.sha256) {
|
|
132
|
-
problems.push(`sha256 mismatch: ${p}`);
|
|
133
|
-
}
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
if (cur.mode === "managed_blocks") {
|
|
137
|
-
const curBlocks = cur.blocks || {};
|
|
138
|
-
const sBlocks = s.blocks || {};
|
|
139
|
-
for (const [bid, curSha] of Object.entries(curBlocks)) {
|
|
140
|
-
if (!sBlocks[bid]) {
|
|
141
|
-
problems.push(`missing block in manifest: ${p} (${bid})`);
|
|
142
|
-
} else if (sBlocks[bid] !== curSha) {
|
|
143
|
-
problems.push(`block sha256 mismatch: ${p} (${bid})`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (problems.length > 0) {
|
|
150
|
-
throw new UserError("Workspace drift detected.", { details: problems.join("\n") });
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
package/src/opencode-env.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { pathExists, readText } from "./fs.js";
|
|
3
|
-
|
|
4
|
-
const OPENCODE_AGENT_NAMES = ["planner-sisyphus", "librarian", "explore", "oracle"];
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @param {string} value
|
|
8
|
-
*/
|
|
9
|
-
function relativeOrDot(value) {
|
|
10
|
-
return value ? value.replaceAll(path.sep, "/") : ".";
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param {any} raw
|
|
15
|
-
* @param {string} agentName
|
|
16
|
-
*/
|
|
17
|
-
function readAgentState(raw, agentName) {
|
|
18
|
-
const agents = raw && typeof raw === "object" && raw.agents && typeof raw.agents === "object" ? raw.agents : {};
|
|
19
|
-
const entry = agents[agentName];
|
|
20
|
-
return {
|
|
21
|
-
present: !!entry && typeof entry === "object",
|
|
22
|
-
enabled: !!(entry && typeof entry === "object" && entry.enabled === true),
|
|
23
|
-
replacePlan: entry && typeof entry === "object" && typeof entry.replace_plan === "boolean" ? entry.replace_plan : null,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} workspaceRoot
|
|
29
|
-
*/
|
|
30
|
-
export async function detectOpenCodeEnvironment(workspaceRoot) {
|
|
31
|
-
const opencodeDir = path.join(workspaceRoot, ".opencode");
|
|
32
|
-
const configPath = path.join(opencodeDir, "oh-my-opencode.json");
|
|
33
|
-
const examplePath = path.join(opencodeDir, "oh-my-opencode.json.example");
|
|
34
|
-
const opencodeDirExists = await pathExists(opencodeDir);
|
|
35
|
-
const configExists = await pathExists(configPath);
|
|
36
|
-
const exampleExists = await pathExists(examplePath);
|
|
37
|
-
|
|
38
|
-
/** @type {any} */
|
|
39
|
-
let config = null;
|
|
40
|
-
let configStatus = "missing";
|
|
41
|
-
let configError = "";
|
|
42
|
-
if (configExists) {
|
|
43
|
-
try {
|
|
44
|
-
config = JSON.parse(await readText(configPath));
|
|
45
|
-
configStatus = "loaded";
|
|
46
|
-
} catch (error) {
|
|
47
|
-
configStatus = "invalid";
|
|
48
|
-
configError = error instanceof Error ? error.message : String(error);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const agents = Object.fromEntries(OPENCODE_AGENT_NAMES.map((name) => [name, readAgentState(config, name)]));
|
|
53
|
-
const enabledAgents = OPENCODE_AGENT_NAMES.filter((name) => agents[name]?.enabled === true);
|
|
54
|
-
const recommendedAgentsReady = ["planner-sisyphus", "librarian", "explore", "oracle"].every((name) => agents[name]?.enabled === true);
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
workspaceRoot,
|
|
58
|
-
opencodeDir,
|
|
59
|
-
opencodeDirExists,
|
|
60
|
-
configPath,
|
|
61
|
-
configExists,
|
|
62
|
-
configStatus,
|
|
63
|
-
configError,
|
|
64
|
-
examplePath,
|
|
65
|
-
exampleExists,
|
|
66
|
-
mode: configStatus === "loaded" ? "oMo-enabled" : "standard-opencode",
|
|
67
|
-
recommendedAgentsReady,
|
|
68
|
-
enabledAgents,
|
|
69
|
-
agents,
|
|
70
|
-
rel: {
|
|
71
|
-
opencodeDir: relativeOrDot(path.relative(workspaceRoot, opencodeDir)),
|
|
72
|
-
configPath: relativeOrDot(path.relative(workspaceRoot, configPath)),
|
|
73
|
-
examplePath: relativeOrDot(path.relative(workspaceRoot, examplePath)),
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
package/src/path-utils.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Join a POSIX-style relative path (with `/`) onto an absolute root.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} rootDir
|
|
7
|
-
* @param {string} relPosix
|
|
8
|
-
*/
|
|
9
|
-
export function joinRel(rootDir, relPosix) {
|
|
10
|
-
return path.join(rootDir, ...String(relPosix).split("/"));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Normalize a relative path from manifest (always forward slashes).
|
|
15
|
-
*
|
|
16
|
-
* @param {string} rel
|
|
17
|
-
*/
|
|
18
|
-
export function normalizeRel(rel) {
|
|
19
|
-
return String(rel).replaceAll("\\", "/").replaceAll(/\/+/g, "/").replace(/^\/+/, "");
|
|
20
|
-
}
|