Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
4e59e4d
fix(release): handle published draft flag
stephamie7 Aug 12, 2026
edcef18
fix(release): verify Gitee release after sync
stephamie7 Aug 12, 2026
5e878e4
fix(release): report Gitee API request failures
stephamie7 Aug 12, 2026
7fadadb
fix(release): handle null Gitee lookup
stephamie7 Aug 12, 2026
d556068
Merge remote-tracking branch 'origin/dev' into fix-gitee-release-tag-…
stephamie7 Aug 13, 2026
62ca118
refactor(delegation): migrate legacy flows to delegate_task
Aug 17, 2026
8339f3d
chore: sync main into dev after main-11c2de91fb8a
github-actions[bot] Aug 17, 2026
9d3810a
Merge pull request #719 from AgentFlocks/chore/sync-main-into-dev-mai…
duguwanglong Aug 17, 2026
32c3661
refactor(session): centralize prompt context assembly
Aug 17, 2026
c40cc9a
chore(agents): make todo prompt guidance unconditional
Aug 17, 2026
2351407
fix(delegation): preserve migration compatibility
Aug 17, 2026
2cf940f
refactor(prompt): remove obsolete TUI copies
Aug 17, 2026
ad65f36
fix(session): preserve legacy prompt assembly API
Aug 18, 2026
cb631eb
fix(permission): enforce delegation policy
Aug 18, 2026
78843aa
fix(webui): keep streaming indicator during delegation
Aug 18, 2026
fc18693
Merge pull request #716 from AgentFlocks/refactor/delegate-task-migra…
duguwanglong Aug 18, 2026
2cc197d
fix(session): preserve prompt context compatibility
Aug 18, 2026
4176bcd
Merge pull request #720 from AgentFlocks/refactor/prompt-context-asse…
duguwanglong Aug 19, 2026
5600c59
perf(workflow): remove synchronous step storage waits
Aug 21, 2026
c01cb25
fix(workflow): finalize atomic step persistence
Aug 21, 2026
76f3099
fix(workflow): preserve steps without callback waits
Aug 21, 2026
0908fd3
fix(workflow): persist queued trigger executions
Aug 21, 2026
afc6649
refactor(workflow): simplify step persistence plumbing
Aug 21, 2026
3f3dae6
perf(kafka): skip unneeded workflow tool context
Aug 25, 2026
431968c
fix(workflow): avoid inherited connection close after fork
Aug 25, 2026
bd88b19
chore(workflow): remove unused execution imports
Aug 26, 2026
43cf614
fix(webui): show extra memory root files
Aug 28, 2026
7a97adf
fix(workspace): enforce memory edit permissions
Aug 28, 2026
e9d4d4d
Merge pull request #724 from AgentFlocks/codex/memory-view-all-files
stephamie7 Aug 28, 2026
f46f79f
Fix process duration elapsed display
Aug 28, 2026
fcd402a
Merge pull request #725 from AgentFlocks/codex/process-duration-actual
stephamie7 Aug 28, 2026
b784486
Keep process duration running during output
Aug 28, 2026
f1041e8
Handle truncated streamed tool arguments
Aug 28, 2026
5d4cc3e
Fix question tool deny handling for agents
Aug 28, 2026
33803ac
Merge pull request #726 from AgentFlocks/codex/process-duration-actual
stephamie7 Aug 28, 2026
0415eff
Retry truncated streamed tool arguments safely
Aug 28, 2026
206e7fc
fix workspace listing with symlink root
Aug 28, 2026
719bf4f
Merge pull request #729 from AgentFlocks/codex/fix-workspace-symlink-…
stephamie7 Aug 31, 2026
bb73c80
Merge pull request #727 from AgentFlocks/codex/question-deny-always-load
stephamie7 Aug 31, 2026
a6be434
Fix stream truncation fallback regressions
Aug 31, 2026
e1669dc
Avoid tool execution after argument stream truncation
Aug 31, 2026
b867c75
Merge pull request #728 from AgentFlocks/codex/stream-tool-args-trunc…
stephamie7 Sep 1, 2026
303978b
feat(webui): link home stat cards
Sep 1, 2026
cd390ca
Merge pull request #722 from AgentFlocks/fix/workflow-step-storage-wait
stephamie7 Sep 1, 2026
161179e
Merge pull request #730 from AgentFlocks/codex/home-stats-card-links
stephamie7 Sep 1, 2026
46172ff
Refine onboarding two-step setup
Sep 6, 2026
1e97a0d
Refine ThreatBook intelligence onboarding page
Sep 6, 2026
5759ce1
Soften onboarding skip copy
Sep 6, 2026
aff8166
Clarify onboarding skip destinations
Sep 6, 2026
308b512
Add ThreatBook free key link to model provider setup
Sep 6, 2026
6ba5573
Add ThreatBook MCP free key link
Sep 6, 2026
1c6c896
Complete regional ThreatBook MCP setup
Sep 6, 2026
f23ae17
Reveal saved MCP keys on demand
Sep 6, 2026
8403470
Fully mask saved MCP keys
Sep 6, 2026
322cb73
Add Flocks LLM usage portal link
Sep 6, 2026
ba50754
Shorten Flocks LLM usage label
Sep 6, 2026
cd949fb
Reveal saved onboarding keys on demand
Sep 6, 2026
bd838fa
Complete regional ThreatBook tool guidance
Sep 6, 2026
0e4fcfc
Harden credential configuration flows
Sep 7, 2026
2ddf55c
Allow all users to access onboarding
Sep 7, 2026
5204d04
feat(hub): prioritize installed plugins
Sep 7, 2026
11fac47
Merge pull request #736 from AgentFlocks/codex/hub-installed-updates
stephamie7 Sep 7, 2026
3fb973e
fix(workspace): order outputs directories descending
Sep 7, 2026
fed43a1
Add free key link to ThreatBook model editor
Sep 7, 2026
41acdf7
fix(soc): make dashboard metrics and tasks authoritative
Sep 7, 2026
f0bb01e
fix(soc): reject misleading dashboard zero metrics
Sep 7, 2026
f235fcd
fix(soc): harden dashboard metric quality contracts
Sep 7, 2026
ffdb07f
Merge pull request #735 from AgentFlocks/codex/onboarding-two-step
stephamie7 Sep 8, 2026
d40cb95
Merge pull request #737 from AgentFlocks/codex/workspace-outputs-dire…
stephamie7 Sep 8, 2026
fcaf9a6
Merge pull request #705 from AgentFlocks/fix-gitee-release-tag-gate
stephamie7 Sep 8, 2026
4321667
Merge pull request #738 from AgentFlocks/codex/soc-dashboard-data-int…
stephamie7 Sep 8, 2026
2798c55
fix workspace uploads with symlink root
Sep 9, 2026
44babe3
Merge pull request #739 from AgentFlocks/codex/fix-workspace-upload-s…
stephamie7 Sep 9, 2026
75f5b2d
feat(notifications): add scheduled token policy reminders
duguwanglong Sep 9, 2026
6e306af
Add per-session runtime status endpoint
Sep 9, 2026
93adfa2
feat(notifications): display token policy announcement in centered modal
duguwanglong Sep 9, 2026
28aaf95
fix(notifications): retire token trial notice and render release note…
duguwanglong Sep 9, 2026
0a3ebeb
Fix shell status and persist command results
Sep 9, 2026
e54f429
Merge pull request #741 from AgentFlocks/codex/session-status-by-id
stephamie7 Sep 9, 2026
1ad1de1
fix(notifications): revise October model usage allowance announcement
duguwanglong Sep 9, 2026
20639d4
Merge pull request #742 from AgentFlocks/feat/token-policy-notice
stephamie7 Sep 9, 2026
8668562
chore/update-version-2026.9.9
stephamie7 Sep 9, 2026
f34b7a1
Merge pull request #743 from AgentFlocks/chore/update-version-2026.9.9
stephamie7 Sep 9, 2026
072ee3a
fix(notifications): simplify token policy announcement copy
duguwanglong Sep 9, 2026
454522c
Merge pull request #744 from AgentFlocks/feat/simplify-token-policy-copy
stephamie7 Sep 9, 2026
023e5a6
fix(webui): name update modal mock for hooks lint
stephamie7 Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
833 changes: 775 additions & 58 deletions .flocks/flockshub/plugins/webuis/soc_ui/soc_dashboard/api/handlers.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ routes:
handler: handlers.get_activity
timeoutMs: 5000
description: Incremental alert denoise and triage activity
- method: GET
path: /ai-tasks
handler: handlers.get_ai_tasks
timeoutMs: 5000
description: Authoritative SOC workflow execution task snapshot
- method: GET
path: /task-center
handler: handlers.get_task_center
Expand Down
511 changes: 395 additions & 116 deletions .flocks/flockshub/plugins/webuis/soc_ui/soc_dashboard/src/Page.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
type SeverityItem = {
label?: string;
value?: number;
value?: number | null;
};

