feat: add follow-up task suggestions (#102422)

* feat(tools): add follow-up task suggestions

* chore: leave changelog to release flow

* fix(tools): add task suggestion display metadata

* fix(tools): update task suggestion display snapshot

* docs: format task suggestion tool table

* test(gateway): expect compaction worktree workspace

* test(gateway): preserve configured compaction workspace

* fix(ui): translate task suggestions
This commit is contained in:
Peter Steinberger 2026-07-09 06:30:01 +01:00 committed by GitHub
parent acac359de6
commit 5533d979d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
93 changed files with 2895 additions and 128 deletions

View file

@ -409,6 +409,23 @@
"plan.0.step"
]
},
"spawn_task": {
"emoji": "✨",
"title": "Suggest Task",
"detailKeys": [
"title",
"tldr",
"cwd"
]
},
"dismiss_task": {
"emoji": "🗑️",
"title": "Dismiss Task",
"detailKeys": [
"task_id",
"reason"
]
},
"skill_workshop": {
"emoji": "🧰",
"title": "Skill Workshop",

View file

@ -57,6 +57,12 @@ public enum SessionFileRelevance: String, Codable, Sendable {
case mixed = "mixed"
}
public enum TaskSuggestionResolution: String, Codable, Sendable {
case dismissed = "dismissed"
case accepted = "accepted"
case expired = "expired"
}
public struct ConnectParams: Codable, Sendable {
public let minprotocol: Int
public let maxprotocol: Int
@ -2602,6 +2608,7 @@ public struct SessionsCreateParams: Codable, Sendable {
public let task: String?
public let message: String?
public let worktree: Bool?
public let cwd: String?
public init(
key: String?,
@ -2613,7 +2620,8 @@ public struct SessionsCreateParams: Codable, Sendable {
emitcommandhooks: Bool?,
task: String?,
message: String?,
worktree: Bool?)
worktree: Bool?,
cwd: String?)
{
self.key = key
self.agentid = agentid
@ -2625,6 +2633,7 @@ public struct SessionsCreateParams: Codable, Sendable {
self.task = task
self.message = message
self.worktree = worktree
self.cwd = cwd
}
private enum CodingKeys: String, CodingKey {
@ -2638,6 +2647,7 @@ public struct SessionsCreateParams: Codable, Sendable {
case task
case message
case worktree
case cwd
}
}
@ -3231,6 +3241,200 @@ public struct AuditListResult: Codable, Sendable {
}
}
public struct TaskSuggestion: Codable, Sendable {
public let id: String
public let title: String
public let prompt: String
public let tldr: String
public let cwd: String
public let sessionkey: String
public let agentid: String?
public let createdat: Int
public init(
id: String,
title: String,
prompt: String,
tldr: String,
cwd: String,
sessionkey: String,
agentid: String? = nil,
createdat: Int)
{
self.id = id
self.title = title
self.prompt = prompt
self.tldr = tldr
self.cwd = cwd
self.sessionkey = sessionkey
self.agentid = agentid
self.createdat = createdat
}
private enum CodingKeys: String, CodingKey {
case id
case title
case prompt
case tldr
case cwd
case sessionkey = "sessionKey"
case agentid = "agentId"
case createdat = "createdAt"
}
}
public struct TaskSuggestionsAcceptParams: Codable, Sendable {
public let taskid: String
public init(
taskid: String)
{
self.taskid = taskid
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
}
}
public struct TaskSuggestionsAcceptResult: Codable, Sendable {
public let taskid: String
public let key: String
public init(
taskid: String,
key: String)
{
self.taskid = taskid
self.key = key
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
case key
}
}
public struct TaskSuggestionsCreateParams: Codable, Sendable {
public let title: String
public let prompt: String
public let tldr: String
public let cwd: String
public let sessionkey: String
public let agentid: String?
public init(
title: String,
prompt: String,
tldr: String,
cwd: String,
sessionkey: String,
agentid: String? = nil)
{
self.title = title
self.prompt = prompt
self.tldr = tldr
self.cwd = cwd
self.sessionkey = sessionkey
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case title
case prompt
case tldr
case cwd
case sessionkey = "sessionKey"
case agentid = "agentId"
}
}
public struct TaskSuggestionsCreateResult: Codable, Sendable {
public let taskid: String
public let suggestion: TaskSuggestion
public init(
taskid: String,
suggestion: TaskSuggestion)
{
self.taskid = taskid
self.suggestion = suggestion
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
case suggestion
}
}
public struct TaskSuggestionsDismissParams: Codable, Sendable {
public let taskid: String
public let reason: String?
public init(
taskid: String,
reason: String?)
{
self.taskid = taskid
self.reason = reason
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
case reason
}
}
public struct TaskSuggestionsDismissResult: Codable, Sendable {
public let taskid: String
public let dismissed: Bool
public init(
taskid: String,
dismissed: Bool)
{
self.taskid = taskid
self.dismissed = dismissed
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
case dismissed
}
}
public struct TaskSuggestionsListParams: Codable, Sendable {
public let sessionkey: String?
public let agentid: String?
public init(
sessionkey: String?,
agentid: String? = nil)
{
self.sessionkey = sessionkey
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case sessionkey = "sessionKey"
case agentid = "agentId"
}
}
public struct TaskSuggestionsListResult: Codable, Sendable {
public let suggestions: [TaskSuggestion]
public init(
suggestions: [TaskSuggestion])
{
self.suggestions = suggestions
}
private enum CodingKeys: String, CodingKey {
case suggestions
}
}
public struct TaskSummary: Codable, Sendable {
public let id: String
public let kind: String?