@supaku/agentfactory-nextjs 0.3.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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/factory.d.ts +105 -0
  3. package/dist/src/factory.d.ts.map +1 -0
  4. package/dist/src/factory.js +89 -0
  5. package/dist/src/handlers/cleanup.d.ts +44 -0
  6. package/dist/src/handlers/cleanup.d.ts.map +1 -0
  7. package/dist/src/handlers/cleanup.js +34 -0
  8. package/dist/src/handlers/public/session-detail.d.ts +31 -0
  9. package/dist/src/handlers/public/session-detail.d.ts.map +1 -0
  10. package/dist/src/handlers/public/session-detail.js +91 -0
  11. package/dist/src/handlers/public/sessions-list.d.ts +20 -0
  12. package/dist/src/handlers/public/sessions-list.d.ts.map +1 -0
  13. package/dist/src/handlers/public/sessions-list.js +73 -0
  14. package/dist/src/handlers/public/stats.d.ts +22 -0
  15. package/dist/src/handlers/public/stats.d.ts.map +1 -0
  16. package/dist/src/handlers/public/stats.js +53 -0
  17. package/dist/src/handlers/sessions/activity.d.ts +15 -0
  18. package/dist/src/handlers/sessions/activity.d.ts.map +1 -0
  19. package/dist/src/handlers/sessions/activity.js +77 -0
  20. package/dist/src/handlers/sessions/claim.d.ts +15 -0
  21. package/dist/src/handlers/sessions/claim.d.ts.map +1 -0
  22. package/dist/src/handlers/sessions/claim.js +87 -0
  23. package/dist/src/handlers/sessions/completion.d.ts +16 -0
  24. package/dist/src/handlers/sessions/completion.d.ts.map +1 -0
  25. package/dist/src/handlers/sessions/completion.js +82 -0
  26. package/dist/src/handlers/sessions/external-urls.d.ts +15 -0
  27. package/dist/src/handlers/sessions/external-urls.d.ts.map +1 -0
  28. package/dist/src/handlers/sessions/external-urls.js +59 -0
  29. package/dist/src/handlers/sessions/get.d.ts +19 -0
  30. package/dist/src/handlers/sessions/get.d.ts.map +1 -0
  31. package/dist/src/handlers/sessions/get.js +46 -0
  32. package/dist/src/handlers/sessions/list.d.ts +26 -0
  33. package/dist/src/handlers/sessions/list.d.ts.map +1 -0
  34. package/dist/src/handlers/sessions/list.js +50 -0
  35. package/dist/src/handlers/sessions/lock-refresh.d.ts +14 -0
  36. package/dist/src/handlers/sessions/lock-refresh.d.ts.map +1 -0
  37. package/dist/src/handlers/sessions/lock-refresh.js +38 -0
  38. package/dist/src/handlers/sessions/progress.d.ts +15 -0
  39. package/dist/src/handlers/sessions/progress.d.ts.map +1 -0
  40. package/dist/src/handlers/sessions/progress.js +82 -0
  41. package/dist/src/handlers/sessions/prompts.d.ts +15 -0
  42. package/dist/src/handlers/sessions/prompts.d.ts.map +1 -0
  43. package/dist/src/handlers/sessions/prompts.js +91 -0
  44. package/dist/src/handlers/sessions/status.d.ts +18 -0
  45. package/dist/src/handlers/sessions/status.d.ts.map +1 -0
  46. package/dist/src/handlers/sessions/status.js +131 -0
  47. package/dist/src/handlers/sessions/tool-error.d.ts +15 -0
  48. package/dist/src/handlers/sessions/tool-error.d.ts.map +1 -0
  49. package/dist/src/handlers/sessions/tool-error.js +91 -0
  50. package/dist/src/handlers/sessions/transfer-ownership.d.ts +14 -0
  51. package/dist/src/handlers/sessions/transfer-ownership.d.ts.map +1 -0
  52. package/dist/src/handlers/sessions/transfer-ownership.js +56 -0
  53. package/dist/src/handlers/workers/get-delete.d.ts +15 -0
  54. package/dist/src/handlers/workers/get-delete.d.ts.map +1 -0
  55. package/dist/src/handlers/workers/get-delete.js +58 -0
  56. package/dist/src/handlers/workers/heartbeat.d.ts +14 -0
  57. package/dist/src/handlers/workers/heartbeat.d.ts.map +1 -0
  58. package/dist/src/handlers/workers/heartbeat.js +42 -0
  59. package/dist/src/handlers/workers/list.d.ts +22 -0
  60. package/dist/src/handlers/workers/list.d.ts.map +1 -0
  61. package/dist/src/handlers/workers/list.js +33 -0
  62. package/dist/src/handlers/workers/poll.d.ts +14 -0
  63. package/dist/src/handlers/workers/poll.d.ts.map +1 -0
  64. package/dist/src/handlers/workers/poll.js +78 -0
  65. package/dist/src/handlers/workers/register.d.ts +9 -0
  66. package/dist/src/handlers/workers/register.d.ts.map +1 -0
  67. package/dist/src/handlers/workers/register.js +41 -0
  68. package/dist/src/index.d.ts +39 -0
  69. package/dist/src/index.d.ts.map +1 -0
  70. package/dist/src/index.js +41 -0
  71. package/dist/src/middleware/cron-auth.d.ts +21 -0
  72. package/dist/src/middleware/cron-auth.d.ts.map +1 -0
  73. package/dist/src/middleware/cron-auth.js +46 -0
  74. package/dist/src/middleware/worker-auth.d.ts +25 -0
  75. package/dist/src/middleware/worker-auth.d.ts.map +1 -0
  76. package/dist/src/middleware/worker-auth.js +43 -0
  77. package/dist/src/types.d.ts +62 -0
  78. package/dist/src/types.d.ts.map +1 -0
  79. package/dist/src/types.js +7 -0
  80. package/dist/src/webhook/handlers/issue-updated.d.ts +14 -0
  81. package/dist/src/webhook/handlers/issue-updated.d.ts.map +1 -0
  82. package/dist/src/webhook/handlers/issue-updated.js +462 -0
  83. package/dist/src/webhook/handlers/session-created.d.ts +9 -0
  84. package/dist/src/webhook/handlers/session-created.d.ts.map +1 -0
  85. package/dist/src/webhook/handlers/session-created.js +229 -0
  86. package/dist/src/webhook/handlers/session-prompted.d.ts +9 -0
  87. package/dist/src/webhook/handlers/session-prompted.d.ts.map +1 -0
  88. package/dist/src/webhook/handlers/session-prompted.js +197 -0
  89. package/dist/src/webhook/handlers/session-updated.d.ts +9 -0
  90. package/dist/src/webhook/handlers/session-updated.d.ts.map +1 -0
  91. package/dist/src/webhook/handlers/session-updated.js +29 -0
  92. package/dist/src/webhook/processor.d.ts +22 -0
  93. package/dist/src/webhook/processor.d.ts.map +1 -0
  94. package/dist/src/webhook/processor.js +98 -0
  95. package/dist/src/webhook/signature.d.ts +16 -0
  96. package/dist/src/webhook/signature.d.ts.map +1 -0
  97. package/dist/src/webhook/signature.js +23 -0
  98. package/dist/src/webhook/utils.d.ts +61 -0
  99. package/dist/src/webhook/utils.d.ts.map +1 -0
  100. package/dist/src/webhook/utils.js +159 -0
  101. package/package.json +66 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * POST /api/sessions/[id]/activity