export function severityKey(value: unknown) {
Expand All @@ -12,16 +12,19 @@ export function severityKey(value: unknown) {
return '';
}

export function severityRows(stats: { severityLevels?: SeverityItem[] }) {
export function severityRows(
stats: { severityLevels?: SeverityItem[] },
metricsAvailable = true,
) {
const counts = { critical: 0, high: 0, medium: 0, low: 0 };
for (const item of stats.severityLevels || []) {
const key = severityKey(item.label);
if (key) counts[key] += Number(item.value || 0);
}
return [
{ key: 'critical', label: '严重', value: counts.critical, tone: 'critical' },
{ key: 'high', label: '高危', value: counts.high, tone: 'high' },
{ key: 'medium', label: '中危', value: counts.medium, tone: 'medium' },
{ key: 'low', label: '低危', value: counts.low, tone: 'low' },
{ key: 'critical', label: '严重', value: metricsAvailable ? counts.critical : null, tone: 'critical' },
{ key: 'high', label: '高危', value: metricsAvailable ? counts.high : null, tone: 'high' },
{ key: 'medium', label: '中危', value: metricsAvailable ? counts.medium : null, tone: 'medium' },
{ key: 'low', label: '低危', value: metricsAvailable ? counts.low : null, tone: 'low' },
];
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@

### 3. 单台巡检(`inspect_host`)

- 工具/模型:Python + `ssh_host_cmd` 预检 + `task`(`subagent_type=host-forensics-fast`)
- 工具/模型:Python + `ssh_host_cmd` 预检 + `delegate_task`(`subagent_type=host-forensics-fast`)
- 输入:`hosts`、`host_idx`、`ssh_user`、`per_host_dir`、`batch_report_path`、`triage_results`
- 处理逻辑:
- 取当前 `hosts[host_idx]`,计算 `ssh_target`,并归一化出 `ssh_host` / `ssh_user`。
- 先用 `ssh_host_cmd("echo FLOCKS_SSH_OK")` 做轻量 SSH 预检。
- 若预检失败:按错误文本归类(如 `auth_failed`、`connect_timeout`、`connection_refused` 等),直接写入索引与单机报告。
- 若预检通过:构造 prompt,明确要求子 Agent 调用 SSH 工具时分别传 `host` 和 `username`。
- 调用 `tool.run_safe('task', ...)` 执行巡检;若仅因超时失败,则自动重试 1 次。
- 调用 `tool.run_safe('delegate_task', ...)` 执行巡检;若仅因超时失败,则自动重试 1 次。
- 将本轮完整输出立即写入 `host_triage/NNNN_slug.md`。
- 从子 Agent 输出中提取 `Verdict`,未识别时回退为 `UNKNOWN`。
- 向 `triage_results` 仅追加轻量字段:`{host, ssh_user, ssh_target, ssh_host, success, verdict, failure_category, inspect_attempts, error, per_host_md}`。
Expand Down
66 changes: 53 additions & 13 deletions .github/workflows/sync-gitee.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
> "${release_metadata}"

resolved_tag="$(jq -er '.tag_name' "${release_metadata}")"
is_draft="$(jq -er '.draft' "${release_metadata}")"
is_draft="$(jq -r '.draft' "${release_metadata}")"
published_at="$(jq -r '.published_at // empty' "${release_metadata}")"

if [[ "${resolved_tag}" != "${TAG_NAME}" ]]; then
Expand Down Expand Up @@ -218,14 +218,18 @@ jobs:
encoded_tag="$(jq -rn --arg value "${TAG_NAME}" '$value | @uri')"
release_lookup="${RUNNER_TEMP}/gitee-release-lookup.json"
release_response="${RUNNER_TEMP}/gitee-release-response.json"
lookup_status="$(
if ! lookup_status="$(
curl --silent --show-error --retry 3 \
--output "${release_lookup}" \
--write-out '%{http_code}' \
--get \
--data-urlencode "access_token=${GITEE_TOKEN}" \
"${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases/tags/${encoded_tag}"
)"
)"; then
echo "::error title=Gitee Release lookup request failed::Could not query ${TAG_NAME} after retries."
exit 1
fi
echo "Gitee Release lookup returned HTTP ${lookup_status}."

common_fields=(
--data-urlencode "access_token=${GITEE_TOKEN}"
Expand All @@ -235,37 +239,73 @@ jobs:
--data-urlencode "prerelease=${prerelease}"
)

release_missing="false"
if [[ "${lookup_status}" == "200" ]]; then
release_id="$(jq -er '.id' "${release_lookup}")"
sync_method="PATCH"
sync_url="${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases/${release_id}"
echo "Gitee Release ${TAG_NAME} already exists; updating its metadata only."
release_id="$(jq -r '.id // empty' "${release_lookup}")"
if [[ -n "${release_id}" ]]; then
sync_method="PATCH"
sync_url="${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases/${release_id}"
echo "Gitee Release ${TAG_NAME} already exists; updating its metadata only."
elif jq -e 'type == "null"' "${release_lookup}" > /dev/null; then
release_missing="true"
echo "Gitee returned HTTP 200 with null for missing Release ${TAG_NAME}."
else
echo "::error title=Unexpected Gitee Release lookup response::HTTP 200 response does not contain a Release ID."
exit 1
fi
elif [[ "${lookup_status}" == "404" ]]; then
sync_method="POST"
sync_url="${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases"
common_fields+=(--data-urlencode "target_commitish=${VERIFIED_SHA}")
echo "Creating Gitee Release ${TAG_NAME} at verified commit ${VERIFIED_SHA}."
release_missing="true"
else
message="$(jq -r '.message // "unknown Gitee API error"' "${release_lookup}" 2>/dev/null || true)"
echo "::error title=Gitee Release lookup failed::HTTP ${lookup_status}: ${message}"
exit 1
fi

sync_status="$(
if [[ "${release_missing}" == "true" ]]; then
sync_method="POST"
sync_url="${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases"
common_fields+=(--data-urlencode "target_commitish=${VERIFIED_SHA}")
echo "Creating Gitee Release ${TAG_NAME} at verified commit ${VERIFIED_SHA}."
fi

if ! sync_status="$(
curl --silent --show-error --retry 3 \
--output "${release_response}" \
--write-out '%{http_code}' \
--request "${sync_method}" \
"${common_fields[@]}" \
"${sync_url}"
)"
)"; then
echo "::error title=Gitee Release sync request failed::Release ${sync_method} failed after retries."
exit 1
fi
echo "Gitee Release ${sync_method} returned HTTP ${sync_status}."

