@lovelybunch/api 1.0.57 → 1.0.59
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/git.d.ts +13 -0
- package/dist/lib/git.js +137 -5
- package/dist/lib/jobs/global-job-scheduler.d.ts +2 -0
- package/dist/lib/jobs/global-job-scheduler.js +11 -0
- package/dist/lib/jobs/job-runner.d.ts +17 -0
- package/dist/lib/jobs/job-runner.js +167 -0
- package/dist/lib/jobs/job-scheduler.d.ts +39 -0
- package/dist/lib/jobs/job-scheduler.js +309 -0
- package/dist/lib/jobs/job-store.d.ts +16 -0
- package/dist/lib/jobs/job-store.js +211 -0
- package/dist/lib/storage/file-storage.js +7 -5
- package/dist/lib/terminal/terminal-manager.d.ts +2 -0
- package/dist/lib/terminal/terminal-manager.js +65 -0
- package/dist/routes/api/v1/ai/route.d.ts +1 -7
- package/dist/routes/api/v1/ai/route.js +25 -12
- package/dist/routes/api/v1/git/index.js +63 -1
- package/dist/routes/api/v1/jobs/[id]/route.d.ts +133 -0
- package/dist/routes/api/v1/jobs/[id]/route.js +135 -0
- package/dist/routes/api/v1/jobs/[id]/run/route.d.ts +31 -0
- package/dist/routes/api/v1/jobs/[id]/run/route.js +37 -0
- package/dist/routes/api/v1/jobs/index.d.ts +3 -0
- package/dist/routes/api/v1/jobs/index.js +14 -0
- package/dist/routes/api/v1/jobs/route.d.ts +108 -0
- package/dist/routes/api/v1/jobs/route.js +144 -0
- package/dist/routes/api/v1/jobs/status/route.d.ts +23 -0
- package/dist/routes/api/v1/jobs/status/route.js +21 -0
- package/dist/routes/api/v1/resources/[id]/route.d.ts +2 -44
- package/dist/server-with-static.js +5 -0
- package/dist/server.js +5 -0
- package/package.json +4 -4
- package/static/assets/index-CHq6mL1J.css +33 -0
- package/static/assets/index-QHnHUcsV.js +820 -0
- package/static/index.html +2 -2
- package/static/assets/index-CRg4lVi6.js +0 -779
- package/static/assets/index-VqhUTak4.css +0 -33
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
import { DayOfWeek, ScheduledJobSchedule, ScheduledJobStatus } from '@lovelybunch/types';
|
|
3
|
+
export declare function normalizeSchedule(schedule?: Partial<ScheduledJobSchedule>): ScheduledJobSchedule;
|
|
4
|
+
export declare function normalizeStatus(status?: ScheduledJobStatus): ScheduledJobStatus;
|
|
5
|
+
export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
6
|
+
success: true;
|
|
7
|
+
data: {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
prompt: string;
|
|
12
|
+
model: string;
|
|
13
|
+
status: ScheduledJobStatus;
|
|
14
|
+
schedule: {
|
|
15
|
+
type: "cron";
|
|
16
|
+
expression: string;
|
|
17
|
+
timezone?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: "interval";
|
|
21
|
+
hours: number;
|
|
22
|
+
daysOfWeek: DayOfWeek[];
|
|
23
|
+
timezone?: string;
|
|
24
|
+
anchorHour?: number;
|
|
25
|
+
};
|
|
26
|
+
metadata: {
|
|
27
|
+
createdAt: string;
|
|
28
|
+
updatedAt: string;
|
|
29
|
+
lastRunAt?: string;
|
|
30
|
+
nextRunAt?: string;
|
|
31
|
+
};
|
|
32
|
+
runs: {
|
|
33
|
+
id: string;
|
|
34
|
+
jobId: string;
|
|
35
|
+
trigger: import("@lovelybunch/types").ScheduledJobTrigger;
|
|
36
|
+
status: import("@lovelybunch/types").ScheduledJobRunStatus;
|
|
37
|
+
startedAt: string;
|
|
38
|
+
finishedAt?: string;
|
|
39
|
+
outputPath?: string;
|
|
40
|
+
summary?: string;
|
|
41
|
+
error?: string;
|
|
42
|
+
cliCommand?: string;
|
|
43
|
+
}[];
|
|
44
|
+
tags?: string[];
|
|
45
|
+
contextPaths?: string[];
|
|
46
|
+
}[];
|
|
47
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
48
|
+
success: false;
|
|
49
|
+
error: {
|
|
50
|
+
code: string;
|
|
51
|
+
message: any;
|
|
52
|
+
};
|
|
53
|
+
}, 500, "json">)>;
|
|
54
|
+
export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
55
|
+
success: false;
|
|
56
|
+
error: {
|
|
57
|
+
code: string;
|
|
58
|
+
message: any;
|
|
59
|
+
};
|
|
60
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
61
|
+
success: true;
|
|
62
|
+
data: {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
prompt: string;
|
|
67
|
+
model: string;
|
|
68
|
+
status: ScheduledJobStatus;
|
|
69
|
+
schedule: {
|
|
70
|
+
type: "cron";
|
|
71
|
+
expression: string;
|
|
72
|
+
timezone?: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: "interval";
|
|
76
|
+
hours: number;
|
|
77
|
+
daysOfWeek: DayOfWeek[];
|
|
78
|
+
timezone?: string;
|
|
79
|
+
anchorHour?: number;
|
|
80
|
+
};
|
|
81
|
+
metadata: {
|
|
82
|
+
createdAt: string;
|
|
83
|
+
updatedAt: string;
|
|
84
|
+
lastRunAt?: string;
|
|
85
|
+
nextRunAt?: string;
|
|
86
|
+
};
|
|
87
|
+
runs: {
|
|
88
|
+
id: string;
|
|
89
|
+
jobId: string;
|
|
90
|
+
trigger: import("@lovelybunch/types").ScheduledJobTrigger;
|
|
91
|
+
status: import("@lovelybunch/types").ScheduledJobRunStatus;
|
|
92
|
+
startedAt: string;
|
|
93
|
+
finishedAt?: string;
|
|
94
|
+
outputPath?: string;
|
|
95
|
+
summary?: string;
|
|
96
|
+
error?: string;
|
|
97
|
+
cliCommand?: string;
|
|
98
|
+
}[];
|
|
99
|
+
tags?: string[];
|
|
100
|
+
contextPaths?: string[];
|
|
101
|
+
};
|
|
102
|
+
}, 201, "json">) | (Response & import("hono").TypedResponse<{
|
|
103
|
+
success: false;
|
|
104
|
+
error: {
|
|
105
|
+
code: string;
|
|
106
|
+
message: any;
|
|
107
|
+
};
|
|
108
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { JobStore } from '../../../../lib/jobs/job-store.js';
|
|
3
|
+
import { getGlobalJobScheduler } from '../../../../lib/jobs/global-job-scheduler.js';
|
|
4
|
+
const store = new JobStore();
|
|
5
|
+
const scheduler = getGlobalJobScheduler();
|
|
6
|
+
const DAY_ORDER = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
|
|
7
|
+
function normalizeDays(days) {
|
|
8
|
+
if (!Array.isArray(days) || days.length === 0) {
|
|
9
|
+
return ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
|
|
10
|
+
}
|
|
11
|
+
const unique = Array.from(new Set(days.map((day) => day.toLowerCase())));
|
|
12
|
+
return unique
|
|
13
|
+
.filter((day) => DAY_ORDER.includes(day))
|
|
14
|
+
.sort((a, b) => DAY_ORDER.indexOf(a) - DAY_ORDER.indexOf(b));
|
|
15
|
+
}
|
|
16
|
+
function validateIntervalSchedule(schedule) {
|
|
17
|
+
const hours = Number(schedule?.hours ?? 6);
|
|
18
|
+
if (!Number.isFinite(hours) || hours < 1) {
|
|
19
|
+
throw new Error('Interval hours must be a positive number of hours (>= 1).');
|
|
20
|
+
}
|
|
21
|
+
if (hours > 24 * 30) {
|
|
22
|
+
throw new Error('Interval hours must be less than or equal to 720 (30 days).');
|
|
23
|
+
}
|
|
24
|
+
const days = normalizeDays(schedule?.daysOfWeek);
|
|
25
|
+
if (days.length === 0) {
|
|
26
|
+
throw new Error('At least one day of the week must be selected.');
|
|
27
|
+
}
|
|
28
|
+
let anchorHour;
|
|
29
|
+
if (schedule?.anchorHour !== undefined) {
|
|
30
|
+
const parsed = Number(schedule.anchorHour);
|
|
31
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 23) {
|
|
32
|
+
throw new Error('Anchor hour must be between 0 and 23.');
|
|
33
|
+
}
|
|
34
|
+
anchorHour = parsed;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
type: 'interval',
|
|
38
|
+
hours,
|
|
39
|
+
daysOfWeek: days,
|
|
40
|
+
anchorHour
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function normalizeSchedule(schedule) {
|
|
44
|
+
if (!schedule || schedule.type !== 'cron') {
|
|
45
|
+
return validateIntervalSchedule(schedule);
|
|
46
|
+
}
|
|
47
|
+
const expression = schedule.expression?.trim();
|
|
48
|
+
if (!expression) {
|
|
49
|
+
throw new Error('Cron expression is required when using cron schedules.');
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
type: 'cron',
|
|
53
|
+
expression,
|
|
54
|
+
timezone: schedule.timezone,
|
|
55
|
+
description: schedule.description,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function normalizeStatus(status) {
|
|
59
|
+
return status === 'active' ? 'active' : 'paused';
|
|
60
|
+
}
|
|
61
|
+
export async function GET(c) {
|
|
62
|
+
try {
|
|
63
|
+
const jobs = await store.listJobs();
|
|
64
|
+
return c.json({
|
|
65
|
+
success: true,
|
|
66
|
+
data: jobs
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('Failed to list scheduled jobs:', error);
|
|
71
|
+
return c.json({
|
|
72
|
+
success: false,
|
|
73
|
+
error: {
|
|
74
|
+
code: 'LIST_JOBS_ERROR',
|
|
75
|
+
message: error?.message ?? 'Unknown error listing jobs'
|
|
76
|
+
}
|
|
77
|
+
}, 500);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export async function POST(c) {
|
|
81
|
+
try {
|
|
82
|
+
const body = await c.req.json();
|
|
83
|
+
if (!body?.prompt || typeof body.prompt !== 'string') {
|
|
84
|
+
return c.json({
|
|
85
|
+
success: false,
|
|
86
|
+
error: {
|
|
87
|
+
code: 'MISSING_PROMPT',
|
|
88
|
+
message: 'A prompt is required to create a scheduled job.'
|
|
89
|
+
}
|
|
90
|
+
}, 400);
|
|
91
|
+
}
|
|
92
|
+
const now = new Date();
|
|
93
|
+
const id = body.id || `job-${randomUUID()}`;
|
|
94
|
+
let schedule;
|
|
95
|
+
try {
|
|
96
|
+
schedule = normalizeSchedule(body.schedule);
|
|
97
|
+
}
|
|
98
|
+
catch (validationError) {
|
|
99
|
+
return c.json({
|
|
100
|
+
success: false,
|
|
101
|
+
error: {
|
|
102
|
+
code: 'INVALID_SCHEDULE',
|
|
103
|
+
message: validationError?.message || 'Invalid schedule definition.'
|
|
104
|
+
}
|
|
105
|
+
}, 400);
|
|
106
|
+
}
|
|
107
|
+
const status = normalizeStatus(body.status);
|
|
108
|
+
const job = {
|
|
109
|
+
id,
|
|
110
|
+
name: body.name || id,
|
|
111
|
+
description: body.description,
|
|
112
|
+
prompt: body.prompt,
|
|
113
|
+
model: (body.model || 'claude').toString(),
|
|
114
|
+
status,
|
|
115
|
+
schedule,
|
|
116
|
+
metadata: {
|
|
117
|
+
createdAt: now,
|
|
118
|
+
updatedAt: now,
|
|
119
|
+
lastRunAt: undefined,
|
|
120
|
+
nextRunAt: undefined,
|
|
121
|
+
},
|
|
122
|
+
runs: [],
|
|
123
|
+
tags: Array.isArray(body.tags) ? body.tags : [],
|
|
124
|
+
contextPaths: Array.isArray(body.contextPaths) ? body.contextPaths : [],
|
|
125
|
+
};
|
|
126
|
+
await store.saveJob(job);
|
|
127
|
+
await scheduler.refresh(job.id);
|
|
128
|
+
const created = await store.getJob(job.id);
|
|
129
|
+
return c.json({
|
|
130
|
+
success: true,
|
|
131
|
+
data: created ?? job
|
|
132
|
+
}, 201);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Failed to create scheduled job:', error);
|
|
136
|
+
return c.json({
|
|
137
|
+
success: false,
|
|
138
|
+
error: {
|
|
139
|
+
code: 'CREATE_JOB_ERROR',
|
|
140
|
+
message: error?.message ?? 'Unknown error creating job'
|
|
141
|
+
}
|
|
142
|
+
}, 500);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
success: true;
|
|
4
|
+
data: {
|
|
5
|
+
initialized: boolean;
|
|
6
|
+
jobCount: number;
|
|
7
|
+
runningCount: number;
|
|
8
|
+
jobs: {
|
|
9
|
+
id: string;
|
|
10
|
+
status: import("@lovelybunch/types").ScheduledJobStatus;
|
|
11
|
+
nextRunAt?: string;
|
|
12
|
+
lastRunAt?: string;
|
|
13
|
+
timerActive: boolean;
|
|
14
|
+
running: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
18
|
+
success: false;
|
|
19
|
+
error: {
|
|
20
|
+
code: string;
|
|
21
|
+
message: any;
|
|
22
|
+
};
|
|
23
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getGlobalJobScheduler } from '../../../../../lib/jobs/global-job-scheduler.js';
|
|
2
|
+
const scheduler = getGlobalJobScheduler();
|
|
3
|
+
export async function GET(c) {
|
|
4
|
+
try {
|
|
5
|
+
const status = scheduler.getStatus();
|
|
6
|
+
return c.json({
|
|
7
|
+
success: true,
|
|
8
|
+
data: status
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
console.error('Failed to fetch scheduler status:', error);
|
|
13
|
+
return c.json({
|
|
14
|
+
success: false,
|
|
15
|
+
error: {
|
|
16
|
+
code: 'SCHEDULER_STATUS_ERROR',
|
|
17
|
+
message: error?.message ?? 'Unknown error retrieving scheduler status'
|
|
18
|
+
}
|
|
19
|
+
}, 500);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,46 +1,4 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
2
|
export declare function GET(c: Context): Promise<Response>;
|
|
3
|
-
export declare function PUT(c: Context): Promise<
|
|
4
|
-
|
|
5
|
-
error: {
|
|
6
|
-
code: string;
|
|
7
|
-
message: string;
|
|
8
|
-
};
|
|
9
|
-
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
10
|
-
success: true;
|
|
11
|
-
data: {
|
|
12
|
-
id: string;
|
|
13
|
-
name: string;
|
|
14
|
-
type: string;
|
|
15
|
-
size: number;
|
|
16
|
-
uploadedAt: string;
|
|
17
|
-
metadata: {
|
|
18
|
-
tags?: string[];
|
|
19
|
-
description?: string;
|
|
20
|
-
};
|
|
21
|
-
path: string;
|
|
22
|
-
thumbnailPath?: string;
|
|
23
|
-
};
|
|
24
|
-
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
25
|
-
success: false;
|
|
26
|
-
error: {
|
|
27
|
-
code: string;
|
|
28
|
-
message: any;
|
|
29
|
-
};
|
|
30
|
-
}, 500, "json">)>;
|
|
31
|
-
export declare function DELETE(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
32
|
-
success: false;
|
|
33
|
-
error: {
|
|
34
|
-
code: string;
|
|
35
|
-
message: string;
|
|
36
|
-
};
|
|
37
|
-
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
38
|
-
success: true;
|
|
39
|
-
message: string;
|
|
40
|
-
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
41
|
-
success: false;
|
|
42
|
-
error: {
|
|
43
|
-
code: string;
|
|
44
|
-
message: any;
|
|
45
|
-
};
|
|
46
|
-
}, 500, "json">)>;
|
|
3
|
+
export declare function PUT(c: Context): Promise<Response>;
|
|
4
|
+
export declare function DELETE(c: Context): Promise<Response>;
|
|
@@ -8,6 +8,7 @@ import { trimTrailingSlash } from 'hono/trailing-slash';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs';
|
|
10
10
|
import { getGlobalTerminalManager } from './lib/terminal/global-manager.js';
|
|
11
|
+
import { getGlobalJobScheduler } from './lib/jobs/global-job-scheduler.js';
|
|
11
12
|
import { fileURLToPath } from 'url';
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = path.dirname(__filename);
|
|
@@ -99,6 +100,7 @@ import agents from './routes/api/v1/agents/index.js';
|
|
|
99
100
|
import agentsById from './routes/api/v1/agents/[id]/index.js';
|
|
100
101
|
import git from './routes/api/v1/git/index.js';
|
|
101
102
|
import mcp from './routes/api/v1/mcp/index.js';
|
|
103
|
+
import jobs from './routes/api/v1/jobs/index.js';
|
|
102
104
|
// Register API routes FIRST
|
|
103
105
|
console.log('🔗 Registering API routes...');
|
|
104
106
|
app.route('/api/v1/auth', auth);
|
|
@@ -122,7 +124,10 @@ app.route('/api/v1/agents', agents);
|
|
|
122
124
|
app.route('/api/v1/agents/:id', agentsById);
|
|
123
125
|
app.route('/api/v1/git', git);
|
|
124
126
|
app.route('/api/v1/mcp', mcp);
|
|
127
|
+
app.route('/api/v1/jobs', jobs);
|
|
125
128
|
console.log('✅ API routes registered');
|
|
129
|
+
// Initialize background services
|
|
130
|
+
getGlobalJobScheduler();
|
|
126
131
|
// Health check endpoint
|
|
127
132
|
app.get('/api/health', (c) => {
|
|
128
133
|
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
|
package/dist/server.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Hono } from 'hono';
|
|
|
5
5
|
import { cors } from 'hono/cors';
|
|
6
6
|
import { trimTrailingSlash } from 'hono/trailing-slash';
|
|
7
7
|
import { getGlobalTerminalManager } from './lib/terminal/global-manager.js';
|
|
8
|
+
import { getGlobalJobScheduler } from './lib/jobs/global-job-scheduler.js';
|
|
8
9
|
import path from 'path';
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -98,6 +99,7 @@ import agentsById from './routes/api/v1/agents/[id]/index.js';
|
|
|
98
99
|
import git from './routes/api/v1/git/index.js';
|
|
99
100
|
import mcp from './routes/api/v1/mcp/index.js';
|
|
100
101
|
import symlinks from './routes/api/v1/symlinks/index.js';
|
|
102
|
+
import jobs from './routes/api/v1/jobs/index.js';
|
|
101
103
|
// Register API routes
|
|
102
104
|
app.route('/api/v1/auth', auth);
|
|
103
105
|
app.route('/api/v1/auth-settings', authSettings);
|
|
@@ -121,6 +123,7 @@ app.route('/api/v1/agents/:id', agentsById);
|
|
|
121
123
|
app.route('/api/v1/git', git);
|
|
122
124
|
app.route('/api/v1/mcp', mcp);
|
|
123
125
|
app.route('/api/v1/symlinks', symlinks);
|
|
126
|
+
app.route('/api/v1/jobs', jobs);
|
|
124
127
|
// Health check endpoint
|
|
125
128
|
app.get('/health', (c) => {
|
|
126
129
|
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
@@ -137,3 +140,5 @@ injectWebSocket(server);
|
|
|
137
140
|
console.log(`🚀 Server running at http://localhost:${port}`);
|
|
138
141
|
console.log(`🔌 WebSocket available at ws://localhost:${port}/ws/terminal/:sessionId`);
|
|
139
142
|
console.log(`🔎 Preview WebSocket available at ws://localhost:${port}/ws/terminal-preview/:sessionId`);
|
|
143
|
+
// Initialize background services
|
|
144
|
+
getGlobalJobScheduler();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lovelybunch/api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.59",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/server-with-static.js",
|
|
6
6
|
"exports": {
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@hono/node-server": "^1.13.7",
|
|
34
34
|
"@hono/node-ws": "^1.0.6",
|
|
35
|
-
"@lovelybunch/core": "^1.0.
|
|
36
|
-
"@lovelybunch/mcp": "^1.0.
|
|
37
|
-
"@lovelybunch/types": "^1.0.
|
|
35
|
+
"@lovelybunch/core": "^1.0.59",
|
|
36
|
+
"@lovelybunch/mcp": "^1.0.59",
|
|
37
|
+
"@lovelybunch/types": "^1.0.59",
|
|
38
38
|
"arctic": "^1.9.2",
|
|
39
39
|
"bcrypt": "^5.1.1",
|
|
40
40
|
"cookie": "^0.6.0",
|