baa-conductor

git clone 

commit
7b39f32
parent
e91ac94
author
im_wower
date
2026-03-29 03:18:46 +0800 CST
feat: expose recent session urls in describe
2 files changed,  +30, -4
M apps/conductor-daemon/src/local-api.ts
+17, -0
 1@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
 2 import { randomUUID } from "node:crypto";
 3 import { join } from "node:path";
 4 import {
 5+  buildArtifactRelativePath,
 6   buildArtifactPublicUrl,
 7   getArtifactContentType,
 8   type ArtifactStore
 9@@ -105,6 +106,8 @@ const SSE_RESPONSE_HEADERS = {
10 } as const;
11 const ALLOWED_ARTIFACT_SCOPES = new Set(["exec", "msg", "session"]);
12 const ARTIFACT_FILE_SEGMENT_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/u;
13+const RECENT_SESSIONS_TXT_ARTIFACT_PATH = buildArtifactRelativePath("session", "latest.txt");
14+const RECENT_SESSIONS_JSON_ARTIFACT_PATH = buildArtifactRelativePath("session", "latest.json");
15 const BROWSER_CLAUDE_PLATFORM = "claude";
16 const BROWSER_CLAUDE_ROOT_URL = "https://claude.ai/";
17 const BROWSER_CLAUDE_ORGANIZATIONS_PATH = "/api/organizations";
18@@ -1056,6 +1059,18 @@ function requireArtifactStore(artifactStore: ArtifactStore | null): ArtifactStor
19   return artifactStore;
20 }
21 
22+function buildRecentSessionsArtifactUrls(artifactStore: ArtifactStore | null): {
23+  recent_sessions_json_url: string | null;
24+  recent_sessions_url: string | null;
25+} {
26+  const publicBaseUrl = artifactStore?.getPublicBaseUrl() ?? null;
27+
28+  return {
29+    recent_sessions_url: buildArtifactPublicUrl(publicBaseUrl, RECENT_SESSIONS_TXT_ARTIFACT_PATH),
30+    recent_sessions_json_url: buildArtifactPublicUrl(publicBaseUrl, RECENT_SESSIONS_JSON_ARTIFACT_PATH)
31+  };
32+}
33+
34 function summarizeTask(task: TaskRecord): JsonObject {
35   return {
36     task_id: task.taskId,
37@@ -4083,6 +4098,7 @@ async function handleDescribeRead(context: LocalApiRequestContext, version: stri
38       truth_source: "local sqlite control plane",
39       origin
40     },
41+    ...buildRecentSessionsArtifactUrls(context.artifactStore),
42     auth: buildHttpAuthData(snapshot),
43     system,
44     websocket: buildFirefoxWebSocketData(snapshot),
45@@ -4227,6 +4243,7 @@ async function handleScopedDescribeRead(
46         truth_source: "local sqlite control plane",
47         origin
48       },
49+      ...buildRecentSessionsArtifactUrls(context.artifactStore),
50       recommended_flow: [
51         "GET /describe/business",
52         "Optionally GET /v1/capabilities",
M tasks/T-S047.md
+13, -4
 1@@ -2,7 +2,7 @@
 2 
 3 ## 状态
 4 
 5-- 当前状态:`待开始`
 6+- 当前状态:`已完成`
 7 - 规模预估:`S`
 8 - 依赖任务:无
 9 - 建议执行者:`Codex` 或 `Claude`(改动小,边界清晰)
10@@ -69,19 +69,28 @@ URL 通过 `publicBaseUrl` 拼接,不硬编码域名。
11 
12 ### 开始执行
13 
14-- 执行者:
15-- 开始时间:
16+- 执行者:`Codex`
17+- 开始时间:`2026-03-29 03:13:59 CST`
18 - 状态变更:`待开始` → `进行中`
19 
20 ### 完成摘要
21 
22-- 完成时间:
23+- 完成时间:`2026-03-29 03:18:18 CST`
24 - 状态变更:`进行中` → `已完成`
25 - 修改了哪些文件:
26+  - `apps/conductor-daemon/src/local-api.ts`
27+  - `tasks/T-S047.md`
28 - 核心实现思路:
29+  - 在 `local-api.ts` 中新增 recent sessions URL helper,基于 `artifactStore.getPublicBaseUrl()` 和 session artifact 的固定相对路径生成 `recent_sessions_url` / `recent_sessions_json_url`
30+  - 将两个字段接入 `/describe` 与 `/describe/business` 响应,确保业务入口可直接暴露最近会话索引的可 fetch URL
31 - 跑了哪些测试:
32+  - `pnpm test`(`/Users/george/code/baa-conductor-describe-sessions-url/apps/conductor-daemon`)
33+  - `node --input-type=module -e '...'` 定向调用 `/describe`,确认返回 `https://conductor.makefile.so/artifact/session/latest.txt` 与 `https://conductor.makefile.so/artifact/session/latest.json`
34 
35 ### 执行过程中遇到的问题
36 
37+- 新建 worktree 初始缺少 `node_modules`,首次 `pnpm test` 因 `tsc` 不存在失败;执行 `pnpm install --frozen-lockfile` 后恢复正常验证流程
38+
39 ### 剩余风险
40 
41+- 代码与本地验证已完成,但验收中的 `curl http://100.71.210.78:4317/describe` 仍依赖后续将本分支变更部署到目标实例