if [[ ! "${sync_status}" =~ ^2[0-9][0-9]$ ]]; then
message="$(jq -r '.message // "unknown Gitee API error"' "${release_response}" 2>/dev/null || true)"
echo "::error title=Gitee Release sync failed::HTTP ${sync_status}: ${message}"
exit 1
fi

if ! verification_status="$(
curl --silent --show-error --retry 3 \
--output "${release_response}" \
--write-out '%{http_code}' \
--get \
--data-urlencode "access_token=${GITEE_TOKEN}" \
"${GITEE_API_BASE_URL}/repos/${GITEE_OWNER}/${GITEE_REPO}/releases/tags/${encoded_tag}"
)"; then
echo "::error title=Gitee Release verification request failed::Could not verify ${TAG_NAME} after retries."
exit 1
fi
echo "Gitee Release verification returned HTTP ${verification_status}."

if [[ "${verification_status}" != "200" ]]; then
message="$(jq -r '.message // "unknown Gitee API error"' "${release_response}" 2>/dev/null || true)"
echo "::error title=Gitee Release verification failed::HTTP ${verification_status}: ${message}"
exit 1
fi

synced_tag="$(jq -er '.tag_name' "${release_response}")"
synced_release_id="$(jq -er '.id' "${release_response}")"
if [[ "${synced_tag}" != "${TAG_NAME}" ]]; then
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,18 @@ Non-browser clients (TUI, SDKs, scripts):
curl -H "Authorization: Bearer <token>" https://flocks.example.com/api/health
```

Query the live runtime status of a specific session:

```bash
curl -H "Authorization: Bearer <token>" \
https://flocks.example.com/api/session/<sessionID>/status
```

`status.type` is one of `idle`, `queued`, `busy`, `retry`, `compacting`, or
`dreaming`. Automation clients can use `isProcessing` to determine whether
accepted work is still running or waiting. `idle` only means that the session
is currently inactive; it does not indicate whether the previous run succeeded.

Reverse-proxy deployments:

- Always set `X-Forwarded-For` on the proxy. Without it, any direct
Expand Down
11 changes: 11 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ flocks start --server-host 0.0.0.0 --webui-host 0.0.0.0
curl -H "Authorization: Bearer <token>" https://flocks.example.com/api/health
```