3
+ *
4
+ * Report agent activity to be forwarded to Linear.
5
+ */
6
+ import { NextResponse } from 'next/server';
7
+ import { requireWorkerAuth } from '../../middleware/worker-auth.js';
8
+ import { getSessionState, createLogger } from '@supaku/agentfactory-server';
9
+ import { createAgentSession } from '@supaku/agentfactory-linear';
10
+ const log = createLogger('api:sessions:activity');
11
+ export function createSessionActivityHandler(config) {
12
+ return async function POST(request, { params }) {
13
+ const authError = requireWorkerAuth(request);
14
+ if (authError)
15
+ return authError;
16
+ const { id: sessionId } = await params;
17
+ try {
18
+ const body = await request.json();
19
+ const { workerId, activity } = body;
20
+ if (!workerId || typeof workerId !== 'string') {
21
+ return NextResponse.json({ error: 'Bad Request', message: 'workerId is required' }, { status: 400 });
22
+ }
23
+ if (!activity || !activity.type || !activity.content) {
24
+ return NextResponse.json({ error: 'Bad Request', message: 'activity with type and content is required' }, { status: 400 });
25
+ }
26
+ const session = await getSessionState(sessionId);
27
+ if (!session) {
28
+ return NextResponse.json({ error: 'Not Found', message: 'Session not found' }, { status: 404 });
29
+ }
30
+ if (session.workerId && session.workerId !== workerId) {
31
+ return NextResponse.json({ error: 'Forbidden', message: 'Session is owned by another worker' }, { status: 403 });
32
+ }
33
+ try {
34
+ const linearClient = await config.linearClient.getClient(session.organizationId);
35
+ const agentSession = createAgentSession({
36
+ client: linearClient.linearClient,
37
+ issueId: session.issueId,
38
+ sessionId,
39
+ autoTransition: false,
40
+ });
41
+ switch (activity.type) {
42
+ case 'thought':
43
+ await agentSession.emitThought(activity.content);
44
+ break;
45
+ case 'action':
46
+ await agentSession.emitAction(activity.toolName || 'Tool', activity.toolInput || {});
47
+ break;
48
+ case 'response':
49
+ await agentSession.emitResponse(activity.content);
50
+ break;
51
+ }
52
+ log.debug('Activity forwarded to Linear', {
53
+ sessionId,
54
+ activityType: activity.type,
55
+ issueId: session.issueId,
56
+ });
57
+ return NextResponse.json({
58
+ forwarded: true,
59
+ });
60
+ }
61
+ catch (linearError) {
62
+ log.error('Failed to forward activity to Linear', {
63
+ error: linearError,
64
+ sessionId,
65
+ });
66
+ return NextResponse.json({
67
+ forwarded: false,
68
+ reason: 'Failed to forward to Linear',
69
+ });
70
+ }
71
+ }
72
+ catch (error) {
73
+ log.error('Failed to process activity', { error, sessionId });
74
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to process activity' }, { status: 500 });
75
+ }
76
+ };
77
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * POST /api/sessions/[id]/claim
3
+ *
4
+ * Claim a session for processing.
5
+ * Uses atomic operations to prevent race conditions.
6
+ */
7
+ import { NextRequest, NextResponse } from 'next/server';
8
+ interface RouteParams {
9
+ params: Promise<{
10
+ id: string;
11
+ }>;
12
+ }
13
+ export declare function createSessionClaimHandler(): (request: NextRequest, { params }: RouteParams) => Promise<NextResponse<unknown>>;
14
+ export {};
15
+ //# sourceMappingURL=claim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/claim.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAcvD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAED,wBAAgB,yBAAyB,KACZ,SAAS,WAAW,EAAE,YAAY,WAAW,oCA6FzE"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * POST /api/sessions/[id]/claim
3
+ *
4
+ * Claim a session for processing.
5
+ * Uses atomic operations to prevent race conditions.
6
+ */
7
+ import { NextResponse } from 'next/server';
8
+ import { requireWorkerAuth } from '../../middleware/worker-auth.js';
9
+ import { claimWork, requeueWork, releaseClaim, claimSession, getSessionState, addWorkerSession, createLogger, } from '@supaku/agentfactory-server';
10
+ const log = createLogger('api:sessions:claim');
11
+ export function createSessionClaimHandler() {
12
+ return async function POST(request, { params }) {
13
+ const authError = requireWorkerAuth(request);
14
+ if (authError)
15
+ return authError;
16
+ const { id: sessionId } = await params;
17
+ try {
18
+ const body = await request.json();
19
+ const { workerId } = body;
20
+ if (!workerId || typeof workerId !== 'string') {
21
+ return NextResponse.json({ error: 'Bad Request', message: 'workerId is required' }, { status: 400 });
22
+ }
23
+ const work = await claimWork(sessionId, workerId);
24
+ if (!work) {
25
+ log.debug('Failed to claim work from queue', { sessionId, workerId });
26
+ return NextResponse.json({
27
+ claimed: false,
28
+ reason: 'Work item not available or already claimed',
29
+ });
30
+ }
31
+ const claimed = await claimSession(sessionId, workerId);
32
+ if (!claimed) {
33
+ const sessionState = await getSessionState(sessionId);
34
+ if (!sessionState) {
35
+ log.warn('Session state expired, dropping orphaned work item', {
36
+ sessionId,
37
+ workerId,
38
+ issueIdentifier: work.issueIdentifier,
39
+ });
40
+ await releaseClaim(sessionId);
41
+ return NextResponse.json({
42
+ claimed: false,
43
+ reason: 'Session state expired, work item dropped',
44
+ });
45
+ }
46
+ if (sessionState.status !== 'pending') {
47
+ log.warn('Session not in pending status, dropping work item', {
48
+ sessionId,
49
+ workerId,
50
+ issueIdentifier: work.issueIdentifier,
51
+ sessionStatus: sessionState.status,
52
+ });
53
+ await releaseClaim(sessionId);
54
+ return NextResponse.json({
55
+ claimed: false,
56
+ reason: `Session in ${sessionState.status} status, work item dropped`,
57
+ });
58
+ }
59
+ log.warn('Transient failure updating session state, re-queuing', {
60
+ sessionId,
61
+ workerId,
62
+ });
63
+ await requeueWork(work);
64
+ return NextResponse.json({
65
+ claimed: false,
66
+ reason: 'Session state update failed, work re-queued',
67
+ });
68
+ }
69
+ await addWorkerSession(workerId, sessionId);
70
+ const session = await getSessionState(sessionId);
71
+ log.info('Session claimed', {
72
+ sessionId,
73
+ workerId,
74
+ issueIdentifier: work.issueIdentifier,
75
+ });
76
+ return NextResponse.json({
77
+ claimed: true,
78
+ session,
79
+ work,
80
+ });
81
+ }
82
+ catch (error) {
83
+ log.error('Failed to claim session', { error, sessionId });
84
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to claim session' }, { status: 500 });
85
+ }
86
+ };
87
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * POST /api/sessions/[id]/completion
3
+ *
4
+ * Post agent completion comment to Linear.
5
+ * Uses multi-comment splitting for long messages.
6
+ */
7
+ import { NextRequest, NextResponse } from 'next/server';
8
+ import type { RouteConfig } from '../../types.js';
9
+ interface RouteParams {
10
+ params: Promise<{
11
+ id: string;
12
+ }>;
13
+ }
14
+ export declare function createSessionCompletionHandler(config: RouteConfig): (request: NextRequest, { params }: RouteParams) => Promise<NextResponse<unknown>>;
15
+ export {};
16
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/completion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAIjD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAWD,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,WAAW,IACrC,SAAS,WAAW,EAAE,YAAY,WAAW,oCA6FzE"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * POST /api/sessions/[id]/completion
3
+ *
4
+ * Post agent completion comment to Linear.
5
+ * Uses multi-comment splitting for long messages.
6
+ */
7
+ import { NextResponse } from 'next/server';
8
+ import { requireWorkerAuth } from '../../middleware/worker-auth.js';
9
+ import { getSessionState, createLogger } from '@supaku/agentfactory-server';
10
+ import { buildCompletionComments } from '@supaku/agentfactory-linear';
11
+ const log = createLogger('api:sessions:completion');
12
+ export function createSessionCompletionHandler(config) {
13
+ return async function POST(request, { params }) {
14
+ const authError = requireWorkerAuth(request);
15
+ if (authError)
16
+ return authError;
17
+ const { id: sessionId } = await params;
18
+ try {
19
+ const body = (await request.json());
20
+ const { workerId, summary, planItems = [] } = body;
21
+ if (!summary || typeof summary !== 'string') {
22
+ return NextResponse.json({ error: 'Bad Request', message: 'summary is required' }, { status: 400 });
23
+ }
24
+ const session = await getSessionState(sessionId);
25
+ if (!session) {
26
+ return NextResponse.json({ error: 'Not Found', message: 'Session not found' }, { status: 404 });
27
+ }
28
+ if (workerId && session.workerId && session.workerId !== workerId) {
29
+ return NextResponse.json({ error: 'Forbidden', message: 'Session is owned by another worker' }, { status: 403 });
30
+ }
31
+ const comments = buildCompletionComments(summary, planItems, sessionId);
32
+ log.info('Posting completion comments', {
33
+ sessionId,
34
+ issueId: session.issueId,
35
+ parts: comments.length,
36
+ summaryLength: summary.length,
37
+ });
38
+ const linearClient = await config.linearClient.getClient(session.organizationId);
39
+ let postedCount = 0;
40
+ const errors = [];
41
+ for (const chunk of comments) {
42
+ try {
43
+ await linearClient.createComment(session.issueId, chunk.body);
44
+ postedCount++;
45
+ log.debug(`Posted completion comment part ${chunk.partNumber}/${chunk.totalParts}`, {
46
+ sessionId,
47
+ issueId: session.issueId,
48
+ });
49
+ if (chunk.partNumber < chunk.totalParts) {
50
+ await new Promise((resolve) => setTimeout(resolve, 100));
51
+ }
52
+ }
53
+ catch (error) {
54
+ const errorMsg = error instanceof Error ? error.message : String(error);
55
+ errors.push(`Part ${chunk.partNumber}: ${errorMsg}`);
56
+ log.error(`Failed to post completion comment part ${chunk.partNumber}`, {
57
+ error,
58
+ sessionId,
59
+ issueId: session.issueId,
60
+ });
61
+ }
62
+ }
63
+ if (postedCount === 0) {
64
+ return NextResponse.json({
65
+ error: 'Internal Server Error',
66
+ message: 'Failed to post any completion comments',
67
+ errors,
68
+ }, { status: 500 });
69
+ }
70
+ return NextResponse.json({
71
+ posted: true,
72
+ partsPosted: postedCount,
73
+ totalParts: comments.length,
74
+ errors: errors.length > 0 ? errors : undefined,
75
+ });
76
+ }
77
+ catch (error) {
78
+ log.error('Failed to process completion', { error, sessionId });
79
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to process completion' }, { status: 500 });
80
+ }
81
+ };
82
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * POST /api/sessions/[id]/external-urls
3
+ *
4
+ * Update external URLs for an agent session.
5
+ */
6
+ import { NextRequest, NextResponse } from 'next/server';
7
+ import type { RouteConfig } from '../../types.js';
8
+ interface RouteParams {
9
+ params: Promise<{
10
+ id: string;
11
+ }>;
12
+ }
13
+ export declare function createSessionExternalUrlsHandler(config: RouteConfig): (request: NextRequest, { params }: RouteParams) => Promise<NextResponse<unknown>>;
14
+ export {};
15
+ //# sourceMappingURL=external-urls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-urls.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/external-urls.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAIjD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAOD,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,IACvC,SAAS,WAAW,EAAE,YAAY,WAAW,oCAwEzE"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * POST /api/sessions/[id]/external-urls
3
+ *
4
+ * Update external URLs for an agent session.
5
+ */
6
+ import { NextResponse } from 'next/server';
7
+ import { requireWorkerAuth } from '../../middleware/worker-auth.js';
8
+ import { getSessionState, createLogger } from '@supaku/agentfactory-server';
9
+ const log = createLogger('api:sessions:external-urls');
10
+ export function createSessionExternalUrlsHandler(config) {
11
+ return async function POST(request, { params }) {
12
+ const authError = requireWorkerAuth(request);
13
+ if (authError)
14
+ return authError;
15
+ const { id: sessionId } = await params;
16
+ try {
17
+ const body = await request.json();
18
+ const { externalUrls, workspaceId } = body;
19
+ if (!externalUrls || !Array.isArray(externalUrls)) {
20
+ return NextResponse.json({ error: 'Bad Request', message: 'externalUrls array is required' }, { status: 400 });
21
+ }
22
+ for (const extUrl of externalUrls) {
23
+ if (!extUrl.label || !extUrl.url) {
24
+ return NextResponse.json({ error: 'Bad Request', message: 'Each external URL must have label and url' }, { status: 400 });
25
+ }
26
+ }
27
+ const session = await getSessionState(sessionId);
28
+ if (!session) {
29
+ return NextResponse.json({ error: 'Not Found', message: 'Session not found' }, { status: 404 });
30
+ }
31
+ const effectiveWorkspaceId = workspaceId || session.organizationId;
32
+ if (!effectiveWorkspaceId) {
33
+ log.warn('No workspace ID available, falling back to default client', {
34
+ sessionId,
35
+ hasWorkspaceIdInRequest: !!workspaceId,
36
+ hasOrganizationIdInSession: !!session.organizationId,
37
+ });
38
+ }
39
+ const linearClient = await config.linearClient.getClient(effectiveWorkspaceId);
40
+ await linearClient.updateAgentSession({
41
+ sessionId,
42
+ externalUrls,
43
+ });
44
+ log.info('External URLs updated', {
45
+ sessionId,
46
+ urlCount: externalUrls.length,
47
+ labels: externalUrls.map((u) => u.label),
48
+ });
49
+ return NextResponse.json({
50
+ updated: true,
51
+ externalUrls,
52
+ });
53
+ }
54
+ catch (error) {
55
+ log.error('Failed to update external URLs', { error, sessionId });
56
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to update external URLs' }, { status: 500 });
57
+ }
58
+ };
59
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * GET /api/sessions/[id]
3
+ * Returns a single agent session by ID
4
+ */
5
+ import { NextRequest, NextResponse } from 'next/server';
6
+ import type { AgentSessionResponse } from './list.js';
7
+ interface RouteParams {
8
+ params: Promise<{
9
+ id: string;
10
+ }>;
11
+ }
12
+ export declare function createSessionGetHandler(): (_request: NextRequest, { params }: RouteParams) => Promise<NextResponse<{
13
+ error: string;
14
+ message: string;
15
+ }> | NextResponse<{
16
+ session: AgentSessionResponse;
17
+ }>>;
18
+ export {};
19
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/get.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAIrD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAwBD,wBAAgB,uBAAuB,KACX,UAAU,WAAW,EAAE,YAAY,WAAW;;;;;IAwBzE"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * GET /api/sessions/[id]
3
+ * Returns a single agent session by ID
4
+ */
5
+ import { NextResponse } from 'next/server';
6
+ import { getSessionState, createLogger } from '@supaku/agentfactory-server';
7
+ const log = createLogger('api:sessions:[id]');
8
+ function toResponse(session) {
9
+ return {
10
+ id: session.linearSessionId,
11
+ linearSessionId: session.linearSessionId,
12
+ issueId: session.issueId,
13
+ identifier: session.issueIdentifier || session.issueId.slice(0, 8),
14
+ claudeSessionId: session.claudeSessionId || undefined,
15
+ status: session.status,
16
+ createdAt: new Date(session.createdAt * 1000).toISOString(),
17
+ updatedAt: new Date(session.updatedAt * 1000).toISOString(),
18
+ worktreePath: session.worktreePath,
19
+ workerId: session.workerId || undefined,
20
+ queuedAt: session.queuedAt
21
+ ? new Date(session.queuedAt).toISOString()
22
+ : undefined,
23
+ claimedAt: session.claimedAt
24
+ ? new Date(session.claimedAt * 1000).toISOString()
25
+ : undefined,
26
+ agentId: session.agentId || undefined,
27
+ };
28
+ }
29
+ export function createSessionGetHandler() {
30
+ return async function GET(_request, { params }) {
31
+ const { id: sessionId } = await params;
32
+ try {
33
+ const session = await getSessionState(sessionId);
34
+ if (!session) {
35
+ return NextResponse.json({ error: 'Not Found', message: 'Session not found' }, { status: 404 });
36
+ }
37
+ return NextResponse.json({
38
+ session: toResponse(session),
39
+ });
40
+ }
41
+ catch (error) {
42
+ log.error('Failed to fetch session', { error, sessionId });
43
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to fetch session' }, { status: 500 });
44
+ }
45
+ };
46
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * GET /api/sessions
3
+ * Returns list of all agent sessions from Redis
4
+ */
5
+ import { NextResponse } from 'next/server';
6
+ export interface AgentSessionResponse {
7
+ id: string;
8
+ linearSessionId: string;
9
+ issueId: string;
10
+ identifier: string;
11
+ claudeSessionId?: string;
12
+ status: 'pending' | 'claimed' | 'running' | 'finalizing' | 'completed' | 'failed' | 'stopped';
13
+ createdAt: string;
14
+ updatedAt: string;
15
+ worktreePath: string;
16
+ workerId?: string;
17
+ queuedAt?: string;
18
+ claimedAt?: string;
19
+ agentId?: string;
20
+ }
21
+ export declare function createSessionListHandler(): () => Promise<NextResponse<{
22
+ sessions: AgentSessionResponse[];
23
+ count: number;
24
+ timestamp: string;
25
+ }>>;
26
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/list.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK1C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAA;IAC7F,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAwBD,wBAAgB,wBAAwB;;;;IAsBvC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GET /api/sessions
3
+ * Returns list of all agent sessions from Redis
4
+ */
5
+ import { NextResponse } from 'next/server';
6
+ import { getAllSessions, createLogger } from '@supaku/agentfactory-server';
7
+ const log = createLogger('api/sessions');
8
+ function toResponse(session) {
9
+ return {
10
+ id: session.linearSessionId,
11
+ linearSessionId: session.linearSessionId,
12
+ issueId: session.issueId,
13
+ identifier: session.issueIdentifier || session.issueId.slice(0, 8),
14
+ claudeSessionId: session.claudeSessionId || undefined,
15
+ status: session.status,
16
+ createdAt: new Date(session.createdAt * 1000).toISOString(),
17
+ updatedAt: new Date(session.updatedAt * 1000).toISOString(),
18
+ worktreePath: session.worktreePath,
19
+ workerId: session.workerId || undefined,
20
+ queuedAt: session.queuedAt
21
+ ? new Date(session.queuedAt).toISOString()
22
+ : undefined,
23
+ claimedAt: session.claimedAt
24
+ ? new Date(session.claimedAt * 1000).toISOString()
25
+ : undefined,
26
+ agentId: session.agentId || undefined,
27
+ };
28
+ }
29
+ export function createSessionListHandler() {
30
+ return async function GET() {
31
+ try {
32
+ const allSessions = await getAllSessions();
33
+ const sessions = allSessions.map(toResponse);
34
+ return NextResponse.json({
35
+ sessions,
36
+ count: sessions.length,
37
+ timestamp: new Date().toISOString(),
38
+ });
39
+ }
40
+ catch (error) {
41
+ log.error('Failed to fetch sessions', { error });
42
+ return NextResponse.json({
43
+ sessions: [],
44
+ count: 0,
45
+ timestamp: new Date().toISOString(),
46
+ error: 'Failed to fetch sessions from Redis',
47
+ });
48
+ }
49
+ };
50
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * POST /api/sessions/[id]/lock-refresh
3
+ *
4
+ * Refresh the issue lock TTL for an active session.
5
+ */
6
+ import { NextRequest, NextResponse } from 'next/server';
7
+ interface RouteParams {
8
+ params: Promise<{
9
+ id: string;
10
+ }>;
11
+ }
12
+ export declare function createSessionLockRefreshHandler(): (request: NextRequest, { params }: RouteParams) => Promise<NextResponse<unknown>>;
13
+ export {};
14
+ //# sourceMappingURL=lock-refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock-refresh.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/lock-refresh.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAED,wBAAgB,+BAA+B,KAClB,SAAS,WAAW,EAAE,YAAY,WAAW,oCA6CzE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * POST /api/sessions/[id]/lock-refresh
3
+ *
4
+ * Refresh the issue lock TTL for an active session.
5
+ */
6
+ import { NextResponse } from 'next/server';
7
+ import { requireWorkerAuth } from '../../middleware/worker-auth.js';
8
+ import { getSessionState, refreshIssueLockTTL, createLogger } from '@supaku/agentfactory-server';
9
+ const log = createLogger('api:sessions:lock-refresh');
10
+ export function createSessionLockRefreshHandler() {
11
+ return async function POST(request, { params }) {
12
+ const authError = requireWorkerAuth(request);
13
+ if (authError)
14
+ return authError;
15
+ const { id: sessionId } = await params;
16
+ try {
17
+ const body = await request.json();
18
+ const { workerId, issueId } = body;
19
+ if (!workerId || !issueId) {
20
+ return NextResponse.json({ error: 'Bad Request', message: 'workerId and issueId are required' }, { status: 400 });
21
+ }
22
+ const session = await getSessionState(sessionId);
23
+ if (!session) {
24
+ return NextResponse.json({ error: 'Not Found', message: 'Session not found' }, { status: 404 });
25
+ }
26
+ if (session.workerId && session.workerId !== workerId) {
27
+ return NextResponse.json({ error: 'Forbidden', message: 'Session is owned by another worker' }, { status: 403 });
28
+ }
29
+ const refreshed = await refreshIssueLockTTL(issueId);
30
+ log.debug('Lock TTL refreshed', { sessionId, issueId, refreshed });
31
+ return NextResponse.json({ refreshed });
32
+ }
33
+ catch (error) {
34
+ log.error('Failed to refresh lock TTL', { error, sessionId });
35
+ return NextResponse.json({ error: 'Internal Server Error', message: 'Failed to refresh lock TTL' }, { status: 500 });
36
+ }
37
+ };
38
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * POST /api/sessions/[id]/progress
3
+ *
4
+ * Post a progress update as an agent activity to Linear.
5
+ */
6
+ import { NextRequest, NextResponse } from 'next/server';
7
+ import type { RouteConfig } from '../../types.js';
8
+ interface RouteParams {
9
+ params: Promise<{
10
+ id: string;
11
+ }>;
12
+ }
13
+ export declare function createSessionProgressHandler(config: RouteConfig): (request: NextRequest, { params }: RouteParams) => Promise<NextResponse<unknown>>;
14
+ export {};
15
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../../src/handlers/sessions/progress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAIjD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAeD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,WAAW,IACnC,SAAS,WAAW,EAAE,YAAY,WAAW,oCAsFzE"}