@chenmk/superflow 0.2.5 → 0.4.0
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 +24 -2
- package/README.zh-CN.md +17 -1
- package/assets/manifest.json +7 -4
- package/assets/prompts/superflow-clarify.md +6 -0
- package/assets/prompts/superflow-design.md +3 -0
- package/assets/prompts/superflow-docs.md +4 -1
- package/assets/prompts/superflow-pipeline.md +8 -0
- package/assets/scripts/superflow-archive-command-hook.sh +80 -0
- package/assets/scripts/superflow-delivery-check.sh +23 -4
- package/assets/scripts/superflow-dependency-update-hook.sh +1 -1
- package/assets/scripts/superflow-managed-work-check.mjs +194 -0
- package/assets/scripts/superflow-managed-work-guard.sh +103 -0
- package/assets/skills/openspec-propose/SKILL.md +11 -0
- package/assets/skills/superflow-archive/SKILL.md +5 -0
- package/assets/skills/superflow-clarify/SKILL.md +26 -7
- package/assets/skills/superflow-design/SKILL.md +38 -7
- package/assets/skills/superflow-docs/SKILL.md +27 -0
- package/assets/skills/superflow-pipeline/SKILL.md +75 -0
- package/assets/skills/superflow-pipeline/references/api-design-template.md +11 -0
- package/assets/skills/superflow-pipeline/references/batch-prompt-template.md +27 -0
- package/assets/skills/superflow-pipeline/references/document-templates.md +8 -0
- package/assets/skills/superflow-pipeline/references/implementation-prompt-template.md +29 -1
- package/assets/skills/superflow-pipeline/references/managed-work.md +58 -0
- package/assets/skills/superflow-pipeline/references/quality-gate.md +3 -0
- package/assets/skills/superflow-pipeline/references/superpower-technical-design-template.md +51 -0
- package/assets/skills/superflow-pipeline/references/test-execution-template.md +10 -0
- package/assets/skills/superflow-pipeline/scripts/superflow-archive.sh +1 -1
- package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +215 -2
- package/assets/skills/superflow-verify/SKILL.md +7 -0
- package/assets/skills-en/openspec-propose/SKILL.md +14 -0
- package/assets/skills-en/superflow-archive/SKILL.md +6 -0
- package/assets/skills-en/superflow-clarify/SKILL.md +26 -7
- package/assets/skills-en/superflow-design/SKILL.md +38 -6
- package/assets/skills-en/superflow-docs/SKILL.md +27 -0
- package/assets/skills-en/superflow-pipeline/SKILL.md +76 -0
- package/assets/skills-en/superflow-pipeline/references/api-design-template.md +13 -0
- package/assets/skills-en/superflow-pipeline/references/batch-prompt-template.md +16 -0
- package/assets/skills-en/superflow-pipeline/references/document-templates.md +5 -0
- package/assets/skills-en/superflow-pipeline/references/implementation-prompt-template.md +17 -0
- package/assets/skills-en/superflow-pipeline/references/managed-work.md +34 -0
- package/assets/skills-en/superflow-pipeline/references/quality-gate.md +25 -0
- package/assets/skills-en/superflow-pipeline/references/superpower-technical-design-template.md +57 -0
- package/assets/skills-en/superflow-pipeline/references/test-execution-template.md +12 -0
- package/assets/skills-en/superflow-pipeline/scripts/superflow-archive.sh +1 -1
- package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +214 -2
- package/assets/skills-en/superflow-verify/SKILL.md +8 -0
- package/dist/app/cli.js +120 -102
- package/dist/app/cli.js.map +1 -1
- package/dist/app/commands/archive.js +7 -3
- package/dist/app/commands/archive.js.map +1 -1
- package/dist/app/commands/change-guard.js +27 -0
- package/dist/app/commands/change-guard.js.map +1 -0
- package/dist/app/commands/design.js +2 -20
- package/dist/app/commands/design.js.map +1 -1
- package/dist/app/commands/init.js +7 -7
- package/dist/app/commands/init.js.map +1 -1
- package/dist/app/commands/managed-service.js +5 -0
- package/dist/app/commands/managed-service.js.map +1 -0
- package/dist/app/commands/pipeline.js +123 -3
- package/dist/app/commands/pipeline.js.map +1 -1
- package/dist/app/commands/status.js +199 -77
- package/dist/app/commands/status.js.map +1 -1
- package/dist/app/commands/uninstall.js +5 -2
- package/dist/app/commands/uninstall.js.map +1 -1
- package/dist/app/commands/update.js +33 -11
- package/dist/app/commands/update.js.map +1 -1
- package/dist/app/commands/verify.js +7 -3
- package/dist/app/commands/verify.js.map +1 -1
- package/dist/domains/config/cli-help.js +103 -73
- package/dist/domains/config/cli-help.js.map +1 -1
- package/dist/domains/config/context.js +1 -5
- package/dist/domains/config/context.js.map +1 -1
- package/dist/domains/deps.js +3 -6
- package/dist/domains/deps.js.map +1 -1
- package/dist/domains/hook.js +71 -37
- package/dist/domains/hook.js.map +1 -1
- package/dist/domains/managed-work/contract.js +218 -0
- package/dist/domains/managed-work/contract.js.map +1 -0
- package/dist/domains/managed-work/i18n.js +12 -0
- package/dist/domains/managed-work/i18n.js.map +1 -0
- package/dist/domains/managed-work/input.js +111 -0
- package/dist/domains/managed-work/input.js.map +1 -0
- package/dist/domains/managed-work/journal.js +122 -0
- package/dist/domains/managed-work/journal.js.map +1 -0
- package/dist/domains/managed-work/lock.js +40 -0
- package/dist/domains/managed-work/lock.js.map +1 -0
- package/dist/domains/managed-work/notifications.js +53 -0
- package/dist/domains/managed-work/notifications.js.map +1 -0
- package/dist/domains/managed-work/paths.js +18 -0
- package/dist/domains/managed-work/paths.js.map +1 -0
- package/dist/domains/managed-work/prompts.js +218 -0
- package/dist/domains/managed-work/prompts.js.map +1 -0
- package/dist/domains/managed-work/runner.js +626 -0
- package/dist/domains/managed-work/runner.js.map +1 -0
- package/dist/domains/managed-work/schemas.js +85 -0
- package/dist/domains/managed-work/schemas.js.map +1 -0
- package/dist/domains/managed-work/service.js +121 -0
- package/dist/domains/managed-work/service.js.map +1 -0
- package/dist/domains/managed-work/state.js +90 -0
- package/dist/domains/managed-work/state.js.map +1 -0
- package/dist/domains/managed-work/storage.js +181 -0
- package/dist/domains/managed-work/storage.js.map +1 -0
- package/dist/domains/managed-work/types.js +16 -0
- package/dist/domains/managed-work/types.js.map +1 -0
- package/dist/domains/managed-work/wait.js +40 -0
- package/dist/domains/managed-work/wait.js.map +1 -0
- package/dist/platform/agent-process.js +308 -0
- package/dist/platform/agent-process.js.map +1 -0
- package/dist/platform/assets.js +9 -0
- package/dist/platform/assets.js.map +1 -0
- package/dist/platform/process-liveness.js +10 -0
- package/dist/platform/process-liveness.js.map +1 -0
- package/dist/platform/version-check.js +30 -9
- package/dist/platform/version-check.js.map +1 -1
- package/package.json +3 -2
- package/scripts/release-notes-check.js +102 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "crypto";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { managedText } from "./i18n.js";
|
|
5
|
+
import { DEFAULT_MANAGED_BUDGETS, HARD_MAX_ACTIVE_RUN_HOURS, HARD_MAX_EXECUTOR_INVOCATIONS, HARD_MAX_REVIEW_ROUNDS, HARD_MAX_SINGLE_INVOCATION_HOURS, HARD_MAX_TOTAL_AGENT_INVOCATIONS, } from "./types.js";
|
|
6
|
+
export function createManagedTaskContract(input) {
|
|
7
|
+
const request = input.request.trim();
|
|
8
|
+
if (!request) {
|
|
9
|
+
throw new Error(managedText(input.language, "托管任务内容不能为空", "Managed task cannot be empty"));
|
|
10
|
+
}
|
|
11
|
+
const projectRoot = path.resolve(input.projectRoot);
|
|
12
|
+
const relatedProjectRoots = [
|
|
13
|
+
...new Set((input.relatedProjectRoots ?? [])
|
|
14
|
+
.map((root) => path.resolve(root))
|
|
15
|
+
.filter((root) => root !== projectRoot)),
|
|
16
|
+
].sort();
|
|
17
|
+
const supervisorAgent = input.supervisorAgent ?? "codex";
|
|
18
|
+
const executorAgent = input.executorAgent ?? oppositeAgent(supervisorAgent);
|
|
19
|
+
if (supervisorAgent === executorAgent) {
|
|
20
|
+
throw new Error(managedText(input.language, "监督 Agent 和执行 Agent 不能相同", "Supervisor and executor agents must be different"));
|
|
21
|
+
}
|
|
22
|
+
const taskId = buildTaskId();
|
|
23
|
+
const now = new Date().toISOString();
|
|
24
|
+
const profile = input.profile && input.profile !== "auto"
|
|
25
|
+
? input.profile
|
|
26
|
+
: classifyManagedProfile(request);
|
|
27
|
+
const budgets = resolveBudgets(input.budgets, input.language);
|
|
28
|
+
const taskPrompt = input.taskPromptPath
|
|
29
|
+
? buildTaskPrompt(projectRoot, taskId, input.taskPromptPath)
|
|
30
|
+
: null;
|
|
31
|
+
const contract = {
|
|
32
|
+
schemaVersion: 1,
|
|
33
|
+
taskId,
|
|
34
|
+
request,
|
|
35
|
+
source: input.source ?? "direct_prompt",
|
|
36
|
+
projectRoot,
|
|
37
|
+
relatedProjectRoots,
|
|
38
|
+
profile,
|
|
39
|
+
language: input.language ?? "zh",
|
|
40
|
+
objective: taskPrompt
|
|
41
|
+
? managedText(input.language, `严格执行冻结的 Superflow 任务 Prompt:${taskPrompt.snapshotPath}`, `Execute the frozen Superflow task prompt exactly: ${taskPrompt.snapshotPath}`)
|
|
42
|
+
: request,
|
|
43
|
+
doneCriteria: defaultDoneCriteria(profile, input.language),
|
|
44
|
+
taskPrompt,
|
|
45
|
+
supervisorAgent,
|
|
46
|
+
executorAgent,
|
|
47
|
+
contractHash: "",
|
|
48
|
+
permissions: {
|
|
49
|
+
autonomy: "maximum_within_safe_scope",
|
|
50
|
+
gitCommit: false,
|
|
51
|
+
gitPush: false,
|
|
52
|
+
productionWrites: false,
|
|
53
|
+
bypassSandbox: false,
|
|
54
|
+
},
|
|
55
|
+
budgets,
|
|
56
|
+
createdAt: now,
|
|
57
|
+
updatedAt: now,
|
|
58
|
+
status: "queued",
|
|
59
|
+
};
|
|
60
|
+
contract.contractHash = calculateManagedContractHash(contract);
|
|
61
|
+
return contract;
|
|
62
|
+
}
|
|
63
|
+
export function validateManagedTaskContract(contract) {
|
|
64
|
+
const message = (zh, en) => managedText(contract.language, zh, en);
|
|
65
|
+
if (contract.schemaVersion !== 1) {
|
|
66
|
+
throw new Error(message(`不支持的托管任务合同版本:${contract.schemaVersion}`, `Unsupported managed task contract version: ${contract.schemaVersion}`));
|
|
67
|
+
}
|
|
68
|
+
if (contract.supervisorAgent === contract.executorAgent) {
|
|
69
|
+
throw new Error(message("监督 Agent 和执行 Agent 不能相同", "Supervisor and executor agents must be different"));
|
|
70
|
+
}
|
|
71
|
+
validateManagedBudgets(contract.budgets, contract.language);
|
|
72
|
+
validateTaskPromptMetadata(contract);
|
|
73
|
+
if (contract.permissions.gitCommit ||
|
|
74
|
+
contract.permissions.gitPush ||
|
|
75
|
+
contract.permissions.productionWrites ||
|
|
76
|
+
contract.permissions.bypassSandbox) {
|
|
77
|
+
throw new Error(message("托管任务合同试图放宽不可覆盖的安全边界", "Managed task contract attempts to relax non-overridable safety boundaries"));
|
|
78
|
+
}
|
|
79
|
+
if (contract.contractHash !== calculateManagedContractHash(contract)) {
|
|
80
|
+
throw new Error(message("托管任务合同哈希校验失败,拒绝继续", "Managed task contract hash verification failed; refusing to continue"));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function calculateManagedContractHash(contract) {
|
|
84
|
+
const immutable = {
|
|
85
|
+
schemaVersion: contract.schemaVersion,
|
|
86
|
+
taskId: contract.taskId,
|
|
87
|
+
request: contract.request,
|
|
88
|
+
source: contract.source,
|
|
89
|
+
projectRoot: path.resolve(contract.projectRoot),
|
|
90
|
+
relatedProjectRoots: contract.relatedProjectRoots.map((root) => path.resolve(root)),
|
|
91
|
+
profile: contract.profile,
|
|
92
|
+
...(contract.language ? { language: contract.language } : {}),
|
|
93
|
+
objective: contract.objective,
|
|
94
|
+
doneCriteria: contract.doneCriteria,
|
|
95
|
+
taskPrompt: contract.taskPrompt,
|
|
96
|
+
supervisorAgent: contract.supervisorAgent,
|
|
97
|
+
executorAgent: contract.executorAgent,
|
|
98
|
+
permissions: contract.permissions,
|
|
99
|
+
budgets: contract.budgets,
|
|
100
|
+
};
|
|
101
|
+
return createHash("sha256").update(JSON.stringify(immutable)).digest("hex");
|
|
102
|
+
}
|
|
103
|
+
export function validateManagedTaskPromptSnapshot(contract) {
|
|
104
|
+
if (!contract.taskPrompt)
|
|
105
|
+
return;
|
|
106
|
+
let content;
|
|
107
|
+
try {
|
|
108
|
+
content = readFileSync(contract.taskPrompt.snapshotPath, "utf-8");
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new Error(managedText(contract.language, "冻结的任务 Prompt 快照不存在,拒绝继续", "Frozen task prompt snapshot is missing; refusing to continue"));
|
|
112
|
+
}
|
|
113
|
+
if (sha256(content) !== contract.taskPrompt.sha256) {
|
|
114
|
+
throw new Error(managedText(contract.language, "冻结的任务 Prompt 快照哈希校验失败,拒绝继续", "Frozen task prompt snapshot hash verification failed; refusing to continue"));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function buildTaskPrompt(projectRoot, taskId, inputPath) {
|
|
118
|
+
const originalPath = path.resolve(inputPath);
|
|
119
|
+
const content = readFileSync(originalPath, "utf-8");
|
|
120
|
+
return {
|
|
121
|
+
originalPath,
|
|
122
|
+
snapshotPath: path.join(projectRoot, ".superflow", "tasks", taskId, "source-prompt.md"),
|
|
123
|
+
sha256: sha256(content),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function validateTaskPromptMetadata(contract) {
|
|
127
|
+
if (!contract.taskPrompt)
|
|
128
|
+
return;
|
|
129
|
+
if (!/^[a-f0-9]{64}$/.test(contract.taskPrompt.sha256)) {
|
|
130
|
+
throw new Error(managedText(contract.language, "任务 Prompt 哈希格式非法", "Task prompt hash format is invalid"));
|
|
131
|
+
}
|
|
132
|
+
const expectedSnapshot = path.join(contract.projectRoot, ".superflow", "tasks", contract.taskId, "source-prompt.md");
|
|
133
|
+
if (path.resolve(contract.taskPrompt.snapshotPath) !== expectedSnapshot) {
|
|
134
|
+
throw new Error(managedText(contract.language, "任务 Prompt 快照路径不属于当前托管任务", "Task prompt snapshot path does not belong to this managed task"));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function sha256(value) {
|
|
138
|
+
return createHash("sha256").update(value).digest("hex");
|
|
139
|
+
}
|
|
140
|
+
export function classifyManagedProfile(request) {
|
|
141
|
+
const normalized = request.toLowerCase();
|
|
142
|
+
if (/(等待|监控|观察|轮询|watch|monitor|日志持续)/i.test(normalized)) {
|
|
143
|
+
return "monitor";
|
|
144
|
+
}
|
|
145
|
+
if (/(openspec|sdd|数据库|database|sql|mapper|跨仓|cross[- ]?repo|支付|payment|退款|refund|消息队列|message queue|mq|api|接口|状态机|state machine|生产|production)/i.test(normalized)) {
|
|
146
|
+
return "sdd";
|
|
147
|
+
}
|
|
148
|
+
if (/(修复|fix|开发|develop|实现|implement|代码|code|测试|test|bug|build|compile|启动应用|start (?:the )?app|重构|refactor)/i.test(normalized)) {
|
|
149
|
+
return "engineering";
|
|
150
|
+
}
|
|
151
|
+
return "quick";
|
|
152
|
+
}
|
|
153
|
+
function resolveBudgets(overrides = {}, language) {
|
|
154
|
+
const budgets = { ...DEFAULT_MANAGED_BUDGETS, ...overrides };
|
|
155
|
+
validateManagedBudgets(budgets, language);
|
|
156
|
+
return budgets;
|
|
157
|
+
}
|
|
158
|
+
function validateManagedBudgets(budgets, language) {
|
|
159
|
+
assertIntegerRange("maxReviewRounds", budgets.maxReviewRounds, HARD_MAX_REVIEW_ROUNDS, language);
|
|
160
|
+
assertIntegerRange("maxExecutorInvocations", budgets.maxExecutorInvocations, HARD_MAX_EXECUTOR_INVOCATIONS, language);
|
|
161
|
+
assertIntegerRange("maxTotalAgentInvocations", budgets.maxTotalAgentInvocations, HARD_MAX_TOTAL_AGENT_INVOCATIONS, language);
|
|
162
|
+
assertRange("maxActiveRunHours", budgets.maxActiveRunHours, HARD_MAX_ACTIVE_RUN_HOURS, language);
|
|
163
|
+
assertRange("maxSingleInvocationHours", budgets.maxSingleInvocationHours, HARD_MAX_SINGLE_INVOCATION_HOURS, language);
|
|
164
|
+
if (budgets.stalledTimeoutMinutes <= budgets.noProgressWarningMinutes) {
|
|
165
|
+
throw new Error(managedText(language, "卡死判定时间必须大于无进展告警时间", "Stalled timeout must be greater than the no-progress warning time"));
|
|
166
|
+
}
|
|
167
|
+
if (!Number.isFinite(budgets.activeRunWarningHours) ||
|
|
168
|
+
budgets.activeRunWarningHours <= 0 ||
|
|
169
|
+
budgets.activeRunWarningHours >= budgets.maxActiveRunHours) {
|
|
170
|
+
throw new Error(managedText(language, "运行告警时间必须大于 0 且小于实际工作时间硬上限", "Active-run warning time must be greater than 0 and below the hard active-run limit"));
|
|
171
|
+
}
|
|
172
|
+
if (!Number.isFinite(budgets.noProgressWarningMinutes) ||
|
|
173
|
+
budgets.noProgressWarningMinutes <= 0 ||
|
|
174
|
+
!Number.isFinite(budgets.stalledTimeoutMinutes)) {
|
|
175
|
+
throw new Error(managedText(language, "无进展和卡死判定时间必须是正数", "No-progress warning and stalled timeout must be positive numbers"));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function assertRange(field, value, max, language) {
|
|
179
|
+
if (!Number.isFinite(value) || value <= 0 || value > max) {
|
|
180
|
+
throw new Error(managedText(language, `${field} 必须大于 0 且不能超过硬上限 ${max}`, `${field} must be greater than 0 and cannot exceed the hard limit ${max}`));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function assertIntegerRange(field, value, max, language) {
|
|
184
|
+
assertRange(field, value, max, language);
|
|
185
|
+
if (!Number.isInteger(value)) {
|
|
186
|
+
throw new Error(managedText(language, `${field} 必须是整数`, `${field} must be an integer`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function oppositeAgent(agent) {
|
|
190
|
+
return agent === "codex" ? "claude" : "codex";
|
|
191
|
+
}
|
|
192
|
+
function buildTaskId() {
|
|
193
|
+
const stamp = new Date()
|
|
194
|
+
.toISOString()
|
|
195
|
+
.replace(/[-:TZ.]/g, "")
|
|
196
|
+
.slice(0, 14);
|
|
197
|
+
return `task-${stamp}-${randomUUID().slice(0, 8)}`;
|
|
198
|
+
}
|
|
199
|
+
function defaultDoneCriteria(profile, language) {
|
|
200
|
+
const common = language === "en"
|
|
201
|
+
? [
|
|
202
|
+
"Complete the user goal without silently expanding scope",
|
|
203
|
+
"Provide reviewable deliverables and verification evidence",
|
|
204
|
+
"Record residual issues, blockers, and unexecuted checks",
|
|
205
|
+
"After final acceptance, wait for user approval; never commit or push Git automatically",
|
|
206
|
+
]
|
|
207
|
+
: [
|
|
208
|
+
"完成用户目标且不静默扩大业务范围",
|
|
209
|
+
"提供可复核的目标产物和验证证据",
|
|
210
|
+
"记录遗留问题、阻塞和未执行项",
|
|
211
|
+
"最终验收后等待用户批准,禁止自动 Git 提交或推送",
|
|
212
|
+
];
|
|
213
|
+
if (profile === "engineering" || profile === "sdd") {
|
|
214
|
+
common.splice(2, 0, managedText(language, "执行与风险匹配的构建、测试和运行验证", "Run build, test, and runtime verification proportionate to risk"));
|
|
215
|
+
}
|
|
216
|
+
return common;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/domains/managed-work/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function managedLanguage(language) {
|
|
2
|
+
return language === "en" ? "en" : "zh";
|
|
3
|
+
}
|
|
4
|
+
export function managedText(language, zh, en) {
|
|
5
|
+
return managedLanguage(language) === "en" ? en : zh;
|
|
6
|
+
}
|
|
7
|
+
export function managedList(language, values, emptyZh = "无", emptyEn = "none") {
|
|
8
|
+
if (values.length === 0)
|
|
9
|
+
return managedText(language, emptyZh, emptyEn);
|
|
10
|
+
return values.join(managedText(language, "、", ", "));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../src/domains/managed-work/i18n.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,QAAmB;IACjD,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAA8B,EAC9B,EAAU,EACV,EAAU;IAEV,OAAO,eAAe,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAA8B,EAC9B,MAAgB,EAChB,OAAO,GAAG,GAAG,EACb,OAAO,GAAG,MAAM;IAEhB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { existsSync, readFileSync, realpathSync, statSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { managedText } from "./i18n.js";
|
|
5
|
+
export function resolveManagedInput(rawInput, options = {}) {
|
|
6
|
+
const request = rawInput.trim();
|
|
7
|
+
if (!request) {
|
|
8
|
+
throw new Error(managedText(options.language, "托管任务内容不能为空", "Managed task cannot be empty"));
|
|
9
|
+
}
|
|
10
|
+
const configuredRoot = canonicalRoot(options.projectRoot ?? process.cwd());
|
|
11
|
+
const candidate = path.resolve(configuredRoot, request);
|
|
12
|
+
if (!existsSync(candidate)) {
|
|
13
|
+
return {
|
|
14
|
+
request,
|
|
15
|
+
projectRoot: configuredRoot,
|
|
16
|
+
relatedProjectRoots: normalizeRoots(options.relatedProjectRoots),
|
|
17
|
+
profile: options.profile,
|
|
18
|
+
source: "direct_prompt",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const resolved = realpathSync(candidate);
|
|
22
|
+
const promptPath = statSync(resolved).isDirectory()
|
|
23
|
+
? promptFromChangeDirectory(resolved, options.language)
|
|
24
|
+
: resolved;
|
|
25
|
+
rejectSddTasksChecklist(promptPath, options.language);
|
|
26
|
+
const projectRoot = options.projectRoot
|
|
27
|
+
? configuredRoot
|
|
28
|
+
: gitProjectRoot(path.dirname(promptPath)) ?? configuredRoot;
|
|
29
|
+
const relatedProjectRoots = normalizeRoots(options.relatedProjectRoots);
|
|
30
|
+
assertPromptInsideAllowedRoots(promptPath, [projectRoot, ...relatedProjectRoots], options.language);
|
|
31
|
+
const isSdd = isSddPrompt(promptPath);
|
|
32
|
+
return {
|
|
33
|
+
request: promptPath,
|
|
34
|
+
projectRoot,
|
|
35
|
+
relatedProjectRoots,
|
|
36
|
+
profile: options.profile && options.profile !== "auto"
|
|
37
|
+
? options.profile
|
|
38
|
+
: isSdd
|
|
39
|
+
? "sdd"
|
|
40
|
+
: "engineering",
|
|
41
|
+
source: isSdd ? "sdd" : "task_file",
|
|
42
|
+
taskPromptPath: promptPath,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function promptFromChangeDirectory(changeDir, language) {
|
|
46
|
+
const stateFile = path.join(changeDir, ".sdd", "state.yaml");
|
|
47
|
+
if (!existsSync(stateFile)) {
|
|
48
|
+
throw new Error(managedText(language, "目录缺少 .sdd/state.yaml,无法定位 implementation_prompt", "Directory is missing .sdd/state.yaml; cannot locate implementation_prompt"));
|
|
49
|
+
}
|
|
50
|
+
const state = readFileSync(stateFile, "utf-8");
|
|
51
|
+
const match = state.match(/^implementation_prompt:\s*(.+?)\s*$/m);
|
|
52
|
+
const configured = match ? unquote(match[1]) : "";
|
|
53
|
+
if (!configured || configured === "null") {
|
|
54
|
+
throw new Error(managedText(language, ".sdd/state.yaml 尚未记录可执行的 implementation_prompt", ".sdd/state.yaml does not contain an executable implementation_prompt"));
|
|
55
|
+
}
|
|
56
|
+
const promptPath = realpathIfExists(path.resolve(changeDir, configured));
|
|
57
|
+
if (!promptPath || !statSync(promptPath).isFile()) {
|
|
58
|
+
throw new Error(managedText(language, `implementation_prompt 文件不存在:${configured}`, `implementation_prompt file does not exist: ${configured}`));
|
|
59
|
+
}
|
|
60
|
+
return promptPath;
|
|
61
|
+
}
|
|
62
|
+
function rejectSddTasksChecklist(promptPath, language) {
|
|
63
|
+
const normalized = promptPath.replaceAll("\\", "/");
|
|
64
|
+
if (path.basename(promptPath).toLowerCase() === "tasks.md" &&
|
|
65
|
+
normalized.includes("/openspec/changes/")) {
|
|
66
|
+
throw new Error(managedText(language, "tasks.md 是任务清单,不是 Agent 执行 Prompt;请提供 prompt/*.md 或 change 目录", "tasks.md is a checklist, not an Agent execution prompt; provide prompt/*.md or a change directory"));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function assertPromptInsideAllowedRoots(promptPath, roots, language) {
|
|
70
|
+
if (roots.some((root) => isInside(promptPath, root)))
|
|
71
|
+
return;
|
|
72
|
+
throw new Error(managedText(language, "任务 Prompt 不在项目目录或允许的关联仓库内", "Task prompt is outside the project and allowed related repositories"));
|
|
73
|
+
}
|
|
74
|
+
function isInside(file, root) {
|
|
75
|
+
const relative = path.relative(canonicalRoot(root), canonicalRoot(file));
|
|
76
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
77
|
+
}
|
|
78
|
+
function normalizeRoots(roots = []) {
|
|
79
|
+
return [...new Set(roots.map(canonicalRoot))].sort();
|
|
80
|
+
}
|
|
81
|
+
function canonicalRoot(value) {
|
|
82
|
+
const resolved = path.resolve(value);
|
|
83
|
+
return existsSync(resolved) ? realpathSync(resolved) : resolved;
|
|
84
|
+
}
|
|
85
|
+
function gitProjectRoot(directory) {
|
|
86
|
+
try {
|
|
87
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
88
|
+
cwd: directory,
|
|
89
|
+
encoding: "utf-8",
|
|
90
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
91
|
+
}).trim();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function isSddPrompt(promptPath) {
|
|
98
|
+
return promptPath.replaceAll("\\", "/").includes("/openspec/changes/");
|
|
99
|
+
}
|
|
100
|
+
function realpathIfExists(value) {
|
|
101
|
+
return existsSync(value) ? realpathSync(value) : null;
|
|
102
|
+
}
|
|
103
|
+
function unquote(value) {
|
|
104
|
+
const trimmed = value.trim();
|
|
105
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
106
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
107
|
+
return trimmed.slice(1, -1);
|
|
108
|
+
}
|
|
109
|
+
return trimmed;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../../src/domains/managed-work/input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "crypto";
|
|
2
|
+
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { managedRunDir } from "./paths.js";
|
|
5
|
+
export function appendManagedEvent(state, input) {
|
|
6
|
+
const runDir = managedRunDir(state.projectRoot, state.taskId, state.runId);
|
|
7
|
+
const file = path.join(runDir, "progress.jsonl");
|
|
8
|
+
const previous = lastEvent(file);
|
|
9
|
+
const base = {
|
|
10
|
+
sequence: (previous?.sequence ?? 0) + 1,
|
|
11
|
+
eventId: randomUUID(),
|
|
12
|
+
eventType: input.eventType,
|
|
13
|
+
actor: input.actor,
|
|
14
|
+
role: input.role,
|
|
15
|
+
timestamp: new Date().toISOString(),
|
|
16
|
+
status: state.status,
|
|
17
|
+
summary: input.summary,
|
|
18
|
+
evidencePaths: input.evidencePaths ?? [],
|
|
19
|
+
previousEventHash: previous?.eventHash ?? null,
|
|
20
|
+
};
|
|
21
|
+
const event = {
|
|
22
|
+
...base,
|
|
23
|
+
eventHash: createHash("sha256").update(JSON.stringify(base)).digest("hex"),
|
|
24
|
+
};
|
|
25
|
+
appendFileSync(file, `${JSON.stringify(event)}\n`, "utf-8");
|
|
26
|
+
regenerateProgress(state, file);
|
|
27
|
+
return event;
|
|
28
|
+
}
|
|
29
|
+
export function readManagedEvents(state) {
|
|
30
|
+
const file = path.join(managedRunDir(state.projectRoot, state.taskId, state.runId), "progress.jsonl");
|
|
31
|
+
if (!existsSync(file))
|
|
32
|
+
return [];
|
|
33
|
+
return readFileSync(file, "utf-8")
|
|
34
|
+
.split(/\r?\n/)
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.map((line) => JSON.parse(line));
|
|
37
|
+
}
|
|
38
|
+
export function verifyManagedJournal(state) {
|
|
39
|
+
let previous = null;
|
|
40
|
+
let sequence = 0;
|
|
41
|
+
for (const event of readManagedEvents(state)) {
|
|
42
|
+
const { eventHash, ...base } = event;
|
|
43
|
+
const expected = createHash("sha256")
|
|
44
|
+
.update(JSON.stringify(base))
|
|
45
|
+
.digest("hex");
|
|
46
|
+
if (event.sequence !== sequence + 1)
|
|
47
|
+
return false;
|
|
48
|
+
if (event.previousEventHash !== previous)
|
|
49
|
+
return false;
|
|
50
|
+
if (eventHash !== expected)
|
|
51
|
+
return false;
|
|
52
|
+
sequence = event.sequence;
|
|
53
|
+
previous = eventHash;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
function lastEvent(file) {
|
|
58
|
+
if (!existsSync(file))
|
|
59
|
+
return null;
|
|
60
|
+
const lines = readFileSync(file, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
61
|
+
if (lines.length === 0)
|
|
62
|
+
return null;
|
|
63
|
+
return JSON.parse(lines[lines.length - 1]);
|
|
64
|
+
}
|
|
65
|
+
function regenerateProgress(state, file) {
|
|
66
|
+
const events = readFileSync(file, "utf-8")
|
|
67
|
+
.split(/\r?\n/)
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.map((line) => JSON.parse(line));
|
|
70
|
+
const latest = events[events.length - 1];
|
|
71
|
+
if (state.language === "en") {
|
|
72
|
+
const markdown = [
|
|
73
|
+
"# Managed Task Progress",
|
|
74
|
+
"",
|
|
75
|
+
`Task: ${state.taskId}`,
|
|
76
|
+
`Run: ${state.runId}`,
|
|
77
|
+
`Status: ${state.status}`,
|
|
78
|
+
`Step: ${state.currentStep}`,
|
|
79
|
+
`Review round: ${state.reviewRound}`,
|
|
80
|
+
`Executor calls: ${state.executorInvocations}`,
|
|
81
|
+
`Total Agent calls: ${state.totalAgentInvocations}`,
|
|
82
|
+
`Supervisor session: ${shortId(state.supervisorSession.sessionId)}`,
|
|
83
|
+
`Executor session: ${shortId(state.executorSession.sessionId)}`,
|
|
84
|
+
`Latest event: ${latest?.summary ?? "none"}`,
|
|
85
|
+
"",
|
|
86
|
+
"## Timeline",
|
|
87
|
+
"",
|
|
88
|
+
...events
|
|
89
|
+
.slice(-50)
|
|
90
|
+
.map((event) => `- ${event.timestamp} [${event.eventType}] ${event.summary}`),
|
|
91
|
+
"",
|
|
92
|
+
].join("\n");
|
|
93
|
+
writeFileSync(path.join(path.dirname(file), "progress.md"), markdown, "utf-8");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const markdown = [
|
|
97
|
+
"# 托管任务进度",
|
|
98
|
+
"",
|
|
99
|
+
`任务:${state.taskId}`,
|
|
100
|
+
`运行:${state.runId}`,
|
|
101
|
+
`状态:${state.status}`,
|
|
102
|
+
`步骤:${state.currentStep}`,
|
|
103
|
+
`检查轮次:${state.reviewRound}`,
|
|
104
|
+
`执行调用:${state.executorInvocations}`,
|
|
105
|
+
`总 Agent 调用:${state.totalAgentInvocations}`,
|
|
106
|
+
`监督会话:${shortId(state.supervisorSession.sessionId)}`,
|
|
107
|
+
`执行会话:${shortId(state.executorSession.sessionId)}`,
|
|
108
|
+
`最近事件:${latest?.summary ?? "无"}`,
|
|
109
|
+
"",
|
|
110
|
+
"## 时间线",
|
|
111
|
+
"",
|
|
112
|
+
...events
|
|
113
|
+
.slice(-50)
|
|
114
|
+
.map((event) => `- ${event.timestamp} [${event.eventType}] ${event.summary}`),
|
|
115
|
+
"",
|
|
116
|
+
].join("\n");
|
|
117
|
+
writeFileSync(path.join(path.dirname(file), "progress.md"), markdown, "utf-8");
|
|
118
|
+
}
|
|
119
|
+
function shortId(value) {
|
|
120
|
+
return value ? value.slice(0, 8) : "--";
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../../src/domains/managed-work/journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, unlinkSync, writeFileSync, } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { isProcessAlive } from "../../platform/process-liveness.js";
|
|
4
|
+
import { managedText } from "./i18n.js";
|
|
5
|
+
export function acquireManagedLock(file, token, language) {
|
|
6
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
7
|
+
if (existsSync(file)) {
|
|
8
|
+
const owner = readOwner(file);
|
|
9
|
+
if (owner && isProcessAlive(owner.pid)) {
|
|
10
|
+
throw new Error(managedText(language, `任务正在由进程 ${owner.pid} 执行`, `Task is already being executed by process ${owner.pid}`));
|
|
11
|
+
}
|
|
12
|
+
unlinkSync(file);
|
|
13
|
+
}
|
|
14
|
+
const owner = {
|
|
15
|
+
pid: process.pid,
|
|
16
|
+
token,
|
|
17
|
+
createdAt: new Date().toISOString(),
|
|
18
|
+
};
|
|
19
|
+
const fd = openSync(file, "wx");
|
|
20
|
+
writeFileSync(fd, JSON.stringify(owner), "utf-8");
|
|
21
|
+
closeSync(fd);
|
|
22
|
+
return {
|
|
23
|
+
file,
|
|
24
|
+
owner,
|
|
25
|
+
release: () => {
|
|
26
|
+
const current = readOwner(file);
|
|
27
|
+
if (current?.token === token && existsSync(file))
|
|
28
|
+
unlinkSync(file);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function readOwner(file) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/domains/managed-work/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,IAAI,CAAC;AACZ,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAcxC,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,KAAa,EACb,QAAmB;IAEnB,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,WAAW,CACT,QAAQ,EACR,WAAW,KAAK,CAAC,GAAG,KAAK,EACzB,6CAA6C,KAAK,CAAC,GAAG,EAAE,CACzD,CACF,CAAC;QACJ,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAc;QACvB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK;QACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAClD,SAAS,CAAC,EAAE,CAAC,CAAC;IACd,OAAO;QACL,IAAI;QACJ,KAAK;QACL,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,OAAO,EAAE,KAAK,KAAK,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC;gBAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACrE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAc,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { managedHome } from "./paths.js";
|
|
6
|
+
export function notifyManagedTask(notification, env = process.env) {
|
|
7
|
+
const file = path.join(managedHome(env), "managed", "notifications.jsonl");
|
|
8
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
9
|
+
const contentHash = createHash("sha256")
|
|
10
|
+
.update(`${notification.title}\n${notification.message}`)
|
|
11
|
+
.digest("hex")
|
|
12
|
+
.slice(0, 16);
|
|
13
|
+
const key = `${notification.taskId}:${notification.type}:${contentHash}`;
|
|
14
|
+
if (existingKeys(file).has(key))
|
|
15
|
+
return false;
|
|
16
|
+
const event = {
|
|
17
|
+
...notification,
|
|
18
|
+
key,
|
|
19
|
+
createdAt: new Date().toISOString(),
|
|
20
|
+
};
|
|
21
|
+
appendFileSync(file, `${JSON.stringify(event)}\n`, "utf-8");
|
|
22
|
+
if (process.platform === "darwin" &&
|
|
23
|
+
env.SUPERFLOW_DISABLE_OS_NOTIFICATIONS !== "1") {
|
|
24
|
+
sendMacNotification(event.title, event.message);
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
function existingKeys(file) {
|
|
29
|
+
if (!existsSync(file))
|
|
30
|
+
return new Set();
|
|
31
|
+
return new Set(readFileSync(file, "utf-8")
|
|
32
|
+
.split(/\r?\n/)
|
|
33
|
+
.filter(Boolean)
|
|
34
|
+
.flatMap((line) => {
|
|
35
|
+
try {
|
|
36
|
+
return [JSON.parse(line).key];
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
function sendMacNotification(title, message) {
|
|
44
|
+
const script = `display notification ${appleString(message)} with title ${appleString(title)}`;
|
|
45
|
+
spawnSync("osascript", ["-e", script], {
|
|
46
|
+
stdio: "ignore",
|
|
47
|
+
timeout: 5_000,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function appleString(value) {
|
|
51
|
+
return JSON.stringify(value.slice(0, 300));
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/domains/managed-work/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACzE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiBzC,MAAM,UAAU,iBAAiB,CAC/B,YAA4D,EAC5D,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAC3E,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC;SACrC,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;SACxD,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC;IACzE,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9C,MAAM,KAAK,GAAwB;QACjC,GAAG,YAAY;QACf,GAAG;QACH,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,IACE,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC7B,GAAG,CAAC,kCAAkC,KAAK,GAAG,EAC9C,CAAC;QACD,mBAAmB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IACxC,OAAO,IAAI,GAAG,CACZ,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;SACxB,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,OAAO,CAAC;SACf,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,IAAI,CAAC;YACH,OAAO,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,OAAe;IACzD,MAAM,MAAM,GAAG,wBAAwB,WAAW,CAAC,OAAO,CAAC,eAAe,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;IAC/F,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;QACrC,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import os from "os";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export function managedHome(env = process.env) {
|
|
4
|
+
return path.resolve(env.SUPERFLOW_HOME ?? path.join(os.homedir(), ".superflow"));
|
|
5
|
+
}
|
|
6
|
+
export function managedRegistryPath(env = process.env) {
|
|
7
|
+
return path.join(managedHome(env), "managed", "registry.json");
|
|
8
|
+
}
|
|
9
|
+
export function managedServicePath(env = process.env) {
|
|
10
|
+
return path.join(managedHome(env), "managed", "service.json");
|
|
11
|
+
}
|
|
12
|
+
export function managedTaskDir(projectRoot, taskId) {
|
|
13
|
+
return path.join(projectRoot, ".superflow", "tasks", taskId);
|
|
14
|
+
}
|
|
15
|
+
export function managedRunDir(projectRoot, taskId, runId) {
|
|
16
|
+
return path.join(managedTaskDir(projectRoot, taskId), "runs", runId);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/domains/managed-work/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,OAAO,IAAI,CAAC,OAAO,CACjB,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,MAAc;IAChE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,WAAmB,EACnB,MAAc,EACd,KAAa;IAEb,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACvE,CAAC"}
|