@xfey/tutti 0.1.21 → 0.1.23
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/dist/collaboration-state/index.d.ts +1 -1
- package/dist/collaboration-state/index.js +1 -1
- package/dist/collaboration-state/messages.js +50 -1
- package/dist/collaboration-state/scratchpad.d.ts +2 -0
- package/dist/collaboration-state/scratchpad.js +63 -0
- package/dist/collaboration-state/storage-types.d.ts +5 -0
- package/dist/collaboration-state/types.d.ts +8 -1
- package/dist/control-plane/scratchpad-refresh-start.d.ts +2 -0
- package/dist/control-plane/scratchpad-refresh-start.js +10 -0
- package/dist/control-plane/scratchpad-refresh.d.ts +2 -0
- package/dist/control-plane/scratchpad-refresh.js +1 -0
- package/dist/project-timeline/index.d.ts +17 -3
- package/dist/server-shell/cli/host-lifecycle.js +2 -19
- package/dist/server-shell/cli/launch-command.d.ts +11 -0
- package/dist/server-shell/cli/launch-command.js +42 -6
- package/dist/server-shell/cli/terminal-qr.d.ts +3 -0
- package/dist/server-shell/cli/terminal-qr.js +17 -0
- package/dist/server-shell/http/routes/project-api/openapi-collaboration-routes.d.ts +1 -0
- package/dist/server-shell/http/routes/project-api/openapi-timeline-routes.d.ts +94 -5
- package/dist/server-shell/http/routes/project-api/openapi.d.ts +95 -5
- package/dist/server-shell/http/routes/project-api/payload-validation.d.ts +6 -2
- package/dist/server-shell/http/routes/project-api/payload-validation.js +3 -0
- package/dist/server-shell/http/routes/project-api/project-timeline-projection.js +694 -502
- package/migrations/0013_scratchpad_receipt_sources.sql +24 -0
- package/migrations/README.md +3 -2
- package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -1
- package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -1
- package/node_modules/@tutti/shared/dist/schemas/api/messages.d.ts +1 -0
- package/node_modules/@tutti/shared/dist/schemas/api/messages.js +1 -0
- package/node_modules/@tutti/shared/dist/schemas/api/project-timeline.d.ts +313 -12
- package/node_modules/@tutti/shared/dist/schemas/api/project-timeline.js +131 -14
- package/node_modules/@tutti/shared/dist/schemas/api/types.d.ts +5 -1
- package/package.json +1 -1
- package/web/assets/index-BfFYfzeO.js +29 -0
- package/web/assets/index-De6mK5Q2.css +1 -0
- package/web/index.html +2 -2
- package/web/assets/index-BtneECwp.js +0 -29
- package/web/assets/index-CM9mbbeW.css +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { CollaborationStateCursorError } from "./serialization.js";
|
|
2
2
|
export { createIdleExecutionStatusProjection } from "./execution-status.js";
|
|
3
3
|
export { createMainChatAgentMessage, createMainChatMessage, createMainChatSystemMessage, hasMainChatWorklistFeedbackMessage, readCompletedWorklistFeedbackTaskIds, readMessageProjectionById, readMainChatMessageWindow, readMainChatMessagesAfter, readMainChatMessagesAfterCursor, readMainChatMessagesBeforeCursor, } from "./messages.js";
|
|
4
|
-
export { createEmptyScratchpadProjection, readScratchpadProjection, submitScratchpadProjection, upsertScratchpadProjection, } from "./scratchpad.js";
|
|
4
|
+
export { createEmptyScratchpadProjection, readScratchpadReceiptSourceRefs, readScratchpadProjection, submitScratchpadProjection, upsertScratchpadProjection, } from "./scratchpad.js";
|
|
5
5
|
export { advanceScratchpadTaskCompileSourceCursor, markScratchpadRefreshFailed, markScratchpadRefreshStarted, markScratchpadRefreshSucceeded, markScratchpadSourceDirty, readScratchpadSourceState, } from "./scratchpad-source-state.js";
|
|
6
6
|
export { deleteStaleClarificationSubmitReplayHints, readActiveClarificationProjection, readClarificationRoundProjection, readClarificationRoundsForThread, readClarificationThreadResponse, readSealedClarificationRoundsWithoutSuccessor, readSubmittedTaskCompileClarificationRounds, readSubmittedTaskCompileClarificationRoundsAfterCursor, } from "./clarification-records.js";
|
|
7
7
|
export { createClarificationRoundAgentMessage, createClarificationRoundMessage, readClarificationRoundMessagesWindow, } from "./clarification-messages.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { CollaborationStateCursorError } from "./serialization.js";
|
|
2
2
|
export { createIdleExecutionStatusProjection } from "./execution-status.js";
|
|
3
3
|
export { createMainChatAgentMessage, createMainChatMessage, createMainChatSystemMessage, hasMainChatWorklistFeedbackMessage, readCompletedWorklistFeedbackTaskIds, readMessageProjectionById, readMainChatMessageWindow, readMainChatMessagesAfter, readMainChatMessagesAfterCursor, readMainChatMessagesBeforeCursor, } from "./messages.js";
|
|
4
|
-
export { createEmptyScratchpadProjection, readScratchpadProjection, submitScratchpadProjection, upsertScratchpadProjection, } from "./scratchpad.js";
|
|
4
|
+
export { createEmptyScratchpadProjection, readScratchpadReceiptSourceRefs, readScratchpadProjection, submitScratchpadProjection, upsertScratchpadProjection, } from "./scratchpad.js";
|
|
5
5
|
export { advanceScratchpadTaskCompileSourceCursor, markScratchpadRefreshFailed, markScratchpadRefreshStarted, markScratchpadRefreshSucceeded, markScratchpadSourceDirty, readScratchpadSourceState, } from "./scratchpad-source-state.js";
|
|
6
6
|
export { deleteStaleClarificationSubmitReplayHints, readActiveClarificationProjection, readClarificationRoundProjection, readClarificationRoundsForThread, readClarificationThreadResponse, readSealedClarificationRoundsWithoutSuccessor, readSubmittedTaskCompileClarificationRounds, readSubmittedTaskCompileClarificationRoundsAfterCursor, } from "./clarification-records.js";
|
|
7
7
|
export { createClarificationRoundAgentMessage, createClarificationRoundMessage, readClarificationRoundMessagesWindow, } from "./clarification-messages.js";
|
|
@@ -245,10 +245,59 @@ export function readMainChatMessageWindow(db, options = {}) {
|
|
|
245
245
|
if (before !== null && after !== null) {
|
|
246
246
|
throw new Error("before and after cursors cannot be used together");
|
|
247
247
|
}
|
|
248
|
+
if (options.around !== undefined && (before !== null || after !== null)) {
|
|
249
|
+
throw new Error("around cannot be used with before or after cursors");
|
|
250
|
+
}
|
|
248
251
|
let rows;
|
|
249
252
|
let hasOlder = false;
|
|
250
253
|
let hasNewer = false;
|
|
251
|
-
if (
|
|
254
|
+
if (options.around !== undefined) {
|
|
255
|
+
const target = db
|
|
256
|
+
.prepare(`
|
|
257
|
+
SELECT *
|
|
258
|
+
FROM messages
|
|
259
|
+
WHERE scope_kind = 'main_chat'
|
|
260
|
+
AND id = ?
|
|
261
|
+
`)
|
|
262
|
+
.get(options.around);
|
|
263
|
+
if (target === undefined) {
|
|
264
|
+
rows = [];
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
const beforeLimit = Math.floor((limit - 1) / 2);
|
|
268
|
+
const afterLimit = Math.max(0, limit - beforeLimit - 1);
|
|
269
|
+
const olderRows = db
|
|
270
|
+
.prepare(`
|
|
271
|
+
SELECT *
|
|
272
|
+
FROM messages
|
|
273
|
+
WHERE scope_kind = 'main_chat'
|
|
274
|
+
AND (
|
|
275
|
+
created_at < ?
|
|
276
|
+
OR (created_at = ? AND id < ?)
|
|
277
|
+
)
|
|
278
|
+
ORDER BY created_at DESC, id DESC
|
|
279
|
+
LIMIT ?
|
|
280
|
+
`)
|
|
281
|
+
.all(target.created_at, target.created_at, target.id, beforeLimit + 1);
|
|
282
|
+
const newerRows = db
|
|
283
|
+
.prepare(`
|
|
284
|
+
SELECT *
|
|
285
|
+
FROM messages
|
|
286
|
+
WHERE scope_kind = 'main_chat'
|
|
287
|
+
AND (
|
|
288
|
+
created_at > ?
|
|
289
|
+
OR (created_at = ? AND id > ?)
|
|
290
|
+
)
|
|
291
|
+
ORDER BY created_at ASC, id ASC
|
|
292
|
+
LIMIT ?
|
|
293
|
+
`)
|
|
294
|
+
.all(target.created_at, target.created_at, target.id, afterLimit + 1);
|
|
295
|
+
hasOlder = olderRows.length > beforeLimit;
|
|
296
|
+
hasNewer = newerRows.length > afterLimit;
|
|
297
|
+
rows = [...olderRows.slice(0, beforeLimit).reverse(), target, ...newerRows.slice(0, afterLimit)];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else if (before !== null) {
|
|
252
301
|
rows = db
|
|
253
302
|
.prepare(`
|
|
254
303
|
SELECT *
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ScratchpadProjection } from "@tutti/shared/schemas/api";
|
|
2
2
|
import type { SqliteDatabase } from "../store/index.js";
|
|
3
|
+
import type { ScratchpadSourceRefRow } from "./storage-types.js";
|
|
3
4
|
import type { ScratchpadSnapshotInput, SubmitScratchpadInput } from "./types.js";
|
|
4
5
|
export declare function createEmptyScratchpadProjection(): ScratchpadProjection;
|
|
5
6
|
export declare function upsertScratchpadProjection(db: SqliteDatabase, input: ScratchpadSnapshotInput): ScratchpadProjection;
|
|
6
7
|
export declare function submitScratchpadProjection(db: SqliteDatabase, input: SubmitScratchpadInput): ScratchpadProjection;
|
|
7
8
|
export declare function readScratchpadProjection(db: SqliteDatabase): ScratchpadProjection;
|
|
9
|
+
export declare function readScratchpadReceiptSourceRefs(db: SqliteDatabase, workflowRef: string): ScratchpadSourceRefRow[];
|
|
8
10
|
//# sourceMappingURL=scratchpad.d.ts.map
|
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
import { nowIso, parseJson, stringifyJson } from "./serialization.js";
|
|
2
2
|
const SCRATCHPAD_RECEIPT_LIMIT = 100;
|
|
3
|
+
function normalizeSourceRefs(sourceRefs = []) {
|
|
4
|
+
const byMessageId = new Map();
|
|
5
|
+
for (const sourceRef of sourceRefs) {
|
|
6
|
+
if (sourceRef.message_id.trim() === "" || sourceRef.created_at.trim() === "") {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
byMessageId.set(sourceRef.message_id, sourceRef);
|
|
10
|
+
}
|
|
11
|
+
return [...byMessageId.values()].sort((left, right) => {
|
|
12
|
+
const timeOrder = left.created_at.localeCompare(right.created_at);
|
|
13
|
+
return timeOrder === 0 ? left.message_id.localeCompare(right.message_id) : timeOrder;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function replaceCurrentScratchpadSourceRefs(db, sourceRefs) {
|
|
17
|
+
db.prepare("DELETE FROM scratchpad_source_refs WHERE scratchpad_id = 'current'").run();
|
|
18
|
+
const normalized = normalizeSourceRefs(sourceRefs);
|
|
19
|
+
if (normalized.length === 0) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const insert = db.prepare(`
|
|
23
|
+
INSERT INTO scratchpad_source_refs (
|
|
24
|
+
scratchpad_id,
|
|
25
|
+
message_id,
|
|
26
|
+
source_scope,
|
|
27
|
+
created_at
|
|
28
|
+
)
|
|
29
|
+
VALUES ('current', ?, ?, ?)
|
|
30
|
+
`);
|
|
31
|
+
for (const sourceRef of normalized) {
|
|
32
|
+
insert.run(sourceRef.message_id, sourceRef.source_scope, sourceRef.created_at);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function copyCurrentScratchpadSourcesToReceipt(db, workflowRef) {
|
|
36
|
+
db.prepare("DELETE FROM scratchpad_receipt_sources WHERE workflow_ref = ?").run(workflowRef);
|
|
37
|
+
db.prepare(`
|
|
38
|
+
INSERT INTO scratchpad_receipt_sources (
|
|
39
|
+
workflow_ref,
|
|
40
|
+
message_id,
|
|
41
|
+
source_scope,
|
|
42
|
+
created_at
|
|
43
|
+
)
|
|
44
|
+
SELECT
|
|
45
|
+
?,
|
|
46
|
+
message_id,
|
|
47
|
+
source_scope,
|
|
48
|
+
created_at
|
|
49
|
+
FROM scratchpad_source_refs
|
|
50
|
+
WHERE scratchpad_id = 'current'
|
|
51
|
+
ORDER BY created_at ASC, message_id ASC
|
|
52
|
+
`).run(workflowRef);
|
|
53
|
+
}
|
|
3
54
|
export function createEmptyScratchpadProjection() {
|
|
4
55
|
return {
|
|
5
56
|
id: "current",
|
|
@@ -76,6 +127,7 @@ export function upsertScratchpadProjection(db, input) {
|
|
|
76
127
|
submitted_by_workflow_ref = NULL,
|
|
77
128
|
submitted_at = NULL
|
|
78
129
|
`).run(input.topic, input.background_summary, stringifyJson(input.current_consensus), stringifyJson(input.open_questions), stringifyJson(input.task_changes), input.updated_by_activity_ref ?? null, updatedAt);
|
|
130
|
+
replaceCurrentScratchpadSourceRefs(db, input.source_refs);
|
|
79
131
|
return readScratchpadProjection(db);
|
|
80
132
|
}
|
|
81
133
|
export function submitScratchpadProjection(db, input) {
|
|
@@ -105,6 +157,7 @@ export function submitScratchpadProjection(db, input) {
|
|
|
105
157
|
task_changes_json = excluded.task_changes_json,
|
|
106
158
|
submitted_at = excluded.submitted_at
|
|
107
159
|
`).run(input.workflow_ref, input.activity_ref, scratchpad.topic, scratchpad.background_summary, stringifyJson(scratchpad.current_consensus), stringifyJson(scratchpad.open_questions), stringifyJson(scratchpad.task_changes), submittedAt);
|
|
160
|
+
copyCurrentScratchpadSourcesToReceipt(db, input.workflow_ref);
|
|
108
161
|
db.prepare(`
|
|
109
162
|
UPDATE scratchpad
|
|
110
163
|
SET
|
|
@@ -168,4 +221,14 @@ export function readScratchpadProjection(db) {
|
|
|
168
221
|
}
|
|
169
222
|
return scratchpad;
|
|
170
223
|
}
|
|
224
|
+
export function readScratchpadReceiptSourceRefs(db, workflowRef) {
|
|
225
|
+
return db
|
|
226
|
+
.prepare(`
|
|
227
|
+
SELECT message_id, source_scope, created_at
|
|
228
|
+
FROM scratchpad_receipt_sources
|
|
229
|
+
WHERE workflow_ref = ?
|
|
230
|
+
ORDER BY created_at ASC, message_id ASC
|
|
231
|
+
`)
|
|
232
|
+
.all(workflowRef);
|
|
233
|
+
}
|
|
171
234
|
//# sourceMappingURL=scratchpad.js.map
|
|
@@ -35,6 +35,11 @@ export type ScratchpadReceiptRow = {
|
|
|
35
35
|
task_changes_json: string;
|
|
36
36
|
submitted_at: string;
|
|
37
37
|
};
|
|
38
|
+
export type ScratchpadSourceRefRow = {
|
|
39
|
+
message_id: MessageId;
|
|
40
|
+
source_scope: "main_chat" | "clarification_round";
|
|
41
|
+
created_at: string;
|
|
42
|
+
};
|
|
38
43
|
export type ScratchpadSourceStateRow = {
|
|
39
44
|
main_chat_cursor_created_at: string | null;
|
|
40
45
|
main_chat_cursor_message_id: string | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RunLineage } from "@tutti/shared/domain";
|
|
2
2
|
import type { AccountAvatarProjection } from "@tutti/shared/domain";
|
|
3
|
-
import type { ActivityRef, ClarificationRoundRef, TaskId, TaskModuleId, WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
3
|
+
import type { ActivityRef, ClarificationRoundRef, MessageId, TaskId, TaskModuleId, WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
4
4
|
import type { ClarificationRequestPayload, ClarificationRoundProjection, ClarificationSuccessorRef, ClarificationThreadProjection, MessageProjection, ReadStateScope, ReadStateSummaryProjection, RecoverySummaryProjection, RunResultProjection, ScratchpadProjection, TaskContractProjection, TaskDetailProjection, TaskDetailResultProjection, TaskProjection, WorklistProjection } from "@tutti/shared/schemas/api";
|
|
5
5
|
export type MessageAuthorInput = {
|
|
6
6
|
kind: "human" | "system" | "agent";
|
|
@@ -53,9 +53,15 @@ export type ScratchpadSnapshotInput = {
|
|
|
53
53
|
current_consensus: string[];
|
|
54
54
|
open_questions: string[];
|
|
55
55
|
task_changes: string[];
|
|
56
|
+
source_refs?: ScratchpadSourceRefInput[];
|
|
56
57
|
updated_by_activity_ref?: ActivityRef;
|
|
57
58
|
now?: () => Date;
|
|
58
59
|
};
|
|
60
|
+
export type ScratchpadSourceRefInput = {
|
|
61
|
+
message_id: MessageId;
|
|
62
|
+
source_scope: "main_chat" | "clarification_round";
|
|
63
|
+
created_at: string;
|
|
64
|
+
};
|
|
59
65
|
export type SubmitScratchpadInput = {
|
|
60
66
|
workflow_ref: WorkflowInvocationRef;
|
|
61
67
|
activity_ref: ActivityRef;
|
|
@@ -286,6 +292,7 @@ export type ReadMessageWindowOptions = {
|
|
|
286
292
|
anchor?: "latest" | "start";
|
|
287
293
|
before?: string;
|
|
288
294
|
after?: string;
|
|
295
|
+
around?: string;
|
|
289
296
|
};
|
|
290
297
|
export type ReadMainChatMessagesAfterOptions = {
|
|
291
298
|
after_created_at: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createWorkflowInvocationRef, type ActivityRef } from "@tutti/shared/ids";
|
|
2
2
|
import type { RefreshScratchpadDisposition, RefreshScratchpadResult, ProcedureLane } from "@tutti/shared/schemas/api";
|
|
3
3
|
import type { ScratchpadSourceCursorUpdate } from "../collaboration-state/scratchpad-source-state.js";
|
|
4
|
+
import type { ScratchpadSourceRefInput } from "../collaboration-state/types.js";
|
|
4
5
|
import type { ProcedureEngine, ProcedureEngineState } from "../procedure-engine/index.js";
|
|
5
6
|
import type { HostProjectStore } from "../store/index.js";
|
|
6
7
|
import type { WorkspaceEventBus } from "../server-shell/http/workspace-events.js";
|
|
@@ -12,6 +13,7 @@ type ScratchpadProjectContext = {
|
|
|
12
13
|
export type ScratchpadSourceBatch = {
|
|
13
14
|
workflow_input: Parameters<ProcedureWorkflowRunner["runScratchpadRefresh"]>[0];
|
|
14
15
|
cursor_update: ScratchpadSourceCursorUpdate;
|
|
16
|
+
source_refs: ScratchpadSourceRefInput[];
|
|
15
17
|
source_message_count: number;
|
|
16
18
|
};
|
|
17
19
|
export declare function readControlPlaneScratchpadSourceBatch(store: HostProjectStore, options?: {
|
|
@@ -96,6 +96,10 @@ export function readControlPlaneScratchpadSourceBatch(store, options = {}) {
|
|
|
96
96
|
...newMainChatSourceMessages,
|
|
97
97
|
...clarificationSourceMessages,
|
|
98
98
|
]);
|
|
99
|
+
const sourceRefMessages = sortScratchpadSourceMessages([
|
|
100
|
+
...(isInitialMainChatRefresh ? recentMessages : []),
|
|
101
|
+
...sourceMessages,
|
|
102
|
+
]);
|
|
99
103
|
const latestMainChatSource = mainChatSourceMessages.at(-1);
|
|
100
104
|
const latestClarificationRound = clarificationRounds.at(-1);
|
|
101
105
|
const cursorUpdate = {};
|
|
@@ -124,6 +128,11 @@ export function readControlPlaneScratchpadSourceBatch(store, options = {}) {
|
|
|
124
128
|
new_messages: compactScratchpadSourceMessages(sourceMessages),
|
|
125
129
|
},
|
|
126
130
|
cursor_update: cursorUpdate,
|
|
131
|
+
source_refs: sourceRefMessages.map((message) => ({
|
|
132
|
+
message_id: message.id,
|
|
133
|
+
source_scope: message.scope.kind,
|
|
134
|
+
created_at: message.created_at,
|
|
135
|
+
})),
|
|
127
136
|
source_message_count: sourceMessages.length + (isInitialMainChatRefresh ? recentMessages.length : 0),
|
|
128
137
|
};
|
|
129
138
|
}
|
|
@@ -153,6 +162,7 @@ export async function runControlPlaneScratchpadRefreshProcedure(options) {
|
|
|
153
162
|
workflowRef: options.workflowRef,
|
|
154
163
|
activityRef: options.activityRef,
|
|
155
164
|
cursorUpdate: options.sourceBatch.cursor_update,
|
|
165
|
+
sourceRefs: options.sourceBatch.source_refs,
|
|
156
166
|
now: options.now,
|
|
157
167
|
});
|
|
158
168
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ActivityRef, WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
2
2
|
import type { ScratchpadSourceCursorUpdate } from "../collaboration-state/scratchpad-source-state.js";
|
|
3
|
+
import type { ScratchpadSourceRefInput } from "../collaboration-state/types.js";
|
|
3
4
|
import type { WorkspaceEventBus } from "../server-shell/http/workspace-events.js";
|
|
4
5
|
import type { HostProjectStore } from "../store/index.js";
|
|
5
6
|
import type { ScratchpadRefreshWorkflowOutput } from "./workflows/index.js";
|
|
@@ -10,6 +11,7 @@ export declare function applyScratchpadRefreshOutput(input: {
|
|
|
10
11
|
workflowRef: WorkflowInvocationRef;
|
|
11
12
|
activityRef: ActivityRef;
|
|
12
13
|
cursorUpdate: ScratchpadSourceCursorUpdate;
|
|
14
|
+
sourceRefs: ScratchpadSourceRefInput[];
|
|
13
15
|
now: () => Date;
|
|
14
16
|
}): {
|
|
15
17
|
kind: "needs_human";
|
|
@@ -31,6 +31,7 @@ export function applyScratchpadRefreshOutput(input) {
|
|
|
31
31
|
current_consensus: input.output.scratchpad_snapshot.current_consensus,
|
|
32
32
|
open_questions: input.output.scratchpad_snapshot.open_questions,
|
|
33
33
|
task_changes: input.output.scratchpad_snapshot.task_changes,
|
|
34
|
+
source_refs: input.sourceRefs,
|
|
34
35
|
updated_by_activity_ref: input.activityRef,
|
|
35
36
|
now: input.now,
|
|
36
37
|
});
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { type ActivityRef, type EventRef, type TaskId, type WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
2
|
-
import type { ProjectTimelineItem } from "@tutti/shared/schemas/api";
|
|
3
2
|
import type { SqliteDatabase } from "../store/index.js";
|
|
4
3
|
export type ProjectTimelineEventKind = "context_sync" | "reference_summary" | "promotion_reconcile";
|
|
4
|
+
export type ProjectTimelineEventStatus = "completed" | "failed";
|
|
5
|
+
export type ProjectTimelineEventItem = {
|
|
6
|
+
id: string;
|
|
7
|
+
kind: "procedure" | "promotion";
|
|
8
|
+
occurred_at: string;
|
|
9
|
+
title: string;
|
|
10
|
+
status: ProjectTimelineEventStatus;
|
|
11
|
+
summary?: string;
|
|
12
|
+
activity_ref?: ActivityRef;
|
|
13
|
+
workflow_ref?: WorkflowInvocationRef;
|
|
14
|
+
task_id?: TaskId;
|
|
15
|
+
commit_oid?: string;
|
|
16
|
+
commit_short_oid?: string;
|
|
17
|
+
meta?: string[];
|
|
18
|
+
};
|
|
5
19
|
export type ProjectTimelineEventInput = {
|
|
6
20
|
event_kind: ProjectTimelineEventKind;
|
|
7
|
-
status:
|
|
21
|
+
status: ProjectTimelineEventStatus;
|
|
8
22
|
summary?: string;
|
|
9
23
|
activity_ref?: ActivityRef;
|
|
10
24
|
workflow_ref?: WorkflowInvocationRef;
|
|
@@ -16,5 +30,5 @@ export type ProjectTimelineEventInput = {
|
|
|
16
30
|
export declare function recordProjectTimelineEvent(db: SqliteDatabase, input: ProjectTimelineEventInput): EventRef;
|
|
17
31
|
export declare function readProjectTimelineEventItems(db: SqliteDatabase, options?: {
|
|
18
32
|
limit?: number;
|
|
19
|
-
}):
|
|
33
|
+
}): ProjectTimelineEventItem[];
|
|
20
34
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -10,28 +10,11 @@ import { HOST_SERVER_VERSION, startForegroundHostServer, } from "./host-server-r
|
|
|
10
10
|
import { deleteMachineRuntimeEndpoint, readHostRegistrationSecret, readMachineProjectBinding, readMachineRuntimeEndpoint, } from "./machine-local.js";
|
|
11
11
|
import { prepareLaunchProject, resolveLaunchLocalContext, } from "./launch.js";
|
|
12
12
|
import { registerHostWithRelay, relayErrorToLaunchError, } from "./relay-registration.js";
|
|
13
|
-
import { formatJoinLinkValidity } from "./terminal-qr.js";
|
|
13
|
+
import { formatJoinLinkValidity, formatTerminalLink } from "./terminal-qr.js";
|
|
14
14
|
export { createRuntimeEndpointProbe } from "./host-runtime-endpoint.js";
|
|
15
15
|
const DEFAULT_SHUTDOWN_WAIT_MS = 2_000;
|
|
16
|
-
const OSC8_START = "\u001B]8;;";
|
|
17
|
-
const OSC8_END = "\u001B]8;;\u001B\\";
|
|
18
|
-
function isTerminalSafeHttpUrl(value) {
|
|
19
|
-
if (!value.startsWith("http://") && !value.startsWith("https://")) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
return Array.from(value).every((character) => {
|
|
23
|
-
const codePoint = character.codePointAt(0);
|
|
24
|
-
return codePoint !== undefined && codePoint > 0x1f && codePoint !== 0x7f;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function terminalLink(value, options) {
|
|
28
|
-
if (options.hyperlinks !== true || !isTerminalSafeHttpUrl(value)) {
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
|
-
return `${OSC8_START}${value}\u001B\\${value}${OSC8_END}`;
|
|
32
|
-
}
|
|
33
16
|
function urlLine(label, value, options) {
|
|
34
|
-
return `${label}: ${
|
|
17
|
+
return `${label}: ${formatTerminalLink(value, options)}`;
|
|
35
18
|
}
|
|
36
19
|
function endpointWithoutToken(endpoint) {
|
|
37
20
|
return {
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { LaunchConfirmationRequest } from "./git-bootstrap.js";
|
|
2
2
|
export declare function confirmFromTty(request: LaunchConfirmationRequest): Promise<boolean>;
|
|
3
|
+
export declare function renderCompletionPage(options: {
|
|
4
|
+
joinUrl: string;
|
|
5
|
+
joinTokenExpiresAt?: string;
|
|
6
|
+
joinTokenReusable?: boolean;
|
|
7
|
+
projectId: string;
|
|
8
|
+
workspaceRoot: string;
|
|
9
|
+
relayUrl: string;
|
|
10
|
+
branch?: string;
|
|
11
|
+
tty?: boolean;
|
|
12
|
+
hyperlinks?: boolean;
|
|
13
|
+
}): string;
|
|
3
14
|
export declare function runForegroundLaunchCommand(options: {
|
|
4
15
|
target?: string;
|
|
5
16
|
yes: boolean;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { basename } from "node:path";
|
|
2
3
|
import { formatLaunchLifecycleResult, startLaunchProject, waitForForegroundHostShutdown } from "./host-lifecycle.js";
|
|
3
4
|
import { prepareLaunchProject } from "./launch.js";
|
|
4
5
|
import { spawnDetachedHost, waitForManagedHostReady } from "./managed-host.js";
|
|
5
6
|
import { resolveLaunchWorkspacePath } from "./project-resolver.js";
|
|
6
|
-
import { formatJoinLinkValidity, renderTerminalQr } from "./terminal-qr.js";
|
|
7
|
+
import { formatJoinLinkValidity, formatTerminalLink, renderTerminalQr } from "./terminal-qr.js";
|
|
7
8
|
import { renderTuttiTerminalLogo } from "./terminal-logo.js";
|
|
8
9
|
import { runProviderSetupTui } from "./provider-tui.js";
|
|
9
10
|
import { LaunchError } from "./errors.js";
|
|
@@ -39,13 +40,39 @@ async function waitForEnter() {
|
|
|
39
40
|
readline.close();
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
43
|
+
function formatProjectLabel(workspaceRoot, projectId) {
|
|
44
|
+
return basename(workspaceRoot) || projectId;
|
|
45
|
+
}
|
|
46
|
+
function borderedBlock(lines) {
|
|
47
|
+
const width = Math.max(...lines.map((line) => line.length));
|
|
48
|
+
const top = `╭${"─".repeat(width + 2)}╮`;
|
|
49
|
+
const bottom = `╰${"─".repeat(width + 2)}╯`;
|
|
50
|
+
const body = lines.map((line) => `│ ${line.padEnd(width, " ")} │`);
|
|
51
|
+
return [top, ...body, bottom].join("\n");
|
|
52
|
+
}
|
|
53
|
+
export function renderCompletionPage(options) {
|
|
54
|
+
const isTty = options.tty ?? process.stdout.isTTY === true;
|
|
55
|
+
const projectLabel = formatProjectLabel(options.workspaceRoot, options.projectId);
|
|
56
|
+
const joinUrl = formatTerminalLink(options.joinUrl, { hyperlinks: options.hyperlinks === true });
|
|
57
|
+
const summaryLines = [
|
|
58
|
+
"Tutti is hosting this project.",
|
|
59
|
+
`Project: ${projectLabel}`,
|
|
60
|
+
"Status: background host ready",
|
|
61
|
+
`Branch: ${options.branch ?? "tutti/mainline"}`,
|
|
62
|
+
`Relay: ${options.relayUrl}`,
|
|
63
|
+
];
|
|
64
|
+
const nextSteps = [
|
|
65
|
+
"Next:",
|
|
66
|
+
" Open the join URL or scan the QR code.",
|
|
67
|
+
" `tutti invite` rotates a fresh link.",
|
|
68
|
+
" `tutti ps` shows running hosts.",
|
|
69
|
+
" `tutti stop` stops this host.",
|
|
70
|
+
];
|
|
44
71
|
return [
|
|
45
72
|
...(isTty ? [CLEAR, renderTuttiTerminalLogo({ tty: true }), ""] : []),
|
|
46
|
-
|
|
73
|
+
isTty ? borderedBlock(summaryLines) : summaryLines.join("\n"),
|
|
47
74
|
"",
|
|
48
|
-
`Join URL: ${
|
|
75
|
+
`Join URL: ${joinUrl}`,
|
|
49
76
|
formatJoinLinkValidity({
|
|
50
77
|
...(options.joinTokenExpiresAt === undefined
|
|
51
78
|
? {}
|
|
@@ -55,9 +82,12 @@ function renderCompletionPage(options) {
|
|
|
55
82
|
: { reusable: options.joinTokenReusable }),
|
|
56
83
|
}),
|
|
57
84
|
"",
|
|
85
|
+
"QR code:",
|
|
58
86
|
renderTerminalQr(options.joinUrl),
|
|
59
87
|
"",
|
|
60
|
-
|
|
88
|
+
...nextSteps,
|
|
89
|
+
"",
|
|
90
|
+
isTty ? "[Enter] close this view. The host keeps running." : "The host keeps running.",
|
|
61
91
|
].join("\n");
|
|
62
92
|
}
|
|
63
93
|
async function ensureProviderConfigured(preparation) {
|
|
@@ -118,6 +148,12 @@ export async function runBackgroundLaunchCommand(options) {
|
|
|
118
148
|
}
|
|
119
149
|
process.stdout.write(`${renderCompletionPage({
|
|
120
150
|
joinUrl: ready.join_url,
|
|
151
|
+
projectId: preparation.project_id,
|
|
152
|
+
workspaceRoot: preparation.workspace_root,
|
|
153
|
+
relayUrl: preparation.relay_url,
|
|
154
|
+
branch: preparation.branch,
|
|
155
|
+
tty: process.stdout.isTTY === true,
|
|
156
|
+
hyperlinks: process.stdout.isTTY === true,
|
|
121
157
|
...(ready.join_token_expires_at === undefined
|
|
122
158
|
? {}
|
|
123
159
|
: { joinTokenExpiresAt: ready.join_token_expires_at }),
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
|
+
const OSC8_START = "\u001B]8;;";
|
|
4
|
+
const OSC8_END = "\u001B]8;;\u001B\\";
|
|
5
|
+
function isTerminalSafeHttpUrl(value) {
|
|
6
|
+
if (!value.startsWith("http://") && !value.startsWith("https://")) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return Array.from(value).every((character) => {
|
|
10
|
+
const codePoint = character.codePointAt(0);
|
|
11
|
+
return codePoint !== undefined && codePoint > 0x1f && codePoint !== 0x7f;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function formatTerminalLink(value, options = {}) {
|
|
15
|
+
if (options.hyperlinks !== true || !isTerminalSafeHttpUrl(value)) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
return `${OSC8_START}${value}\u001B\\${value}${OSC8_END}`;
|
|
19
|
+
}
|
|
3
20
|
export function renderTerminalQr(input) {
|
|
4
21
|
const qrcode = require("qrcode-terminal");
|
|
5
22
|
let output = "";
|
|
@@ -8,6 +8,7 @@ export declare const HOST_PROJECT_COLLABORATION_OPENAPI_ROUTES: ({
|
|
|
8
8
|
anchor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"latest">, import("@sinclair/typebox").TLiteral<"start">]>>;
|
|
9
9
|
before: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
10
10
|
after: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
11
|
+
around: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
11
12
|
}>;
|
|
12
13
|
responses: {
|
|
13
14
|
200: {
|
|
@@ -67,7 +67,7 @@ export declare const HOST_PROJECT_TIMELINE_OPENAPI_ROUTES: {
|
|
|
67
67
|
}>;
|
|
68
68
|
items: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
69
69
|
id: import("@sinclair/typebox").TString;
|
|
70
|
-
kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"
|
|
70
|
+
kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"task_accepted">, import("@sinclair/typebox").TLiteral<"task_update">, import("@sinclair/typebox").TLiteral<"checkpoint">]>;
|
|
71
71
|
occurred_at: import("@sinclair/typebox").TString;
|
|
72
72
|
title: import("@sinclair/typebox").TString;
|
|
73
73
|
summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -75,9 +75,10 @@ export declare const HOST_PROJECT_TIMELINE_OPENAPI_ROUTES: {
|
|
|
75
75
|
task_title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
76
76
|
activity_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
77
77
|
workflow_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
status: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"
|
|
78
|
+
run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
79
|
+
message_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
80
|
+
status: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"completed">, import("@sinclair/typebox").TLiteral<"failed">, import("@sinclair/typebox").TLiteral<"needs_human">]>>;
|
|
81
|
+
update_state: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"needs_input">, import("@sinclair/typebox").TLiteral<"completed">, import("@sinclair/typebox").TLiteral<"failed">]>>;
|
|
81
82
|
token_usage: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
82
83
|
input_tokens: import("@sinclair/typebox").TInteger;
|
|
83
84
|
cached_input_tokens: import("@sinclair/typebox").TInteger;
|
|
@@ -106,7 +107,95 @@ export declare const HOST_PROJECT_TIMELINE_OPENAPI_ROUTES: {
|
|
|
106
107
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
107
108
|
event_count: import("@sinclair/typebox").TInteger;
|
|
108
109
|
}>>>;
|
|
109
|
-
|
|
110
|
+
trace_card: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
111
|
+
tone: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"neutral">, import("@sinclair/typebox").TLiteral<"success">, import("@sinclair/typebox").TLiteral<"warning">, import("@sinclair/typebox").TLiteral<"error">]>;
|
|
112
|
+
summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
113
|
+
origin: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
114
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
115
|
+
summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
116
|
+
snippets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
117
|
+
message_id: import("@sinclair/typebox").TString;
|
|
118
|
+
author: import("@sinclair/typebox").TString;
|
|
119
|
+
body: import("@sinclair/typebox").TString;
|
|
120
|
+
created_at: import("@sinclair/typebox").TString;
|
|
121
|
+
}>>>;
|
|
122
|
+
source_count: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
123
|
+
unavailable_reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
124
|
+
}>>;
|
|
125
|
+
decisions: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
126
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
127
|
+
summary: import("@sinclair/typebox").TString;
|
|
128
|
+
source: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"scratchpad">, import("@sinclair/typebox").TLiteral<"clarification">, import("@sinclair/typebox").TLiteral<"contract">]>>;
|
|
129
|
+
}>>>;
|
|
130
|
+
clarification: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
131
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
132
|
+
summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
133
|
+
request: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
134
|
+
status: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"active">, import("@sinclair/typebox").TLiteral<"resolved">]>>;
|
|
135
|
+
answer_count: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
136
|
+
answers: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
137
|
+
message_id: import("@sinclair/typebox").TString;
|
|
138
|
+
author: import("@sinclair/typebox").TString;
|
|
139
|
+
body: import("@sinclair/typebox").TString;
|
|
140
|
+
created_at: import("@sinclair/typebox").TString;
|
|
141
|
+
}>>>;
|
|
142
|
+
}>>;
|
|
143
|
+
contract: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
144
|
+
goal: import("@sinclair/typebox").TString;
|
|
145
|
+
scope: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
|
|
146
|
+
truncated: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
147
|
+
}>>;
|
|
148
|
+
result: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
149
|
+
summary: import("@sinclair/typebox").TString;
|
|
150
|
+
error_code: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
151
|
+
}>>;
|
|
152
|
+
changes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
153
|
+
items: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
154
|
+
status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"added">, import("@sinclair/typebox").TLiteral<"modified">, import("@sinclair/typebox").TLiteral<"deleted">, import("@sinclair/typebox").TLiteral<"renamed">, import("@sinclair/typebox").TLiteral<"unknown">]>;
|
|
155
|
+
path: import("@sinclair/typebox").TString;
|
|
156
|
+
previous_path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
157
|
+
}>>;
|
|
158
|
+
total_count: import("@sinclair/typebox").TInteger;
|
|
159
|
+
truncated: import("@sinclair/typebox").TBoolean;
|
|
160
|
+
}>>;
|
|
161
|
+
verification: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
162
|
+
checks: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"passed">, import("@sinclair/typebox").TLiteral<"failed">, import("@sinclair/typebox").TLiteral<"skipped">]>;
|
|
163
|
+
skip_reason_code: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
164
|
+
skip_reason_summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
165
|
+
}>>;
|
|
166
|
+
promotion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
167
|
+
status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"promoted">, import("@sinclair/typebox").TLiteral<"not_promoted">, import("@sinclair/typebox").TLiteral<"not_attempted">]>;
|
|
168
|
+
commit_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
169
|
+
commit_short_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
170
|
+
summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
171
|
+
reason_code: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
172
|
+
}>>;
|
|
173
|
+
checkpoint: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
174
|
+
counters: import("@sinclair/typebox").TObject<{
|
|
175
|
+
completed: import("@sinclair/typebox").TInteger;
|
|
176
|
+
failed: import("@sinclair/typebox").TInteger;
|
|
177
|
+
remaining: import("@sinclair/typebox").TInteger;
|
|
178
|
+
}>;
|
|
179
|
+
items: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
180
|
+
task_id: import("@sinclair/typebox").TString;
|
|
181
|
+
title: import("@sinclair/typebox").TString;
|
|
182
|
+
status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"done">, import("@sinclair/typebox").TLiteral<"failed">]>;
|
|
183
|
+
summary: import("@sinclair/typebox").TString;
|
|
184
|
+
}>>;
|
|
185
|
+
generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
186
|
+
path: import("@sinclair/typebox").TString;
|
|
187
|
+
name: import("@sinclair/typebox").TString;
|
|
188
|
+
}>>>;
|
|
189
|
+
truncated: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
190
|
+
}>>;
|
|
191
|
+
links: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
192
|
+
kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"worklist_task">, import("@sinclair/typebox").TLiteral<"chat_message">, import("@sinclair/typebox").TLiteral<"reference_file">, import("@sinclair/typebox").TLiteral<"repo_path">]>;
|
|
193
|
+
label: import("@sinclair/typebox").TString;
|
|
194
|
+
task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
195
|
+
message_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
196
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
197
|
+
}>>;
|
|
198
|
+
}>>;
|
|
110
199
|
}>>;
|
|
111
200
|
}>;
|
|
112
201
|
};
|