feat(runtime-api): expose thread branch metadata
Add read-only workspace and branch metadata to runtime thread summaries so VS Code Agent View can show when a thread lane is on another branch. Non-git workspaces return null branch metadata instead of failing. Refs #2580, #2721. Credits the existing branch-visibility trail from #1217/#2341 in the changelog.
This commit is contained in:
+9
-6
@@ -56,13 +56,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
local runtime attach checks, status bar state, and a read-only Agent View
|
||||
preview backed by recent runtime thread summaries, plus a read-only
|
||||
`GET /v1/snapshots` endpoint for GUI clients to inspect side-git restore
|
||||
points. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
points. Thread summaries now include read-only workspace and branch metadata
|
||||
so the VS Code Agent View can show when a thread or agent lane is on another
|
||||
branch. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
inline edits, or retry/undo/restore runtime mutation endpoints yet (#461,
|
||||
#462, #480, #1584, #2580, #2808). Thanks @AiurArtanis for the Agent View
|
||||
prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI runtime API
|
||||
direction, and @BigBenLabs, @lzx1545642258, @yangdaowan, @mangdehuang,
|
||||
@VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the GUI/VS Code demand
|
||||
and validation trail.
|
||||
#462, #480, #1217, #2341, #1584, #2580, #2808). Thanks @AiurArtanis for the
|
||||
Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI
|
||||
runtime API direction, @douglarek, @caeserchen, and @nightt5879 for the branch
|
||||
visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
@mangdehuang, @VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the
|
||||
GUI/VS Code demand and validation trail.
|
||||
- Added a static prompt composer override for embedders that need to replace
|
||||
the byte-stable base/personality prompt segment while leaving mode metadata,
|
||||
approval policy, tool taxonomy, Context Management, and the Compaction Relay
|
||||
|
||||
@@ -56,13 +56,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
local runtime attach checks, status bar state, and a read-only Agent View
|
||||
preview backed by recent runtime thread summaries, plus a read-only
|
||||
`GET /v1/snapshots` endpoint for GUI clients to inspect side-git restore
|
||||
points. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
points. Thread summaries now include read-only workspace and branch metadata
|
||||
so the VS Code Agent View can show when a thread or agent lane is on another
|
||||
branch. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
inline edits, or retry/undo/restore runtime mutation endpoints yet (#461,
|
||||
#462, #480, #1584, #2580, #2808). Thanks @AiurArtanis for the Agent View
|
||||
prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI runtime API
|
||||
direction, and @BigBenLabs, @lzx1545642258, @yangdaowan, @mangdehuang,
|
||||
@VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the GUI/VS Code demand
|
||||
and validation trail.
|
||||
#462, #480, #1217, #2341, #1584, #2580, #2808). Thanks @AiurArtanis for the
|
||||
Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI
|
||||
runtime API direction, @douglarek, @caeserchen, and @nightt5879 for the branch
|
||||
visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
@mangdehuang, @VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the
|
||||
GUI/VS Code demand and validation trail.
|
||||
- Added a static prompt composer override for embedders that need to replace
|
||||
the byte-stable base/personality prompt segment while leaving mode metadata,
|
||||
approval policy, tool taxonomy, Context Management, and the Compaction Relay
|
||||
|
||||
@@ -264,6 +264,8 @@ struct ThreadSummary {
|
||||
preview: String,
|
||||
model: String,
|
||||
mode: String,
|
||||
workspace: PathBuf,
|
||||
branch: Option<String>,
|
||||
archived: bool,
|
||||
updated_at: chrono::DateTime<Utc>,
|
||||
latest_turn_id: Option<String>,
|
||||
@@ -1245,6 +1247,8 @@ async fn list_threads_summary(
|
||||
preview,
|
||||
model: thread.model,
|
||||
mode: thread.mode,
|
||||
branch: current_git_branch(&thread.workspace),
|
||||
workspace: thread.workspace,
|
||||
archived: thread.archived,
|
||||
updated_at: thread.updated_at,
|
||||
latest_turn_id: thread.latest_turn_id,
|
||||
@@ -2011,9 +2015,7 @@ fn collect_workspace_status(workspace: &std::path::Path) -> WorkspaceStatusRespo
|
||||
}
|
||||
|
||||
status.git_repo = true;
|
||||
status.branch = run_git(workspace, &["rev-parse", "--abbrev-ref", "HEAD"])
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty());
|
||||
status.branch = current_git_branch(workspace);
|
||||
|
||||
if let Some(porcelain) = run_git(workspace, &["status", "--porcelain=v1"]) {
|
||||
for line in porcelain.lines() {
|
||||
@@ -2055,6 +2057,24 @@ fn run_git(workspace: &std::path::Path, args: &[&str]) -> Option<String> {
|
||||
String::from_utf8(output.stdout).ok()
|
||||
}
|
||||
|
||||
fn current_git_branch(workspace: &std::path::Path) -> Option<String> {
|
||||
let repo_check = run_git(workspace, &["rev-parse", "--is-inside-work-tree"])?;
|
||||
if repo_check.trim() != "true" {
|
||||
return None;
|
||||
}
|
||||
let branch = run_git(workspace, &["rev-parse", "--abbrev-ref", "HEAD"])?;
|
||||
let branch = branch.trim();
|
||||
if branch.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if branch != "HEAD" {
|
||||
return Some(branch.to_string());
|
||||
}
|
||||
let short_hash = run_git(workspace, &["rev-parse", "--short", "HEAD"])?;
|
||||
let short_hash = short_hash.trim();
|
||||
(!short_hash.is_empty()).then(|| format!("detached@{short_hash}"))
|
||||
}
|
||||
|
||||
fn resolve_skills_dir(config: &Config, workspace: &std::path::Path) -> PathBuf {
|
||||
// Canonicalize the workspace once so the symlink-containment check below
|
||||
// compares like-for-like. If the workspace can't be canonicalized at all
|
||||
@@ -2427,6 +2447,18 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn run_test_git(workspace: &std::path::Path, args: &[&str]) -> Result<()> {
|
||||
let output = crate::dependencies::Git::output(args, workspace)
|
||||
.with_context(|| format!("git {args:?} failed to spawn"))?;
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"git {args:?} failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_detail_tool_use_preserves_caller_metadata() {
|
||||
let detail = session_to_detail(saved_session_with_blocks(vec![
|
||||
@@ -2869,6 +2901,100 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_summary_includes_workspace_branch_metadata() -> Result<()> {
|
||||
let tmp = tempfile::tempdir()?;
|
||||
let root = tmp.path().join("runtime");
|
||||
let sessions_dir = root.join("sessions");
|
||||
let repo = tmp.path().join("repo");
|
||||
fs::create_dir_all(&repo)?;
|
||||
run_test_git(&repo, &["init", "-b", "feature/agent"])?;
|
||||
fs::write(repo.join("README.md"), "branch visibility\n")?;
|
||||
run_test_git(&repo, &["add", "README.md"])?;
|
||||
run_test_git(
|
||||
&repo,
|
||||
&[
|
||||
"-c",
|
||||
"user.name=CodeWhale Test",
|
||||
"-c",
|
||||
"user.email=codewhale@example.invalid",
|
||||
"commit",
|
||||
"-m",
|
||||
"init",
|
||||
],
|
||||
)?;
|
||||
|
||||
let non_git = tmp.path().join("non-git");
|
||||
fs::create_dir_all(&non_git)?;
|
||||
|
||||
let Some((addr, _runtime_threads, handle)) =
|
||||
spawn_test_server_with_root(root, sessions_dir).await?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let client = crate::tls::reqwest_client();
|
||||
|
||||
let git_thread: serde_json::Value = client
|
||||
.post(format!("http://{addr}/v1/threads"))
|
||||
.json(&json!({
|
||||
"title": "Git workspace",
|
||||
"workspace": repo,
|
||||
}))
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.json()
|
||||
.await?;
|
||||
let git_thread_id = git_thread["id"]
|
||||
.as_str()
|
||||
.context("missing git thread id")?
|
||||
.to_string();
|
||||
|
||||
let plain_thread: serde_json::Value = client
|
||||
.post(format!("http://{addr}/v1/threads"))
|
||||
.json(&json!({
|
||||
"title": "Plain workspace",
|
||||
"workspace": non_git,
|
||||
}))
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.json()
|
||||
.await?;
|
||||
let plain_thread_id = plain_thread["id"]
|
||||
.as_str()
|
||||
.context("missing plain thread id")?
|
||||
.to_string();
|
||||
|
||||
let summary: serde_json::Value = client
|
||||
.get(format!("http://{addr}/v1/threads/summary?limit=100"))
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.json()
|
||||
.await?;
|
||||
let summaries = summary.as_array().context("summary should be an array")?;
|
||||
let git_summary = summaries
|
||||
.iter()
|
||||
.find(|item| item["id"] == git_thread_id)
|
||||
.context("missing git workspace summary")?;
|
||||
assert_eq!(git_summary["branch"], "feature/agent");
|
||||
assert_eq!(git_summary["workspace"], repo.to_string_lossy().as_ref());
|
||||
|
||||
let plain_summary = summaries
|
||||
.iter()
|
||||
.find(|item| item["id"] == plain_thread_id)
|
||||
.context("missing plain workspace summary")?;
|
||||
assert_eq!(plain_summary["branch"], serde_json::Value::Null);
|
||||
assert_eq!(
|
||||
plain_summary["workspace"],
|
||||
non_git.to_string_lossy().as_ref()
|
||||
);
|
||||
|
||||
handle.abort();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn workspace_and_automation_endpoints_work() -> Result<()> {
|
||||
let Some((addr, _runtime_threads, handle)) = spawn_test_server().await? else {
|
||||
|
||||
@@ -184,6 +184,8 @@ function readThreadSummaries(value) {
|
||||
preview: readString(record.preview) ?? "",
|
||||
model: readString(record.model) ?? "unknown",
|
||||
mode: readString(record.mode) ?? "agent",
|
||||
workspace: readString(record.workspace),
|
||||
branch: readString(record.branch),
|
||||
archived: record.archived === true,
|
||||
updatedAt: readString(record.updated_at) ?? "",
|
||||
latestTurnStatus: readString(record.latest_turn_status),
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -125,11 +125,13 @@ exports.RuntimeStatusView = RuntimeStatusView;
|
||||
function renderThread(thread) {
|
||||
const status = thread.latestTurnStatus ? ` · ${thread.latestTurnStatus}` : "";
|
||||
const archived = thread.archived ? " · archived" : "";
|
||||
const branch = thread.branch ? ` · branch ${thread.branch}` : "";
|
||||
const workspace = thread.workspace ? ` · ${thread.workspace}` : "";
|
||||
const updated = thread.updatedAt ? ` · ${formatTimestamp(thread.updatedAt)}` : "";
|
||||
return `<div class="thread">
|
||||
<div class="thread-title">${escapeHtml(thread.title)}</div>
|
||||
<div class="thread-preview">${escapeHtml(thread.preview || "No recent message.")}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${thread.mode} · ${thread.model}${status}${archived}${updated}`)}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${thread.mode} · ${thread.model}${status}${branch}${archived}${updated}${workspace}`)}</div>
|
||||
</div>`;
|
||||
}
|
||||
function labelFor(kind) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAGjC,MAAa,iBAAiB;IACrB,MAAM,CAAU,QAAQ,GAAG,yBAAyB,CAAC;IAEpD,IAAI,CAAsB;IAC1B,KAAK,GAAiB;QAC5B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,uBAAuB;QAChC,MAAM,EAAE,mCAAmC;KAC5C,CAAC;IACM,OAAO,GAAoB,EAAE,CAAC;IAC9B,aAAa,GAAG,gDAAgD,CAAC;IAEzE,kBAAkB,CAAC,IAAwB;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,OAA6B,EAAE,EAAE;YACjE,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAChC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBACvC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;gBAC1C,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACzC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAmB;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,OAAwB,EAAE,MAAc;QACpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,MAAM,WAAW,GACf,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,CAAC,CAAC,qBAAqB,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG;;;;yHAI4F,KAAK;;;;;;;;;;;;;;;;wBAgBtG,UAAU,CAAC,KAAK,CAAC;sBACnB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;4BACvB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;;;;;;IAMtD,WAAW;mBACI,KAAK;;;;;;;QAOhB,CAAC;IACP,CAAC;;AAxFH,8CAyFC;AAED,SAAS,YAAY,CAAC,MAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO;gCACuB,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;kCACtB,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,oBAAoB,CAAC;+BACrD,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,EAAE,CAAC;SACvH,CAAC;AACV,CAAC;AAED,SAAS,QAAQ,CAAC,IAA0B;IAC1C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,eAAe;YAClB,OAAO,gBAAgB,CAAC;QAC1B,KAAK,OAAO;YACV,OAAO,eAAe,CAAC;QACzB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,QAAQ,GAAG,gEAAgE,CAAC;IAClF,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
||||
@@ -16,6 +16,8 @@ export interface ThreadSummary {
|
||||
preview: string;
|
||||
model: string;
|
||||
mode: string;
|
||||
workspace?: string;
|
||||
branch?: string;
|
||||
archived: boolean;
|
||||
updatedAt: string;
|
||||
latestTurnStatus?: string;
|
||||
@@ -198,6 +200,8 @@ function readThreadSummaries(value: unknown): ThreadSummary[] {
|
||||
preview: readString(record.preview) ?? "",
|
||||
model: readString(record.model) ?? "unknown",
|
||||
mode: readString(record.mode) ?? "agent",
|
||||
workspace: readString(record.workspace),
|
||||
branch: readString(record.branch),
|
||||
archived: record.archived === true,
|
||||
updatedAt: readString(record.updated_at) ?? "",
|
||||
latestTurnStatus: readString(record.latest_turn_status),
|
||||
|
||||
@@ -95,11 +95,13 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
function renderThread(thread: ThreadSummary): string {
|
||||
const status = thread.latestTurnStatus ? ` · ${thread.latestTurnStatus}` : "";
|
||||
const archived = thread.archived ? " · archived" : "";
|
||||
const branch = thread.branch ? ` · branch ${thread.branch}` : "";
|
||||
const workspace = thread.workspace ? ` · ${thread.workspace}` : "";
|
||||
const updated = thread.updatedAt ? ` · ${formatTimestamp(thread.updatedAt)}` : "";
|
||||
return `<div class="thread">
|
||||
<div class="thread-title">${escapeHtml(thread.title)}</div>
|
||||
<div class="thread-preview">${escapeHtml(thread.preview || "No recent message.")}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${thread.mode} · ${thread.model}${status}${archived}${updated}`)}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${thread.mode} · ${thread.model}${status}${branch}${archived}${updated}${workspace}`)}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user