@agent-native/scheduling 0.1.23 → 0.1.25
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/README.md +16 -0
- package/agent-native.package.json +154 -0
- package/dist/actions/_helpers.d.ts +10 -0
- package/dist/actions/_helpers.d.ts.map +1 -1
- package/dist/actions/_helpers.js +14 -0
- package/dist/actions/_helpers.js.map +1 -1
- package/dist/actions/add-booking-attendee.js +2 -0
- package/dist/actions/add-booking-attendee.js.map +1 -1
- package/dist/actions/add-booking-note.js +2 -1
- package/dist/actions/add-booking-note.js.map +1 -1
- package/dist/actions/confirm-booking.js +5 -0
- package/dist/actions/confirm-booking.js.map +1 -1
- package/dist/actions/duplicate-event-type.js +2 -0
- package/dist/actions/duplicate-event-type.js.map +1 -1
- package/dist/actions/get-booking.d.ts +3 -1
- package/dist/actions/get-booking.js +8 -1
- package/dist/actions/get-booking.js.map +1 -1
- package/dist/actions/mark-no-show.js +6 -0
- package/dist/actions/mark-no-show.js.map +1 -1
- package/dist/actions/remove-booking-attendee.js +2 -0
- package/dist/actions/remove-booking-attendee.js.map +1 -1
- package/dist/actions/revoke-private-link.js +18 -1
- package/dist/actions/revoke-private-link.js.map +1 -1
- package/dist/actions/send-reschedule-link.js +2 -0
- package/dist/actions/send-reschedule-link.js.map +1 -1
- package/dist/manifest.d.ts +5 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +6 -1
- package/dist/manifest.js.map +1 -1
- package/dist/server/availability-engine.d.ts +20 -0
- package/dist/server/availability-engine.d.ts.map +1 -1
- package/dist/server/availability-engine.js +73 -23
- package/dist/server/availability-engine.js.map +1 -1
- package/dist/server/booking-service.d.ts.map +1 -1
- package/dist/server/booking-service.js +16 -5
- package/dist/server/booking-service.js.map +1 -1
- package/dist/server/bookings-repo.d.ts.map +1 -1
- package/dist/server/bookings-repo.js +50 -48
- package/dist/server/bookings-repo.js.map +1 -1
- package/dist/server/providers/index.d.ts +2 -0
- package/dist/server/providers/index.d.ts.map +1 -1
- package/dist/server/providers/index.js +1 -0
- package/dist/server/providers/index.js.map +1 -1
- package/dist/server/providers/teams.d.ts +22 -0
- package/dist/server/providers/teams.d.ts.map +1 -0
- package/dist/server/providers/teams.js +112 -0
- package/dist/server/providers/teams.js.map +1 -0
- package/docs/eject.md +11 -10
- package/docs/llms-full.txt +75 -14
- package/docs/llms.txt +15 -1
- package/docs/providers.md +30 -2
- package/docs/skills/integrations/SKILL.md +19 -1
- package/package.json +7 -6
- package/src/actions/_helpers.ts +18 -0
- package/src/actions/add-booking-attendee.ts +2 -0
- package/src/actions/add-booking-note.ts +2 -1
- package/src/actions/booking-authz.spec.ts +288 -0
- package/src/actions/confirm-booking.ts +4 -0
- package/src/actions/duplicate-event-type.ts +2 -0
- package/src/actions/event-type-authz.spec.ts +209 -0
- package/src/actions/get-booking.ts +7 -1
- package/src/actions/mark-no-show.ts +5 -0
- package/src/actions/remove-booking-attendee.ts +2 -0
- package/src/actions/revoke-private-link.ts +16 -1
- package/src/actions/send-reschedule-link.ts +2 -0
- package/src/manifest.test.ts +19 -0
- package/src/manifest.ts +9 -7
- package/src/server/availability-engine.test.ts +344 -0
- package/src/server/availability-engine.ts +100 -22
- package/src/server/booking-service.spec.ts +557 -0
- package/src/server/booking-service.ts +17 -6
- package/src/server/bookings-repo.ts +54 -48
- package/src/server/providers/index.ts +2 -0
- package/src/server/providers/teams.test.ts +246 -0
- package/src/server/providers/teams.ts +183 -0
|
@@ -5,11 +5,15 @@ import {
|
|
|
5
5
|
updateBookingStatus,
|
|
6
6
|
getBookingByUid,
|
|
7
7
|
} from "../server/bookings-repo.js";
|
|
8
|
+
import { assertBookingHost } from "./_helpers.js";
|
|
8
9
|
|
|
9
10
|
export default defineAction({
|
|
10
11
|
description: "Confirm a pending booking (requires-confirmation flow)",
|
|
11
12
|
schema: z.object({ uid: z.string() }),
|
|
12
13
|
run: async (args) => {
|
|
14
|
+
const booking = await getBookingByUid(args.uid);
|
|
15
|
+
if (!booking) throw new Error(`Booking ${args.uid} not found`);
|
|
16
|
+
assertBookingHost(booking, "confirm this booking");
|
|
13
17
|
await updateBookingStatus(args.uid, "confirmed");
|
|
14
18
|
return { booking: await getBookingByUid(args.uid) };
|
|
15
19
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
|
|
4
5
|
import {
|
|
@@ -17,6 +18,7 @@ export default defineAction({
|
|
|
17
18
|
run: async (args) => {
|
|
18
19
|
const source = await getEventTypeById(args.id);
|
|
19
20
|
if (!source) throw new Error("Event type not found");
|
|
21
|
+
await assertAccess("event-type", args.id, "editor");
|
|
20
22
|
return {
|
|
21
23
|
eventType: await createEventType({
|
|
22
24
|
ownerEmail: source.teamId ? undefined : currentUserEmail(),
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-tenant write (IDOR) regression tests for event-type-scoped actions
|
|
3
|
+
* that mutate a resource owned by another tenant: revoking a private hashed
|
|
4
|
+
* link and duplicating an event type. Mirrors the `assertAccess("event-type",
|
|
5
|
+
* ..., <role>)` guard already used by `add-private-link.ts` /
|
|
6
|
+
* `delete-event-type.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
getRequestUserEmail,
|
|
15
|
+
runWithRequestContext,
|
|
16
|
+
} from "@agent-native/core/server/request-context";
|
|
17
|
+
import {
|
|
18
|
+
ForbiddenError,
|
|
19
|
+
registerShareableResource,
|
|
20
|
+
} from "@agent-native/core/sharing";
|
|
21
|
+
import { createClient, type Client } from "@libsql/client";
|
|
22
|
+
import { drizzle } from "drizzle-orm/libsql";
|
|
23
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
24
|
+
|
|
25
|
+
import * as schema from "../schema/index.js";
|
|
26
|
+
import { setSchedulingContext } from "../server/context.js";
|
|
27
|
+
import duplicateEventType from "./duplicate-event-type.js";
|
|
28
|
+
import revokePrivateLink from "./revoke-private-link.js";
|
|
29
|
+
|
|
30
|
+
const OWNER_EMAIL = "owner@example.com";
|
|
31
|
+
const OUTSIDER_EMAIL = "outsider@example.com";
|
|
32
|
+
const EVENT_TYPE_ID = "event-type-1";
|
|
33
|
+
const HASH = "private-link-hash-1";
|
|
34
|
+
|
|
35
|
+
let client: Client;
|
|
36
|
+
let dbDir: string;
|
|
37
|
+
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
dbDir = mkdtempSync(join(tmpdir(), "scheduling-eventtype-authz-test-"));
|
|
40
|
+
client = createClient({ url: `file:${join(dbDir, `${randomUUID()}.db`)}` });
|
|
41
|
+
await client.execute(`
|
|
42
|
+
CREATE TABLE event_types (
|
|
43
|
+
id TEXT PRIMARY KEY,
|
|
44
|
+
title TEXT NOT NULL,
|
|
45
|
+
slug TEXT NOT NULL,
|
|
46
|
+
description TEXT,
|
|
47
|
+
length INTEGER NOT NULL DEFAULT 30,
|
|
48
|
+
durations TEXT,
|
|
49
|
+
position INTEGER NOT NULL DEFAULT 0,
|
|
50
|
+
hidden INTEGER NOT NULL DEFAULT 0,
|
|
51
|
+
color TEXT,
|
|
52
|
+
scheduling_type TEXT NOT NULL DEFAULT 'personal',
|
|
53
|
+
team_id TEXT,
|
|
54
|
+
locations TEXT,
|
|
55
|
+
custom_fields TEXT,
|
|
56
|
+
schedule_id TEXT,
|
|
57
|
+
minimum_booking_notice INTEGER NOT NULL DEFAULT 0,
|
|
58
|
+
before_event_buffer INTEGER NOT NULL DEFAULT 0,
|
|
59
|
+
after_event_buffer INTEGER NOT NULL DEFAULT 0,
|
|
60
|
+
slot_interval INTEGER,
|
|
61
|
+
period_type TEXT NOT NULL DEFAULT 'rolling',
|
|
62
|
+
period_days INTEGER DEFAULT 60,
|
|
63
|
+
period_start_date TEXT,
|
|
64
|
+
period_end_date TEXT,
|
|
65
|
+
seats_per_time_slot INTEGER,
|
|
66
|
+
requires_confirmation INTEGER NOT NULL DEFAULT 0,
|
|
67
|
+
disable_guests INTEGER NOT NULL DEFAULT 0,
|
|
68
|
+
hide_calendar_notes INTEGER NOT NULL DEFAULT 0,
|
|
69
|
+
success_redirect_url TEXT,
|
|
70
|
+
booking_limits TEXT,
|
|
71
|
+
lock_time_zone_toggle INTEGER NOT NULL DEFAULT 0,
|
|
72
|
+
recurring_event TEXT,
|
|
73
|
+
event_name TEXT,
|
|
74
|
+
metadata TEXT,
|
|
75
|
+
created_at TEXT NOT NULL,
|
|
76
|
+
updated_at TEXT NOT NULL,
|
|
77
|
+
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
78
|
+
org_id TEXT,
|
|
79
|
+
visibility TEXT NOT NULL DEFAULT 'private'
|
|
80
|
+
);
|
|
81
|
+
`);
|
|
82
|
+
await client.execute(`
|
|
83
|
+
CREATE TABLE hashed_links (
|
|
84
|
+
id TEXT PRIMARY KEY,
|
|
85
|
+
hash TEXT NOT NULL UNIQUE,
|
|
86
|
+
event_type_id TEXT NOT NULL,
|
|
87
|
+
expires_at TEXT,
|
|
88
|
+
is_single_use INTEGER NOT NULL DEFAULT 0,
|
|
89
|
+
used_at TEXT,
|
|
90
|
+
created_at TEXT NOT NULL
|
|
91
|
+
);
|
|
92
|
+
`);
|
|
93
|
+
await client.execute(`
|
|
94
|
+
CREATE TABLE event_type_shares (
|
|
95
|
+
id TEXT PRIMARY KEY,
|
|
96
|
+
resource_id TEXT NOT NULL,
|
|
97
|
+
principal_type TEXT NOT NULL,
|
|
98
|
+
principal_id TEXT NOT NULL,
|
|
99
|
+
role TEXT NOT NULL DEFAULT 'viewer',
|
|
100
|
+
created_by TEXT NOT NULL,
|
|
101
|
+
created_at TEXT NOT NULL
|
|
102
|
+
);
|
|
103
|
+
`);
|
|
104
|
+
|
|
105
|
+
const db = drizzle(client, { schema });
|
|
106
|
+
setSchedulingContext({
|
|
107
|
+
getDb: () => db,
|
|
108
|
+
schema,
|
|
109
|
+
// Mirrors real app wiring (templates/scheduling's server plugin): the
|
|
110
|
+
// scheduling package's own "current user" and the framework's
|
|
111
|
+
// request-context ALS (used by `assertAccess`) both resolve to the same
|
|
112
|
+
// identity.
|
|
113
|
+
getCurrentUserEmail: () => getRequestUserEmail(),
|
|
114
|
+
});
|
|
115
|
+
registerShareableResource({
|
|
116
|
+
type: "event-type",
|
|
117
|
+
resourceTable: schema.eventTypes,
|
|
118
|
+
sharesTable: schema.eventTypeShares,
|
|
119
|
+
displayName: "Event Type",
|
|
120
|
+
getDb: () => db,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const now = new Date().toISOString();
|
|
124
|
+
await client.execute({
|
|
125
|
+
sql: `INSERT INTO event_types (
|
|
126
|
+
id, title, slug, length, created_at, updated_at, owner_email, visibility
|
|
127
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
128
|
+
args: [
|
|
129
|
+
EVENT_TYPE_ID,
|
|
130
|
+
"30 Min Meeting",
|
|
131
|
+
"30min",
|
|
132
|
+
30,
|
|
133
|
+
now,
|
|
134
|
+
now,
|
|
135
|
+
OWNER_EMAIL,
|
|
136
|
+
"private",
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
await client.execute({
|
|
140
|
+
sql: `INSERT INTO hashed_links (id, hash, event_type_id, created_at) VALUES (?, ?, ?, ?)`,
|
|
141
|
+
args: ["link-1", HASH, EVENT_TYPE_ID, now],
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
afterEach(() => {
|
|
146
|
+
client.close();
|
|
147
|
+
rmSync(dbDir, { recursive: true, force: true });
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
async function hashedLinkExists(): Promise<boolean> {
|
|
151
|
+
const { rows } = await client.execute({
|
|
152
|
+
sql: "SELECT 1 FROM hashed_links WHERE hash = ?",
|
|
153
|
+
args: [HASH],
|
|
154
|
+
});
|
|
155
|
+
return rows.length > 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function eventTypeCount(): Promise<number> {
|
|
159
|
+
const { rows } = await client.execute("SELECT * FROM event_types");
|
|
160
|
+
return rows.length;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
describe("revoke-private-link authorization", () => {
|
|
164
|
+
it("returns the same idempotent result for an inaccessible link and keeps it", async () => {
|
|
165
|
+
const result: any = await runWithRequestContext(
|
|
166
|
+
{ userEmail: OUTSIDER_EMAIL },
|
|
167
|
+
() => revokePrivateLink.run({ hash: HASH }),
|
|
168
|
+
);
|
|
169
|
+
expect(result.ok).toBe(true);
|
|
170
|
+
expect(await hashedLinkExists()).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("allows the owning event type's editor (the owner) to revoke the link", async () => {
|
|
174
|
+
const result: any = await runWithRequestContext(
|
|
175
|
+
{ userEmail: OWNER_EMAIL },
|
|
176
|
+
() => revokePrivateLink.run({ hash: HASH }),
|
|
177
|
+
);
|
|
178
|
+
expect(result.ok).toBe(true);
|
|
179
|
+
expect(await hashedLinkExists()).toBe(false);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("is idempotent for an unknown hash without requiring access", async () => {
|
|
183
|
+
const result: any = await runWithRequestContext(
|
|
184
|
+
{ userEmail: OUTSIDER_EMAIL },
|
|
185
|
+
() => revokePrivateLink.run({ hash: "does-not-exist" }),
|
|
186
|
+
);
|
|
187
|
+
expect(result.ok).toBe(true);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe("duplicate-event-type authorization", () => {
|
|
192
|
+
it("rejects a caller with no access to the source event type and does not duplicate it", async () => {
|
|
193
|
+
await expect(
|
|
194
|
+
runWithRequestContext({ userEmail: OUTSIDER_EMAIL }, () =>
|
|
195
|
+
duplicateEventType.run({ id: EVENT_TYPE_ID, newSlug: "copy" }),
|
|
196
|
+
),
|
|
197
|
+
).rejects.toBeInstanceOf(ForbiddenError);
|
|
198
|
+
expect(await eventTypeCount()).toBe(1);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("allows the owner to duplicate their own event type", async () => {
|
|
202
|
+
const result: any = await runWithRequestContext(
|
|
203
|
+
{ userEmail: OWNER_EMAIL },
|
|
204
|
+
() => duplicateEventType.run({ id: EVENT_TYPE_ID, newSlug: "copy" }),
|
|
205
|
+
);
|
|
206
|
+
expect(result.eventType?.slug).toBe("copy");
|
|
207
|
+
expect(await eventTypeCount()).toBe(2);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
@@ -2,9 +2,15 @@ import { defineAction } from "@agent-native/core";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
import { getBookingByUid } from "../server/bookings-repo.js";
|
|
5
|
+
import { assertBookingHost } from "./_helpers.js";
|
|
5
6
|
|
|
6
7
|
export default defineAction({
|
|
7
8
|
description: "Get a booking by uid",
|
|
8
9
|
schema: z.object({ uid: z.string() }),
|
|
9
|
-
run: async (args) =>
|
|
10
|
+
run: async (args) => {
|
|
11
|
+
const booking = await getBookingByUid(args.uid);
|
|
12
|
+
if (!booking) return { booking: null };
|
|
13
|
+
assertBookingHost(booking, "view this booking");
|
|
14
|
+
return { booking };
|
|
15
|
+
},
|
|
10
16
|
});
|
|
@@ -2,6 +2,8 @@ import { defineAction } from "@agent-native/core";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
import { markNoShow } from "../server/booking-service.js";
|
|
5
|
+
import { getBookingByUid } from "../server/bookings-repo.js";
|
|
6
|
+
import { assertBookingHost } from "./_helpers.js";
|
|
5
7
|
|
|
6
8
|
export default defineAction({
|
|
7
9
|
description: "Mark an attendee as no-show on a booking",
|
|
@@ -10,6 +12,9 @@ export default defineAction({
|
|
|
10
12
|
attendeeEmail: z.string(),
|
|
11
13
|
}),
|
|
12
14
|
run: async (args) => {
|
|
15
|
+
const booking = await getBookingByUid(args.uid);
|
|
16
|
+
if (!booking) throw new Error(`Booking ${args.uid} not found`);
|
|
17
|
+
assertBookingHost(booking, "mark no-show on this booking");
|
|
13
18
|
await markNoShow(args.uid, args.attendeeEmail);
|
|
14
19
|
return { ok: true };
|
|
15
20
|
},
|
|
@@ -4,6 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
import { getBookingByUid } from "../server/bookings-repo.js";
|
|
6
6
|
import { getSchedulingContext } from "../server/context.js";
|
|
7
|
+
import { assertBookingHost } from "./_helpers.js";
|
|
7
8
|
|
|
8
9
|
export default defineAction({
|
|
9
10
|
description: "Remove an attendee from a booking",
|
|
@@ -11,6 +12,7 @@ export default defineAction({
|
|
|
11
12
|
run: async (args) => {
|
|
12
13
|
const booking = await getBookingByUid(args.uid);
|
|
13
14
|
if (!booking) throw new Error(`Booking ${args.uid} not found`);
|
|
15
|
+
assertBookingHost(booking, "remove an attendee from this booking");
|
|
14
16
|
const { getDb, schema } = getSchedulingContext();
|
|
15
17
|
await getDb()
|
|
16
18
|
.delete(schema.bookingAttendees)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
2
3
|
import { eq } from "drizzle-orm";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
|
|
@@ -9,7 +10,21 @@ export default defineAction({
|
|
|
9
10
|
schema: z.object({ hash: z.string() }),
|
|
10
11
|
run: async (args) => {
|
|
11
12
|
const { getDb, schema } = getSchedulingContext();
|
|
12
|
-
|
|
13
|
+
const db = getDb();
|
|
14
|
+
const [link] = await db
|
|
15
|
+
.select({ eventTypeId: schema.hashedLinks.eventTypeId })
|
|
16
|
+
.from(schema.hashedLinks)
|
|
17
|
+
.where(eq(schema.hashedLinks.hash, args.hash))
|
|
18
|
+
.limit(1);
|
|
19
|
+
if (!link) return { ok: true };
|
|
20
|
+
try {
|
|
21
|
+
await assertAccess("event-type", link.eventTypeId, "editor");
|
|
22
|
+
} catch {
|
|
23
|
+
// Keep private-link hashes unprobeable: callers without access receive
|
|
24
|
+
// the same idempotent result as callers presenting an unknown hash.
|
|
25
|
+
return { ok: true };
|
|
26
|
+
}
|
|
27
|
+
await db
|
|
13
28
|
.delete(schema.hashedLinks)
|
|
14
29
|
.where(eq(schema.hashedLinks.hash, args.hash));
|
|
15
30
|
return { ok: true };
|
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
|
|
4
4
|
import { getBookingByUid } from "../server/bookings-repo.js";
|
|
5
5
|
import { getSchedulingContext } from "../server/context.js";
|
|
6
|
+
import { assertBookingHost } from "./_helpers.js";
|
|
6
7
|
|
|
7
8
|
export default defineAction({
|
|
8
9
|
description:
|
|
@@ -11,6 +12,7 @@ export default defineAction({
|
|
|
11
12
|
run: async (args) => {
|
|
12
13
|
const booking = await getBookingByUid(args.uid);
|
|
13
14
|
if (!booking) throw new Error(`Booking ${args.uid} not found`);
|
|
15
|
+
assertBookingHost(booking, "view the reschedule link for this booking");
|
|
14
16
|
const baseUrl = getSchedulingContext().publicBaseUrl ?? "";
|
|
15
17
|
return {
|
|
16
18
|
url: `${baseUrl}/reschedule/${booking.uid}?token=${booking.rescheduleToken}`,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
import { assertAgentNativePackageManifest } from "../../core/src/package-lifecycle/manifest.js";
|
|
7
|
+
import { MANIFEST } from "./manifest.js";
|
|
8
|
+
|
|
9
|
+
describe("scheduling package manifest", () => {
|
|
10
|
+
it("keeps the published static manifest in parity with the typed manifest", () => {
|
|
11
|
+
const file = fileURLToPath(
|
|
12
|
+
new URL("../agent-native.package.json", import.meta.url),
|
|
13
|
+
);
|
|
14
|
+
const published = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
15
|
+
assertAgentNativePackageManifest(published);
|
|
16
|
+
expect(published).toEqual(MANIFEST);
|
|
17
|
+
expect(published.peerProviders).toContain("teams");
|
|
18
|
+
});
|
|
19
|
+
});
|
package/src/manifest.ts
CHANGED
|
@@ -9,22 +9,19 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export interface SchedulingManifest {
|
|
12
|
+
manifestVersion: 1;
|
|
12
13
|
name: string;
|
|
13
|
-
version: string;
|
|
14
14
|
actions: string[];
|
|
15
15
|
schemaEntryPoint: string;
|
|
16
|
-
docs: {
|
|
17
|
-
llms: string;
|
|
18
|
-
llmsFull: string;
|
|
19
|
-
skills: string[];
|
|
20
|
-
};
|
|
16
|
+
docs: { llms: string; llmsFull: string; skills: string[] };
|
|
21
17
|
requiredSecrets: { key: string; label: string; optional?: boolean }[];
|
|
22
18
|
peerProviders: string[];
|
|
19
|
+
eject?: { sourceRoot: string; targetDirectory: string };
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
export const MANIFEST: SchedulingManifest = {
|
|
23
|
+
manifestVersion: 1,
|
|
26
24
|
name: "@agent-native/scheduling",
|
|
27
|
-
version: "0.1.0",
|
|
28
25
|
actions: [
|
|
29
26
|
// Event types
|
|
30
27
|
"list-event-types",
|
|
@@ -168,7 +165,12 @@ export const MANIFEST: SchedulingManifest = {
|
|
|
168
165
|
"google-calendar",
|
|
169
166
|
"office365",
|
|
170
167
|
"zoom",
|
|
168
|
+
"teams",
|
|
171
169
|
"google-meet",
|
|
172
170
|
"builtin-video",
|
|
173
171
|
],
|
|
172
|
+
eject: {
|
|
173
|
+
sourceRoot: "src",
|
|
174
|
+
targetDirectory: "packages/scheduling",
|
|
175
|
+
},
|
|
174
176
|
};
|