agentweaver 0.1.9 → 0.1.11
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 +226 -200
- package/dist/artifacts.js +101 -56
- package/dist/errors.js +7 -0
- package/dist/executors/{codex-local-executor.js → codex-executor.js} +4 -4
- package/dist/executors/configs/{codex-local-config.js → codex-config.js} +1 -1
- package/dist/executors/configs/jira-fetch-config.js +2 -0
- package/dist/executors/configs/telegram-notifier-config.js +3 -0
- package/dist/executors/fetch-gitlab-diff-executor.js +1 -1
- package/dist/executors/fetch-gitlab-review-executor.js +1 -1
- package/dist/executors/git-commit-executor.js +25 -0
- package/dist/executors/telegram-notifier-executor.js +54 -0
- package/dist/flow-state.js +46 -1
- package/dist/gitlab.js +13 -8
- package/dist/index.js +507 -520
- package/dist/interactive-ui.js +495 -87
- package/dist/jira.js +52 -5
- package/dist/pipeline/auto-flow.js +6 -6
- package/dist/pipeline/context.js +1 -0
- package/dist/pipeline/declarative-flows.js +7 -4
- package/dist/pipeline/flow-catalog.js +60 -23
- package/dist/pipeline/flow-model-settings.js +77 -0
- package/dist/pipeline/flow-specs/auto-common.json +446 -0
- package/dist/pipeline/flow-specs/auto-golang.json +563 -0
- package/dist/pipeline/flow-specs/{bug-analyze.json → bugz/bug-analyze.json} +43 -25
- package/dist/pipeline/flow-specs/{bug-fix.json → bugz/bug-fix.json} +5 -4
- package/dist/pipeline/flow-specs/git-commit.json +196 -0
- package/dist/pipeline/flow-specs/{gitlab-diff-review.json → gitlab/gitlab-diff-review.json} +20 -50
- package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +165 -0
- package/dist/pipeline/flow-specs/{mr-description.json → gitlab/mr-description.json} +17 -10
- package/dist/pipeline/flow-specs/{run-go-linter-loop.json → go/run-go-linter-loop.json} +40 -14
- package/dist/pipeline/flow-specs/{run-go-tests-loop.json → go/run-go-tests-loop.json} +40 -14
- package/dist/pipeline/flow-specs/implement.json +5 -4
- package/dist/pipeline/flow-specs/plan.json +40 -148
- package/dist/pipeline/flow-specs/{review-fix.json → review/review-fix.json} +73 -13
- package/dist/pipeline/flow-specs/review/review-loop.json +280 -0
- package/dist/pipeline/flow-specs/review/review-project.json +87 -0
- package/dist/pipeline/flow-specs/review/review.json +126 -0
- package/dist/pipeline/flow-specs/task-describe.json +191 -11
- package/dist/pipeline/launch-profile-config.js +38 -0
- package/dist/pipeline/node-registry.js +75 -45
- package/dist/pipeline/nodes/build-failure-summary-node.js +16 -29
- package/dist/pipeline/nodes/build-review-fix-prompt-node.js +36 -0
- package/dist/pipeline/nodes/codex-prompt-node.js +41 -0
- package/dist/pipeline/nodes/commit-message-form-node.js +79 -0
- package/dist/pipeline/nodes/git-commit-form-node.js +138 -0
- package/dist/pipeline/nodes/git-commit-node.js +28 -0
- package/dist/pipeline/nodes/git-status-node.js +221 -0
- package/dist/pipeline/nodes/gitlab-review-artifacts-node.js +10 -6
- package/dist/pipeline/nodes/jira-context-node.js +10 -0
- package/dist/pipeline/nodes/llm-prompt-node.js +62 -0
- package/dist/pipeline/nodes/plan-codex-node.js +1 -1
- package/dist/pipeline/nodes/read-file-node.js +11 -0
- package/dist/pipeline/nodes/review-findings-form-node.js +18 -14
- package/dist/pipeline/nodes/select-files-form-node.js +72 -0
- package/dist/pipeline/nodes/telegram-notifier-node.js +28 -0
- package/dist/pipeline/nodes/user-input-node.js +29 -8
- package/dist/pipeline/nodes/write-selection-file-node.js +46 -0
- package/dist/pipeline/prompt-registry.js +2 -4
- package/dist/pipeline/prompt-runtime.js +13 -3
- package/dist/pipeline/registry.js +6 -8
- package/dist/pipeline/spec-compiler.js +5 -0
- package/dist/pipeline/spec-loader.js +18 -7
- package/dist/pipeline/spec-types.js +7 -3
- package/dist/pipeline/spec-validator.js +4 -0
- package/dist/pipeline/types.js +1 -0
- package/dist/pipeline/value-resolver.js +40 -38
- package/dist/prompts.js +104 -110
- package/dist/runtime/agentweaver-home.js +8 -0
- package/dist/runtime/command-resolution.js +0 -38
- package/dist/runtime/env-loader.js +43 -0
- package/dist/runtime/process-runner.js +45 -1
- package/dist/structured-artifact-schema-registry.js +53 -0
- package/dist/structured-artifact-schemas.json +0 -20
- package/dist/structured-artifacts.js +3 -43
- package/dist/user-input.js +30 -2
- package/package.json +2 -6
- package/Dockerfile.codex +0 -56
- package/dist/executors/claude-executor.js +0 -46
- package/dist/executors/codex-docker-executor.js +0 -27
- package/dist/executors/configs/claude-config.js +0 -12
- package/dist/executors/configs/codex-docker-config.js +0 -10
- package/dist/executors/configs/verify-build-config.js +0 -7
- package/dist/executors/verify-build-executor.js +0 -123
- package/dist/pipeline/flow-specs/auto.json +0 -979
- package/dist/pipeline/flow-specs/gitlab-review.json +0 -317
- package/dist/pipeline/flow-specs/plan-opencode.json +0 -603
- package/dist/pipeline/flow-specs/preflight.json +0 -206
- package/dist/pipeline/flow-specs/review-project.json +0 -243
- package/dist/pipeline/flow-specs/review.json +0 -312
- package/dist/pipeline/flow-specs/run-linter-loop.json +0 -155
- package/dist/pipeline/flow-specs/run-tests-loop.json +0 -155
- package/dist/pipeline/flows/preflight-flow.js +0 -19
- package/dist/pipeline/nodes/claude-prompt-node.js +0 -54
- package/dist/pipeline/nodes/codex-docker-prompt-node.js +0 -32
- package/dist/pipeline/nodes/codex-local-prompt-node.js +0 -32
- package/dist/pipeline/nodes/review-claude-node.js +0 -38
- package/dist/pipeline/nodes/review-reply-codex-node.js +0 -40
- package/dist/pipeline/nodes/verify-build-node.js +0 -15
- package/dist/runtime/docker-runtime.js +0 -51
- package/docker-compose.yml +0 -445
- package/verify_build.sh +0 -105
package/dist/jira.js
CHANGED
|
@@ -5,6 +5,57 @@ import { TaskRunnerError } from "./errors.js";
|
|
|
5
5
|
const ISSUE_KEY_RE = /^[A-Z][A-Z0-9_]*-[0-9]+$/;
|
|
6
6
|
const TEXT_ATTACHMENT_EXTENSIONS = new Set([".md", ".json", ".txt"]);
|
|
7
7
|
const DOWNLOAD_ONLY_ATTACHMENT_EXTENSIONS = new Set([".doc"]);
|
|
8
|
+
const JIRA_AUTH_MODES = new Set(["auto", "basic", "bearer"]);
|
|
9
|
+
function parseJiraAuthMode(rawMode) {
|
|
10
|
+
const mode = rawMode?.trim().toLowerCase() || "auto";
|
|
11
|
+
if (!JIRA_AUTH_MODES.has(mode)) {
|
|
12
|
+
throw new TaskRunnerError("JIRA_AUTH_MODE must be one of: auto, basic, bearer.");
|
|
13
|
+
}
|
|
14
|
+
return mode;
|
|
15
|
+
}
|
|
16
|
+
export function detectJiraDeployment(url) {
|
|
17
|
+
try {
|
|
18
|
+
return new URL(url).hostname.toLowerCase().includes("atlassian") ? "cloud" : "server";
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return url.toLowerCase().includes("atlassian") ? "cloud" : "server";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function resolveJiraAuthMode(url) {
|
|
25
|
+
const authMode = parseJiraAuthMode(process.env.JIRA_AUTH_MODE);
|
|
26
|
+
if (authMode !== "auto") {
|
|
27
|
+
return authMode;
|
|
28
|
+
}
|
|
29
|
+
return detectJiraDeployment(url) === "cloud" ? "basic" : "bearer";
|
|
30
|
+
}
|
|
31
|
+
export function buildJiraAuthHeaders(url) {
|
|
32
|
+
const jiraApiKey = process.env.JIRA_API_KEY?.trim();
|
|
33
|
+
if (!jiraApiKey) {
|
|
34
|
+
throw new TaskRunnerError("JIRA_API_KEY is required for Jira authentication.");
|
|
35
|
+
}
|
|
36
|
+
const authMode = resolveJiraAuthMode(url);
|
|
37
|
+
if (authMode === "bearer") {
|
|
38
|
+
return {
|
|
39
|
+
Authorization: `Bearer ${jiraApiKey}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const jiraUsername = process.env.JIRA_USERNAME?.trim();
|
|
43
|
+
if (!jiraUsername) {
|
|
44
|
+
const host = (() => {
|
|
45
|
+
try {
|
|
46
|
+
return new URL(url).host;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return "unknown";
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
52
|
+
throw new TaskRunnerError(`JIRA_USERNAME is required for Jira Cloud Basic auth (detected from URL host: ${host}).`);
|
|
53
|
+
}
|
|
54
|
+
const encodedCredentials = Buffer.from(`${jiraUsername}:${jiraApiKey}`).toString("base64");
|
|
55
|
+
return {
|
|
56
|
+
Authorization: `Basic ${encodedCredentials}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
8
59
|
function sanitizeAttachmentFileName(fileName) {
|
|
9
60
|
const parsed = path.parse(fileName);
|
|
10
61
|
const baseName = parsed.name
|
|
@@ -29,13 +80,9 @@ function parseJiraAttachments(issueBody) {
|
|
|
29
80
|
}
|
|
30
81
|
}
|
|
31
82
|
async function fetchAuthorizedBuffer(url, accept) {
|
|
32
|
-
const jiraApiKey = process.env.JIRA_API_KEY;
|
|
33
|
-
if (!jiraApiKey) {
|
|
34
|
-
throw new TaskRunnerError("JIRA_API_KEY is required for Jira fetch.");
|
|
35
|
-
}
|
|
36
83
|
const response = await fetch(url, {
|
|
37
84
|
headers: {
|
|
38
|
-
|
|
85
|
+
...buildJiraAuthHeaders(url),
|
|
39
86
|
Accept: accept,
|
|
40
87
|
},
|
|
41
88
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { loadDeclarativeFlow } from "./declarative-flows.js";
|
|
2
|
-
let
|
|
3
|
-
export function
|
|
4
|
-
if (
|
|
5
|
-
return
|
|
2
|
+
let cachedAutoGolangFlow = null;
|
|
3
|
+
export function loadAutoGolangFlow() {
|
|
4
|
+
if (cachedAutoGolangFlow) {
|
|
5
|
+
return cachedAutoGolangFlow;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
return
|
|
7
|
+
cachedAutoGolangFlow = loadDeclarativeFlow({ source: "built-in", fileName: "auto-golang.json" });
|
|
8
|
+
return cachedAutoGolangFlow;
|
|
9
9
|
}
|
package/dist/pipeline/context.js
CHANGED
|
@@ -39,18 +39,21 @@ export function loadDeclarativeFlow(flow) {
|
|
|
39
39
|
}
|
|
40
40
|
export function resolveNamedDeclarativeFlowRef(fileName, cwd) {
|
|
41
41
|
const projectMatches = listProjectFlowSpecFiles(cwd).filter((candidate) => path.basename(candidate) === fileName);
|
|
42
|
-
const
|
|
43
|
-
if (projectMatches.length > 0 &&
|
|
42
|
+
const builtInMatches = listBuiltInFlowSpecFiles().filter((candidate) => path.basename(candidate) === fileName);
|
|
43
|
+
if (projectMatches.length > 0 && builtInMatches.length > 0) {
|
|
44
44
|
throw new Error(`Ambiguous nested flow '${fileName}': both built-in and project-local specs exist in ${projectFlowSpecsDir(cwd)}.`);
|
|
45
45
|
}
|
|
46
46
|
if (projectMatches.length > 1) {
|
|
47
47
|
throw new Error(`Ambiguous project-local flow '${fileName}' in ${projectFlowSpecsDir(cwd)}.`);
|
|
48
48
|
}
|
|
49
|
+
if (builtInMatches.length > 1) {
|
|
50
|
+
throw new Error(`Ambiguous built-in flow '${fileName}'. Use unique nested flow file names.`);
|
|
51
|
+
}
|
|
49
52
|
if (projectMatches[0]) {
|
|
50
53
|
return { source: "project-local", filePath: projectMatches[0] };
|
|
51
54
|
}
|
|
52
|
-
if (
|
|
53
|
-
return { source: "built-in", fileName };
|
|
55
|
+
if (builtInMatches[0]) {
|
|
56
|
+
return { source: "built-in", fileName: builtInMatches[0] };
|
|
54
57
|
}
|
|
55
58
|
throw new Error(`Nested flow '${fileName}' was not found.`);
|
|
56
59
|
}
|
|
@@ -1,47 +1,84 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { TaskRunnerError } from "../errors.js";
|
|
3
|
-
import {
|
|
3
|
+
import { loadAutoGolangFlow } from "./auto-flow.js";
|
|
4
4
|
import { loadDeclarativeFlow } from "./declarative-flows.js";
|
|
5
|
-
import { listProjectFlowSpecFiles } from "./spec-loader.js";
|
|
6
|
-
export const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
import { listBuiltInFlowSpecFiles, listProjectFlowSpecFiles, projectFlowSpecsDir } from "./spec-loader.js";
|
|
6
|
+
export const BUILT_IN_COMMAND_FLOW_IDS = [
|
|
7
|
+
"auto-golang",
|
|
8
|
+
"auto-common",
|
|
9
|
+
"bug-analyze",
|
|
10
|
+
"bug-fix",
|
|
11
|
+
"git-commit",
|
|
12
|
+
"gitlab-diff-review",
|
|
13
|
+
"gitlab-review",
|
|
14
|
+
"mr-description",
|
|
15
|
+
"plan",
|
|
16
|
+
"task-describe",
|
|
17
|
+
"implement",
|
|
18
|
+
"review",
|
|
19
|
+
"review-fix",
|
|
20
|
+
"review-loop",
|
|
21
|
+
"run-go-tests-loop",
|
|
22
|
+
"run-go-linter-loop",
|
|
20
23
|
];
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
const BUILT_IN_COMMAND_FLOW_FILES = {
|
|
25
|
+
"auto-golang": "auto-golang.json",
|
|
26
|
+
"auto-common": "auto-common.json",
|
|
27
|
+
"bug-analyze": "bugz/bug-analyze.json",
|
|
28
|
+
"bug-fix": "bugz/bug-fix.json",
|
|
29
|
+
"git-commit": "git-commit.json",
|
|
30
|
+
"gitlab-diff-review": "gitlab/gitlab-diff-review.json",
|
|
31
|
+
"gitlab-review": "gitlab/gitlab-review.json",
|
|
32
|
+
"mr-description": "gitlab/mr-description.json",
|
|
33
|
+
plan: "plan.json",
|
|
34
|
+
"task-describe": "task-describe.json",
|
|
35
|
+
implement: "implement.json",
|
|
36
|
+
review: "review/review.json",
|
|
37
|
+
"review-fix": "review/review-fix.json",
|
|
38
|
+
"review-loop": "review/review-loop.json",
|
|
39
|
+
"run-go-tests-loop": "go/run-go-tests-loop.json",
|
|
40
|
+
"run-go-linter-loop": "go/run-go-linter-loop.json",
|
|
41
|
+
};
|
|
42
|
+
function builtInCommandIdForFile(fileName) {
|
|
43
|
+
for (const [flowId, candidate] of Object.entries(BUILT_IN_COMMAND_FLOW_FILES)) {
|
|
44
|
+
if (candidate === fileName) {
|
|
45
|
+
return flowId;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function loadBuiltInCatalogEntry(fileName) {
|
|
51
|
+
const commandId = builtInCommandIdForFile(fileName);
|
|
52
|
+
const relativePath = fileName.replace(/\.json$/i, "").split(/[\\/]+/).filter((segment) => segment.length > 0);
|
|
53
|
+
const id = commandId ?? relativePath.join("/");
|
|
54
|
+
const flow = id === "auto-golang" ? loadAutoGolangFlow() : loadDeclarativeFlow({ source: "built-in", fileName });
|
|
23
55
|
return {
|
|
24
56
|
id,
|
|
25
57
|
source: "built-in",
|
|
26
58
|
fileName,
|
|
27
59
|
absolutePath: flow.absolutePath,
|
|
60
|
+
treePath: ["default", ...relativePath],
|
|
28
61
|
flow,
|
|
29
62
|
};
|
|
30
63
|
}
|
|
31
|
-
function loadProjectCatalogEntry(filePath) {
|
|
64
|
+
function loadProjectCatalogEntry(cwd, filePath) {
|
|
32
65
|
const flow = loadDeclarativeFlow({ source: "project-local", filePath });
|
|
66
|
+
const relativeFilePath = path.relative(projectFlowSpecsDir(cwd), path.resolve(filePath));
|
|
67
|
+
const relativePathWithoutExt = relativeFilePath.replace(/\.json$/i, "");
|
|
68
|
+
const relativeSegments = relativePathWithoutExt.split(path.sep).filter((segment) => segment.length > 0);
|
|
33
69
|
return {
|
|
34
|
-
id:
|
|
70
|
+
id: relativeSegments.join("/"),
|
|
35
71
|
source: "project-local",
|
|
36
72
|
fileName: path.basename(filePath),
|
|
37
73
|
absolutePath: path.resolve(filePath),
|
|
74
|
+
treePath: ["custom", ...relativeSegments],
|
|
38
75
|
flow,
|
|
39
76
|
};
|
|
40
77
|
}
|
|
41
78
|
export function loadInteractiveFlowCatalog(cwd) {
|
|
42
|
-
const entries =
|
|
79
|
+
const entries = listBuiltInFlowSpecFiles().map((fileName) => loadBuiltInCatalogEntry(fileName));
|
|
43
80
|
for (const filePath of listProjectFlowSpecFiles(cwd)) {
|
|
44
|
-
entries.push(loadProjectCatalogEntry(filePath));
|
|
81
|
+
entries.push(loadProjectCatalogEntry(cwd, filePath));
|
|
45
82
|
}
|
|
46
83
|
const byId = new Map();
|
|
47
84
|
for (const entry of entries) {
|
|
@@ -57,7 +94,7 @@ export function findCatalogEntry(flowId, entries) {
|
|
|
57
94
|
return entries.find((entry) => entry.id === flowId);
|
|
58
95
|
}
|
|
59
96
|
export function isBuiltInCommandFlowId(flowId) {
|
|
60
|
-
return
|
|
97
|
+
return BUILT_IN_COMMAND_FLOW_IDS.includes(flowId);
|
|
61
98
|
}
|
|
62
99
|
export function toDeclarativeFlowRef(entry) {
|
|
63
100
|
return entry.source === "built-in"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_MODEL_BY_EXECUTOR, defaultModelForExecutor } from "./launch-profile-config.js";
|
|
4
|
+
import { scopeArtifactsDir } from "../artifacts.js";
|
|
5
|
+
const FLOW_MODEL_SETTINGS_FILE = "agentweaver-flow-model-settings.json";
|
|
6
|
+
function flowModelSettingsPath(scopeKey) {
|
|
7
|
+
return path.join(scopeArtifactsDir(scopeKey), FLOW_MODEL_SETTINGS_FILE);
|
|
8
|
+
}
|
|
9
|
+
function ensureArtifactsDir(scopeKey) {
|
|
10
|
+
const artifactsDir = scopeArtifactsDir(scopeKey);
|
|
11
|
+
if (!existsSync(artifactsDir)) {
|
|
12
|
+
mkdirSync(artifactsDir, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function loadFlowModelSettings(scopeKey) {
|
|
16
|
+
const filePath = flowModelSettingsPath(scopeKey);
|
|
17
|
+
if (!existsSync(filePath)) {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const content = readFileSync(filePath, "utf8");
|
|
22
|
+
const parsed = JSON.parse(content);
|
|
23
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function saveFlowModelSettings(scopeKey, store) {
|
|
33
|
+
ensureArtifactsDir(scopeKey);
|
|
34
|
+
const filePath = flowModelSettingsPath(scopeKey);
|
|
35
|
+
const tempPath = `${filePath}.tmp`;
|
|
36
|
+
const content = JSON.stringify(store, null, 2);
|
|
37
|
+
writeFileSync(tempPath, content, "utf8");
|
|
38
|
+
renameSync(tempPath, filePath);
|
|
39
|
+
}
|
|
40
|
+
export function getEffectiveModelForFlow(flowId, scopeKey, executor) {
|
|
41
|
+
const store = loadFlowModelSettings(scopeKey);
|
|
42
|
+
const flowSettings = store[flowId];
|
|
43
|
+
if (!flowSettings) {
|
|
44
|
+
return defaultModelForExecutor(executor);
|
|
45
|
+
}
|
|
46
|
+
if (flowSettings.lastSelectedModel && flowSettings.lastSelectedModel !== "default") {
|
|
47
|
+
return flowSettings.lastSelectedModel;
|
|
48
|
+
}
|
|
49
|
+
if (flowSettings.defaultModel && flowSettings.defaultModel !== "default") {
|
|
50
|
+
return flowSettings.defaultModel;
|
|
51
|
+
}
|
|
52
|
+
return defaultModelForExecutor(executor);
|
|
53
|
+
}
|
|
54
|
+
export function updateLastSelectedModel(flowId, scopeKey, executor, model) {
|
|
55
|
+
const store = loadFlowModelSettings(scopeKey);
|
|
56
|
+
const existingSettings = store[flowId];
|
|
57
|
+
if (existingSettings) {
|
|
58
|
+
store[flowId] = {
|
|
59
|
+
...existingSettings,
|
|
60
|
+
executor,
|
|
61
|
+
defaultModel: model,
|
|
62
|
+
lastSelectedModel: model,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
store[flowId] = {
|
|
67
|
+
executor,
|
|
68
|
+
defaultModel: DEFAULT_MODEL_BY_EXECUTOR[executor],
|
|
69
|
+
lastSelectedModel: model,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
saveFlowModelSettings(scopeKey, store);
|
|
73
|
+
}
|
|
74
|
+
export function getFlowModelSettings(flowId, scopeKey) {
|
|
75
|
+
const store = loadFlowModelSettings(scopeKey);
|
|
76
|
+
return store[flowId] ?? null;
|
|
77
|
+
}
|