@multileaf/ai-workflow 0.3.0 → 0.3.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/CHANGELOG.md +6 -0
- package/dist/decision.d.ts +1 -0
- package/dist/decision.js +3 -0
- package/dist/semantic.d.ts +1 -0
- package/dist/semantic.js +3 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +40 -3
- package/docs/semantic-mapping.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project are documented in this file. The format foll
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.3.1] - 2026-10-08
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Interactive optional-model onboarding during `aiw install`: in an interactive terminal, the installer asks whether to enable semantic mapping and advisory decision triage and writes `.aiw/semantic.yml` / `.aiw/decision.yml` with defaults before `/ai-init` runs. Non-interactive installs skip the prompts, and existing configuration files are never overwritten.
|
|
12
|
+
|
|
7
13
|
## [0.3.0] - 2026-10-08
|
|
8
14
|
|
|
9
15
|
### Added
|
package/dist/decision.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export type DecisionProvider = {
|
|
|
43
43
|
export declare const DECISION_CONFIG_PATH = "decision.yml";
|
|
44
44
|
export declare const DEFAULT_DECISION_CONFIG: DecisionConfig;
|
|
45
45
|
export declare function parseDecisionConfig(text: string): DecisionConfig;
|
|
46
|
+
export declare function serializeDecisionConfig(config: DecisionConfig): string;
|
|
46
47
|
export declare function loadDecisionConfig(fs: FileSystem, aiwPath: string): DecisionConfig | undefined;
|
|
47
48
|
export declare function parseDecisionResponse(text: string): DecisionResponse;
|
|
48
49
|
export declare function createOllamaDecisionProvider(config: DecisionConfig): DecisionProvider;
|
package/dist/decision.js
CHANGED
|
@@ -24,6 +24,9 @@ export function parseDecisionConfig(text) {
|
|
|
24
24
|
throw new Error("decision.baseUrl must be an http(s) URL when decision mapping is enabled");
|
|
25
25
|
return { enabled: true, model, baseUrl };
|
|
26
26
|
}
|
|
27
|
+
export function serializeDecisionConfig(config) {
|
|
28
|
+
return `decision:\n enabled: ${config.enabled}\n model: ${config.model}\n baseUrl: ${config.baseUrl}\n`;
|
|
29
|
+
}
|
|
27
30
|
export function loadDecisionConfig(fs, aiwPath) {
|
|
28
31
|
const configPath = `${aiwPath}/${DECISION_CONFIG_PATH}`;
|
|
29
32
|
if (!fs.exists(configPath))
|
package/dist/semantic.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare const SEMANTIC_CONFIG_PATH = "semantic.yml";
|
|
|
29
29
|
export declare const SEMANTIC_INDEX_PATH = "semantic/index.json";
|
|
30
30
|
export declare const DEFAULT_SEMANTIC_CONFIG: SemanticConfig;
|
|
31
31
|
export declare function parseSemanticConfig(text: string): SemanticConfig;
|
|
32
|
+
export declare function serializeSemanticConfig(config: SemanticConfig): string;
|
|
32
33
|
export declare function loadSemanticConfig(fs: FileSystem, aiwPath: string): SemanticConfig | undefined;
|
|
33
34
|
export declare function createOllamaEmbeddingProvider(config: SemanticConfig): EmbeddingProvider;
|
|
34
35
|
export declare function chunkText(content: string, chunkChars: number): string[];
|
package/dist/semantic.js
CHANGED
|
@@ -35,6 +35,9 @@ export function parseSemanticConfig(text) {
|
|
|
35
35
|
throw new Error("semantic.topK must be a positive integer");
|
|
36
36
|
return { enabled: true, model, baseUrl, chunkChars: parsedChunk, topK: parsedTopK };
|
|
37
37
|
}
|
|
38
|
+
export function serializeSemanticConfig(config) {
|
|
39
|
+
return `semantic:\n enabled: ${config.enabled}\n model: ${config.model}\n baseUrl: ${config.baseUrl}\n chunkChars: ${config.chunkChars}\n topK: ${config.topK}\n`;
|
|
40
|
+
}
|
|
38
41
|
export function loadSemanticConfig(fs, aiwPath) {
|
|
39
42
|
const configPath = `${aiwPath}/${SEMANTIC_CONFIG_PATH}`;
|
|
40
43
|
if (!fs.exists(configPath))
|
package/dist/workflow.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ import type { CommandResult, FileSystem } from "./types.js";
|
|
|
2
2
|
import type { WorkflowDependencies } from "./services.js";
|
|
3
3
|
export type WorkflowServices = WorkflowDependencies;
|
|
4
4
|
export declare function runCommand(args: string[], root: string, fs: FileSystem, services?: WorkflowServices): Promise<CommandResult>;
|
|
5
|
+
export type ConfirmQuestion = (question: string) => Promise<string>;
|
|
6
|
+
export declare function configureOptionalModels(fs: FileSystem, aiwPath: string, answer: ConfirmQuestion): Promise<string[]>;
|
package/dist/workflow.js
CHANGED
|
@@ -21,8 +21,8 @@ import { validatePackageContract } from "./package-contract.js";
|
|
|
21
21
|
import { parseLock, resolvePackage, serializeLock } from "./lockfile.js";
|
|
22
22
|
import { executeVercelSkills, installVercelSkill, nodeCommandExecutor } from "./vercel-skills.js";
|
|
23
23
|
import { scanProject } from "./scanner.js";
|
|
24
|
-
import { buildEvidenceTriageRequest, createOllamaDecisionProvider,
|
|
25
|
-
import { buildSemanticIndex, createOllamaEmbeddingProvider, loadSemanticConfig, parseSemanticIndex, querySemanticIndex, SEMANTIC_INDEX_PATH, serializeSemanticIndex, } from "./semantic.js";
|
|
24
|
+
import { buildEvidenceTriageRequest, createOllamaDecisionProvider, DEFAULT_DECISION_CONFIG, DECISION_CONFIG_PATH, loadDecisionConfig, serializeDecisionConfig, } from "./decision.js";
|
|
25
|
+
import { buildSemanticIndex, createOllamaEmbeddingProvider, DEFAULT_SEMANTIC_CONFIG, loadSemanticConfig, parseSemanticIndex, querySemanticIndex, SEMANTIC_CONFIG_PATH, SEMANTIC_INDEX_PATH, serializeSemanticConfig, serializeSemanticIndex, } from "./semantic.js";
|
|
26
26
|
import { assertKnownPermissions, assertPermissions, assertPackagePermissions, serializePermissionReview, } from "./package-audit.js";
|
|
27
27
|
import { planPackageUpdate } from "./package-updates.js";
|
|
28
28
|
import { searchRegistry, serializeRegistry } from "./registry.js";
|
|
@@ -327,9 +327,22 @@ export async function runCommand(args, root, fs, services = {}) {
|
|
|
327
327
|
pendingWrites.delete(manifestPath);
|
|
328
328
|
pendingWrites.set(manifestPath, `schema: 1\nproject:\n name: ${root.split("/").pop()}\ntarget:\n active: ${target}\npolicies:\n artifact_language: en\n`);
|
|
329
329
|
writeProjectFilesAtomically(fs, root, [...pendingWrites].map(([path, content]) => ({ path, content })), [...BASE_DIRECTORIES.map((directory) => join(aiw, directory)), join(root, ".context/adrs")]);
|
|
330
|
+
let optionalModels = [];
|
|
331
|
+
if (stdin.isTTY) {
|
|
332
|
+
const terminal = createInterface({ input: stdin, output: stdout });
|
|
333
|
+
try {
|
|
334
|
+
optionalModels = await configureOptionalModels(fs, aiw, (question) => terminal.question(question));
|
|
335
|
+
}
|
|
336
|
+
finally {
|
|
337
|
+
terminal.close();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
330
340
|
return {
|
|
331
341
|
exitCode: 0,
|
|
332
|
-
output: `AI Workflow initialized for target: ${target} with only the ai-init skill. Run /ai-init to scan the project and choose which resources to install
|
|
342
|
+
output: `AI Workflow initialized for target: ${target} with only the ai-init skill. Run /ai-init to scan the project and choose which resources to install.` +
|
|
343
|
+
(optionalModels.length
|
|
344
|
+
? ` Optional models enabled: ${optionalModels.join(", ")}. They activate once the models are available.`
|
|
345
|
+
: ""),
|
|
333
346
|
};
|
|
334
347
|
}
|
|
335
348
|
if (command === "telemetry") {
|
|
@@ -1781,6 +1794,30 @@ function approvalArtifactPath(aiw, stage) {
|
|
|
1781
1794
|
};
|
|
1782
1795
|
return resolve(aiw, paths[stage]);
|
|
1783
1796
|
}
|
|
1797
|
+
export async function configureOptionalModels(fs, aiwPath, answer) {
|
|
1798
|
+
const enabled = [];
|
|
1799
|
+
const semanticPath = join(aiwPath, SEMANTIC_CONFIG_PATH);
|
|
1800
|
+
if (!fs.exists(semanticPath)) {
|
|
1801
|
+
const response = (await answer(`Enable semantic mapping with a local embedding model (default: ${DEFAULT_SEMANTIC_CONFIG.model} at ${DEFAULT_SEMANTIC_CONFIG.baseUrl})? [y/N] `))
|
|
1802
|
+
.trim()
|
|
1803
|
+
.toLowerCase();
|
|
1804
|
+
if (response === "y" || response === "yes") {
|
|
1805
|
+
fs.write(semanticPath, serializeSemanticConfig({ ...DEFAULT_SEMANTIC_CONFIG, enabled: true }));
|
|
1806
|
+
enabled.push(`semantic (${DEFAULT_SEMANTIC_CONFIG.model})`);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
const decisionPath = join(aiwPath, DECISION_CONFIG_PATH);
|
|
1810
|
+
if (!fs.exists(decisionPath)) {
|
|
1811
|
+
const response = (await answer(`Enable advisory decision triage with a local decision model (default: ${DEFAULT_DECISION_CONFIG.model} at ${DEFAULT_DECISION_CONFIG.baseUrl})? [y/N] `))
|
|
1812
|
+
.trim()
|
|
1813
|
+
.toLowerCase();
|
|
1814
|
+
if (response === "y" || response === "yes") {
|
|
1815
|
+
fs.write(decisionPath, serializeDecisionConfig({ ...DEFAULT_DECISION_CONFIG, enabled: true }));
|
|
1816
|
+
enabled.push(`decision (${DEFAULT_DECISION_CONFIG.model})`);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
return enabled;
|
|
1820
|
+
}
|
|
1784
1821
|
function formatConfidence(confidence) {
|
|
1785
1822
|
return confidence === undefined ? "unknown" : confidence.toFixed(3);
|
|
1786
1823
|
}
|
package/docs/semantic-mapping.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Semantic Mapping
|
|
2
2
|
|
|
3
|
-
AI Workflow can build a semantic index of the scanned project with a local embedding model such as `embeddinggemma-2` served by Ollama. Semantic mapping is opt-in and flag-gated: it activates only when a valid configuration exists, and every scan and flow query re-reads the flag.
|
|
3
|
+
AI Workflow can build a semantic index of the scanned project with a local embedding model such as `embeddinggemma-2` served by Ollama. Semantic mapping is opt-in and flag-gated: it activates only when a valid configuration exists, and every scan and flow query re-reads the flag. During an interactive `aiw install`, the installer offers to create this configuration with defaults; answering `y` writes it before `/ai-init` runs. Declining, or installing non-interactively, leaves the file absent.
|
|
4
4
|
|
|
5
5
|
## Configuration
|
|
6
6
|
|