@plandesk/api 0.8.0 → 0.9.0
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/events.d.ts +6 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/routes/agent-runs.d.ts +1 -1
- package/dist/routes/agent-runs.js +20 -0
- package/dist/routes/goals.d.ts +4 -0
- package/dist/routes/goals.js +138 -0
- package/dist/routes/projects.d.ts +1 -1
- package/dist/routes/projects.js +12 -1
- package/dist/routes/submissions.d.ts +5 -0
- package/dist/routes/submissions.js +58 -0
- package/dist/serialize.d.ts +22 -1
- package/dist/serialize.js +35 -0
- package/dist/server.js +5 -1
- package/dist/services/canvas.d.ts +2 -0
- package/dist/services/canvas.js +2 -1
- package/dist/services/goals.d.ts +239 -0
- package/dist/services/goals.js +323 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +3 -0
- package/dist/services/projects.js +4 -1
- package/dist/services/sync.d.ts +5 -3
- package/dist/services/sync.js +45 -2
- package/dist/services/tasks.d.ts +10 -1
- package/dist/services/tasks.js +33 -5
- package/package.json +2 -2
- package/web/assets/index-DcD7-VGi.css +1 -0
- package/web/assets/index-Dcaq3wR-.js +318 -0
- package/web/index.html +2 -2
- package/web/assets/index-CUxSE_WZ.css +0 -1
- package/web/assets/index-DSmNB4RA.js +0 -235
package/dist/events.d.ts
CHANGED
|
@@ -67,7 +67,12 @@ export type SubmissionsPulledEvent = {
|
|
|
67
67
|
type: 'submissions_pulled';
|
|
68
68
|
projectId: string;
|
|
69
69
|
};
|
|
70
|
-
export type
|
|
70
|
+
export type GoalUpdatedEvent = {
|
|
71
|
+
type: 'goal_updated';
|
|
72
|
+
goalId: string;
|
|
73
|
+
projectId: string;
|
|
74
|
+
};
|
|
75
|
+
export type PlankDeskEvent = TaskUpdatedEvent | TagUpdatedEvent | CanvasUpdatedEvent | DocumentCreatedEvent | CommentCreatedEvent | CommentUpdatedEvent | FolderCreatedEvent | FolderUpdatedEvent | NoteCreatedEvent | NoteUpdatedEvent | AgentRunStartedEvent | AgentRunProgressEvent | AgentRunCompletedEvent | SubmissionsPulledEvent | GoalUpdatedEvent;
|
|
71
76
|
export type EventListener = (event: PlankDeskEvent) => void;
|
|
72
77
|
export type EventBus = {
|
|
73
78
|
subscribe(listener: EventListener): () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ export { mountStatic } from './static.js';
|
|
|
5
5
|
export { createServices, type Services, type ServicesDeps } from './services/index.js';
|
|
6
6
|
export { createEventBus, type EventBus, type PlankDeskEvent } from './events.js';
|
|
7
7
|
export type { ProjectService } from './services/projects.js';
|
|
8
|
+
export type { GoalService, VerificationEvidence } from './services/goals.js';
|
|
9
|
+
export { GoalCompletionBlockedError, GoalVerificationRequiredError, InvalidGoalTransitionError, InvalidVerificationSurfaceError, } from './services/goals.js';
|
|
8
10
|
export type { TaskService } from './services/tasks.js';
|
|
11
|
+
export { InvalidGoalReferenceError } from './services/tasks.js';
|
|
9
12
|
export type { TagService } from './services/tags.js';
|
|
10
13
|
export type { CanvasService } from './services/canvas.js';
|
|
11
14
|
export type { DocumentService } from './services/documents.js';
|
|
@@ -22,6 +25,6 @@ export { InvalidCanvasError } from './services/canvas.js';
|
|
|
22
25
|
export { InvalidAgentRunError } from './services/agent-runs.js';
|
|
23
26
|
export { InvalidScaffoldError } from './services/projects.js';
|
|
24
27
|
export { InvalidShareError } from './services/share.js';
|
|
25
|
-
export { InvalidTriageError, SyncUnavailableError, SyncUnauthorizedError, type SyncRemote, type SyncService, } from './services/sync.js';
|
|
28
|
+
export { InvalidTriageError, InvalidTriageInputError, SyncUnavailableError, SyncUnauthorizedError, type SyncRemote, type SyncService, } from './services/sync.js';
|
|
26
29
|
export declare const version: () => string;
|
|
27
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,8 @@ export { healthRouter } from './routes/health.js';
|
|
|
4
4
|
export { mountStatic } from './static.js';
|
|
5
5
|
export { createServices } from './services/index.js';
|
|
6
6
|
export { createEventBus } from './events.js';
|
|
7
|
+
export { GoalCompletionBlockedError, GoalVerificationRequiredError, InvalidGoalTransitionError, InvalidVerificationSurfaceError, } from './services/goals.js';
|
|
8
|
+
export { InvalidGoalReferenceError } from './services/tasks.js';
|
|
7
9
|
export { InvalidDocumentError } from './services/documents.js';
|
|
8
10
|
export { InvalidFolderError } from './services/folders.js';
|
|
9
11
|
export { InvalidNoteError } from './services/notes.js';
|
|
@@ -13,7 +15,7 @@ export { InvalidCanvasError } from './services/canvas.js';
|
|
|
13
15
|
export { InvalidAgentRunError } from './services/agent-runs.js';
|
|
14
16
|
export { InvalidScaffoldError } from './services/projects.js';
|
|
15
17
|
export { InvalidShareError } from './services/share.js';
|
|
16
|
-
export { InvalidTriageError, SyncUnavailableError, SyncUnauthorizedError, } from './services/sync.js';
|
|
18
|
+
export { InvalidTriageError, InvalidTriageInputError, SyncUnavailableError, SyncUnauthorizedError, } from './services/sync.js';
|
|
17
19
|
import { readFileSync } from 'node:fs';
|
|
18
20
|
import { dirname, join } from 'node:path';
|
|
19
21
|
import { fileURLToPath } from 'node:url';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import type
|
|
2
|
+
import { type AgentRunService } from '../services/agent-runs.js';
|
|
3
3
|
export declare function createAgentRunsRouter(agentRunService: AgentRunService): Hono;
|
|
4
4
|
//# sourceMappingURL=agent-runs.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
+
import { InvalidAgentRunError } from '../services/agent-runs.js';
|
|
2
3
|
import { parsePaginationParams } from '../serialize.js';
|
|
3
4
|
export function createAgentRunsRouter(agentRunService) {
|
|
4
5
|
const router = new Hono();
|
|
@@ -13,6 +14,25 @@ export function createAgentRunsRouter(agentRunService) {
|
|
|
13
14
|
}
|
|
14
15
|
return c.json(runs);
|
|
15
16
|
});
|
|
17
|
+
router.post('/agent-runs/:id/progress', async (c) => {
|
|
18
|
+
const body = await c.req.json();
|
|
19
|
+
if (typeof body.message !== 'string' || body.message.trim() === '') {
|
|
20
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const event = agentRunService.recordProgress(c.req.param('id'), body.message);
|
|
24
|
+
if (!event) {
|
|
25
|
+
return c.json({ error: 'not_found' }, 404);
|
|
26
|
+
}
|
|
27
|
+
return c.json(event, 201);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (error instanceof InvalidAgentRunError) {
|
|
31
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
16
36
|
return router;
|
|
17
37
|
}
|
|
18
38
|
//# sourceMappingURL=agent-runs.js.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { InvalidGoalStatusError, isGoalStatus } from '@plandesk/db';
|
|
3
|
+
import { GoalCompletionBlockedError, GoalVerificationRequiredError, InvalidGoalTransitionError, InvalidVerificationSurfaceError, } from '../services/goals.js';
|
|
4
|
+
function mapGoalInput(body) {
|
|
5
|
+
return {
|
|
6
|
+
...(body.objective !== undefined ? { objective: body.objective } : {}),
|
|
7
|
+
...(body.verification_surface !== undefined
|
|
8
|
+
? { verificationSurface: body.verification_surface }
|
|
9
|
+
: {}),
|
|
10
|
+
...(body.constraints !== undefined ? { constraints: body.constraints } : {}),
|
|
11
|
+
...(body.boundaries !== undefined ? { boundaries: body.boundaries } : {}),
|
|
12
|
+
...(body.iteration_policy !== undefined ? { iterationPolicy: body.iteration_policy } : {}),
|
|
13
|
+
...(body.stop_condition !== undefined ? { stopCondition: body.stop_condition } : {}),
|
|
14
|
+
...(body.budget !== undefined ? { budget: body.budget } : {}),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function handleGoalError(c, error) {
|
|
18
|
+
if (error instanceof InvalidGoalStatusError || error instanceof InvalidGoalTransitionError) {
|
|
19
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
20
|
+
}
|
|
21
|
+
if (error instanceof InvalidVerificationSurfaceError) {
|
|
22
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
23
|
+
}
|
|
24
|
+
if (error instanceof GoalVerificationRequiredError) {
|
|
25
|
+
return c.json({
|
|
26
|
+
error: 'verification_required',
|
|
27
|
+
required_kind: error.requiredKind,
|
|
28
|
+
}, 400);
|
|
29
|
+
}
|
|
30
|
+
if (error instanceof GoalCompletionBlockedError) {
|
|
31
|
+
return c.json({
|
|
32
|
+
error: 'blocked_by_incomplete_tasks',
|
|
33
|
+
incomplete_task_ids: error.incompleteTaskIds,
|
|
34
|
+
}, 400);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
export function createGoalsRouter(goalService) {
|
|
39
|
+
const router = new Hono();
|
|
40
|
+
router.post('/projects/:id/goals', async (c) => {
|
|
41
|
+
const body = await c.req.json();
|
|
42
|
+
if (typeof body.objective !== 'string' || body.objective.trim() === '') {
|
|
43
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
44
|
+
}
|
|
45
|
+
if (body.status !== undefined && !isGoalStatus(body.status)) {
|
|
46
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const goal = goalService.create(c.req.param('id'), {
|
|
50
|
+
objective: body.objective,
|
|
51
|
+
...(body.status !== undefined ? { status: body.status } : {}),
|
|
52
|
+
...mapGoalInput(body),
|
|
53
|
+
});
|
|
54
|
+
if (!goal) {
|
|
55
|
+
return c.json({ error: 'not_found' }, 404);
|
|
56
|
+
}
|
|
57
|
+
return c.json(goal, 201);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return handleGoalError(c, error);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
router.get('/projects/:id/goals', (c) => {
|
|
64
|
+
const goals = goalService.listByProject(c.req.param('id'));
|
|
65
|
+
if (!goals) {
|
|
66
|
+
return c.json({ error: 'not_found' }, 404);
|
|
67
|
+
}
|
|
68
|
+
return c.json(goals);
|
|
69
|
+
});
|
|
70
|
+
router.get('/goals/:id', (c) => {
|
|
71
|
+
const goal = goalService.get(c.req.param('id'));
|
|
72
|
+
if (!goal) {
|
|
73
|
+
return c.json({ error: 'not_found' }, 404);
|
|
74
|
+
}
|
|
75
|
+
return c.json(goal);
|
|
76
|
+
});
|
|
77
|
+
router.patch('/goals/:id', async (c) => {
|
|
78
|
+
const body = await c.req.json();
|
|
79
|
+
if (body.objective !== undefined && body.objective.trim() === '') {
|
|
80
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const goal = goalService.update(c.req.param('id'), mapGoalInput(body));
|
|
84
|
+
if (!goal) {
|
|
85
|
+
return c.json({ error: 'not_found' }, 404);
|
|
86
|
+
}
|
|
87
|
+
return c.json(goal);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
return handleGoalError(c, error);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
router.post('/goals/:id/pause', (c) => {
|
|
94
|
+
try {
|
|
95
|
+
const goal = goalService.pause(c.req.param('id'));
|
|
96
|
+
if (!goal) {
|
|
97
|
+
return c.json({ error: 'not_found' }, 404);
|
|
98
|
+
}
|
|
99
|
+
return c.json(goal);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return handleGoalError(c, error);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
router.post('/goals/:id/resume', (c) => {
|
|
106
|
+
try {
|
|
107
|
+
const goal = goalService.resume(c.req.param('id'));
|
|
108
|
+
if (!goal) {
|
|
109
|
+
return c.json({ error: 'not_found' }, 404);
|
|
110
|
+
}
|
|
111
|
+
return c.json(goal);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return handleGoalError(c, error);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
router.post('/goals/:id/complete', async (c) => {
|
|
118
|
+
let body = {};
|
|
119
|
+
try {
|
|
120
|
+
body = await c.req.json();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// empty body is valid when the goal has no verification_surface
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const goal = goalService.complete(c.req.param('id'), body.evidence);
|
|
127
|
+
if (!goal) {
|
|
128
|
+
return c.json({ error: 'not_found' }, 404);
|
|
129
|
+
}
|
|
130
|
+
return c.json(goal);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return handleGoalError(c, error);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return router;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=goals.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import type { ProjectService } from '../services/projects.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type TaskService } from '../services/tasks.js';
|
|
4
4
|
export declare function createProjectsRouter(projectService: ProjectService, taskService: TaskService): Hono;
|
|
5
5
|
//# sourceMappingURL=projects.d.ts.map
|
package/dist/routes/projects.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { InvalidTaskStatusError, isTaskStatus } from '@plandesk/db';
|
|
3
|
+
import { InvalidGoalReferenceError } from '../services/tasks.js';
|
|
3
4
|
import { InvalidTagError } from '../services/tags.js';
|
|
4
5
|
import { isStringArray } from './tasks.js';
|
|
5
6
|
import { parsePaginationParams } from '../serialize.js';
|
|
@@ -81,6 +82,7 @@ export function createProjectsRouter(projectService, taskService) {
|
|
|
81
82
|
...(body.y !== undefined ? { y: body.y } : {}),
|
|
82
83
|
...(body.assignee !== undefined ? { assignee: body.assignee } : {}),
|
|
83
84
|
...(dueDate !== undefined ? { dueDate } : {}),
|
|
85
|
+
...(body.goal_id !== undefined ? { goalId: body.goal_id } : {}),
|
|
84
86
|
...(body.tags !== undefined ? { tags: body.tags } : {}),
|
|
85
87
|
});
|
|
86
88
|
if (!task) {
|
|
@@ -89,7 +91,9 @@ export function createProjectsRouter(projectService, taskService) {
|
|
|
89
91
|
return c.json(task, 201);
|
|
90
92
|
}
|
|
91
93
|
catch (error) {
|
|
92
|
-
if (error instanceof InvalidTaskStatusError ||
|
|
94
|
+
if (error instanceof InvalidTaskStatusError ||
|
|
95
|
+
error instanceof InvalidTagError ||
|
|
96
|
+
error instanceof InvalidGoalReferenceError) {
|
|
93
97
|
return c.json({ error: 'invalid_argument' }, 400);
|
|
94
98
|
}
|
|
95
99
|
throw error;
|
|
@@ -118,6 +122,13 @@ export function createProjectsRouter(projectService, taskService) {
|
|
|
118
122
|
throw error;
|
|
119
123
|
}
|
|
120
124
|
});
|
|
125
|
+
router.get('/projects/:id/next-task', (c) => {
|
|
126
|
+
const result = taskService.nextActionable(c.req.param('id'));
|
|
127
|
+
if (!result) {
|
|
128
|
+
return c.json({ error: 'not_found' }, 404);
|
|
129
|
+
}
|
|
130
|
+
return c.json(result);
|
|
131
|
+
});
|
|
121
132
|
return router;
|
|
122
133
|
}
|
|
123
134
|
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { type SyncService } from '../services/sync.js';
|
|
3
|
+
import type { ProjectService } from '../services/projects.js';
|
|
4
|
+
export declare function createSubmissionsRouter(syncService: SyncService, projectService: ProjectService): Hono;
|
|
5
|
+
//# sourceMappingURL=submissions.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { shareSubmissionStatuses } from '@plandesk/db';
|
|
3
|
+
import { InvalidTriageError, SyncUnauthorizedError, SyncUnavailableError, } from '../services/sync.js';
|
|
4
|
+
function isSubmissionStatus(value) {
|
|
5
|
+
return shareSubmissionStatuses.includes(value);
|
|
6
|
+
}
|
|
7
|
+
export function createSubmissionsRouter(syncService, projectService) {
|
|
8
|
+
const router = new Hono();
|
|
9
|
+
router.get('/projects/:id/submissions', (c) => {
|
|
10
|
+
const projectId = c.req.param('id');
|
|
11
|
+
if (!projectService.get(projectId)) {
|
|
12
|
+
return c.json({ error: 'not_found' }, 404);
|
|
13
|
+
}
|
|
14
|
+
const statusParam = c.req.query('status') ?? 'pending';
|
|
15
|
+
if (!isSubmissionStatus(statusParam)) {
|
|
16
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
17
|
+
}
|
|
18
|
+
return c.json(syncService.listTriage(projectId, statusParam));
|
|
19
|
+
});
|
|
20
|
+
router.post('/submissions/:id/triage', async (c) => {
|
|
21
|
+
const submissionId = c.req.param('id');
|
|
22
|
+
const body = await c.req.json();
|
|
23
|
+
if (body.action !== 'accept' && body.action !== 'reject') {
|
|
24
|
+
return c.json({ error: 'invalid_argument' }, 400);
|
|
25
|
+
}
|
|
26
|
+
const submission = syncService.getSubmission(submissionId);
|
|
27
|
+
if (submission === undefined) {
|
|
28
|
+
return c.json({ error: 'not_found' }, 404);
|
|
29
|
+
}
|
|
30
|
+
const remote = syncService.getRemote(submission.project_id);
|
|
31
|
+
if (remote === undefined) {
|
|
32
|
+
return c.json({ error: 'not_published' }, 400);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
// Triage never creates a `todo` task — the scope->todo release is the human's own
|
|
36
|
+
// board action, enforced in syncService.triage(). A merge (link_task_id) links to
|
|
37
|
+
// an existing task instead of creating one; the two are mutually exclusive, so
|
|
38
|
+
// only one is forwarded.
|
|
39
|
+
const linkTaskId = body.action === 'accept' ? body.link_task_id : undefined;
|
|
40
|
+
const result = await syncService.triage(submissionId, body.action, remote, body.action === 'accept' && linkTaskId === undefined ? body.as_task : undefined, linkTaskId);
|
|
41
|
+
return c.json(result);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error instanceof InvalidTriageError) {
|
|
45
|
+
return c.json({ error: 'not_found' }, 404);
|
|
46
|
+
}
|
|
47
|
+
if (error instanceof SyncUnauthorizedError) {
|
|
48
|
+
return c.json({ error: 'sync_unauthorized' }, 400);
|
|
49
|
+
}
|
|
50
|
+
if (error instanceof SyncUnavailableError) {
|
|
51
|
+
return c.json({ error: 'sync_unavailable' }, 502);
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return router;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=submissions.js.map
|
package/dist/serialize.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentRun, AgentRunEvent, Document, DocumentComment, Edge, Folder, Note, Project, Tag, Task, TaskStatus } from '@plandesk/db';
|
|
1
|
+
import type { AgentRun, AgentRunEvent, Document, DocumentComment, Edge, Folder, Goal, Note, Project, Tag, Task, TaskStatus } from '@plandesk/db';
|
|
2
2
|
export type PaginationParams = {
|
|
3
3
|
limit?: number;
|
|
4
4
|
offset?: number;
|
|
@@ -29,10 +29,31 @@ export type SerializedTag = {
|
|
|
29
29
|
created_at: string;
|
|
30
30
|
};
|
|
31
31
|
export declare function serializeTag(tag: Tag): SerializedTag;
|
|
32
|
+
export declare function serializeGoal(goal: Goal): {
|
|
33
|
+
id: string;
|
|
34
|
+
project_id: string;
|
|
35
|
+
objective: string;
|
|
36
|
+
status: "active" | "paused" | "complete" | "blocked";
|
|
37
|
+
verification_surface: string | null;
|
|
38
|
+
constraints: string | null;
|
|
39
|
+
boundaries: string | null;
|
|
40
|
+
iteration_policy: string | null;
|
|
41
|
+
stop_condition: string | null;
|
|
42
|
+
budget: string | null;
|
|
43
|
+
last_verification: {
|
|
44
|
+
at: string;
|
|
45
|
+
green: boolean;
|
|
46
|
+
kind: string | null;
|
|
47
|
+
detail?: string;
|
|
48
|
+
} | null;
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at: string;
|
|
51
|
+
};
|
|
32
52
|
export declare function serializeTask(task: Task, tags?: Tag[]): {
|
|
33
53
|
tags?: SerializedTag[] | undefined;
|
|
34
54
|
id: string;
|
|
35
55
|
project_id: string;
|
|
56
|
+
goal_id: string;
|
|
36
57
|
label: string;
|
|
37
58
|
status: "scope" | "todo" | "in_progress" | "done" | "backlog";
|
|
38
59
|
description: string | null;
|
package/dist/serialize.js
CHANGED
|
@@ -45,10 +45,45 @@ export function serializeTag(tag) {
|
|
|
45
45
|
created_at: tag.createdAt.toISOString(),
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
function parseLastVerification(raw) {
|
|
49
|
+
if (raw === null) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (typeof parsed.at === 'string' &&
|
|
55
|
+
typeof parsed.green === 'boolean' &&
|
|
56
|
+
(parsed.kind === null || typeof parsed.kind === 'string')) {
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function serializeGoal(goal) {
|
|
66
|
+
return {
|
|
67
|
+
id: goal.id,
|
|
68
|
+
project_id: goal.projectId,
|
|
69
|
+
objective: goal.objective,
|
|
70
|
+
status: goal.status,
|
|
71
|
+
verification_surface: goal.verificationSurface,
|
|
72
|
+
constraints: goal.constraints,
|
|
73
|
+
boundaries: goal.boundaries,
|
|
74
|
+
iteration_policy: goal.iterationPolicy,
|
|
75
|
+
stop_condition: goal.stopCondition,
|
|
76
|
+
budget: goal.budget,
|
|
77
|
+
last_verification: parseLastVerification(goal.lastVerification),
|
|
78
|
+
created_at: goal.createdAt.toISOString(),
|
|
79
|
+
updated_at: goal.updatedAt.toISOString(),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
48
82
|
export function serializeTask(task, tags) {
|
|
49
83
|
return {
|
|
50
84
|
id: task.id,
|
|
51
85
|
project_id: task.projectId,
|
|
86
|
+
goal_id: task.goalId,
|
|
52
87
|
label: task.label,
|
|
53
88
|
status: task.status,
|
|
54
89
|
description: task.description,
|
package/dist/server.js
CHANGED
|
@@ -12,17 +12,20 @@ import { createNotesRouter } from './routes/notes.js';
|
|
|
12
12
|
import { createEventsRouter } from './routes/events.js';
|
|
13
13
|
import { createTokensRouter } from './routes/tokens.js';
|
|
14
14
|
import { createAgentRunsRouter } from './routes/agent-runs.js';
|
|
15
|
+
import { createGoalsRouter } from './routes/goals.js';
|
|
16
|
+
import { createSubmissionsRouter } from './routes/submissions.js';
|
|
15
17
|
import { mountStatic } from './static.js';
|
|
16
18
|
import { createServices } from './services/index.js';
|
|
17
19
|
export function createApp(deps) {
|
|
18
20
|
const services = deps.services ?? createServices({ db: deps.db, eventBus: deps.eventBus });
|
|
19
|
-
const { eventBus, projectService, taskService, tagService, canvasService, documentService, folderService, noteService, commentService, agentRunService, tokenService, } = services;
|
|
21
|
+
const { eventBus, projectService, goalService, taskService, tagService, canvasService, documentService, folderService, noteService, commentService, agentRunService, tokenService, syncService, } = services;
|
|
20
22
|
const app = new Hono();
|
|
21
23
|
if (deps.authPassword !== undefined && deps.authPassword.length > 0) {
|
|
22
24
|
app.use('*', createAuthMiddleware(deps.authPassword));
|
|
23
25
|
}
|
|
24
26
|
app.route('/api/v1', healthRouter);
|
|
25
27
|
app.route('/api/v1', createProjectsRouter(projectService, taskService));
|
|
28
|
+
app.route('/api/v1', createGoalsRouter(goalService));
|
|
26
29
|
app.route('/api/v1', createTasksRouter(taskService));
|
|
27
30
|
app.route('/api/v1', createTagsRouter(tagService));
|
|
28
31
|
app.route('/api/v1', createCanvasRouter(canvasService));
|
|
@@ -32,6 +35,7 @@ export function createApp(deps) {
|
|
|
32
35
|
app.route('/api/v1', createCommentsRouter(commentService));
|
|
33
36
|
app.route('/api/v1', createTokensRouter(tokenService));
|
|
34
37
|
app.route('/api/v1', createAgentRunsRouter(agentRunService));
|
|
38
|
+
app.route('/api/v1', createSubmissionsRouter(syncService, projectService));
|
|
35
39
|
app.route('/api/v1', createEventsRouter(eventBus));
|
|
36
40
|
mountStatic(app);
|
|
37
41
|
if (deps.mcp) {
|
|
@@ -33,6 +33,7 @@ export declare function createCanvasService(deps: CanvasServiceDeps): {
|
|
|
33
33
|
tags?: import("../serialize.js").SerializedTag[] | undefined;
|
|
34
34
|
id: string;
|
|
35
35
|
project_id: string;
|
|
36
|
+
goal_id: string;
|
|
36
37
|
label: string;
|
|
37
38
|
status: "scope" | "todo" | "in_progress" | "done" | "backlog";
|
|
38
39
|
description: string | null;
|
|
@@ -75,6 +76,7 @@ export declare function createCanvasService(deps: CanvasServiceDeps): {
|
|
|
75
76
|
tags?: import("../serialize.js").SerializedTag[] | undefined;
|
|
76
77
|
id: string;
|
|
77
78
|
project_id: string;
|
|
79
|
+
goal_id: string;
|
|
78
80
|
label: string;
|
|
79
81
|
status: "scope" | "todo" | "in_progress" | "done" | "backlog";
|
|
80
82
|
description: string | null;
|
package/dist/services/canvas.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEdge, createTask, deleteEdge as dbDeleteEdge, getEdgeByProjectAndId, getProject, getTask, listEdges, listTasks, updateEdge, updateProject, updateTask, } from '@plandesk/db';
|
|
1
|
+
import { createEdge, createTask, getOrCreateDefaultGoal, deleteEdge as dbDeleteEdge, getEdgeByProjectAndId, getProject, getTask, listEdges, listTasks, updateEdge, updateProject, updateTask, } from '@plandesk/db';
|
|
2
2
|
import { serializeEdge, serializeTask } from '../serialize.js';
|
|
3
3
|
export class InvalidCanvasError extends Error {
|
|
4
4
|
constructor(message) {
|
|
@@ -93,6 +93,7 @@ export function createCanvasService(deps) {
|
|
|
93
93
|
}
|
|
94
94
|
const created = createTask(tx, {
|
|
95
95
|
projectId,
|
|
96
|
+
goalId: getOrCreateDefaultGoal(tx, projectId).id,
|
|
96
97
|
id: node.id,
|
|
97
98
|
label: node.label,
|
|
98
99
|
status: 'todo',
|