@fitlab-ai/agent-infra 0.5.1 → 0.5.2
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 +15 -1
- package/README.zh-CN.md +15 -1
- package/lib/defaults.json +3 -0
- package/lib/init.js +15 -5
- package/lib/render.js +77 -15
- package/lib/sandbox/commands/enter.js +22 -7
- package/lib/sandbox/runtimes/base.dockerfile +10 -0
- package/lib/update.js +19 -5
- package/package.json +2 -1
- package/templates/.agents/{README.md → README.en.md} +13 -3
- package/templates/.agents/README.zh-CN.md +13 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +111 -0
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +111 -0
- package/templates/.agents/rules/label-milestone-setup.github.en.md +50 -0
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +50 -0
- package/templates/.agents/rules/release-commands.github.en.md +30 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +30 -0
- package/templates/.agents/rules/security-alerts.github.en.md +43 -0
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +43 -0
- package/templates/.agents/scripts/validate-artifact.js +0 -2
- package/templates/.agents/skills/cancel-task/{SKILL.md → SKILL.en.md} +7 -6
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +7 -6
- package/templates/.agents/skills/close-codescan/{SKILL.md → SKILL.en.md} +3 -11
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -11
- package/templates/.agents/skills/close-dependabot/{SKILL.md → SKILL.en.md} +5 -13
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +5 -13
- package/templates/.agents/skills/create-issue/{SKILL.md → SKILL.en.md} +2 -5
- package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +2 -5
- package/templates/.agents/skills/create-issue/reference/{label-and-type.md → label-and-type.en.md} +4 -16
- package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +4 -16
- package/templates/.agents/skills/create-pr/{SKILL.md → SKILL.en.md} +3 -4
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -4
- package/templates/.agents/skills/create-pr/reference/{pr-body-template.md → pr-body-template.en.md} +8 -13
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +8 -13
- package/templates/.agents/skills/create-release-note/{SKILL.md → SKILL.en.md} +6 -18
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +6 -18
- package/templates/.agents/skills/import-codescan/{SKILL.md → SKILL.en.md} +1 -3
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -3
- package/templates/.agents/skills/import-dependabot/{SKILL.md → SKILL.en.md} +1 -3
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -3
- package/templates/.agents/skills/import-issue/{SKILL.md → SKILL.en.md} +2 -10
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +2 -10
- package/templates/.agents/skills/init-labels/{SKILL.md → SKILL.en.md} +9 -13
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -13
- package/templates/.agents/skills/init-milestones/{SKILL.md → SKILL.en.md} +5 -6
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/refine-title/{SKILL.md → SKILL.en.md} +7 -17
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +6 -16
- package/templates/.agents/skills/release/{SKILL.md → SKILL.en.md} +2 -1
- package/templates/.agents/skills/release/SKILL.zh-CN.md +2 -1
- package/templates/.agents/skills/restore-task/{SKILL.md → SKILL.en.md} +5 -11
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +5 -11
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +219 -59
- /package/templates/.agents/{QUICKSTART.md → QUICKSTART.en.md} +0 -0
- /package/templates/.agents/rules/{commit-and-pr.md → commit-and-pr.en.md} +0 -0
- /package/templates/.agents/rules/{issue-sync.md → issue-sync.github.en.md} +0 -0
- /package/templates/.agents/rules/{issue-sync.zh-CN.md → issue-sync.github.zh-CN.md} +0 -0
- /package/templates/.agents/rules/{milestone-inference.md → milestone-inference.github.en.md} +0 -0
- /package/templates/.agents/rules/{milestone-inference.zh-CN.md → milestone-inference.github.zh-CN.md} +0 -0
- /package/templates/.agents/rules/{pr-sync.md → pr-sync.github.en.md} +0 -0
- /package/templates/.agents/rules/{pr-sync.zh-CN.md → pr-sync.github.zh-CN.md} +0 -0
- /package/templates/.agents/rules/{task-management.md → task-management.en.md} +0 -0
- /package/templates/.agents/skills/analyze-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/archive-tasks/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/block-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/check-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/commit/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/commit/reference/{commit-message.md → commit-message.en.md} +0 -0
- /package/templates/.agents/skills/commit/reference/{copyright-check.md → copyright-check.en.md} +0 -0
- /package/templates/.agents/skills/commit/reference/{pr-summary-sync.md → pr-summary-sync.en.md} +0 -0
- /package/templates/.agents/skills/commit/reference/{task-status-update.md → task-status-update.en.md} +0 -0
- /package/templates/.agents/skills/complete-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/create-issue/reference/{template-matching.md → template-matching.en.md} +0 -0
- /package/templates/.agents/skills/create-pr/reference/{branch-strategy.md → branch-strategy.en.md} +0 -0
- /package/templates/.agents/skills/create-pr/reference/{comment-publish.md → comment-publish.en.md} +0 -0
- /package/templates/.agents/skills/create-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/implement-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/implement-task/reference/{branch-management.md → branch-management.en.md} +0 -0
- /package/templates/.agents/skills/implement-task/reference/{implementation-rules.md → implementation-rules.en.md} +0 -0
- /package/templates/.agents/skills/implement-task/reference/{output-template.md → output-template.en.md} +0 -0
- /package/templates/.agents/skills/implement-task/reference/{report-template.md → report-template.en.md} +0 -0
- /package/templates/.agents/skills/init-labels/scripts/{init-labels.sh → init-labels.github.sh} +0 -0
- /package/templates/.agents/skills/init-milestones/scripts/{init-milestones.sh → init-milestones.github.sh} +0 -0
- /package/templates/.agents/skills/plan-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/refine-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/refine-task/reference/{fix-workflow.md → fix-workflow.en.md} +0 -0
- /package/templates/.agents/skills/refine-task/reference/{report-template.md → report-template.en.md} +0 -0
- /package/templates/.agents/skills/release/scripts/{manage-milestones.sh → manage-milestones.github.sh} +0 -0
- /package/templates/.agents/skills/review-task/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/review-task/reference/{output-templates.md → output-templates.en.md} +0 -0
- /package/templates/.agents/skills/review-task/reference/{report-template.md → report-template.en.md} +0 -0
- /package/templates/.agents/skills/review-task/reference/{review-criteria.md → review-criteria.en.md} +0 -0
- /package/templates/.agents/skills/test/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/test-integration/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/update-agent-infra/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/skills/upgrade-dependency/{SKILL.md → SKILL.en.md} +0 -0
- /package/templates/.agents/templates/{handoff.md → handoff.en.md} +0 -0
- /package/templates/.agents/templates/{review-report.md → review-report.en.md} +0 -0
- /package/templates/.agents/templates/{task.md → task.en.md} +0 -0
- /package/templates/.agents/workflows/{bug-fix.yaml → bug-fix.en.yaml} +0 -0
- /package/templates/.agents/workflows/{code-review.yaml → code-review.en.yaml} +0 -0
- /package/templates/.agents/workflows/{feature-development.yaml → feature-development.en.yaml} +0 -0
- /package/templates/.agents/workflows/{refactoring.yaml → refactoring.en.yaml} +0 -0
- /package/templates/.agents/workspace/{README.md → README.en.md} +0 -0
- /package/templates/.claude/commands/{analyze-task.md → analyze-task.en.md} +0 -0
- /package/templates/.claude/commands/{archive-tasks.md → archive-tasks.en.md} +0 -0
- /package/templates/.claude/commands/{block-task.md → block-task.en.md} +0 -0
- /package/templates/.claude/commands/{cancel-task.md → cancel-task.en.md} +0 -0
- /package/templates/.claude/commands/{check-task.md → check-task.en.md} +0 -0
- /package/templates/.claude/commands/{close-codescan.md → close-codescan.en.md} +0 -0
- /package/templates/.claude/commands/{close-dependabot.md → close-dependabot.en.md} +0 -0
- /package/templates/.claude/commands/{commit.md → commit.en.md} +0 -0
- /package/templates/.claude/commands/{complete-task.md → complete-task.en.md} +0 -0
- /package/templates/.claude/commands/{create-issue.md → create-issue.en.md} +0 -0
- /package/templates/.claude/commands/{create-pr.md → create-pr.en.md} +0 -0
- /package/templates/.claude/commands/{create-release-note.md → create-release-note.en.md} +0 -0
- /package/templates/.claude/commands/{create-task.md → create-task.en.md} +0 -0
- /package/templates/.claude/commands/{implement-task.md → implement-task.en.md} +0 -0
- /package/templates/.claude/commands/{import-codescan.md → import-codescan.en.md} +0 -0
- /package/templates/.claude/commands/{import-dependabot.md → import-dependabot.en.md} +0 -0
- /package/templates/.claude/commands/{import-issue.md → import-issue.en.md} +0 -0
- /package/templates/.claude/commands/{init-labels.md → init-labels.en.md} +0 -0
- /package/templates/.claude/commands/{init-milestones.md → init-milestones.en.md} +0 -0
- /package/templates/.claude/commands/{plan-task.md → plan-task.en.md} +0 -0
- /package/templates/.claude/commands/{refine-task.md → refine-task.en.md} +0 -0
- /package/templates/.claude/commands/{refine-title.md → refine-title.en.md} +0 -0
- /package/templates/.claude/commands/{release.md → release.en.md} +0 -0
- /package/templates/.claude/commands/{restore-task.md → restore-task.en.md} +0 -0
- /package/templates/.claude/commands/{review-task.md → review-task.en.md} +0 -0
- /package/templates/.claude/commands/{test-integration.md → test-integration.en.md} +0 -0
- /package/templates/.claude/commands/{test.md → test.en.md} +0 -0
- /package/templates/.claude/commands/{update-agent-infra.md → update-agent-infra.en.md} +0 -0
- /package/templates/.claude/commands/{upgrade-dependency.md → upgrade-dependency.en.md} +0 -0
- /package/templates/.gemini/commands/_project_/{analyze-task.toml → analyze-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{archive-tasks.toml → archive-tasks.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{block-task.toml → block-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{cancel-task.toml → cancel-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{check-task.toml → check-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{close-codescan.toml → close-codescan.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{close-dependabot.toml → close-dependabot.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{commit.toml → commit.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{complete-task.toml → complete-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{create-issue.toml → create-issue.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{create-pr.toml → create-pr.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{create-release-note.toml → create-release-note.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{create-task.toml → create-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{implement-task.toml → implement-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{import-codescan.toml → import-codescan.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{import-dependabot.toml → import-dependabot.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{import-issue.toml → import-issue.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{init-labels.toml → init-labels.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{init-milestones.toml → init-milestones.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{plan-task.toml → plan-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{refine-task.toml → refine-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{refine-title.toml → refine-title.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{release.toml → release.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{restore-task.toml → restore-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{review-task.toml → review-task.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{test-integration.toml → test-integration.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{test.toml → test.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{update-agent-infra.toml → update-agent-infra.en.toml} +0 -0
- /package/templates/.gemini/commands/_project_/{upgrade-dependency.toml → upgrade-dependency.en.toml} +0 -0
- /package/templates/.opencode/commands/{analyze-task.md → analyze-task.en.md} +0 -0
- /package/templates/.opencode/commands/{archive-tasks.md → archive-tasks.en.md} +0 -0
- /package/templates/.opencode/commands/{block-task.md → block-task.en.md} +0 -0
- /package/templates/.opencode/commands/{cancel-task.md → cancel-task.en.md} +0 -0
- /package/templates/.opencode/commands/{check-task.md → check-task.en.md} +0 -0
- /package/templates/.opencode/commands/{close-codescan.md → close-codescan.en.md} +0 -0
- /package/templates/.opencode/commands/{close-dependabot.md → close-dependabot.en.md} +0 -0
- /package/templates/.opencode/commands/{commit.md → commit.en.md} +0 -0
- /package/templates/.opencode/commands/{complete-task.md → complete-task.en.md} +0 -0
- /package/templates/.opencode/commands/{create-issue.md → create-issue.en.md} +0 -0
- /package/templates/.opencode/commands/{create-pr.md → create-pr.en.md} +0 -0
- /package/templates/.opencode/commands/{create-release-note.md → create-release-note.en.md} +0 -0
- /package/templates/.opencode/commands/{create-task.md → create-task.en.md} +0 -0
- /package/templates/.opencode/commands/{implement-task.md → implement-task.en.md} +0 -0
- /package/templates/.opencode/commands/{import-codescan.md → import-codescan.en.md} +0 -0
- /package/templates/.opencode/commands/{import-dependabot.md → import-dependabot.en.md} +0 -0
- /package/templates/.opencode/commands/{import-issue.md → import-issue.en.md} +0 -0
- /package/templates/.opencode/commands/{init-labels.md → init-labels.en.md} +0 -0
- /package/templates/.opencode/commands/{init-milestones.md → init-milestones.en.md} +0 -0
- /package/templates/.opencode/commands/{plan-task.md → plan-task.en.md} +0 -0
- /package/templates/.opencode/commands/{refine-task.md → refine-task.en.md} +0 -0
- /package/templates/.opencode/commands/{refine-title.md → refine-title.en.md} +0 -0
- /package/templates/.opencode/commands/{release.md → release.en.md} +0 -0
- /package/templates/.opencode/commands/{restore-task.md → restore-task.en.md} +0 -0
- /package/templates/.opencode/commands/{review-task.md → review-task.en.md} +0 -0
- /package/templates/.opencode/commands/{test-integration.md → test-integration.en.md} +0 -0
- /package/templates/.opencode/commands/{test.md → test.en.md} +0 -0
- /package/templates/.opencode/commands/{update-agent-infra.md → update-agent-infra.en.md} +0 -0
- /package/templates/.opencode/commands/{upgrade-dependency.md → upgrade-dependency.en.md} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: restore-task
|
|
3
|
-
description: "Restore local task files from
|
|
3
|
+
description: "Restore local task files from platform Issue comments"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Restore Task
|
|
7
7
|
|
|
8
|
-
Restore local task workspace files from
|
|
8
|
+
Restore local task workspace files from platform Issue comments that contain sync markers.
|
|
9
9
|
|
|
10
10
|
## Boundary / Critical Rules
|
|
11
11
|
|
|
@@ -21,19 +21,13 @@ Restore local task workspace files from GitHub Issue comments that contain sync
|
|
|
21
21
|
Check:
|
|
22
22
|
- required `{issue-number}`
|
|
23
23
|
- optional `{task-id}`
|
|
24
|
-
- `
|
|
24
|
+
- read `.agents/rules/issue-pr-commands.md` first and use its authentication commands to verify current platform access
|
|
25
25
|
|
|
26
26
|
If the user provided `{task-id}`, validate the `TASK-{yyyyMMdd-HHmmss}` format.
|
|
27
27
|
|
|
28
28
|
### 2. Fetch Issue Comments
|
|
29
29
|
|
|
30
|
-
Read all Issue comments
|
|
31
|
-
|
|
32
|
-
Suggested command:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" --paginate
|
|
36
|
-
```
|
|
30
|
+
Read all Issue comments by following the "Read Issue comments" command in `.agents/rules/issue-pr-commands.md`, preserving the original order and comment IDs.
|
|
37
31
|
|
|
38
32
|
### 3. Determine the task-id and Files to Restore
|
|
39
33
|
|
|
@@ -152,7 +146,7 @@ Stop after completing the checklist. Do not continue the workflow automatically.
|
|
|
152
146
|
## Error Handling
|
|
153
147
|
|
|
154
148
|
- Issue missing or inaccessible
|
|
155
|
-
-
|
|
149
|
+
- Platform CLI unavailable or unauthenticated
|
|
156
150
|
- No sync-marked comments found
|
|
157
151
|
- Unable to determine a unique `task-id`
|
|
158
152
|
- Target directory already exists
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: restore-task
|
|
3
|
-
description: "
|
|
3
|
+
description: "从平台 Issue 评论还原本地任务文件"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 还原任务
|
|
7
7
|
|
|
8
|
-
从带有 sync
|
|
8
|
+
从带有 sync 标记的平台 Issue 评论中恢复本地任务工作区文件。
|
|
9
9
|
|
|
10
10
|
## 行为边界 / 关键规则
|
|
11
11
|
|
|
@@ -21,19 +21,13 @@ description: "从 GitHub Issue 评论还原本地任务文件"
|
|
|
21
21
|
检查:
|
|
22
22
|
- 必填参数 `{issue-number}`
|
|
23
23
|
- 可选参数 `{task-id}`
|
|
24
|
-
-
|
|
24
|
+
- 执行前先读取 `.agents/rules/issue-pr-commands.md`,并按其中的认证命令验证当前平台访问能力
|
|
25
25
|
|
|
26
26
|
如果用户传入了 `{task-id}`,校验其格式为 `TASK-{yyyyMMdd-HHmmss}`。
|
|
27
27
|
|
|
28
28
|
### 2. 获取 Issue 评论
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
建议命令:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" --paginate
|
|
36
|
-
```
|
|
30
|
+
按 `.agents/rules/issue-pr-commands.md` 中的 “Issue 评论读取” 命令读取 Issue 的全部评论,保留原始顺序和评论 ID。
|
|
37
31
|
|
|
38
32
|
### 3. 确定 task-id 与待恢复文件
|
|
39
33
|
|
|
@@ -152,7 +146,7 @@ node .agents/scripts/validate-artifact.js gate restore-task .agents/workspace/ac
|
|
|
152
146
|
## 错误处理
|
|
153
147
|
|
|
154
148
|
- Issue 不存在或无权访问
|
|
155
|
-
-
|
|
149
|
+
- 平台 CLI 未认证
|
|
156
150
|
- 找不到带 sync 标记的评论
|
|
157
151
|
- 无法唯一确定 `task-id`
|
|
158
152
|
- 目标目录已存在
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/**
|
|
3
2
|
* sync-templates.js — Deterministic template sync for managed & ejected files.
|
|
4
3
|
*
|
|
@@ -20,6 +19,9 @@ import path from 'node:path';
|
|
|
20
19
|
import { fileURLToPath } from 'node:url';
|
|
21
20
|
|
|
22
21
|
const DEFAULTS = {
|
|
22
|
+
"platform": {
|
|
23
|
+
"type": "github"
|
|
24
|
+
},
|
|
23
25
|
"sandbox": {
|
|
24
26
|
"runtimes": [
|
|
25
27
|
"node20"
|
|
@@ -74,7 +76,11 @@ const DEFAULTS = {
|
|
|
74
76
|
}
|
|
75
77
|
};
|
|
76
78
|
|
|
77
|
-
const INSTALLER_VERSION = "v0.5.
|
|
79
|
+
const INSTALLER_VERSION = "v0.5.2";
|
|
80
|
+
const PACKAGE_NAME = '@fitlab-ai/agent-infra';
|
|
81
|
+
// Add a new identifier here only after shipping matching .{platform}. template variants.
|
|
82
|
+
const KNOWN_PLATFORMS = new Set(['github']);
|
|
83
|
+
const KNOWN_LANGUAGES = new Set(['en', 'zh-CN']);
|
|
78
84
|
|
|
79
85
|
function norm(p) { return p.replace(/\\/g, '/'); }
|
|
80
86
|
|
|
@@ -132,6 +138,53 @@ function renderPathname(p, project) {
|
|
|
132
138
|
return p.replace(/_project_/g, project);
|
|
133
139
|
}
|
|
134
140
|
|
|
141
|
+
function variantExt(relativePath) {
|
|
142
|
+
return path.extname(relativePath);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function variantBase(relativePath) {
|
|
146
|
+
const ext = variantExt(relativePath);
|
|
147
|
+
return relativePath.slice(0, -ext.length);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function withVariant(relativePath, variant) {
|
|
151
|
+
const ext = variantExt(relativePath);
|
|
152
|
+
const base = variantBase(relativePath);
|
|
153
|
+
return `${base}.${variant}${ext}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function stripVariant(relativePath, variant) {
|
|
157
|
+
return relativePath.replace(new RegExp(`\\.${variant.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\.`), '.');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isPlatformVariant(relativePath, platform) {
|
|
161
|
+
const platforms = new Set([...KNOWN_PLATFORMS, platform]);
|
|
162
|
+
for (const candidate of platforms) {
|
|
163
|
+
if (relativePath.includes(`.${candidate}.`)) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isLangVariant(relativePath) {
|
|
171
|
+
for (const lang of KNOWN_LANGUAGES) {
|
|
172
|
+
if (relativePath.includes(`.${lang}.`)) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function stripLangVariant(relativePath) {
|
|
180
|
+
for (const lang of KNOWN_LANGUAGES) {
|
|
181
|
+
if (relativePath.includes(`.${lang}.`)) {
|
|
182
|
+
return stripVariant(relativePath, lang);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return relativePath;
|
|
186
|
+
}
|
|
187
|
+
|
|
135
188
|
function isTemplateDir(dir) {
|
|
136
189
|
try {
|
|
137
190
|
return fs.statSync(dir).isDirectory();
|
|
@@ -140,37 +193,107 @@ function isTemplateDir(dir) {
|
|
|
140
193
|
}
|
|
141
194
|
}
|
|
142
195
|
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
196
|
+
function verifyPackageDir(dir) {
|
|
197
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
198
|
+
if (!fs.existsSync(pkgPath)) {
|
|
199
|
+
return { templateRoot: null, reason: `package.json not found at ${pkgPath}` };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let pkg;
|
|
203
|
+
try {
|
|
204
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
205
|
+
} catch {
|
|
206
|
+
return { templateRoot: null, reason: `invalid package.json at ${pkgPath}` };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (pkg.name !== PACKAGE_NAME) {
|
|
210
|
+
const packageName = typeof pkg.name === 'string' && pkg.name ? pkg.name : 'an unknown package';
|
|
211
|
+
return { templateRoot: null, reason: `${pkgPath} belongs to ${packageName}` };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const templateRoot = path.join(dir, 'templates');
|
|
215
|
+
if (!isTemplateDir(templateRoot)) {
|
|
216
|
+
return { templateRoot: null, reason: `templates/ not found at ${templateRoot}` };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { templateRoot, reason: null };
|
|
147
220
|
}
|
|
148
221
|
|
|
149
|
-
function
|
|
222
|
+
function resolveUnixTemplateRoot(name) {
|
|
223
|
+
let linkPath;
|
|
150
224
|
try {
|
|
151
|
-
|
|
225
|
+
linkPath = childProcess.execSync(`command -v ${name}`, {
|
|
152
226
|
encoding: 'utf8',
|
|
153
227
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
154
228
|
}).trim();
|
|
155
|
-
const globalTemplateRoot = resolveInstalledTemplateDir(globalRoot);
|
|
156
|
-
if (globalTemplateRoot) return globalTemplateRoot;
|
|
157
229
|
} catch {
|
|
158
|
-
|
|
230
|
+
return { templateRoot: null, reason: 'not found in PATH' };
|
|
159
231
|
}
|
|
160
232
|
|
|
233
|
+
if (!linkPath) {
|
|
234
|
+
return { templateRoot: null, reason: 'not found in PATH' };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let realPath;
|
|
161
238
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
239
|
+
realPath = fs.realpathSync(linkPath);
|
|
240
|
+
} catch {
|
|
241
|
+
return { templateRoot: null, reason: `cannot resolve symlink target for ${linkPath}` };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let dir = path.dirname(realPath);
|
|
245
|
+
while (true) {
|
|
246
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
247
|
+
if (fs.existsSync(pkgPath)) {
|
|
248
|
+
return verifyPackageDir(dir);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const parentDir = path.dirname(dir);
|
|
252
|
+
if (parentDir === dir) {
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
dir = parentDir;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return { templateRoot: null, reason: `no package.json found above ${realPath}` };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function resolveWindowsTemplateRoot(name) {
|
|
262
|
+
let output;
|
|
263
|
+
try {
|
|
264
|
+
output = childProcess.execSync(`where ${name}`, {
|
|
164
265
|
encoding: 'utf8',
|
|
165
266
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
166
267
|
}).trim();
|
|
167
|
-
const localTemplateRoot = resolveInstalledTemplateDir(localRoot);
|
|
168
|
-
if (localTemplateRoot) return localTemplateRoot;
|
|
169
268
|
} catch {
|
|
170
|
-
|
|
269
|
+
return { templateRoot: null, reason: 'not found in PATH' };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const wrapperPaths = output.split(/\r?\n/).map(line => line.trim()).filter(Boolean);
|
|
273
|
+
if (wrapperPaths.length === 0) {
|
|
274
|
+
return { templateRoot: null, reason: 'not found in PATH' };
|
|
171
275
|
}
|
|
172
276
|
|
|
173
|
-
|
|
277
|
+
const wrapperPath = wrapperPaths.find(line => /\.cmd$/i.test(line)) || wrapperPaths[0];
|
|
278
|
+
const packageDir = path.join(path.dirname(wrapperPath), 'node_modules', '@fitlab-ai', 'agent-infra');
|
|
279
|
+
return verifyPackageDir(packageDir);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function resolveTemplateRoot() {
|
|
283
|
+
const resolver = process.platform === 'win32'
|
|
284
|
+
? resolveWindowsTemplateRoot
|
|
285
|
+
: resolveUnixTemplateRoot;
|
|
286
|
+
const errors = [];
|
|
287
|
+
|
|
288
|
+
for (const name of ['ai', 'agent-infra']) {
|
|
289
|
+
const result = resolver(name);
|
|
290
|
+
if (result.templateRoot) {
|
|
291
|
+
return result.templateRoot;
|
|
292
|
+
}
|
|
293
|
+
errors.push({ name, reason: result.reason });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return { templateRoot: null, errors };
|
|
174
297
|
}
|
|
175
298
|
|
|
176
299
|
function isBinary(fp) {
|
|
@@ -194,30 +317,60 @@ function gitUrl(dir) {
|
|
|
194
317
|
function langSelect(rels, lang, allSet, project) {
|
|
195
318
|
const sel = new Map();
|
|
196
319
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const target = norm(renderPathname(r.replace(/\.zh-CN\./, '.'), project));
|
|
320
|
+
for (const r of rels) {
|
|
321
|
+
if (r.includes(`.${lang}.`)) {
|
|
322
|
+
const target = norm(renderPathname(stripVariant(r, lang), project));
|
|
201
323
|
sel.set(target, r);
|
|
202
|
-
}
|
|
203
|
-
for (const r of rels) {
|
|
204
|
-
if (r.includes('.zh-CN.')) continue;
|
|
324
|
+
} else if (!isLangVariant(r)) {
|
|
205
325
|
const target = norm(renderPathname(r, project));
|
|
206
|
-
if (sel.has(target))
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
sel.set(target, r);
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
for (const r of rels) {
|
|
213
|
-
if (r.includes('.zh-CN.')) continue;
|
|
214
|
-
sel.set(norm(renderPathname(r, project)), r);
|
|
326
|
+
if (!sel.has(target)) {
|
|
327
|
+
sel.set(target, r);
|
|
328
|
+
}
|
|
215
329
|
}
|
|
216
330
|
}
|
|
217
331
|
|
|
218
332
|
return sel;
|
|
219
333
|
}
|
|
220
334
|
|
|
335
|
+
function platformSelect(entries, platform, project) {
|
|
336
|
+
const sel = new Map();
|
|
337
|
+
|
|
338
|
+
for (const [target, src] of entries) {
|
|
339
|
+
if (!target.includes(`.${platform}.`)) continue;
|
|
340
|
+
sel.set(norm(renderPathname(stripVariant(target, platform), project)), src);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
for (const [target, src] of entries) {
|
|
344
|
+
const normalizedTarget = norm(renderPathname(target, project));
|
|
345
|
+
if (sel.has(normalizedTarget)) continue;
|
|
346
|
+
if (isPlatformVariant(target, platform)) continue;
|
|
347
|
+
sel.set(normalizedTarget, src);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return sel;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function entryVariantRels(entry, allSet, platform) {
|
|
354
|
+
const rels = [];
|
|
355
|
+
const normalized = norm(entry);
|
|
356
|
+
const candidates = [
|
|
357
|
+
normalized,
|
|
358
|
+
withVariant(normalized, 'en'),
|
|
359
|
+
withVariant(normalized, 'zh-CN'),
|
|
360
|
+
withVariant(normalized, platform),
|
|
361
|
+
withVariant(withVariant(normalized, platform), 'en'),
|
|
362
|
+
withVariant(withVariant(normalized, platform), 'zh-CN')
|
|
363
|
+
];
|
|
364
|
+
|
|
365
|
+
for (const candidate of candidates) {
|
|
366
|
+
if (allSet.has(candidate) && !rels.includes(candidate)) {
|
|
367
|
+
rels.push(candidate);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return rels;
|
|
372
|
+
}
|
|
373
|
+
|
|
221
374
|
function syncTemplates(projectRoot, templateRootOverride) {
|
|
222
375
|
const configDir = path.join(projectRoot, '.agents');
|
|
223
376
|
const cfgPath = path.join(configDir, '.airc.json');
|
|
@@ -228,14 +381,35 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
228
381
|
|
|
229
382
|
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
|
|
230
383
|
const configPathRel = norm(path.relative(projectRoot, cfgPath));
|
|
231
|
-
|
|
384
|
+
let templateRoot = templateRootOverride;
|
|
232
385
|
if (!templateRoot) {
|
|
233
|
-
|
|
386
|
+
const resolvedTemplateRoot = resolveTemplateRoot();
|
|
387
|
+
if (typeof resolvedTemplateRoot === 'string') {
|
|
388
|
+
templateRoot = resolvedTemplateRoot;
|
|
389
|
+
} else {
|
|
390
|
+
const details = resolvedTemplateRoot.errors
|
|
391
|
+
.map(({ name, reason }) => ` - ${name}: ${reason}`)
|
|
392
|
+
.join('\n');
|
|
393
|
+
return {
|
|
394
|
+
error: [
|
|
395
|
+
'Template source not found.',
|
|
396
|
+
'',
|
|
397
|
+
'Attempted binary lookups:',
|
|
398
|
+
details,
|
|
399
|
+
'',
|
|
400
|
+
'Please ensure agent-infra is installed and available on PATH.',
|
|
401
|
+
'If already installed, upgrade to the latest version or reinstall:',
|
|
402
|
+
' npm install -g @fitlab-ai/agent-infra',
|
|
403
|
+
' brew upgrade fitlab-ai/agent-infra/agent-infra || brew install fitlab-ai/agent-infra/agent-infra'
|
|
404
|
+
].join('\n')
|
|
405
|
+
};
|
|
406
|
+
}
|
|
234
407
|
}
|
|
235
408
|
const version = INSTALLER_VERSION;
|
|
236
409
|
const hadTemplateSource = Object.prototype.hasOwnProperty.call(cfg, 'templateSource');
|
|
237
410
|
|
|
238
411
|
const { project, org, language: lang = 'en' } = cfg;
|
|
412
|
+
const platformType = cfg.platform?.type || DEFAULTS.platform.type;
|
|
239
413
|
const vars = { project, org };
|
|
240
414
|
|
|
241
415
|
const managed = [...(cfg.files.managed || [])];
|
|
@@ -274,15 +448,11 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
274
448
|
entryRels = walkDir(dir).map(f => norm(path.relative(templateRoot, f)));
|
|
275
449
|
} else {
|
|
276
450
|
entryRels = [];
|
|
277
|
-
|
|
278
|
-
if (allSet.has(n)) entryRels.push(n);
|
|
279
|
-
const ext = path.extname(entry), base = entry.slice(0, -ext.length);
|
|
280
|
-
const zh = norm(base + '.zh-CN' + ext);
|
|
281
|
-
if (allSet.has(zh)) entryRels.push(zh);
|
|
451
|
+
entryRels = entryVariantRels(entry, allSet, platformType);
|
|
282
452
|
if (!entryRels.length) continue;
|
|
283
453
|
}
|
|
284
454
|
|
|
285
|
-
const selected = langSelect(entryRels, lang, allSet, project);
|
|
455
|
+
const selected = platformSelect(langSelect(entryRels, lang, allSet, project), platformType, project);
|
|
286
456
|
|
|
287
457
|
for (const [tgt, src] of selected) {
|
|
288
458
|
if (expectedTargets) expectedTargets.add(tgt);
|
|
@@ -345,13 +515,10 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
345
515
|
continue;
|
|
346
516
|
}
|
|
347
517
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (allSet.has(zh)) src = zh;
|
|
353
|
-
}
|
|
354
|
-
if (!allSet.has(src)) continue;
|
|
518
|
+
const selected = platformSelect(langSelect(entryVariantRels(entry, allSet, platformType), lang, allSet, project), platformType, project);
|
|
519
|
+
const target = norm(renderPathname(entry, project));
|
|
520
|
+
const src = selected.get(target);
|
|
521
|
+
if (!src) continue;
|
|
355
522
|
|
|
356
523
|
const content = renderContent(fs.readFileSync(path.join(templateRoot, src), 'utf8'), vars);
|
|
357
524
|
const dir = path.dirname(dstFull);
|
|
@@ -364,22 +531,15 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
364
531
|
for (const entry of merged) {
|
|
365
532
|
if (entry.includes('*')) {
|
|
366
533
|
const hits = allRels.filter(r => {
|
|
367
|
-
const t = norm(renderPathname(
|
|
368
|
-
r.includes('.zh-CN.') ? r.replace(/\.zh-CN\./, '.') : r, project
|
|
369
|
-
));
|
|
534
|
+
const t = norm(renderPathname(stripLangVariant(r), project));
|
|
370
535
|
return globMatch(entry, t);
|
|
371
536
|
});
|
|
372
|
-
for (const [t, s] of langSelect(hits, lang, allSet, project)) {
|
|
537
|
+
for (const [t, s] of platformSelect(langSelect(hits, lang, allSet, project), platformType, project)) {
|
|
373
538
|
if (!mergedMap.has(t)) mergedMap.set(t, s);
|
|
374
539
|
}
|
|
375
540
|
} else {
|
|
376
|
-
const rels =
|
|
377
|
-
const
|
|
378
|
-
if (allSet.has(n)) rels.push(n);
|
|
379
|
-
const ext = path.extname(entry), base = entry.slice(0, -ext.length);
|
|
380
|
-
const zh = norm(base + '.zh-CN' + ext);
|
|
381
|
-
if (allSet.has(zh)) rels.push(zh);
|
|
382
|
-
const selected = langSelect(rels, lang, allSet, project);
|
|
541
|
+
const rels = entryVariantRels(entry, allSet, platformType);
|
|
542
|
+
const selected = platformSelect(langSelect(rels, lang, allSet, project), platformType, project);
|
|
383
543
|
for (const [t, s] of selected) {
|
|
384
544
|
if (!mergedMap.has(t)) mergedMap.set(t, s);
|
|
385
545
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/rules/{milestone-inference.md → milestone-inference.github.en.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/skills/commit/reference/{commit-message.md → commit-message.en.md}
RENAMED
|
File without changes
|
/package/templates/.agents/skills/commit/reference/{copyright-check.md → copyright-check.en.md}
RENAMED
|
File without changes
|
/package/templates/.agents/skills/commit/reference/{pr-summary-sync.md → pr-summary-sync.en.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/skills/create-pr/reference/{branch-strategy.md → branch-strategy.en.md}
RENAMED
|
File without changes
|
/package/templates/.agents/skills/create-pr/reference/{comment-publish.md → comment-publish.en.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/skills/init-labels/scripts/{init-labels.sh → init-labels.github.sh}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/skills/refine-task/reference/{fix-workflow.md → fix-workflow.en.md}
RENAMED
|
File without changes
|
/package/templates/.agents/skills/refine-task/reference/{report-template.md → report-template.en.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/skills/review-task/reference/{report-template.md → report-template.en.md}
RENAMED
|
File without changes
|
/package/templates/.agents/skills/review-task/reference/{review-criteria.md → review-criteria.en.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/.agents/workflows/{feature-development.yaml → feature-development.en.yaml}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|