查询指定会话的实时运行状态:

```bash
curl -H "Authorization: Bearer <token>" \
https://flocks.example.com/api/session/<sessionID>/status
```

`status.type` 可能为 `idle`、`queued`、`busy`、`retry`、`compacting` 或
`dreaming`。自动化调用可通过 `isProcessing` 判断是否仍有已接收的工作正在执行或等待执行;
`idle` 只表示当前空闲,不代表上一次执行成功。

反向代理部署:

- 反代必须主动注入 `X-Forwarded-For`。若缺失该头,且前方存在代理,中间件会拒绝信任回环地址,避免任何直连本机的请求被自动提升为 `admin`。
Expand Down
44 changes: 4 additions & 40 deletions flocks/agent/agents/hephaestus/prompt_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def inject(
available_agents=available_agents,
available_tools=tools,
available_skills=skills,
use_task_system=False,
)


Expand All @@ -39,6 +38,8 @@ def build_hephaestus_prompt(
available_skills: List["AvailableSkill"],
use_task_system: bool = False,
) -> str:
del use_task_system

from flocks.agent.prompt_utils import (
build_agent_selection_table,
build_key_triggers_section,
Expand All @@ -62,7 +63,7 @@ def build_hephaestus_prompt(
oracle_section = build_oracle_section(available_agents)
hard_blocks = build_hard_blocks_section()
anti_patterns = build_anti_patterns_section()
todo_discipline = _todo_discipline_section(use_task_system)
todo_discipline = _todo_discipline_section()

template = """You are Hephaestus, an autonomous deep worker for software engineering.

Expand Down Expand Up @@ -245,44 +246,7 @@ def build_hephaestus_prompt(
return prompt


def _todo_discipline_section(use_task_system: bool) -> str:
if use_task_system:
return """## Task Discipline (NON-NEGOTIABLE)

**Track ALL multi-step work with tasks. This is your execution backbone.**

### When to Create Tasks (MANDATORY)

| Trigger | Action |
|---------|--------|
| 2+ step task | `TaskCreate` FIRST, atomic breakdown |
| Uncertain scope | `TaskCreate` to clarify thinking |
| Complex single task | Break down into trackable steps |

### Workflow (STRICT)

1. **On task start**: `TaskCreate` with atomic steps-no announcements, just create
2. **Before each step**: `TaskUpdate(status="in_progress")` (ONE at a time)
3. **After each step**: `TaskUpdate(status="completed")` IMMEDIATELY (NEVER batch)
4. **Scope changes**: Update tasks BEFORE proceeding

### Why This Matters

- **Execution anchor**: Tasks prevent drift from original request
- **Recovery**: If interrupted, tasks enable seamless continuation
- **Accountability**: Each task = explicit commitment to deliver

### Anti-Patterns (BLOCKING)

| Violation | Why It Fails |
|-----------|--------------|
| Skipping tasks on multi-step work | Steps get forgotten, user has no visibility |
| Batch-completing multiple tasks | Defeats real-time tracking purpose |
| Proceeding without `in_progress` | No indication of current work |
| Finishing without completing tasks | Task appears incomplete |

**NO TASKS ON MULTI-STEP WORK = INCOMPLETE WORK.**"""

def _todo_discipline_section() -> str:
return """## Todo Discipline (NON-NEGOTIABLE)

**Track ALL multi-step work with todos. This is your execution backbone.**
Expand Down
Loading
Loading