@lovelybunch/api 1.0.75-alpha.8 → 1.0.75
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/lib/jobs/job-runner.js +10 -2
- package/dist/lib/jobs/job-scheduler.js +21 -0
- package/dist/lib/mail/mail-runner.d.ts +51 -0
- package/dist/lib/mail/mail-runner.js +342 -0
- package/dist/lib/slack/slack-service.d.ts +2 -0
- package/dist/lib/slack/slack-service.js +3 -0
- package/dist/lib/storage/file-storage.d.ts +16 -16
- package/dist/lib/storage/file-storage.js +59 -64
- package/dist/lib/terminal/terminal-manager.d.ts +3 -5
- package/dist/lib/terminal/terminal-manager.js +10 -61
- package/dist/routes/api/v1/ai/route.js +361 -20
- package/dist/routes/api/v1/chats/[id]/index.js +2 -1
- package/dist/routes/api/v1/chats/[id]/route.d.ts +7 -0
- package/dist/routes/api/v1/chats/[id]/route.js +30 -1
- package/dist/routes/api/v1/context/index.js +0 -2
- package/dist/routes/api/v1/git/index.js +23 -0
- package/dist/routes/api/v1/knowledge/[filename]/index.d.ts +1 -0
- package/dist/routes/api/v1/knowledge/[filename]/index.js +1 -0
- package/dist/routes/api/v1/knowledge/[filename]/route.d.ts +3 -0
- package/dist/routes/api/v1/knowledge/[filename]/route.js +254 -0
- package/dist/routes/api/v1/knowledge/index.d.ts +1 -0
- package/dist/routes/api/v1/knowledge/index.js +1 -0
- package/dist/routes/api/v1/knowledge/route.d.ts +3 -0
- package/dist/routes/api/v1/knowledge/route.js +176 -0
- package/dist/routes/api/v1/mail/index.d.ts +3 -0
- package/dist/routes/api/v1/mail/index.js +23 -0
- package/dist/routes/api/v1/mail/route.d.ts +294 -0
- package/dist/routes/api/v1/mail/route.js +344 -0
- package/dist/routes/api/v1/mcp/index.js +109 -34
- package/dist/routes/api/v1/slack/index.d.ts +3 -0
- package/dist/routes/api/v1/slack/index.js +15 -0
- package/dist/routes/api/v1/slack/route.d.ts +124 -0
- package/dist/routes/api/v1/slack/route.js +192 -0
- package/dist/routes/api/v1/tasks/[id]/route.d.ts +117 -0
- package/dist/routes/api/v1/tasks/[id]/route.js +166 -0
- package/dist/routes/api/v1/tasks/index.d.ts +3 -0
- package/dist/routes/api/v1/tasks/index.js +10 -0
- package/dist/routes/api/v1/tasks/route.d.ts +96 -0
- package/dist/routes/api/v1/tasks/route.js +136 -0
- package/dist/routes/api/v1/terminal/[proposalId]/create/route.js +2 -2
- package/dist/routes/api/v1/terminal/[taskId]/create/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/route.js +27 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/route.js +21 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/route.js +21 -0
- package/dist/routes/api/v1/terminal/sessions/route.js +4 -4
- package/dist/server-with-static.js +14 -8
- package/dist/server.js +14 -8
- package/package.json +4 -4
- package/static/assets/{ActivityPage-DSSML9J-.js → ActivityPage-k4I7Q53O.js} +1 -1
- package/static/assets/ApiKeysSettingsPage-B1YvVdmg.js +2 -0
- package/static/assets/{ArchitectureEditPage-CIjqkpMz.js → ArchitectureEditPage-CpowsIx2.js} +1 -1
- package/static/assets/{ArchitecturePage-Db__w054.js → ArchitecturePage-DYxC_aMR.js} +1 -1
- package/static/assets/{AuthSettingsPage-Bpooi8Z0.js → AuthSettingsPage-DtSo78Y_.js} +2 -2
- package/static/assets/{CallbackPage-BGLKeyjv.js → CallbackPage-bROCGapx.js} +1 -1
- package/static/assets/CodePage-CPCj64rX.js +2 -0
- package/static/assets/{CollapsibleSection-B6RO5o5R.js → CollapsibleSection-M5cXbl92.js} +1 -1
- package/static/assets/DashboardPage-B9BZZfw6.js +51 -0
- package/static/assets/{GitPage-DxjLaRWe.js → GitPage-BiDtdSK1.js} +2 -2
- package/static/assets/GitSettingsPage-THm6wDjs.js +6 -0
- package/static/assets/IdentityPage-BC16skg6.js +6 -0
- package/static/assets/{ImplementationStepsEditor-DWjDyZzP.js → ImplementationStepsEditor-HliLQav5.js} +2 -2
- package/static/assets/IntegrationsSettingsPage-CC_VKIQa.js +1 -0
- package/static/assets/JobDetailPage-z1QQYvmU.js +1 -0
- package/static/assets/KnowledgeDetailPage-DzHXBS7Q.js +1 -0
- package/static/assets/KnowledgeEditPage-BwGnUH_m.js +1 -0
- package/static/assets/KnowledgePage-CGIVMS02.js +3 -0
- package/static/assets/{LoginPage-DptfKsWo.js → LoginPage-VQ3lcfLV.js} +1 -1
- package/static/assets/MailInboxPage-DiZKqwdU.js +1 -0
- package/static/assets/MailProcessingModal-DIeSQBoR.js +6 -0
- package/static/assets/MailReadPage-C8AACmZQ.js +1 -0
- package/static/assets/MailSentPage-C_5yFly_.js +1 -0
- package/static/assets/McpSettingsPage-i9YHcu1s.js +1 -0
- package/static/assets/NewKnowledgePage-BnVY7WUD.js +9 -0
- package/static/assets/{NewSkillPage-Cwy2MSr9.js → NewSkillPage-DwniHD6D.js} +1 -1
- package/static/assets/NewTaskPage-F5UX2WMc.js +90 -0
- package/static/assets/NotFoundPage-BbSZX_4L.js +6 -0
- package/static/assets/NotificationsSettingsPage-C8kjcift.js +1 -0
- package/static/assets/ProjectEditPage-DUUlIEqI.js +11 -0
- package/static/assets/{ProjectPage-DgUr4bVU.js → ProjectPage-Unz9PQpA.js} +1 -1
- package/static/assets/PromptsSettingsPage-DVpIuRKI.js +1 -0
- package/static/assets/ResourceDetailPage-DqHZ2KYD.js +1 -0
- package/static/assets/ResourcesPage-BP5tuAi-.js +41 -0
- package/static/assets/RoleEditPage-BgKu8S0-.js +13 -0
- package/static/assets/{RolePage-Sc-GFiL2.js → RolePage-Fed52Ov5.js} +1 -1
- package/static/assets/{RulesSettingsPage-DdMCzh9j.js → RulesSettingsPage-BQ2O0u66.js} +2 -2
- package/static/assets/SchedulePage-jkxjuzBx.js +4 -0
- package/static/assets/SkillDetailPage-k3Q2-NFd.js +1 -0
- package/static/assets/{SkillEditPage-BDd2CtAS.js → SkillEditPage-urF4snjo.js} +1 -1
- package/static/assets/SkillsPage-DlWDhEjR.js +8 -0
- package/static/assets/{SkillsSettingsPage-1N0JQOYc.js → SkillsSettingsPage-BViFgckG.js} +1 -1
- package/static/assets/SourceInput-CAFKTHw-.js +1 -0
- package/static/assets/{TagInput-D_SdcypZ.js → TagInput-C6lI-ePr.js} +1 -1
- package/static/assets/TaskDetailPage-DpbRHnW_.js +16 -0
- package/static/assets/TaskEditPage-DssRbW0h.js +1 -0
- package/static/assets/TasksPage-CD_eo0Bj.js +17 -0
- package/static/assets/TerminalPage-BG_wlccr.js +1 -0
- package/static/assets/TerminalSessionPage-CsK-LznK.js +8 -0
- package/static/assets/UserPreferencesPage-CWUq3efu.js +1 -0
- package/static/assets/UserSettingsPage-CduI_MGS.js +1 -0
- package/static/assets/UtilitiesPage-BAxokhLh.js +1 -0
- package/static/assets/{alert-BD5jo3SI.js → alert-BXsc6_qu.js} +1 -1
- package/static/assets/{arrow-down-BxcoVp6S.js → arrow-down-DmW_3gE8.js} +1 -1
- package/static/assets/{arrow-left-CdM_IPng.js → arrow-left-1S-835kP.js} +1 -1
- package/static/assets/{arrow-up-BOJ6ob9X.js → arrow-up-BYism_o1.js} +1 -1
- package/static/assets/arrow-up-down-Dw3J0a4i.js +6 -0
- package/static/assets/{badge-DEiQk9C9.js → badge-BUEY53dV.js} +1 -1
- package/static/assets/{browser-modal-Dp1eMxt6.js → browser-modal-DCNdI4NT.js} +2 -2
- package/static/assets/{card-BCFxXzRk.js → card-BcPlIAH5.js} +1 -1
- package/static/assets/{chevron-left-C25izNzZ.js → chevron-left-FMmNe7yP.js} +1 -1
- package/static/assets/{plus-iamYJu5V.js → chevron-up-CqM3won3.js} +2 -2
- package/static/assets/{chevrons-up-DqbWMOjv.js → chevrons-up-DTvCkIHc.js} +1 -1
- package/static/assets/{circle-alert-CMRMPnbY.js → circle-alert-dseM-Ib7.js} +1 -1
- package/static/assets/{circle-check-big-NI18oHuP.js → circle-check-big-jKg34xC-.js} +1 -1
- package/static/assets/{circle-check-D5wZZPvj.js → circle-check-eyo6pBP1.js} +1 -1
- package/static/assets/{circle-play-BhVU869u.js → circle-play-BrY_lNiH.js} +1 -1
- package/static/assets/{circle-x-BXDB-G_q.js → circle-x-uqmzEce1.js} +1 -1
- package/static/assets/{clipboard-DC2xmNVx.js → clipboard-tzPFoieb.js} +1 -1
- package/static/assets/{clock-CeCp7Pz1.js → clock-Bjc06QBM.js} +1 -1
- package/static/assets/code-DrYqPukx.js +6 -0
- package/static/assets/{download-ZF_XbTIA.js → download-Bg__QCLT.js} +1 -1
- package/static/assets/{external-link-CYBz87-P.js → external-link-CNDy2UUo.js} +1 -1
- package/static/assets/{eye-BT8MAvKY.js → eye-DLFBnC8t.js} +1 -1
- package/static/assets/{folder-git-2-BE9AIPnj.js → folder-git-2-DUqd0WRi.js} +1 -1
- package/static/assets/index-CHdBxVyk.css +2 -0
- package/static/assets/index-DFcWlnzl.js +487 -0
- package/static/assets/{info-DunFSp-x.js → info-D6jxZC5X.js} +1 -1
- package/static/assets/kiro-CX1mOsRO.js +17 -0
- package/static/assets/{label-vYhfrPMD.js → label-DBuh-ke5.js} +1 -1
- package/static/assets/{markdown-editor-BzZ8tCto.js → markdown-editor-B4YNQFT2.js} +1 -1
- package/static/assets/message-square-B5RWz_ff.js +6 -0
- package/static/assets/paperclip-4A_3MaPx.js +6 -0
- package/static/assets/{pause-BHonpdnw.js → pause-BzhKXHtR.js} +1 -1
- package/static/assets/{play-CCo7tau2.js → play-CHIf-Rcz.js} +1 -1
- package/static/assets/{radio-group-Db-pBuyW.js → radio-group-C1ct-VsJ.js} +1 -1
- package/static/assets/{refresh-cw-Bg7vQzOw.js → refresh-cw-B3OwrDUf.js} +1 -1
- package/static/assets/{search-CH2zaibZ.js → search-Cq1ksEdp.js} +1 -1
- package/static/assets/select-44mcS2_G.js +1 -0
- package/static/assets/{status-utils-BDOyevaX.js → status-utils-CDkPeVfP.js} +1 -1
- package/static/assets/{switch-CH-VOgPo.js → switch-CIwjYvCt.js} +1 -1
- package/static/assets/{tabs-XeRAjZYR.js → tabs-DTV6Su-h.js} +1 -1
- package/static/assets/{tag-CRP5nL5-.js → tag-p6yeowCW.js} +1 -1
- package/static/assets/{terminal-preview-DMJMuORo.js → terminal-preview-DN38x9Jm.js} +1 -1
- package/static/assets/use-terminal-BXJqOeJe.js +1 -0
- package/static/assets/video-BH5ChaoS.js +36 -0
- package/static/index.html +2 -2
- package/static/assets/ApiKeysSettingsPage-Chw9PNL5.js +0 -2
- package/static/assets/CodePage-CrokcH-S.js +0 -2
- package/static/assets/DashboardPage-BaSQQ8Nv.js +0 -41
- package/static/assets/GitSettingsPage-tKBXYAFm.js +0 -6
- package/static/assets/IdentityPage-D2yBjeYn.js +0 -11
- package/static/assets/IntegrationsSettingsPage-Bx8-0Ig4.js +0 -1
- package/static/assets/JobDetailPage-BQmTHled.js +0 -1
- package/static/assets/KnowledgeDetailPage-QMU2bC3L.js +0 -1
- package/static/assets/KnowledgeEditPage-DbMJVcLc.js +0 -1
- package/static/assets/KnowledgePage-aU1GxZSZ.js +0 -8
- package/static/assets/McpSettingsPage-C3WxFwRB.js +0 -1
- package/static/assets/NewKnowledgePage-Cbiswrw_.js +0 -9
- package/static/assets/NewProposalPage-B_sDMBTK.js +0 -90
- package/static/assets/ProjectEditPage-BznWiBBc.js +0 -11
- package/static/assets/PromptsSettingsPage-CY0-870a.js +0 -1
- package/static/assets/ProposalDetailPage-K4iMXHEg.js +0 -1
- package/static/assets/ProposalEditPage-jZOtCMqP.js +0 -1
- package/static/assets/ProposalsPage-C7n4-G05.js +0 -17
- package/static/assets/ResourcesPage-vB5-XkUv.js +0 -71
- package/static/assets/RoleEditPage-Cu7ZB3yj.js +0 -13
- package/static/assets/SchedulePage-Bkkf2wA0.js +0 -4
- package/static/assets/SkillDetailPage-5sDxf3Of.js +0 -1
- package/static/assets/SkillsPage-D2G7EfK8.js +0 -8
- package/static/assets/SourceInput-DlC0zwva.js +0 -1
- package/static/assets/TerminalPage--KZ7azvP.js +0 -1
- package/static/assets/TerminalSessionPage-ClvxK9ia.js +0 -13
- package/static/assets/UserPreferencesPage-CheOH7jZ.js +0 -1
- package/static/assets/UserSettingsPage-C8STDvfQ.js +0 -1
- package/static/assets/UtilitiesPage-9rTxR2md.js +0 -1
- package/static/assets/calendar-Cx5r9R7A.js +0 -6
- package/static/assets/droid-DqWsM2dp.js +0 -17
- package/static/assets/index-DVTgTsDa.css +0 -2
- package/static/assets/index-hqVgTgRB.js +0 -462
- package/static/assets/use-terminal-DuGZuvd2.js +0 -1
- package/static/assets/zap-BlzMp7dY.js +0 -6
|
@@ -49,44 +49,45 @@ export class FileStorageAdapter {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
async ensureDirectories() {
|
|
52
|
-
const dirs = ['
|
|
52
|
+
const dirs = ['tasks', 'specs', 'flags', 'experiments', 'templates', 'jobs'];
|
|
53
53
|
for (const dir of dirs) {
|
|
54
54
|
await fs.mkdir(path.join(this.basePath, dir), { recursive: true });
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
async
|
|
57
|
+
async createTask(task) {
|
|
58
58
|
await this.ensureDirectories();
|
|
59
|
-
// Extract content from the
|
|
60
|
-
const { content, ...frontmatter } =
|
|
59
|
+
// Extract content from the task if it exists
|
|
60
|
+
const { content, ...frontmatter } = task;
|
|
61
61
|
// Normalize date fields to Date instances in case callers provide ISO strings
|
|
62
|
-
const createdAt =
|
|
63
|
-
?
|
|
64
|
-
: new Date(
|
|
65
|
-
const updatedAt =
|
|
66
|
-
?
|
|
67
|
-
: new Date(
|
|
68
|
-
// Convert the
|
|
62
|
+
const createdAt = task.metadata.createdAt instanceof Date
|
|
63
|
+
? task.metadata.createdAt
|
|
64
|
+
: new Date(task.metadata.createdAt);
|
|
65
|
+
const updatedAt = task.metadata.updatedAt instanceof Date
|
|
66
|
+
? task.metadata.updatedAt
|
|
67
|
+
: new Date(task.metadata.updatedAt);
|
|
68
|
+
// Convert the task to markdown with YAML frontmatter
|
|
69
69
|
const frontmatterData = this.sanitizeForYAML({
|
|
70
70
|
// Required fields
|
|
71
|
-
id:
|
|
72
|
-
title:
|
|
71
|
+
id: task.id,
|
|
72
|
+
title: task.title,
|
|
73
73
|
// Deprecated: intent is kept for backward compatibility during migration
|
|
74
74
|
// TODO: Remove intent field in future version
|
|
75
|
-
...(
|
|
75
|
+
...(task.intent && { intent: task.intent }),
|
|
76
76
|
createdAt: createdAt.toISOString(),
|
|
77
77
|
updatedAt: updatedAt.toISOString(),
|
|
78
|
-
status:
|
|
79
|
-
priority:
|
|
78
|
+
status: task.status,
|
|
79
|
+
priority: task.metadata.priority || 'medium',
|
|
80
|
+
...(task.metadata.readiness != null && { readiness: task.metadata.readiness }),
|
|
80
81
|
// Author information
|
|
81
82
|
author: {
|
|
82
|
-
id:
|
|
83
|
-
name:
|
|
84
|
-
email:
|
|
83
|
+
id: task.author.id,
|
|
84
|
+
name: task.author.name,
|
|
85
|
+
email: task.author.email || '',
|
|
85
86
|
role: 'engineer', // Default role
|
|
86
|
-
type:
|
|
87
|
+
type: task.author.type
|
|
87
88
|
},
|
|
88
89
|
// Steps (top-level for consistency with CLI storage format)
|
|
89
|
-
steps:
|
|
90
|
+
steps: task.planSteps.map(step => ({
|
|
90
91
|
id: step.id,
|
|
91
92
|
description: step.description,
|
|
92
93
|
status: step.status,
|
|
@@ -96,10 +97,10 @@ export class FileStorageAdapter {
|
|
|
96
97
|
...(step.executedAt && { executedAt: step.executedAt instanceof Date ? step.executedAt.toISOString() : step.executedAt }),
|
|
97
98
|
})),
|
|
98
99
|
// Metadata
|
|
99
|
-
tags:
|
|
100
|
+
tags: task.metadata.tags || [],
|
|
100
101
|
labels: [],
|
|
101
102
|
// Comments use consistent field names: id, author, content, createdAt
|
|
102
|
-
comments: (
|
|
103
|
+
comments: (task.comments || [])
|
|
103
104
|
.filter((c) => c !== undefined)
|
|
104
105
|
.map((c) => ({
|
|
105
106
|
id: c.id,
|
|
@@ -108,17 +109,17 @@ export class FileStorageAdapter {
|
|
|
108
109
|
createdAt: c.createdAt || c.timestamp || new Date().toISOString(),
|
|
109
110
|
}))
|
|
110
111
|
});
|
|
111
|
-
const markdown = matter.stringify(content || this.getDefaultContent(
|
|
112
|
-
const filePath = path.join(this.basePath, '
|
|
112
|
+
const markdown = matter.stringify(content || this.getDefaultContent(task), frontmatterData);
|
|
113
|
+
const filePath = path.join(this.basePath, 'tasks', `${task.id}.md`);
|
|
113
114
|
await fs.writeFile(filePath, markdown, 'utf-8');
|
|
114
115
|
}
|
|
115
|
-
async
|
|
116
|
+
async getTask(id) {
|
|
116
117
|
try {
|
|
117
|
-
const filePath = path.join(this.basePath, '
|
|
118
|
+
const filePath = path.join(this.basePath, 'tasks', `${id}.md`);
|
|
118
119
|
const fileContent = await fs.readFile(filePath, 'utf-8');
|
|
119
120
|
const { data, content } = matter(fileContent);
|
|
120
|
-
// Convert the frontmatter back to a
|
|
121
|
-
return this.
|
|
121
|
+
// Convert the frontmatter back to a Task
|
|
122
|
+
return this.frontmatterToTask(data, content);
|
|
122
123
|
}
|
|
123
124
|
catch (error) {
|
|
124
125
|
if (error.code === 'ENOENT')
|
|
@@ -126,13 +127,13 @@ export class FileStorageAdapter {
|
|
|
126
127
|
throw error;
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
|
-
async
|
|
130
|
-
const existing = await this.
|
|
130
|
+
async updateTask(id, updates) {
|
|
131
|
+
const existing = await this.getTask(id);
|
|
131
132
|
if (!existing)
|
|
132
|
-
throw new Error(`
|
|
133
|
-
// Never allow id to be updated to prevent overwriting other
|
|
133
|
+
throw new Error(`Task ${id} not found`);
|
|
134
|
+
// Never allow id to be updated to prevent overwriting other tasks
|
|
134
135
|
const { id: _, ...safeUpdates } = updates;
|
|
135
|
-
// Comments live at root level on
|
|
136
|
+
// Comments live at root level on Task (not in metadata).
|
|
136
137
|
// Accept comments from root level or metadata.comments for backward compat.
|
|
137
138
|
let commentsToStore = existing.comments || [];
|
|
138
139
|
if (safeUpdates.comments) {
|
|
@@ -151,36 +152,36 @@ export class FileStorageAdapter {
|
|
|
151
152
|
},
|
|
152
153
|
comments: commentsToStore
|
|
153
154
|
};
|
|
154
|
-
await this.
|
|
155
|
+
await this.createTask(updated);
|
|
155
156
|
}
|
|
156
|
-
async
|
|
157
|
-
const filePath = path.join(this.basePath, '
|
|
157
|
+
async deleteTask(id) {
|
|
158
|
+
const filePath = path.join(this.basePath, 'tasks', `${id}.md`);
|
|
158
159
|
await fs.unlink(filePath);
|
|
159
160
|
}
|
|
160
|
-
async
|
|
161
|
-
const
|
|
161
|
+
async listTasks(filter) {
|
|
162
|
+
const tasksDir = path.join(this.basePath, 'tasks');
|
|
162
163
|
try {
|
|
163
|
-
const files = await fs.readdir(
|
|
164
|
-
const
|
|
164
|
+
const files = await fs.readdir(tasksDir);
|
|
165
|
+
const tasks = await Promise.all(files
|
|
165
166
|
.filter(f => f.endsWith('.md'))
|
|
166
167
|
.map(async (file) => {
|
|
167
|
-
const content = await fs.readFile(path.join(
|
|
168
|
+
const content = await fs.readFile(path.join(tasksDir, file), 'utf-8');
|
|
168
169
|
const { data, content: body } = matter(content);
|
|
169
|
-
return this.
|
|
170
|
+
return this.frontmatterToTask(data, body);
|
|
170
171
|
}));
|
|
171
172
|
// Apply filters
|
|
172
|
-
let filtered =
|
|
173
|
-
if (!
|
|
173
|
+
let filtered = tasks.filter(task => {
|
|
174
|
+
if (!task)
|
|
174
175
|
return false;
|
|
175
|
-
if (filter?.status &&
|
|
176
|
+
if (filter?.status && task.status !== filter.status)
|
|
176
177
|
return false;
|
|
177
|
-
if (filter?.author &&
|
|
178
|
+
if (filter?.author && task.author.id !== filter.author)
|
|
178
179
|
return false;
|
|
179
|
-
if (filter?.priority &&
|
|
180
|
+
if (filter?.priority && task.metadata.priority !== filter.priority)
|
|
180
181
|
return false;
|
|
181
182
|
if (filter?.tags && filter.tags.length > 0) {
|
|
182
|
-
const
|
|
183
|
-
if (!filter.tags.some(tag =>
|
|
183
|
+
const taskTags = task.metadata.tags || [];
|
|
184
|
+
if (!filter.tags.some(tag => taskTags.includes(tag)))
|
|
184
185
|
return false;
|
|
185
186
|
}
|
|
186
187
|
return true;
|
|
@@ -208,9 +209,9 @@ export class FileStorageAdapter {
|
|
|
208
209
|
throw error;
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
|
-
async
|
|
212
|
-
const
|
|
213
|
-
const fuse = new Fuse(
|
|
212
|
+
async searchTasks(query) {
|
|
213
|
+
const allTasks = await this.listTasks();
|
|
214
|
+
const fuse = new Fuse(allTasks, {
|
|
214
215
|
keys: [
|
|
215
216
|
{ name: 'title', weight: 2 },
|
|
216
217
|
{ name: 'intent', weight: 2 }, // Deprecated fallback
|
|
@@ -223,7 +224,7 @@ export class FileStorageAdapter {
|
|
|
223
224
|
});
|
|
224
225
|
return fuse.search(query).map(result => result.item);
|
|
225
226
|
}
|
|
226
|
-
|
|
227
|
+
frontmatterToTask(data, content) {
|
|
227
228
|
// Handle both old format (plan.steps) and new format (top-level steps)
|
|
228
229
|
const steps = data.steps || data.plan?.steps || [];
|
|
229
230
|
// Normalize comments using consistent field names (content/createdAt).
|
|
@@ -258,30 +259,24 @@ export class FileStorageAdapter {
|
|
|
258
259
|
error: step.error,
|
|
259
260
|
executedAt: step.executedAt ? new Date(step.executedAt) : undefined
|
|
260
261
|
})),
|
|
261
|
-
evidence: data.evidence || [],
|
|
262
|
-
policies: data.policies || [],
|
|
263
|
-
featureFlags: data.featureFlags || [],
|
|
264
|
-
experiments: data.experiments || [],
|
|
265
|
-
telemetryContracts: data.telemetryContracts || [],
|
|
266
|
-
releasePlan: data.releasePlan || { strategy: 'immediate' },
|
|
267
262
|
status: data.status || 'draft',
|
|
268
263
|
comments: normalizedComments,
|
|
269
264
|
metadata: {
|
|
270
265
|
createdAt: new Date(data.createdAt || Date.now()),
|
|
271
266
|
updatedAt: new Date(data.updatedAt || Date.now()),
|
|
272
267
|
reviewers: data.reviewers || [],
|
|
273
|
-
aiInteractions: data.aiInteractions || [],
|
|
274
268
|
tags: data.tags || [],
|
|
275
269
|
priority: data.priority || 'medium',
|
|
270
|
+
...(data.readiness != null && { readiness: data.readiness }),
|
|
276
271
|
},
|
|
277
272
|
content // Store the markdown content
|
|
278
273
|
};
|
|
279
274
|
}
|
|
280
|
-
getDefaultContent(
|
|
281
|
-
return `# ${
|
|
275
|
+
getDefaultContent(task) {
|
|
276
|
+
return `# ${task.title}
|
|
282
277
|
|
|
283
278
|
## Problem Statement
|
|
284
|
-
Describe the problem this
|
|
279
|
+
Describe the problem this task addresses.
|
|
285
280
|
|
|
286
281
|
## Proposed Solution
|
|
287
282
|
Describe the solution you're proposing.
|
|
@@ -2,13 +2,11 @@ import { WebSocket } from 'ws';
|
|
|
2
2
|
import { ShellType } from './shell-utils.js';
|
|
3
3
|
export interface TerminalSession {
|
|
4
4
|
id: string;
|
|
5
|
-
|
|
5
|
+
taskId: string;
|
|
6
6
|
pty: any;
|
|
7
7
|
websocket?: WebSocket;
|
|
8
8
|
createdAt: Date;
|
|
9
9
|
lastActivity: Date;
|
|
10
|
-
enableLogging?: boolean;
|
|
11
|
-
logFilePath?: string;
|
|
12
10
|
backlog: string;
|
|
13
11
|
previewSockets?: Set<WebSocket>;
|
|
14
12
|
previewBuffer?: string;
|
|
@@ -21,9 +19,9 @@ export declare class TerminalManager {
|
|
|
21
19
|
private cleanupInterval;
|
|
22
20
|
private static readonly MAX_BACKLOG_BYTES;
|
|
23
21
|
constructor();
|
|
24
|
-
createSession(
|
|
22
|
+
createSession(taskId: string, shellPreference?: ShellType, startupCommand?: string): Promise<TerminalSession>;
|
|
25
23
|
getSession(sessionId: string): TerminalSession | undefined;
|
|
26
|
-
|
|
24
|
+
getSessionsByTask(taskId: string): TerminalSession[];
|
|
27
25
|
attachWebSocket(sessionId: string, ws: WebSocket): boolean;
|
|
28
26
|
destroySession(sessionId: string): boolean;
|
|
29
27
|
resizeSession(sessionId: string, cols: number, rows: number): boolean;
|
|
@@ -16,8 +16,8 @@ export class TerminalManager {
|
|
|
16
16
|
this.cleanupInactiveSessions();
|
|
17
17
|
}, 5 * 60 * 1000);
|
|
18
18
|
}
|
|
19
|
-
async createSession(
|
|
20
|
-
const sessionId = `${
|
|
19
|
+
async createSession(taskId, shellPreference = 'bash', startupCommand) {
|
|
20
|
+
const sessionId = `${taskId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
21
21
|
// Get the project root directory
|
|
22
22
|
let projectRoot;
|
|
23
23
|
if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
|
|
@@ -32,8 +32,8 @@ export class TerminalManager {
|
|
|
32
32
|
}
|
|
33
33
|
// Prepare context information
|
|
34
34
|
const contextInfo = {
|
|
35
|
-
proposalId,
|
|
36
|
-
proposalPath: path.join(projectRoot, '.nut', '
|
|
35
|
+
proposalId: taskId,
|
|
36
|
+
proposalPath: path.join(projectRoot, '.nut', 'tasks', `${taskId}.md`),
|
|
37
37
|
contextPath: path.join(projectRoot, '.nut', 'context'),
|
|
38
38
|
projectRoot,
|
|
39
39
|
};
|
|
@@ -65,22 +65,6 @@ export class TerminalManager {
|
|
|
65
65
|
catch (error) {
|
|
66
66
|
console.error('Error creating init script:', error);
|
|
67
67
|
}
|
|
68
|
-
// Set up logging if enabled
|
|
69
|
-
let logFilePath;
|
|
70
|
-
if (enableLogging) {
|
|
71
|
-
const sessionsDir = path.join(projectRoot, '.nut', 'sessions');
|
|
72
|
-
try {
|
|
73
|
-
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
74
|
-
logFilePath = path.join(sessionsDir, `${sessionId}.log`);
|
|
75
|
-
// Create log file with session header
|
|
76
|
-
const logHeader = `# Terminal Session Log\n# Session ID: ${sessionId}\n# Proposal ID: ${proposalId}\n# Created: ${new Date().toISOString()}\n\n`;
|
|
77
|
-
fs.writeFileSync(logFilePath, logHeader);
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
console.error('Error setting up session logging:', error);
|
|
81
|
-
logFilePath = undefined;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
68
|
// Get shell arguments
|
|
85
69
|
const shellArgs = getShellArgs(shellPath, initScriptPath);
|
|
86
70
|
// Prepare environment variables with API keys injected.
|
|
@@ -92,9 +76,9 @@ export class TerminalManager {
|
|
|
92
76
|
delete injected.NODE_ENV;
|
|
93
77
|
const env = {
|
|
94
78
|
...injected,
|
|
95
|
-
|
|
79
|
+
COCONUT_TASK_ID: taskId,
|
|
96
80
|
COCONUT_CONTEXT_PATH: path.join(projectRoot, '.nut', 'context'),
|
|
97
|
-
|
|
81
|
+
COCONUT_TASK_PATH: path.join(projectRoot, '.nut', 'tasks', `${taskId}.md`),
|
|
98
82
|
GAIT_DATA_PATH: projectRoot,
|
|
99
83
|
TERM: 'xterm-256color',
|
|
100
84
|
COLORTERM: 'truecolor',
|
|
@@ -116,12 +100,10 @@ export class TerminalManager {
|
|
|
116
100
|
});
|
|
117
101
|
const session = {
|
|
118
102
|
id: sessionId,
|
|
119
|
-
|
|
103
|
+
taskId,
|
|
120
104
|
pty: ptyProcess,
|
|
121
105
|
createdAt: new Date(),
|
|
122
106
|
lastActivity: new Date(),
|
|
123
|
-
enableLogging,
|
|
124
|
-
logFilePath,
|
|
125
107
|
backlog: '',
|
|
126
108
|
previewSockets: new Set(),
|
|
127
109
|
previewBuffer: '',
|
|
@@ -140,7 +122,7 @@ export class TerminalManager {
|
|
|
140
122
|
tags: ["agent", "terminal", "session"],
|
|
141
123
|
payload: {
|
|
142
124
|
sessionId,
|
|
143
|
-
|
|
125
|
+
taskId,
|
|
144
126
|
cwd: projectRoot,
|
|
145
127
|
shell: shellPath,
|
|
146
128
|
}
|
|
@@ -153,17 +135,6 @@ export class TerminalManager {
|
|
|
153
135
|
// Set up PTY event handlers
|
|
154
136
|
ptyProcess.onData((data) => {
|
|
155
137
|
session.lastActivity = new Date();
|
|
156
|
-
// Log data if logging is enabled
|
|
157
|
-
if (session.enableLogging && session.logFilePath) {
|
|
158
|
-
try {
|
|
159
|
-
const timestamp = new Date().toISOString();
|
|
160
|
-
const logEntry = `[${timestamp}] OUTPUT: ${data}`;
|
|
161
|
-
fs.appendFileSync(session.logFilePath, logEntry);
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
console.error('Error writing to session log:', error);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
138
|
// Maintain in-memory backlog (trim to last MAX_BACKLOG_BYTES)
|
|
168
139
|
try {
|
|
169
140
|
// Append and trim to max size
|
|
@@ -187,17 +158,6 @@ export class TerminalManager {
|
|
|
187
158
|
ptyProcess.onExit((e) => {
|
|
188
159
|
const endTime = new Date();
|
|
189
160
|
const duration = endTime.getTime() - session.createdAt.getTime();
|
|
190
|
-
// Log session end if logging is enabled
|
|
191
|
-
if (session.enableLogging && session.logFilePath) {
|
|
192
|
-
try {
|
|
193
|
-
const timestamp = endTime.toISOString();
|
|
194
|
-
const logEntry = `\n[${timestamp}] SESSION ENDED: Exit code ${e.exitCode}\n`;
|
|
195
|
-
fs.appendFileSync(session.logFilePath, logEntry);
|
|
196
|
-
}
|
|
197
|
-
catch (error) {
|
|
198
|
-
console.error('Error writing session end to log:', error);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
161
|
// Log session end to activity log
|
|
202
162
|
try {
|
|
203
163
|
const logger = getLogger();
|
|
@@ -249,8 +209,8 @@ export class TerminalManager {
|
|
|
249
209
|
getSession(sessionId) {
|
|
250
210
|
return this.sessions.get(sessionId);
|
|
251
211
|
}
|
|
252
|
-
|
|
253
|
-
return Array.from(this.sessions.values()).filter(session => session.
|
|
212
|
+
getSessionsByTask(taskId) {
|
|
213
|
+
return Array.from(this.sessions.values()).filter(session => session.taskId === taskId);
|
|
254
214
|
}
|
|
255
215
|
attachWebSocket(sessionId, ws) {
|
|
256
216
|
const session = this.sessions.get(sessionId);
|
|
@@ -289,17 +249,6 @@ export class TerminalManager {
|
|
|
289
249
|
const data = JSON.parse(message.toString());
|
|
290
250
|
switch (data.type) {
|
|
291
251
|
case 'input':
|
|
292
|
-
// Log input if logging is enabled
|
|
293
|
-
if (session.enableLogging && session.logFilePath) {
|
|
294
|
-
try {
|
|
295
|
-
const timestamp = new Date().toISOString();
|
|
296
|
-
const logEntry = `[${timestamp}] INPUT: ${data.data}`;
|
|
297
|
-
fs.appendFileSync(session.logFilePath, logEntry);
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
console.error('Error writing input to session log:', error);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
252
|
session.pty.write(data.data);
|
|
304
253
|
session.lastActivity = new Date();
|
|
305
254
|
break;
|