tands 0.1.0 → 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.
- package/README.md +2 -0
- package/dist/sdk/tands-sdk-server.js +25 -1
- package/dist/sdk/tands-sdk.js +57 -1
- package/dist/tands.js +1539 -358
- package/package.json +3 -3
package/dist/tands.js
CHANGED
|
@@ -2580,8 +2580,8 @@ var Doc = class {
|
|
|
2580
2580
|
const lines = content.split("\n").filter((x) => x);
|
|
2581
2581
|
const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
|
|
2582
2582
|
const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
|
|
2583
|
-
for (const
|
|
2584
|
-
this.content.push(
|
|
2583
|
+
for (const line2 of dedented) {
|
|
2584
|
+
this.content.push(line2);
|
|
2585
2585
|
}
|
|
2586
2586
|
}
|
|
2587
2587
|
compile() {
|
|
@@ -19676,9 +19676,101 @@ function date4(params) {
|
|
|
19676
19676
|
return _coercedDate(ZodDate, params);
|
|
19677
19677
|
}
|
|
19678
19678
|
|
|
19679
|
+
// ../types/src/time.ts
|
|
19680
|
+
function isTimeZone(value) {
|
|
19681
|
+
if (!value || value.length > 64) return false;
|
|
19682
|
+
try {
|
|
19683
|
+
new Intl.DateTimeFormat("en", { timeZone: value });
|
|
19684
|
+
return true;
|
|
19685
|
+
} catch {
|
|
19686
|
+
return false;
|
|
19687
|
+
}
|
|
19688
|
+
}
|
|
19689
|
+
var TimeZoneSchema = external_exports.string().refine(isTimeZone, "Not a known time zone.");
|
|
19690
|
+
var DEFAULT_TIME_ZONE = "UTC";
|
|
19691
|
+
|
|
19692
|
+
// ../types/src/recurrence.ts
|
|
19693
|
+
var WeekdaySchema = external_exports.number().int().min(0).max(6);
|
|
19694
|
+
var RecurrenceSchema = external_exports.discriminatedUnion("freq", [
|
|
19695
|
+
external_exports.object({ freq: external_exports.literal("daily"), interval: external_exports.number().int().min(1).max(365) }),
|
|
19696
|
+
external_exports.object({
|
|
19697
|
+
freq: external_exports.literal("weekly"),
|
|
19698
|
+
interval: external_exports.number().int().min(1).max(52),
|
|
19699
|
+
/** The days of the week it happens on (Monday to Friday: every weekday). */
|
|
19700
|
+
weekdays: external_exports.array(WeekdaySchema).min(1).max(7)
|
|
19701
|
+
}),
|
|
19702
|
+
external_exports.object({
|
|
19703
|
+
freq: external_exports.literal("monthly"),
|
|
19704
|
+
interval: external_exports.number().int().min(1).max(12),
|
|
19705
|
+
on: external_exports.discriminatedUnion("kind", [
|
|
19706
|
+
/** A day of the month; in shorter months, their last day. */
|
|
19707
|
+
external_exports.object({ kind: external_exports.literal("day"), day: external_exports.number().int().min(1).max(31) }),
|
|
19708
|
+
/** The first … fourth, or last (-1), such weekday of the month. */
|
|
19709
|
+
external_exports.object({
|
|
19710
|
+
kind: external_exports.literal("weekday"),
|
|
19711
|
+
week: external_exports.union([external_exports.literal(1), external_exports.literal(2), external_exports.literal(3), external_exports.literal(4), external_exports.literal(-1)]),
|
|
19712
|
+
weekday: WeekdaySchema
|
|
19713
|
+
})
|
|
19714
|
+
])
|
|
19715
|
+
})
|
|
19716
|
+
]);
|
|
19717
|
+
var IsoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "A date like 2026-10-16.");
|
|
19718
|
+
var ClockTimeSchema = external_exports.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "A time like 17:00.");
|
|
19719
|
+
var DAY_MS = 24 * 60 * 6e4;
|
|
19720
|
+
|
|
19721
|
+
// ../types/src/notifications.ts
|
|
19722
|
+
var NOTIFICATION_KINDS = ["mention", "dm", "approval", "thread"];
|
|
19723
|
+
var NotificationKindSchema = external_exports.enum(NOTIFICATION_KINDS);
|
|
19724
|
+
var QuietHoursSchema = external_exports.object({
|
|
19725
|
+
on: external_exports.boolean().default(false),
|
|
19726
|
+
from: ClockTimeSchema.default("22:00"),
|
|
19727
|
+
to: ClockTimeSchema.default("08:00"),
|
|
19728
|
+
days: external_exports.array(external_exports.number().int().min(0).max(6)).max(7).default([0, 1, 2, 3, 4, 5, 6])
|
|
19729
|
+
});
|
|
19730
|
+
var NotificationSettingsSchema = external_exports.object({
|
|
19731
|
+
/** A gentle chime (and the Inbox icon's pulse) when something new arrives. */
|
|
19732
|
+
sound: external_exports.boolean().default(true),
|
|
19733
|
+
/** Which kinds chime and pop up (threads you follow: quiet, unless you add them). */
|
|
19734
|
+
alert: external_exports.array(NotificationKindSchema).default(["mention", "dm", "approval"]),
|
|
19735
|
+
/** Do not disturb (decision 194): quiet hours, each week. */
|
|
19736
|
+
quietHours: QuietHoursSchema.default(QuietHoursSchema.parse({})),
|
|
19737
|
+
/** Paused until then (a quick "for an hour"); null: not paused. */
|
|
19738
|
+
pausedUntil: external_exports.iso.datetime().nullable().default(null),
|
|
19739
|
+
/** What still gets through while you're quiet (a DM, a request for your yes). */
|
|
19740
|
+
allowWhenQuiet: external_exports.array(NotificationKindSchema).default([]),
|
|
19741
|
+
/**
|
|
19742
|
+
* Away from the app (decision 195): what's emailed when it's still unread a
|
|
19743
|
+
* little later (grouped into one email), and what's sent to your linked chats.
|
|
19744
|
+
*/
|
|
19745
|
+
email: external_exports.array(NotificationKindSchema).default(["mention", "dm", "approval"]),
|
|
19746
|
+
chat: external_exports.array(NotificationKindSchema).default(["mention", "dm", "approval"]),
|
|
19747
|
+
/** A short email when something has waited unread for hours (at most one a day). */
|
|
19748
|
+
reminder: external_exports.boolean().default(true)
|
|
19749
|
+
});
|
|
19750
|
+
var DEFAULT_NOTIFICATION_SETTINGS = NotificationSettingsSchema.parse(
|
|
19751
|
+
{}
|
|
19752
|
+
);
|
|
19753
|
+
var UpdateNotificationSettingsSchema = external_exports.object({
|
|
19754
|
+
sound: external_exports.boolean(),
|
|
19755
|
+
alert: external_exports.array(NotificationKindSchema).max(NOTIFICATION_KINDS.length),
|
|
19756
|
+
quietHours: QuietHoursSchema,
|
|
19757
|
+
pausedUntil: external_exports.iso.datetime().nullable(),
|
|
19758
|
+
allowWhenQuiet: external_exports.array(NotificationKindSchema).max(NOTIFICATION_KINDS.length),
|
|
19759
|
+
email: external_exports.array(NotificationKindSchema).max(NOTIFICATION_KINDS.length),
|
|
19760
|
+
chat: external_exports.array(NotificationKindSchema).max(NOTIFICATION_KINDS.length),
|
|
19761
|
+
reminder: external_exports.boolean()
|
|
19762
|
+
}).partial().strict();
|
|
19763
|
+
var NotificationSettingsResponseSchema = external_exports.object({
|
|
19764
|
+
settings: NotificationSettingsSchema
|
|
19765
|
+
});
|
|
19766
|
+
var SPACE_NOTIFY_LEVELS = ["all", "mentions", "muted"];
|
|
19767
|
+
var SpaceNotifySchema = external_exports.enum(SPACE_NOTIFY_LEVELS);
|
|
19768
|
+
var SetSpaceNotifyRequestSchema = external_exports.object({ level: SpaceNotifySchema });
|
|
19769
|
+
|
|
19679
19770
|
// ../types/src/apps.ts
|
|
19680
19771
|
var APP_MANIFEST_VERSION = 1;
|
|
19681
19772
|
var MAX_APP_TABS = 10;
|
|
19773
|
+
var MAX_APP_HOME_PAGES = 3;
|
|
19682
19774
|
var APP_TOKEN_SECONDS = 600;
|
|
19683
19775
|
var APP_DATA_LIMIT_BYTES = 100 * 1024 * 1024;
|
|
19684
19776
|
var APP_RECORD_MAX_BYTES = 32 * 1024;
|
|
@@ -19722,7 +19814,20 @@ var AppActionSchema = external_exports.object({
|
|
|
19722
19814
|
/** It changes something (the default): agents ask first. `false`: it only reads. */
|
|
19723
19815
|
changes: external_exports.boolean().default(true),
|
|
19724
19816
|
/** What it's given, checked like a record's fields. */
|
|
19725
|
-
input: external_exports.record(DataNameSchema, AppFieldSchema).refine((fields) => Object.keys(fields).length <= 20, "An action takes at most 20 inputs.").default({})
|
|
19817
|
+
input: external_exports.record(DataNameSchema, AppFieldSchema).refine((fields) => Object.keys(fields).length <= 20, "An action takes at most 20 inputs.").default({}),
|
|
19818
|
+
/**
|
|
19819
|
+
* Its view (decision 216): a page on the app's origin shown under the agent's
|
|
19820
|
+
* answer, told what the action was asked and answered (MCP Apps). Only for
|
|
19821
|
+
* actions that only read, for now.
|
|
19822
|
+
*/
|
|
19823
|
+
view: external_exports.object({
|
|
19824
|
+
url: external_exports.string().min(1).max(500),
|
|
19825
|
+
/** What it's called above the page (default: the action's name). */
|
|
19826
|
+
title: external_exports.string().trim().min(1).max(60).optional()
|
|
19827
|
+
}).optional()
|
|
19828
|
+
}).refine((action) => !action.view || !action.changes, {
|
|
19829
|
+
message: "Only an action that only reads (changes: false) can have a view, for now.",
|
|
19830
|
+
path: ["view"]
|
|
19726
19831
|
});
|
|
19727
19832
|
var AppEventSchema = external_exports.object({
|
|
19728
19833
|
/** What happened, for people choosing it in a trigger. */
|
|
@@ -19751,6 +19856,18 @@ var AppManifestSchema = external_exports.object({
|
|
|
19751
19856
|
url: external_exports.string().min(1).max(500)
|
|
19752
19857
|
})
|
|
19753
19858
|
).min(1, "An app needs at least one tab.").max(MAX_APP_TABS),
|
|
19859
|
+
/**
|
|
19860
|
+
* Home pages it offers (decision 177): an owner or admin may choose one as the
|
|
19861
|
+
* workspace's Home. Shown like a tab, without a space around it.
|
|
19862
|
+
*/
|
|
19863
|
+
home: external_exports.array(
|
|
19864
|
+
external_exports.object({
|
|
19865
|
+
id: AppTabIdSchema,
|
|
19866
|
+
name: external_exports.string().trim().min(1).max(40),
|
|
19867
|
+
description: external_exports.string().trim().max(200).default(""),
|
|
19868
|
+
url: external_exports.string().min(1).max(500)
|
|
19869
|
+
})
|
|
19870
|
+
).max(MAX_APP_HOME_PAGES).optional(),
|
|
19754
19871
|
/** The data it keeps in the workspace (M9 slice 2). */
|
|
19755
19872
|
data: external_exports.object({
|
|
19756
19873
|
collections: external_exports.record(DataNameSchema, AppCollectionSchema).refine(
|
|
@@ -19761,12 +19878,21 @@ var AppManifestSchema = external_exports.object({
|
|
|
19761
19878
|
/** What it does when agents ask (M9 slice 3). */
|
|
19762
19879
|
actions: external_exports.record(DataNameSchema, AppActionSchema).refine((actions) => Object.keys(actions).length <= 20, "An app has at most 20 actions.").optional(),
|
|
19763
19880
|
/** What happens in it, for triggers to listen for (M9 slice 5). */
|
|
19764
|
-
events: external_exports.record(DataNameSchema, AppEventSchema).refine((events) => Object.keys(events).length <= 20, "An app has at most 20 events.").optional()
|
|
19881
|
+
events: external_exports.record(DataNameSchema, AppEventSchema).refine((events) => Object.keys(events).length <= 20, "An app has at most 20 events.").optional(),
|
|
19882
|
+
/**
|
|
19883
|
+
* Publishing it to the marketplace (decision 203): `verify` is the token of
|
|
19884
|
+
* the workspace that may publish it, shown on its Publish page. Only whoever
|
|
19885
|
+
* controls the manifest's address can put it there.
|
|
19886
|
+
*/
|
|
19887
|
+
marketplace: external_exports.object({ verify: external_exports.string().trim().max(100) }).optional()
|
|
19765
19888
|
});
|
|
19889
|
+
var ManifestHashSchema = external_exports.string().regex(/^[0-9a-f]{64}$/, "A manifest's hash.");
|
|
19766
19890
|
var AppActionInfoSchema = external_exports.object({
|
|
19767
19891
|
name: external_exports.string(),
|
|
19768
19892
|
description: external_exports.string(),
|
|
19769
19893
|
changes: external_exports.boolean(),
|
|
19894
|
+
/** It shows its own view under the agent's answer (decision 216). */
|
|
19895
|
+
view: external_exports.boolean().default(false),
|
|
19770
19896
|
input: external_exports.array(
|
|
19771
19897
|
external_exports.object({
|
|
19772
19898
|
name: external_exports.string(),
|
|
@@ -19823,6 +19949,8 @@ var AppSchema = external_exports.object({
|
|
|
19823
19949
|
origin: external_exports.string(),
|
|
19824
19950
|
manifestUrl: external_exports.string(),
|
|
19825
19951
|
tabs: external_exports.array(AppTabSchema),
|
|
19952
|
+
/** Home pages it offers (decision 177). */
|
|
19953
|
+
homePages: external_exports.array(AppTabSchema).default([]),
|
|
19826
19954
|
/** The data it keeps (M9 slice 2). */
|
|
19827
19955
|
collections: external_exports.array(AppCollectionInfoSchema),
|
|
19828
19956
|
/** What it does when agents ask (M9 slice 3). */
|
|
@@ -19834,7 +19962,14 @@ var AppSchema = external_exports.object({
|
|
|
19834
19962
|
dataLimitBytes: external_exports.number(),
|
|
19835
19963
|
installedBy: external_exports.object({ userId: external_exports.string(), name: external_exports.string() }),
|
|
19836
19964
|
installedAt: external_exports.string(),
|
|
19837
|
-
updatedAt: external_exports.string()
|
|
19965
|
+
updatedAt: external_exports.string(),
|
|
19966
|
+
/** The marketplace listing it was installed from (decision 205; null: by its address). */
|
|
19967
|
+
fromListing: external_exports.object({ id: external_exports.string(), slug: external_exports.string() }).nullable().default(null),
|
|
19968
|
+
/**
|
|
19969
|
+
* Tabs & Spaces took that listing down (decision 205), and why: it still
|
|
19970
|
+
* works here, for the workspace's owners and admins to decide.
|
|
19971
|
+
*/
|
|
19972
|
+
takenDown: external_exports.object({ reason: external_exports.string(), at: external_exports.string() }).nullable().default(null)
|
|
19838
19973
|
});
|
|
19839
19974
|
var AppListSchema = external_exports.object({
|
|
19840
19975
|
apps: external_exports.array(AppSchema),
|
|
@@ -19843,7 +19978,9 @@ var AppListSchema = external_exports.object({
|
|
|
19843
19978
|
});
|
|
19844
19979
|
var AppResponseSchema = external_exports.object({ app: AppSchema });
|
|
19845
19980
|
var InstallAppRequestSchema = external_exports.object({
|
|
19846
|
-
manifestUrl: external_exports.url({ protocol: /^https?$/, error: "Enter the manifest's full address." })
|
|
19981
|
+
manifestUrl: external_exports.url({ protocol: /^https?$/, error: "Enter the manifest's full address." }),
|
|
19982
|
+
/** From a listing (decision 203): only the manifest it reviewed, by its hash. */
|
|
19983
|
+
manifestHash: ManifestHashSchema.optional()
|
|
19847
19984
|
});
|
|
19848
19985
|
var AppPreviewSchema = external_exports.object({
|
|
19849
19986
|
app: AppSchema.omit({
|
|
@@ -19852,7 +19989,9 @@ var AppPreviewSchema = external_exports.object({
|
|
|
19852
19989
|
updatedAt: true,
|
|
19853
19990
|
iconUrl: true,
|
|
19854
19991
|
dataBytes: true,
|
|
19855
|
-
dataLimitBytes: true
|
|
19992
|
+
dataLimitBytes: true,
|
|
19993
|
+
fromListing: true,
|
|
19994
|
+
takenDown: true
|
|
19856
19995
|
}),
|
|
19857
19996
|
/** Its picture, inline (it isn't kept until installed). */
|
|
19858
19997
|
icon: external_exports.string().nullable(),
|
|
@@ -19862,7 +20001,17 @@ var AppPreviewSchema = external_exports.object({
|
|
|
19862
20001
|
var TabAppSchema = external_exports.object({ appId: external_exports.string(), tabId: external_exports.string() });
|
|
19863
20002
|
var AppContextSchema = external_exports.object({
|
|
19864
20003
|
user: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
|
|
19865
|
-
|
|
20004
|
+
/**
|
|
20005
|
+
* `readOnly` (decision 215): the workspace is read-only until its bill is
|
|
20006
|
+
* paid, so the app's writes are refused; its page and server can say so.
|
|
20007
|
+
* (False when a token from before it was told says nothing.)
|
|
20008
|
+
*/
|
|
20009
|
+
workspace: external_exports.object({
|
|
20010
|
+
id: external_exports.string(),
|
|
20011
|
+
slug: external_exports.string(),
|
|
20012
|
+
name: external_exports.string(),
|
|
20013
|
+
readOnly: external_exports.boolean().default(false)
|
|
20014
|
+
}),
|
|
19866
20015
|
/**
|
|
19867
20016
|
* `name` is the one the reader sees: General and My Space in their language,
|
|
19868
20017
|
* a DM by its other people. Not imported from ./space, which imports this file.
|
|
@@ -19876,11 +20025,30 @@ var AppContextSchema = external_exports.object({
|
|
|
19876
20025
|
app: external_exports.object({ id: external_exports.string() }),
|
|
19877
20026
|
locale: external_exports.string()
|
|
19878
20027
|
});
|
|
20028
|
+
var AppHomeContextSchema = AppContextSchema.extend({
|
|
20029
|
+
user: external_exports.object({ id: external_exports.string(), name: external_exports.string(), guest: external_exports.boolean() }),
|
|
20030
|
+
space: external_exports.null(),
|
|
20031
|
+
tab: external_exports.null(),
|
|
20032
|
+
/** Which of the app's home pages. */
|
|
20033
|
+
home: external_exports.object({ id: external_exports.string() })
|
|
20034
|
+
});
|
|
20035
|
+
var AppEventKeySchema = external_exports.object({ key: external_exports.string(), eventsUrl: external_exports.string() });
|
|
20036
|
+
var AppEventKeyStatusSchema = external_exports.object({
|
|
20037
|
+
on: external_exports.boolean(),
|
|
20038
|
+
/** Its app declares events (else there's nothing to report). */
|
|
20039
|
+
available: external_exports.boolean(),
|
|
20040
|
+
/** Who allowed it: events report for them. */
|
|
20041
|
+
by: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable(),
|
|
20042
|
+
createdAt: external_exports.string().nullable(),
|
|
20043
|
+
lastUsedAt: external_exports.string().nullable(),
|
|
20044
|
+
/** You may turn it on or off (you manage this space's tabs). */
|
|
20045
|
+
canManage: external_exports.boolean()
|
|
20046
|
+
});
|
|
19879
20047
|
var AppTokenResponseSchema = external_exports.object({
|
|
19880
20048
|
/** A JWT (EdDSA), verified with the deployment's keys at /api/apps/keys. */
|
|
19881
20049
|
token: external_exports.string(),
|
|
19882
20050
|
expiresAt: external_exports.string(),
|
|
19883
|
-
context: AppContextSchema,
|
|
20051
|
+
context: external_exports.union([AppContextSchema, AppHomeContextSchema]),
|
|
19884
20052
|
/** The frame's address and origin (messages go to and come from it only). */
|
|
19885
20053
|
url: external_exports.string(),
|
|
19886
20054
|
origin: external_exports.string()
|
|
@@ -20024,6 +20192,7 @@ var TabSettingsSchema = external_exports.object({
|
|
|
20024
20192
|
});
|
|
20025
20193
|
var AgentManagementSchema = external_exports.enum(["admins", "members"]);
|
|
20026
20194
|
var TaskAssignmentSchema = external_exports.enum(["members", "admins"]);
|
|
20195
|
+
var GroupMentionsSchema = external_exports.enum(["members", "admins"]);
|
|
20027
20196
|
var SpaceSchema = external_exports.object({
|
|
20028
20197
|
id: SpaceIdSchema,
|
|
20029
20198
|
kind: SpaceKindSchema,
|
|
@@ -20043,6 +20212,8 @@ var SpaceSchema = external_exports.object({
|
|
|
20043
20212
|
unpinnedByYou: external_exports.boolean(),
|
|
20044
20213
|
/** In your Starred section. */
|
|
20045
20214
|
starred: external_exports.boolean(),
|
|
20215
|
+
/** How much it notifies you (decision 199): your own choice. */
|
|
20216
|
+
notify: SpaceNotifySchema.default("all"),
|
|
20046
20217
|
/** DMs only: the participants (you included), so each reader can name it (§9.1). */
|
|
20047
20218
|
people: external_exports.array(external_exports.object({ userId: external_exports.string(), name: external_exports.string() })),
|
|
20048
20219
|
/** Your tab row: pinned first, then the rest in your (or the space's) order. */
|
|
@@ -20076,8 +20247,15 @@ var SpaceSchema = external_exports.object({
|
|
|
20076
20247
|
canManage: external_exports.boolean(),
|
|
20077
20248
|
/** Set once archived: hidden from sidebars, restorable or deletable by managers. */
|
|
20078
20249
|
archivedAt: external_exports.iso.datetime().nullable(),
|
|
20079
|
-
createdAt: external_exports.iso.datetime()
|
|
20080
|
-
|
|
20250
|
+
createdAt: external_exports.iso.datetime(),
|
|
20251
|
+
/** Who may notify everyone here with `@space` and `@here` (decision 197). */
|
|
20252
|
+
groupMentions: GroupMentionsSchema.default("members"),
|
|
20253
|
+
/** You may: a member of a normal space as its rule says, General's for workspace admins. */
|
|
20254
|
+
canMentionEveryone: external_exports.boolean().default(false),
|
|
20255
|
+
/** Its icon (normal spaces and General), a picture its managers chose; versioned, so cacheable. */
|
|
20256
|
+
iconUrl: external_exports.string().nullable().default(null)
|
|
20257
|
+
});
|
|
20258
|
+
var MAX_SPACE_ICON_BYTES = 1024 * 1024;
|
|
20081
20259
|
var SpaceListSchema = external_exports.object({
|
|
20082
20260
|
spaces: external_exports.array(SpaceSchema),
|
|
20083
20261
|
canCreate: external_exports.boolean()
|
|
@@ -20092,7 +20270,8 @@ var CreateSpaceRequestSchema = external_exports.object({
|
|
|
20092
20270
|
var UpdateSpaceRequestSchema = external_exports.object({
|
|
20093
20271
|
name: SpaceNameSchema,
|
|
20094
20272
|
description: SpaceDescriptionSchema,
|
|
20095
|
-
visibility: SpaceVisibilitySchema
|
|
20273
|
+
visibility: SpaceVisibilitySchema,
|
|
20274
|
+
groupMentions: GroupMentionsSchema
|
|
20096
20275
|
}).partial().refine((patch) => Object.keys(patch).length > 0, "Nothing to change.");
|
|
20097
20276
|
var ArchivedSpacesResponseSchema = external_exports.object({ spaces: external_exports.array(SpaceSchema) });
|
|
20098
20277
|
var SpaceMemberSchema = external_exports.object({
|
|
@@ -20164,48 +20343,6 @@ var UpdateAgentSettingsRequestSchema = external_exports.object({
|
|
|
20164
20343
|
respondingAgentId: external_exports.string().nullable()
|
|
20165
20344
|
}).partial().refine((patch) => Object.keys(patch).length > 0, "Nothing to change.");
|
|
20166
20345
|
|
|
20167
|
-
// ../types/src/time.ts
|
|
20168
|
-
function isTimeZone(value) {
|
|
20169
|
-
if (!value || value.length > 64) return false;
|
|
20170
|
-
try {
|
|
20171
|
-
new Intl.DateTimeFormat("en", { timeZone: value });
|
|
20172
|
-
return true;
|
|
20173
|
-
} catch {
|
|
20174
|
-
return false;
|
|
20175
|
-
}
|
|
20176
|
-
}
|
|
20177
|
-
var TimeZoneSchema = external_exports.string().refine(isTimeZone, "Not a known time zone.");
|
|
20178
|
-
var DEFAULT_TIME_ZONE = "UTC";
|
|
20179
|
-
|
|
20180
|
-
// ../types/src/recurrence.ts
|
|
20181
|
-
var WeekdaySchema = external_exports.number().int().min(0).max(6);
|
|
20182
|
-
var RecurrenceSchema = external_exports.discriminatedUnion("freq", [
|
|
20183
|
-
external_exports.object({ freq: external_exports.literal("daily"), interval: external_exports.number().int().min(1).max(365) }),
|
|
20184
|
-
external_exports.object({
|
|
20185
|
-
freq: external_exports.literal("weekly"),
|
|
20186
|
-
interval: external_exports.number().int().min(1).max(52),
|
|
20187
|
-
/** The days of the week it happens on (Monday to Friday: every weekday). */
|
|
20188
|
-
weekdays: external_exports.array(WeekdaySchema).min(1).max(7)
|
|
20189
|
-
}),
|
|
20190
|
-
external_exports.object({
|
|
20191
|
-
freq: external_exports.literal("monthly"),
|
|
20192
|
-
interval: external_exports.number().int().min(1).max(12),
|
|
20193
|
-
on: external_exports.discriminatedUnion("kind", [
|
|
20194
|
-
/** A day of the month; in shorter months, their last day. */
|
|
20195
|
-
external_exports.object({ kind: external_exports.literal("day"), day: external_exports.number().int().min(1).max(31) }),
|
|
20196
|
-
/** The first … fourth, or last (-1), such weekday of the month. */
|
|
20197
|
-
external_exports.object({
|
|
20198
|
-
kind: external_exports.literal("weekday"),
|
|
20199
|
-
week: external_exports.union([external_exports.literal(1), external_exports.literal(2), external_exports.literal(3), external_exports.literal(4), external_exports.literal(-1)]),
|
|
20200
|
-
weekday: WeekdaySchema
|
|
20201
|
-
})
|
|
20202
|
-
])
|
|
20203
|
-
})
|
|
20204
|
-
]);
|
|
20205
|
-
var IsoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "A date like 2026-10-16.");
|
|
20206
|
-
var ClockTimeSchema = external_exports.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "A time like 17:00.");
|
|
20207
|
-
var DAY_MS = 24 * 60 * 6e4;
|
|
20208
|
-
|
|
20209
20346
|
// ../types/src/workflows.ts
|
|
20210
20347
|
var MAX_WORKFLOW_STEPS = 30;
|
|
20211
20348
|
var WorkflowStepIdSchema = external_exports.string().regex(/^[a-z0-9]{1,16}$/, "A step id.");
|
|
@@ -20394,6 +20531,7 @@ var FinishPersonStepRequestSchema = external_exports.object({ note: external_exp
|
|
|
20394
20531
|
// ../types/src/triggers.ts
|
|
20395
20532
|
var TaskStatusSchema = external_exports.enum(["todo", "in_progress", "waiting", "done", "cancelled"]);
|
|
20396
20533
|
var MAX_TASK_ASSIGNEES = 10;
|
|
20534
|
+
var INBOX_TRIGGER_KINDS = ["mention", "dm", "thread"];
|
|
20397
20535
|
var TriggerEventSchema = external_exports.discriminatedUnion("kind", [
|
|
20398
20536
|
/** Someone posts in a conversation of the space (optionally with words in it, or by someone). */
|
|
20399
20537
|
external_exports.object({
|
|
@@ -20428,6 +20566,14 @@ var TriggerEventSchema = external_exports.discriminatedUnion("kind", [
|
|
|
20428
20566
|
event: external_exports.string().min(1).max(40),
|
|
20429
20567
|
field: external_exports.string().max(40).nullable().default(null),
|
|
20430
20568
|
value: external_exports.string().trim().max(200).nullable().default(null)
|
|
20569
|
+
}),
|
|
20570
|
+
/**
|
|
20571
|
+
* Something new in your Inbox (decision 198): a personal trigger, only in
|
|
20572
|
+
* your own My Space; what people (not agents) send you, from elsewhere.
|
|
20573
|
+
*/
|
|
20574
|
+
external_exports.object({
|
|
20575
|
+
kind: external_exports.literal("inbox"),
|
|
20576
|
+
kinds: external_exports.array(external_exports.enum(INBOX_TRIGGER_KINDS)).min(1, "Choose what starts it.").max(INBOX_TRIGGER_KINDS.length).default(["mention", "dm"])
|
|
20431
20577
|
})
|
|
20432
20578
|
]);
|
|
20433
20579
|
var TriggerTaskSchema = external_exports.object({
|
|
@@ -20512,6 +20658,8 @@ var TaskRunStatusSchema = external_exports.enum([
|
|
|
20512
20658
|
var TaskRunErrorSchema = external_exports.enum([
|
|
20513
20659
|
"NOT_CONNECTED",
|
|
20514
20660
|
"NOT_READY",
|
|
20661
|
+
// Every Gateway the deployment runs was busy, each time it tried (decision 121).
|
|
20662
|
+
"BUSY",
|
|
20515
20663
|
"PROVIDER_REFUSED",
|
|
20516
20664
|
"RUN_FAILED",
|
|
20517
20665
|
"BUDGET_TURNS",
|
|
@@ -20654,7 +20802,13 @@ var TaskSeriesSchema = external_exports.object({
|
|
|
20654
20802
|
lastAt: external_exports.string().nullable(),
|
|
20655
20803
|
occurrences: external_exports.number().int(),
|
|
20656
20804
|
createdBy: external_exports.object({ userId: external_exports.string(), name: external_exports.string() }),
|
|
20657
|
-
createdAt: external_exports.string()
|
|
20805
|
+
createdAt: external_exports.string(),
|
|
20806
|
+
/** Made ready-made (decision 198): the unread report. */
|
|
20807
|
+
preset: external_exports.enum(["unread_report"]).nullable().default(null)
|
|
20808
|
+
});
|
|
20809
|
+
var UnreadReportResponseSchema = external_exports.object({ report: TaskSeriesSchema.nullable() });
|
|
20810
|
+
var CreateUnreadReportRequestSchema = external_exports.object({
|
|
20811
|
+
time: ClockTimeSchema.default("08:00")
|
|
20658
20812
|
});
|
|
20659
20813
|
var TaskSeriesResponseSchema = external_exports.object({ series: TaskSeriesSchema });
|
|
20660
20814
|
var CreateTaskSeriesRequestSchema = external_exports.object({
|
|
@@ -20767,6 +20921,126 @@ var EmailDraftSchema = external_exports.object({
|
|
|
20767
20921
|
error: external_exports.string().nullable()
|
|
20768
20922
|
});
|
|
20769
20923
|
|
|
20924
|
+
// ../types/src/cards.ts
|
|
20925
|
+
var MAX_MESSAGE_CARDS = 8;
|
|
20926
|
+
var line = (max) => external_exports.string().trim().min(1).max(max);
|
|
20927
|
+
var optionalLine = (max) => external_exports.string().trim().max(max).optional();
|
|
20928
|
+
var link = external_exports.url({ protocol: /^https?$/, error: "An http(s) address." }).max(2e3);
|
|
20929
|
+
var when = external_exports.union([
|
|
20930
|
+
external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "A date like 2030-01-08."),
|
|
20931
|
+
external_exports.iso.datetime({ offset: true })
|
|
20932
|
+
]);
|
|
20933
|
+
var tone = external_exports.enum(["good", "warning", "bad", "neutral"]);
|
|
20934
|
+
var title = optionalLine(120);
|
|
20935
|
+
var EmailsCardSchema = external_exports.object({
|
|
20936
|
+
type: external_exports.literal("emails"),
|
|
20937
|
+
title,
|
|
20938
|
+
items: external_exports.array(
|
|
20939
|
+
external_exports.object({
|
|
20940
|
+
from: line(120),
|
|
20941
|
+
subject: external_exports.string().trim().max(200),
|
|
20942
|
+
snippet: optionalLine(300),
|
|
20943
|
+
at: when.optional(),
|
|
20944
|
+
url: link.optional(),
|
|
20945
|
+
unread: external_exports.boolean().optional(),
|
|
20946
|
+
important: external_exports.boolean().optional(),
|
|
20947
|
+
/** Why it matters, or what to do. */
|
|
20948
|
+
note: optionalLine(240)
|
|
20949
|
+
})
|
|
20950
|
+
).min(1).max(20)
|
|
20951
|
+
});
|
|
20952
|
+
var EventsCardSchema = external_exports.object({
|
|
20953
|
+
type: external_exports.literal("events"),
|
|
20954
|
+
title,
|
|
20955
|
+
items: external_exports.array(
|
|
20956
|
+
external_exports.object({
|
|
20957
|
+
title: line(160),
|
|
20958
|
+
start: when,
|
|
20959
|
+
end: when.optional(),
|
|
20960
|
+
where: optionalLine(160),
|
|
20961
|
+
people: external_exports.array(line(80)).max(20).optional(),
|
|
20962
|
+
url: link.optional(),
|
|
20963
|
+
/** A video call's link. */
|
|
20964
|
+
join: link.optional(),
|
|
20965
|
+
/** The asker's answer to it. */
|
|
20966
|
+
status: external_exports.enum(["accepted", "tentative", "declined", "needs_answer"]).optional(),
|
|
20967
|
+
note: optionalLine(240)
|
|
20968
|
+
})
|
|
20969
|
+
).min(1).max(20)
|
|
20970
|
+
});
|
|
20971
|
+
var MetricsCardSchema = external_exports.object({
|
|
20972
|
+
type: external_exports.literal("metrics"),
|
|
20973
|
+
title,
|
|
20974
|
+
items: external_exports.array(
|
|
20975
|
+
external_exports.object({
|
|
20976
|
+
label: line(60),
|
|
20977
|
+
value: line(40),
|
|
20978
|
+
detail: optionalLine(80),
|
|
20979
|
+
tone: tone.optional()
|
|
20980
|
+
})
|
|
20981
|
+
).min(1).max(6)
|
|
20982
|
+
});
|
|
20983
|
+
var TableCardSchema = external_exports.object({
|
|
20984
|
+
type: external_exports.literal("table"),
|
|
20985
|
+
title,
|
|
20986
|
+
columns: external_exports.array(line(60)).min(1).max(8),
|
|
20987
|
+
rows: external_exports.array(external_exports.array(external_exports.union([external_exports.string().max(200), external_exports.number(), external_exports.null()])).max(8)).min(1).max(50)
|
|
20988
|
+
}).refine((card) => card.rows.every((row) => row.length === card.columns.length), {
|
|
20989
|
+
error: "Every row needs one cell per column.",
|
|
20990
|
+
path: ["rows"]
|
|
20991
|
+
});
|
|
20992
|
+
var ListCardSchema = external_exports.object({
|
|
20993
|
+
type: external_exports.literal("list"),
|
|
20994
|
+
title,
|
|
20995
|
+
items: external_exports.array(
|
|
20996
|
+
external_exports.object({
|
|
20997
|
+
title: line(160),
|
|
20998
|
+
detail: optionalLine(240),
|
|
20999
|
+
/** On the side: a date, an amount, a status. */
|
|
21000
|
+
meta: optionalLine(60),
|
|
21001
|
+
url: link.optional(),
|
|
21002
|
+
tone: tone.optional()
|
|
21003
|
+
})
|
|
21004
|
+
).min(1).max(30)
|
|
21005
|
+
});
|
|
21006
|
+
var LinksCardSchema = external_exports.object({
|
|
21007
|
+
type: external_exports.literal("links"),
|
|
21008
|
+
title,
|
|
21009
|
+
items: external_exports.array(external_exports.object({ label: line(120), url: link, detail: optionalLine(160) })).min(1).max(12)
|
|
21010
|
+
});
|
|
21011
|
+
var NoteCardSchema = external_exports.object({
|
|
21012
|
+
type: external_exports.literal("note"),
|
|
21013
|
+
tone: external_exports.enum(["info", "success", "warning", "danger"]).default("info"),
|
|
21014
|
+
title,
|
|
21015
|
+
text: line(600)
|
|
21016
|
+
});
|
|
21017
|
+
var BarsCardSchema = external_exports.object({
|
|
21018
|
+
type: external_exports.literal("bars"),
|
|
21019
|
+
title,
|
|
21020
|
+
/** After each value: "h", "%", "€". */
|
|
21021
|
+
unit: optionalLine(12),
|
|
21022
|
+
items: external_exports.array(external_exports.object({ label: line(60), value: external_exports.number().finite().nonnegative() })).min(1).max(12)
|
|
21023
|
+
});
|
|
21024
|
+
var ActionsCardSchema = external_exports.object({
|
|
21025
|
+
type: external_exports.literal("actions"),
|
|
21026
|
+
items: external_exports.array(external_exports.object({ label: line(40), prompt: line(500) })).min(1).max(4)
|
|
21027
|
+
});
|
|
21028
|
+
var MessageCardSchema = external_exports.discriminatedUnion("type", [
|
|
21029
|
+
EmailsCardSchema,
|
|
21030
|
+
EventsCardSchema,
|
|
21031
|
+
MetricsCardSchema,
|
|
21032
|
+
TableCardSchema,
|
|
21033
|
+
ListCardSchema,
|
|
21034
|
+
LinksCardSchema,
|
|
21035
|
+
NoteCardSchema,
|
|
21036
|
+
BarsCardSchema,
|
|
21037
|
+
ActionsCardSchema
|
|
21038
|
+
]);
|
|
21039
|
+
var MESSAGE_CARD_TYPES = MessageCardSchema.options.map(
|
|
21040
|
+
(option) => option.shape.type.value
|
|
21041
|
+
);
|
|
21042
|
+
var MessageCardsSchema = external_exports.array(MessageCardSchema).max(MAX_MESSAGE_CARDS);
|
|
21043
|
+
|
|
20770
21044
|
// ../types/src/approvals.ts
|
|
20771
21045
|
var ApprovalStatusSchema = external_exports.enum(["pending", "approved", "declined", "expired"]);
|
|
20772
21046
|
var ApprovalSchema = external_exports.object({
|
|
@@ -20785,6 +21059,8 @@ var ApprovalSchema = external_exports.object({
|
|
|
20785
21059
|
}).nullable(),
|
|
20786
21060
|
/** The message, as proposed (or as approved, when edited). */
|
|
20787
21061
|
body: external_exports.string(),
|
|
21062
|
+
/** Cards posted with it (decision 211: a recurring task's results). */
|
|
21063
|
+
cards: MessageCardsSchema.optional(),
|
|
20788
21064
|
edited: external_exports.boolean(),
|
|
20789
21065
|
/** Why, in the agent's words (optional); a workflow's step: what it asks. */
|
|
20790
21066
|
reason: external_exports.string().nullable(),
|
|
@@ -20810,7 +21086,9 @@ var ApprovalSchema = external_exports.object({
|
|
|
20810
21086
|
description: external_exports.string(),
|
|
20811
21087
|
input: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
20812
21088
|
result: external_exports.string().nullable(),
|
|
20813
|
-
error: external_exports.string().nullable()
|
|
21089
|
+
error: external_exports.string().nullable(),
|
|
21090
|
+
/** A connector's tool: whose account it uses (the workspace's, or the asker's own). */
|
|
21091
|
+
account: external_exports.enum(["workspace", "person"]).nullable().default(null)
|
|
20814
21092
|
}).nullable().default(null),
|
|
20815
21093
|
/** An email (M9 slice 4): from, to, subject; its text is `body` (editable before it's sent). */
|
|
20816
21094
|
email: EmailDraftSchema.nullable().default(null),
|
|
@@ -20959,6 +21237,40 @@ var ChannelLoginSchema = external_exports.object({
|
|
|
20959
21237
|
qr: external_exports.string().nullable()
|
|
20960
21238
|
});
|
|
20961
21239
|
|
|
21240
|
+
// ../types/src/views.ts
|
|
21241
|
+
var MessageViewSchema = external_exports.object({
|
|
21242
|
+
id: external_exports.string().regex(/^[a-f0-9]{24}$/),
|
|
21243
|
+
/** Whose it is: a connector's (its page served by us, sandboxed), or an app's. */
|
|
21244
|
+
source: external_exports.object({ kind: external_exports.enum(["connector", "app"]), id: external_exports.string(), name: external_exports.string() }),
|
|
21245
|
+
/** The tool it shows (an app's: the action). */
|
|
21246
|
+
tool: external_exports.string(),
|
|
21247
|
+
/** An app's view: its page, on the app's origin (null: a connector's, served by us). */
|
|
21248
|
+
url: external_exports.string().nullable().default(null),
|
|
21249
|
+
title: external_exports.string().nullable(),
|
|
21250
|
+
/** Its server asks for a border (true), none (false), or leaves it to us (null). */
|
|
21251
|
+
border: external_exports.boolean().nullable()
|
|
21252
|
+
});
|
|
21253
|
+
var ViewToolResultSchema = external_exports.object({
|
|
21254
|
+
content: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())),
|
|
21255
|
+
structuredContent: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
21256
|
+
isError: external_exports.boolean().optional()
|
|
21257
|
+
});
|
|
21258
|
+
var MessageViewDataSchema = external_exports.object({
|
|
21259
|
+
tool: external_exports.object({
|
|
21260
|
+
name: external_exports.string(),
|
|
21261
|
+
title: external_exports.string().nullable(),
|
|
21262
|
+
description: external_exports.string(),
|
|
21263
|
+
inputSchema: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
21264
|
+
}),
|
|
21265
|
+
input: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
21266
|
+
result: ViewToolResultSchema
|
|
21267
|
+
});
|
|
21268
|
+
var ViewCallRequestSchema = external_exports.object({
|
|
21269
|
+
name: external_exports.string().min(1).max(200),
|
|
21270
|
+
arguments: external_exports.record(external_exports.string(), external_exports.unknown()).default({})
|
|
21271
|
+
});
|
|
21272
|
+
var ViewCallResponseSchema = external_exports.object({ result: ViewToolResultSchema });
|
|
21273
|
+
|
|
20962
21274
|
// ../types/src/message.ts
|
|
20963
21275
|
var MAX_MESSAGE_LENGTH = 1e4;
|
|
20964
21276
|
var MessageIdSchema = external_exports.string().regex(/^[a-f0-9]{24}$/, "Invalid message id");
|
|
@@ -21049,7 +21361,11 @@ var AgentToolSchema = external_exports.enum([
|
|
|
21049
21361
|
// An agent changing its own profile (title, face, instructions…) when asked, approved first.
|
|
21050
21362
|
"update_my_profile",
|
|
21051
21363
|
// Connectors (M12 slice 2): a remote MCP server's tools the workspace chose (reading ones).
|
|
21052
|
-
"use_connector"
|
|
21364
|
+
"use_connector",
|
|
21365
|
+
// Notifications (decision 198): the asker's own Inbox, where only they read the answer.
|
|
21366
|
+
"read_inbox",
|
|
21367
|
+
// Cards (decision 211): mail, events, figures and rows shown under its answer.
|
|
21368
|
+
"show_cards"
|
|
21053
21369
|
]);
|
|
21054
21370
|
var AgentStepSchema = external_exports.object({
|
|
21055
21371
|
tool: AgentToolSchema,
|
|
@@ -21104,6 +21420,10 @@ var MessageSchema = external_exports.object({
|
|
|
21104
21420
|
proposal: TaskProposalSchema.optional(),
|
|
21105
21421
|
/** Something an agent wants to do, waiting for a person's yes (M8 slice 6). */
|
|
21106
21422
|
approval: ApprovalSchema.optional(),
|
|
21423
|
+
/** What an agent's answer shows (decision 211): mail, events, figures, rows… */
|
|
21424
|
+
cards: MessageCardsSchema.optional(),
|
|
21425
|
+
/** Connectors' views in an agent's answer (MCP Apps, decision 213). */
|
|
21426
|
+
views: external_exports.array(MessageViewSchema).optional(),
|
|
21107
21427
|
/** Sent from a messaging app (M13): Telegram… */
|
|
21108
21428
|
via: MessageViaSchema.optional()
|
|
21109
21429
|
});
|
|
@@ -21154,7 +21474,9 @@ var ReferenceSchema = external_exports.object({
|
|
|
21154
21474
|
id: external_exports.string(),
|
|
21155
21475
|
kind: external_exports.enum(["general", "personal", "normal", "dm"]),
|
|
21156
21476
|
name: external_exports.string().nullable(),
|
|
21157
|
-
people: external_exports.array(external_exports.object({ userId: external_exports.string(), name: external_exports.string() }))
|
|
21477
|
+
people: external_exports.array(external_exports.object({ userId: external_exports.string(), name: external_exports.string() })),
|
|
21478
|
+
/** Its icon, when it has one (decision 190). */
|
|
21479
|
+
iconUrl: external_exports.string().nullable().default(null)
|
|
21158
21480
|
}).nullable(),
|
|
21159
21481
|
tab: external_exports.object({
|
|
21160
21482
|
id: external_exports.string(),
|
|
@@ -21453,6 +21775,10 @@ var AUDIT_ACTIONS = {
|
|
|
21453
21775
|
"workspace.data_moved",
|
|
21454
21776
|
"workspace.previous_data_deleted",
|
|
21455
21777
|
"workspace.support_plan_changed",
|
|
21778
|
+
"workspace.billing_contact_changed",
|
|
21779
|
+
"workspace.card_saved",
|
|
21780
|
+
"workspace.card_removed",
|
|
21781
|
+
"workspace.statement_paid",
|
|
21456
21782
|
"workspace.space_imported",
|
|
21457
21783
|
"audit.exported",
|
|
21458
21784
|
"audit.destination_added",
|
|
@@ -21463,12 +21789,15 @@ var AUDIT_ACTIONS = {
|
|
|
21463
21789
|
"member.invite_link_created",
|
|
21464
21790
|
"member.invitation_revoked",
|
|
21465
21791
|
"member.joined",
|
|
21466
|
-
"member.title_changed"
|
|
21792
|
+
"member.title_changed",
|
|
21793
|
+
"member.role_changed"
|
|
21467
21794
|
],
|
|
21468
21795
|
spaces: [
|
|
21469
21796
|
"space.created",
|
|
21470
21797
|
"space.updated",
|
|
21471
21798
|
"space.deleted",
|
|
21799
|
+
"space.icon_changed",
|
|
21800
|
+
"space.icon_removed",
|
|
21472
21801
|
"space.archived",
|
|
21473
21802
|
"space.unarchived",
|
|
21474
21803
|
"space.converted",
|
|
@@ -21508,6 +21837,9 @@ var AUDIT_ACTIONS = {
|
|
|
21508
21837
|
"agent.avatar_changed",
|
|
21509
21838
|
"agent.host_access_changed",
|
|
21510
21839
|
"agent.memory_changed",
|
|
21840
|
+
"agent.published",
|
|
21841
|
+
"agent.unpublished",
|
|
21842
|
+
"agent.added_from_marketplace",
|
|
21511
21843
|
"approval.requested",
|
|
21512
21844
|
"gateway.connected",
|
|
21513
21845
|
"gateway.disconnected",
|
|
@@ -21536,6 +21868,14 @@ var AUDIT_ACTIONS = {
|
|
|
21536
21868
|
"app.installed",
|
|
21537
21869
|
"app.updated",
|
|
21538
21870
|
"app.removed",
|
|
21871
|
+
"app.added_from_marketplace",
|
|
21872
|
+
"app.published",
|
|
21873
|
+
"app.unpublished",
|
|
21874
|
+
"app.publishing_key_created",
|
|
21875
|
+
"app.publishing_key_revoked",
|
|
21876
|
+
"app.taken_down",
|
|
21877
|
+
"app.event_key_allowed",
|
|
21878
|
+
"app.event_key_turned_off",
|
|
21539
21879
|
"app.action_run",
|
|
21540
21880
|
"connection.added",
|
|
21541
21881
|
"connection.removed",
|
|
@@ -21573,6 +21913,10 @@ var AUDIT_ACTIONS = {
|
|
|
21573
21913
|
"billing.stripe_connected",
|
|
21574
21914
|
"billing.stripe_disconnected",
|
|
21575
21915
|
"statement.changed",
|
|
21916
|
+
"statement.extended",
|
|
21917
|
+
"agreement.created",
|
|
21918
|
+
"agreement.updated",
|
|
21919
|
+
"agreement.deleted",
|
|
21576
21920
|
"support.registered",
|
|
21577
21921
|
"support.unregistered",
|
|
21578
21922
|
"support.report_sent",
|
|
@@ -21632,6 +21976,7 @@ var AuditTargetSchema = external_exports.object({
|
|
|
21632
21976
|
"workflow",
|
|
21633
21977
|
"approval",
|
|
21634
21978
|
"statement",
|
|
21979
|
+
"agreement",
|
|
21635
21980
|
"ticket",
|
|
21636
21981
|
"help_request",
|
|
21637
21982
|
"skill",
|
|
@@ -21784,12 +22129,18 @@ var DeploymentSettingsFields = external_exports.object({
|
|
|
21784
22129
|
* for you") keep it awake, never put to sleep (decision 151)? They pay its
|
|
21785
22130
|
* hours where the deployment bills them.
|
|
21786
22131
|
*/
|
|
21787
|
-
allowGatewayKeepAwake: external_exports.boolean()
|
|
22132
|
+
allowGatewayKeepAwake: external_exports.boolean(),
|
|
22133
|
+
/**
|
|
22134
|
+
* Workspaces browse and add from the marketplace (decision 161): Tabs &
|
|
22135
|
+
* Spaces' catalogue, reviewed by us. On unless its admins turn it off.
|
|
22136
|
+
*/
|
|
22137
|
+
marketplace: external_exports.boolean()
|
|
21788
22138
|
});
|
|
21789
22139
|
var DeploymentSettingsSchema = DeploymentSettingsFields.extend({
|
|
21790
22140
|
// Missing in older responses and fixtures: off.
|
|
21791
22141
|
shareFeedback: external_exports.boolean().default(false),
|
|
21792
|
-
allowGatewayKeepAwake: external_exports.boolean().default(false)
|
|
22142
|
+
allowGatewayKeepAwake: external_exports.boolean().default(false),
|
|
22143
|
+
marketplace: external_exports.boolean().default(true)
|
|
21793
22144
|
});
|
|
21794
22145
|
var DeploymentSettingsPatchSchema = DeploymentSettingsFields.partial().strict().refine((patch) => Object.keys(patch).length > 0, "Nothing to update");
|
|
21795
22146
|
var DeploymentInfoSchema = external_exports.object({
|
|
@@ -22065,78 +22416,380 @@ var ReadinessSchema = external_exports.object({
|
|
|
22065
22416
|
checks: external_exports.array(ReadinessCheckSchema)
|
|
22066
22417
|
});
|
|
22067
22418
|
|
|
22068
|
-
// ../types/src/
|
|
22069
|
-
var
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
|
|
22073
|
-
|
|
22074
|
-
|
|
22075
|
-
|
|
22076
|
-
|
|
22077
|
-
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
|
|
22081
|
-
|
|
22082
|
-
|
|
22083
|
-
logoUrl: external_exports.string().nullable().default(null),
|
|
22084
|
-
/** Its data is moving to new storage (M5 slice 4): read-only until it's done. */
|
|
22085
|
-
moving: external_exports.boolean().default(false),
|
|
22086
|
-
/** Its accent colour for each mode; null: the default ink. */
|
|
22087
|
-
accent: WorkspaceAccentSchema.nullable().default(null),
|
|
22088
|
-
/** Its default time zone (M8 slice 1): for schedules when a person's own isn't known. */
|
|
22089
|
-
timeZone: TimeZoneSchema.default(DEFAULT_TIME_ZONE)
|
|
22090
|
-
});
|
|
22091
|
-
var MAX_WORKSPACE_LOGO_BYTES = 2 * 1024 * 1024;
|
|
22092
|
-
var WorkspaceListSchema = external_exports.object({
|
|
22093
|
-
workspaces: external_exports.array(WorkspaceSchema),
|
|
22094
|
-
/** Whether the current user may create a(nother) workspace right now. */
|
|
22095
|
-
canCreate: external_exports.boolean(),
|
|
22096
|
-
/** Whether a new workspace may keep its data in its own MongoDB and bucket (M5). */
|
|
22097
|
-
customInfrastructure: external_exports.boolean()
|
|
22098
|
-
});
|
|
22099
|
-
var MongoUriSchema = external_exports.string().trim().max(2e3).regex(/^mongodb(\+srv)?:\/\/[^\s]+$/, "Use a mongodb:// or mongodb+srv:// connection string");
|
|
22100
|
-
var BucketSchema = external_exports.object({
|
|
22101
|
-
endpoint: external_exports.string().trim().max(500).regex(/^https?:\/\/[^\s/@]+(\/[^\s]*)?$/, "Use an http(s) address, without credentials").optional(),
|
|
22102
|
-
region: external_exports.string().trim().min(1).max(64).default("us-east-1"),
|
|
22103
|
-
bucket: external_exports.string().trim().regex(/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/, "Use a valid bucket name"),
|
|
22104
|
-
accessKeyId: external_exports.string().trim().min(1).max(256),
|
|
22105
|
-
secretAccessKey: external_exports.string().min(1).max(512),
|
|
22106
|
-
/** Path-style addresses (MinIO and most self-hosted stores need them). */
|
|
22107
|
-
forcePathStyle: external_exports.boolean().default(false)
|
|
22108
|
-
});
|
|
22109
|
-
var STORAGE_PROBLEMS = [
|
|
22110
|
-
"INVALID",
|
|
22111
|
-
"UNREACHABLE",
|
|
22112
|
-
"PRIVATE_ADDRESS",
|
|
22113
|
-
"AUTH_FAILED",
|
|
22114
|
-
"NO_BUCKET",
|
|
22115
|
-
"NO_PERMISSION",
|
|
22116
|
-
"NOT_EMPTY"
|
|
22419
|
+
// ../types/src/billing.ts
|
|
22420
|
+
var COMMON_CURRENCIES = [
|
|
22421
|
+
"USD",
|
|
22422
|
+
"EUR",
|
|
22423
|
+
"GBP",
|
|
22424
|
+
"NGN",
|
|
22425
|
+
"KES",
|
|
22426
|
+
"GHS",
|
|
22427
|
+
"ZAR",
|
|
22428
|
+
"CAD",
|
|
22429
|
+
"AUD",
|
|
22430
|
+
"CHF",
|
|
22431
|
+
"JPY",
|
|
22432
|
+
"INR",
|
|
22433
|
+
"BRL"
|
|
22117
22434
|
];
|
|
22118
|
-
var
|
|
22119
|
-
var
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
var
|
|
22129
|
-
name:
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
/**
|
|
22133
|
-
|
|
22134
|
-
/**
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
timeZone: TimeZoneSchema.optional()
|
|
22435
|
+
var CurrencySchema = external_exports.string().regex(/^[A-Z]{3}$/, "Use a three-letter currency code, like USD").refine((code) => knownCurrencies().has(code), "Unknown currency");
|
|
22436
|
+
var known = null;
|
|
22437
|
+
function knownCurrencies() {
|
|
22438
|
+
known ??= new Set(
|
|
22439
|
+
typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("currency") : COMMON_CURRENCIES
|
|
22440
|
+
);
|
|
22441
|
+
return known;
|
|
22442
|
+
}
|
|
22443
|
+
var PriceSchema = external_exports.number().min(0, "Prices can't be negative").max(1e6).transform((value) => Math.round(value * 1e4) / 1e4);
|
|
22444
|
+
var priced = external_exports.object({ enabled: external_exports.boolean(), price: PriceSchema });
|
|
22445
|
+
var ModelPriceSchema = external_exports.object({
|
|
22446
|
+
/** As agents name it: `provider/model`. */
|
|
22447
|
+
model: external_exports.string().trim().min(3).max(200),
|
|
22448
|
+
input: PriceSchema,
|
|
22449
|
+
/** Input read from the prompt cache. */
|
|
22450
|
+
cachedInput: PriceSchema,
|
|
22451
|
+
/** Input written to the prompt cache. */
|
|
22452
|
+
cacheWrite: PriceSchema,
|
|
22453
|
+
output: PriceSchema
|
|
22138
22454
|
});
|
|
22139
|
-
var
|
|
22455
|
+
var BillingSettingsSchema = external_exports.object({
|
|
22456
|
+
currency: CurrencySchema,
|
|
22457
|
+
/** Per person who used the workspace in the month. */
|
|
22458
|
+
seats: priced,
|
|
22459
|
+
/** Per GB-month in the deployment's bucket. */
|
|
22460
|
+
files: priced,
|
|
22461
|
+
/** Per GB-month in the deployment's MongoDB. */
|
|
22462
|
+
database: priced,
|
|
22463
|
+
/** Model cost (from `models`) plus a markup, for runs on the deployment's Gateway. */
|
|
22464
|
+
ai: external_exports.object({
|
|
22465
|
+
enabled: external_exports.boolean(),
|
|
22466
|
+
markupPercent: external_exports.number().min(0).max(1e3),
|
|
22467
|
+
models: external_exports.array(ModelPriceSchema).max(100).refine(
|
|
22468
|
+
(models) => new Set(models.map((m) => m.model)).size === models.length,
|
|
22469
|
+
"Each model once"
|
|
22470
|
+
)
|
|
22471
|
+
}),
|
|
22472
|
+
/** A flat amount per workspace per month (prorated from the day it was created). */
|
|
22473
|
+
deploymentFee: priced,
|
|
22474
|
+
/**
|
|
22475
|
+
* A support plan per workspace per month, opt-in (decision 74): workspaces
|
|
22476
|
+
* that turn it on pay it (prorated by day) and can ask the deployment for
|
|
22477
|
+
* help. Absent in settings saved before it existed: off.
|
|
22478
|
+
*/
|
|
22479
|
+
support: priced.default({ enabled: false, price: 0 }),
|
|
22480
|
+
/**
|
|
22481
|
+
* The deployment's Gateways (decision 151), per hour: a workspace's own
|
|
22482
|
+
* ("Managed for you") while it's awake, or the deployment's shared one while
|
|
22483
|
+
* the workspace is connected to it. Absent in older settings: off.
|
|
22484
|
+
*/
|
|
22485
|
+
gatewayHours: priced.default({ enabled: false, price: 0 }),
|
|
22486
|
+
/** A workspace's own Gateway's storage (its volume), per GB-month, asleep or awake. */
|
|
22487
|
+
gatewayStorage: priced.default({ enabled: false, price: 0 }),
|
|
22488
|
+
/**
|
|
22489
|
+
* What happens when a statement isn't paid (decision 209): reminders always;
|
|
22490
|
+
* with `readOnly`, the workspace becomes read-only `graceDays` after its
|
|
22491
|
+
* due date, until it's paid. Absent in older settings: on, 30 days.
|
|
22492
|
+
*/
|
|
22493
|
+
overdue: external_exports.object({ readOnly: external_exports.boolean(), graceDays: external_exports.number().int().min(1).max(365) }).default({ readOnly: true, graceDays: 30 })
|
|
22494
|
+
});
|
|
22495
|
+
var BILLING_METERS = [
|
|
22496
|
+
"seats",
|
|
22497
|
+
"files",
|
|
22498
|
+
"database",
|
|
22499
|
+
"ai",
|
|
22500
|
+
"deploymentFee",
|
|
22501
|
+
"support",
|
|
22502
|
+
"gatewayHours",
|
|
22503
|
+
"gatewayStorage"
|
|
22504
|
+
];
|
|
22505
|
+
var StripeConnectionSchema = external_exports.object({
|
|
22506
|
+
connected: external_exports.boolean(),
|
|
22507
|
+
/** Test keys create test invoices that nobody really pays. */
|
|
22508
|
+
mode: external_exports.enum(["test", "live"]).nullable(),
|
|
22509
|
+
/** The key's last four characters, to recognise it. */
|
|
22510
|
+
keyHint: external_exports.string().nullable(),
|
|
22511
|
+
connectedAt: external_exports.iso.datetime().nullable()
|
|
22512
|
+
});
|
|
22513
|
+
var ConnectStripeRequestSchema = external_exports.object({
|
|
22514
|
+
secretKey: external_exports.string().trim().regex(
|
|
22515
|
+
/^(sk|rk)_(test|live)_[A-Za-z0-9]{10,}$/,
|
|
22516
|
+
"Use a Stripe secret key (sk_\u2026) or restricted key (rk_\u2026)"
|
|
22517
|
+
)
|
|
22518
|
+
});
|
|
22519
|
+
var AdminBillingSchema = external_exports.object({
|
|
22520
|
+
settings: BillingSettingsSchema,
|
|
22521
|
+
/** Models agents have run on this deployment's Gateways, to price. */
|
|
22522
|
+
modelsInUse: external_exports.array(external_exports.string()),
|
|
22523
|
+
stripe: StripeConnectionSchema
|
|
22524
|
+
});
|
|
22525
|
+
var BillLineSchema = external_exports.object({
|
|
22526
|
+
meter: external_exports.enum([...BILLING_METERS, "agreement"]),
|
|
22527
|
+
/**
|
|
22528
|
+
* billed: charged; notBilled: this deployment doesn't bill it;
|
|
22529
|
+
* own: the workspace brings this resource itself; notChosen: an opt-in plan
|
|
22530
|
+
* (support) the workspace doesn't have; included: its agreement covers it.
|
|
22531
|
+
*/
|
|
22532
|
+
status: external_exports.enum(["billed", "notBilled", "own", "notChosen", "included"]),
|
|
22533
|
+
/** People, GB-months, tokens, or the share of the month (deployment fee, support plan). */
|
|
22534
|
+
quantity: external_exports.number().nonnegative(),
|
|
22535
|
+
/** Price per unit; null for AI (priced per model). */
|
|
22536
|
+
unitPrice: external_exports.number().nullable(),
|
|
22537
|
+
amount: external_exports.number().nonnegative()
|
|
22538
|
+
});
|
|
22539
|
+
var WorkspaceBillSchema = external_exports.object({
|
|
22540
|
+
currency: external_exports.string(),
|
|
22541
|
+
lines: external_exports.array(BillLineSchema),
|
|
22542
|
+
/** AI amount per model (null: the model has no price set). */
|
|
22543
|
+
aiByModel: external_exports.array(external_exports.object({ model: external_exports.string(), amount: external_exports.number().nullable() })),
|
|
22544
|
+
/** Models used but not priced: their tokens aren't charged. */
|
|
22545
|
+
unpricedModels: external_exports.array(external_exports.string()),
|
|
22546
|
+
total: external_exports.number().nonnegative(),
|
|
22547
|
+
/** True for the current month: amounts grow until it ends. */
|
|
22548
|
+
toDate: external_exports.boolean()
|
|
22549
|
+
});
|
|
22550
|
+
var StatementStatusSchema = external_exports.enum(["nothingDue", "due", "paid", "void"]);
|
|
22551
|
+
var StatementSchema = external_exports.object({
|
|
22552
|
+
id: external_exports.string(),
|
|
22553
|
+
workspaceId: external_exports.string(),
|
|
22554
|
+
/**
|
|
22555
|
+
* usage: a month's metered bill, after it ends; agreement: a period of an
|
|
22556
|
+
* agreement's fixed price, at its start (decision 209).
|
|
22557
|
+
*/
|
|
22558
|
+
kind: external_exports.enum(["usage", "agreement"]).default("usage"),
|
|
22559
|
+
/** usage: the month; agreement: the period's first month. */
|
|
22560
|
+
month: external_exports.string(),
|
|
22561
|
+
/** An agreement's period: its first and last months (null for usage). */
|
|
22562
|
+
period: external_exports.object({ from: external_exports.string(), to: external_exports.string() }).nullable().default(null),
|
|
22563
|
+
currency: external_exports.string(),
|
|
22564
|
+
lines: external_exports.array(BillLineSchema),
|
|
22565
|
+
aiByModel: external_exports.array(external_exports.object({ model: external_exports.string(), amount: external_exports.number().nullable() })),
|
|
22566
|
+
unpricedModels: external_exports.array(external_exports.string()),
|
|
22567
|
+
total: external_exports.number().nonnegative(),
|
|
22568
|
+
status: StatementStatusSchema,
|
|
22569
|
+
createdAt: external_exports.iso.datetime(),
|
|
22570
|
+
/** When it must be paid by (null: nothing due, or from before due dates were kept). */
|
|
22571
|
+
dueAt: external_exports.iso.datetime().nullable().default(null),
|
|
22572
|
+
paidAt: external_exports.iso.datetime().nullable(),
|
|
22573
|
+
payment: external_exports.object({
|
|
22574
|
+
/** stripe: an invoice on the deployment's Stripe; manual: settled outside the app. */
|
|
22575
|
+
provider: external_exports.enum(["stripe", "manual"]),
|
|
22576
|
+
invoiceNumber: external_exports.string().nullable(),
|
|
22577
|
+
/** Stripe's page where the invoice can be paid. */
|
|
22578
|
+
invoiceUrl: external_exports.url().nullable(),
|
|
22579
|
+
/** Why the invoice couldn't be created yet (retried every hour). */
|
|
22580
|
+
error: external_exports.string().nullable(),
|
|
22581
|
+
/** Why the saved card couldn't pay it (it can still be paid on Stripe's page). */
|
|
22582
|
+
chargeError: external_exports.string().nullable().default(null)
|
|
22583
|
+
})
|
|
22584
|
+
});
|
|
22585
|
+
var WorkspaceStatementsSchema = external_exports.object({ statements: external_exports.array(StatementSchema) });
|
|
22586
|
+
var AdminStatementsSchema = external_exports.object({
|
|
22587
|
+
month: external_exports.string(),
|
|
22588
|
+
/** Months with statements, newest first. */
|
|
22589
|
+
months: external_exports.array(external_exports.string()),
|
|
22590
|
+
statements: external_exports.array(
|
|
22591
|
+
StatementSchema.extend({
|
|
22592
|
+
workspace: external_exports.object({ id: external_exports.string(), name: external_exports.string(), slug: external_exports.string() })
|
|
22593
|
+
})
|
|
22594
|
+
)
|
|
22595
|
+
});
|
|
22596
|
+
var AgreementPeriodSchema = external_exports.enum(["month", "year"]);
|
|
22597
|
+
var AgreementSchema = external_exports.object({
|
|
22598
|
+
id: external_exports.string(),
|
|
22599
|
+
workspaceId: external_exports.string(),
|
|
22600
|
+
/** What it's called on invoices, like "Enterprise". */
|
|
22601
|
+
name: external_exports.string(),
|
|
22602
|
+
currency: external_exports.string(),
|
|
22603
|
+
/** The fixed price per period. */
|
|
22604
|
+
amount: external_exports.number().nonnegative(),
|
|
22605
|
+
period: AgreementPeriodSchema,
|
|
22606
|
+
startMonth: UsageMonthOf(),
|
|
22607
|
+
/** Its last month, included; null: until it's ended. */
|
|
22608
|
+
endMonth: UsageMonthOf().nullable(),
|
|
22609
|
+
included: external_exports.array(external_exports.enum(BILLING_METERS)),
|
|
22610
|
+
/** For the deployment's admins only (never shown to the workspace). */
|
|
22611
|
+
note: external_exports.string(),
|
|
22612
|
+
createdAt: external_exports.iso.datetime()
|
|
22613
|
+
});
|
|
22614
|
+
function UsageMonthOf() {
|
|
22615
|
+
return external_exports.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/, "Use a month like 2026-11");
|
|
22616
|
+
}
|
|
22617
|
+
var agreementFields = {
|
|
22618
|
+
name: external_exports.string().trim().min(1, "Give it a name").max(80),
|
|
22619
|
+
amount: PriceSchema.refine((amount) => amount > 0, "Use an amount above 0"),
|
|
22620
|
+
period: AgreementPeriodSchema,
|
|
22621
|
+
startMonth: UsageMonthOf(),
|
|
22622
|
+
endMonth: UsageMonthOf().nullable(),
|
|
22623
|
+
included: external_exports.array(external_exports.enum(BILLING_METERS)).max(BILLING_METERS.length).transform((meters) => [...new Set(meters)]),
|
|
22624
|
+
note: external_exports.string().trim().max(2e3)
|
|
22625
|
+
};
|
|
22626
|
+
var endsAfterStart = (a) => !a.startMonth || !a.endMonth || a.endMonth >= a.startMonth;
|
|
22627
|
+
var CreateAgreementRequestSchema = external_exports.object({
|
|
22628
|
+
workspaceId: external_exports.string().min(1),
|
|
22629
|
+
...agreementFields,
|
|
22630
|
+
note: agreementFields.note.default("")
|
|
22631
|
+
}).refine(endsAfterStart, { message: "It can't end before it starts", path: ["endMonth"] });
|
|
22632
|
+
var UpdateAgreementRequestSchema = external_exports.object(agreementFields).partial().refine((patch) => Object.keys(patch).length > 0, "Nothing to change.").refine(endsAfterStart, { message: "It can't end before it starts", path: ["endMonth"] });
|
|
22633
|
+
var AdminAgreementsSchema = external_exports.object({
|
|
22634
|
+
currency: external_exports.string(),
|
|
22635
|
+
/** The current month (UTC): agreements start then or later. */
|
|
22636
|
+
month: external_exports.string(),
|
|
22637
|
+
agreements: external_exports.array(
|
|
22638
|
+
AgreementSchema.extend({
|
|
22639
|
+
workspace: external_exports.object({ id: external_exports.string(), name: external_exports.string(), slug: external_exports.string() })
|
|
22640
|
+
})
|
|
22641
|
+
),
|
|
22642
|
+
workspaces: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string(), slug: external_exports.string() }))
|
|
22643
|
+
});
|
|
22644
|
+
var BillingContactSchema = external_exports.object({
|
|
22645
|
+
/** The name on invoices: a company, or a person. */
|
|
22646
|
+
name: external_exports.string().trim().max(120),
|
|
22647
|
+
email: external_exports.union([external_exports.literal(""), external_exports.email()]),
|
|
22648
|
+
address: external_exports.object({
|
|
22649
|
+
line1: external_exports.string().trim().max(200),
|
|
22650
|
+
line2: external_exports.string().trim().max(200),
|
|
22651
|
+
city: external_exports.string().trim().max(100),
|
|
22652
|
+
postalCode: external_exports.string().trim().max(20),
|
|
22653
|
+
state: external_exports.string().trim().max(100),
|
|
22654
|
+
/** ISO 3166-1 alpha-2, or empty. */
|
|
22655
|
+
country: external_exports.union([
|
|
22656
|
+
external_exports.literal(""),
|
|
22657
|
+
external_exports.string().regex(/^[A-Z]{2}$/, "Use a two-letter country code")
|
|
22658
|
+
])
|
|
22659
|
+
}),
|
|
22660
|
+
/** A VAT or tax number, printed on invoices. */
|
|
22661
|
+
taxId: external_exports.string().trim().max(50)
|
|
22662
|
+
});
|
|
22663
|
+
var SavedCardSchema = external_exports.object({
|
|
22664
|
+
brand: external_exports.string(),
|
|
22665
|
+
last4: external_exports.string(),
|
|
22666
|
+
expMonth: external_exports.number().int(),
|
|
22667
|
+
expYear: external_exports.number().int()
|
|
22668
|
+
});
|
|
22669
|
+
var BillingHoldSchema = external_exports.object({
|
|
22670
|
+
state: external_exports.enum(["overdue", "readOnly"]),
|
|
22671
|
+
/** The oldest unpaid statement's due date. */
|
|
22672
|
+
dueAt: external_exports.iso.datetime(),
|
|
22673
|
+
/** When it becomes read-only (null: the deployment doesn't do that). */
|
|
22674
|
+
readOnlyAt: external_exports.iso.datetime().nullable()
|
|
22675
|
+
});
|
|
22676
|
+
var WorkspaceBillingSchema = external_exports.object({
|
|
22677
|
+
/** null: the deployment doesn't bill workspaces. */
|
|
22678
|
+
plan: external_exports.discriminatedUnion("kind", [
|
|
22679
|
+
external_exports.object({
|
|
22680
|
+
kind: external_exports.literal("usage"),
|
|
22681
|
+
currency: external_exports.string(),
|
|
22682
|
+
/** The meters billed and their prices (null: priced per model, for AI). */
|
|
22683
|
+
meters: external_exports.array(
|
|
22684
|
+
external_exports.object({ meter: external_exports.enum(BILLING_METERS), unitPrice: external_exports.number().nullable() })
|
|
22685
|
+
)
|
|
22686
|
+
}),
|
|
22687
|
+
external_exports.object({
|
|
22688
|
+
kind: external_exports.literal("agreement"),
|
|
22689
|
+
currency: external_exports.string(),
|
|
22690
|
+
agreement: AgreementSchema.omit({ note: true }),
|
|
22691
|
+
/** The meters it doesn't include, billed as usual. */
|
|
22692
|
+
meters: external_exports.array(
|
|
22693
|
+
external_exports.object({ meter: external_exports.enum(BILLING_METERS), unitPrice: external_exports.number().nullable() })
|
|
22694
|
+
)
|
|
22695
|
+
})
|
|
22696
|
+
]).nullable(),
|
|
22697
|
+
/** An agreement that starts later, if one is set. */
|
|
22698
|
+
upcoming: AgreementSchema.omit({ note: true }).nullable(),
|
|
22699
|
+
statements: external_exports.array(StatementSchema),
|
|
22700
|
+
contact: BillingContactSchema,
|
|
22701
|
+
/** Whether invoices can be paid online (the deployment has Stripe). */
|
|
22702
|
+
online: external_exports.boolean(),
|
|
22703
|
+
card: SavedCardSchema.nullable(),
|
|
22704
|
+
hold: BillingHoldSchema.nullable(),
|
|
22705
|
+
/** Owners change the contact and the card; admins see. */
|
|
22706
|
+
canManage: external_exports.boolean()
|
|
22707
|
+
});
|
|
22708
|
+
var CardSetupSchema = external_exports.object({ url: external_exports.url() });
|
|
22709
|
+
|
|
22710
|
+
// ../types/src/accent.ts
|
|
22711
|
+
var HexColorSchema = external_exports.string().regex(/^#[0-9a-fA-F]{6}$/, "Use a colour like #4f46e5").transform((hex3) => hex3.toLowerCase());
|
|
22712
|
+
var WorkspaceAccentSchema = external_exports.object({ light: HexColorSchema, dark: HexColorSchema });
|
|
22713
|
+
|
|
22714
|
+
// ../types/src/workspace.ts
|
|
22715
|
+
var WorkspaceRoleSchema = external_exports.enum(["owner", "admin", "member", "guest"]);
|
|
22716
|
+
var WorkspaceSlugSchema = external_exports.string().regex(/^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/, "Use lowercase letters, numbers and hyphens");
|
|
22717
|
+
var WorkspaceNameSchema = external_exports.string().trim().min(1).max(60);
|
|
22718
|
+
var WorkspaceHomePageSchema = external_exports.object({
|
|
22719
|
+
appId: external_exports.string().min(1).max(64),
|
|
22720
|
+
pageId: external_exports.string().min(1).max(40)
|
|
22721
|
+
});
|
|
22722
|
+
var WorkspaceSchema = external_exports.object({
|
|
22723
|
+
id: external_exports.string(),
|
|
22724
|
+
slug: WorkspaceSlugSchema,
|
|
22725
|
+
name: external_exports.string(),
|
|
22726
|
+
role: WorkspaceRoleSchema,
|
|
22727
|
+
createdAt: external_exports.iso.datetime(),
|
|
22728
|
+
/** The workspace's logo (optional), served from its own storage; versioned, so cacheable. */
|
|
22729
|
+
logoUrl: external_exports.string().nullable().default(null),
|
|
22730
|
+
/** Its data is moving to new storage (M5 slice 4): read-only until it's done. */
|
|
22731
|
+
moving: external_exports.boolean().default(false),
|
|
22732
|
+
/**
|
|
22733
|
+
* Its bills are late (decision 209): owners and admins see it as overdue;
|
|
22734
|
+
* everyone sees it once it's read-only until paid. Null: nothing late.
|
|
22735
|
+
*/
|
|
22736
|
+
billingHold: BillingHoldSchema.nullable().default(null),
|
|
22737
|
+
/** Its accent colour for each mode; null: the default ink. */
|
|
22738
|
+
accent: WorkspaceAccentSchema.nullable().default(null),
|
|
22739
|
+
/** Its default time zone (M8 slice 1): for schedules when a person's own isn't known. */
|
|
22740
|
+
timeZone: TimeZoneSchema.default(DEFAULT_TIME_ZONE),
|
|
22741
|
+
/** Its Home (decision 177): one of an installed app's home pages; null: ours. */
|
|
22742
|
+
homePage: WorkspaceHomePageSchema.nullable().default(null)
|
|
22743
|
+
});
|
|
22744
|
+
var MAX_WORKSPACE_LOGO_BYTES = 2 * 1024 * 1024;
|
|
22745
|
+
var WorkspaceListSchema = external_exports.object({
|
|
22746
|
+
workspaces: external_exports.array(WorkspaceSchema),
|
|
22747
|
+
/** Whether the current user may create a(nother) workspace right now. */
|
|
22748
|
+
canCreate: external_exports.boolean(),
|
|
22749
|
+
/** Whether a new workspace may keep its data in its own MongoDB and bucket (M5). */
|
|
22750
|
+
customInfrastructure: external_exports.boolean()
|
|
22751
|
+
});
|
|
22752
|
+
var MongoUriSchema = external_exports.string().trim().max(2e3).regex(/^mongodb(\+srv)?:\/\/[^\s]+$/, "Use a mongodb:// or mongodb+srv:// connection string");
|
|
22753
|
+
var BucketSchema = external_exports.object({
|
|
22754
|
+
endpoint: external_exports.string().trim().max(500).regex(/^https?:\/\/[^\s/@]+(\/[^\s]*)?$/, "Use an http(s) address, without credentials").optional(),
|
|
22755
|
+
region: external_exports.string().trim().min(1).max(64).default("us-east-1"),
|
|
22756
|
+
bucket: external_exports.string().trim().regex(/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/, "Use a valid bucket name"),
|
|
22757
|
+
accessKeyId: external_exports.string().trim().min(1).max(256),
|
|
22758
|
+
secretAccessKey: external_exports.string().min(1).max(512),
|
|
22759
|
+
/** Path-style addresses (MinIO and most self-hosted stores need them). */
|
|
22760
|
+
forcePathStyle: external_exports.boolean().default(false)
|
|
22761
|
+
});
|
|
22762
|
+
var STORAGE_PROBLEMS = [
|
|
22763
|
+
"INVALID",
|
|
22764
|
+
"UNREACHABLE",
|
|
22765
|
+
"PRIVATE_ADDRESS",
|
|
22766
|
+
"AUTH_FAILED",
|
|
22767
|
+
"NO_BUCKET",
|
|
22768
|
+
"NO_PERMISSION",
|
|
22769
|
+
"NOT_EMPTY"
|
|
22770
|
+
];
|
|
22771
|
+
var StorageProblemSchema = external_exports.enum(STORAGE_PROBLEMS);
|
|
22772
|
+
var StorageCheckSchema = external_exports.discriminatedUnion("ok", [
|
|
22773
|
+
external_exports.object({
|
|
22774
|
+
ok: external_exports.literal(true),
|
|
22775
|
+
/** Where it is: "s3.eu-west-1.amazonaws.com" or the endpoint's host. */
|
|
22776
|
+
host: external_exports.string(),
|
|
22777
|
+
bucket: external_exports.string()
|
|
22778
|
+
}),
|
|
22779
|
+
external_exports.object({ ok: external_exports.literal(false), problem: StorageProblemSchema, detail: external_exports.string() })
|
|
22780
|
+
]);
|
|
22781
|
+
var CreateWorkspaceRequestSchema = external_exports.object({
|
|
22782
|
+
name: WorkspaceNameSchema,
|
|
22783
|
+
/** Optional explicit address; derived from the name when omitted. */
|
|
22784
|
+
slug: WorkspaceSlugSchema.optional(),
|
|
22785
|
+
/** Keep the workspace's data in this MongoDB instead of the deployment's (M5 slice 1). */
|
|
22786
|
+
database: external_exports.object({ uri: MongoUriSchema }).optional(),
|
|
22787
|
+
/** Keep its files in this bucket instead of the deployment's (M5 slice 2). */
|
|
22788
|
+
files: BucketSchema.optional(),
|
|
22789
|
+
/** The creating browser's time zone, used when the account has none yet (M8 slice 1). */
|
|
22790
|
+
timeZone: TimeZoneSchema.optional()
|
|
22791
|
+
});
|
|
22792
|
+
var DatabaseCheckRequestSchema = external_exports.object({ uri: MongoUriSchema });
|
|
22140
22793
|
var DATABASE_PROBLEMS = [
|
|
22141
22794
|
"INVALID",
|
|
22142
22795
|
"UNREACHABLE",
|
|
@@ -22194,7 +22847,9 @@ var UpdateWorkspaceRequestSchema = external_exports.object({
|
|
|
22194
22847
|
/** Owners and admins: the accent colour (null: back to the default). */
|
|
22195
22848
|
accent: WorkspaceAccentSchema.nullable(),
|
|
22196
22849
|
/** Owners and admins: the default time zone. */
|
|
22197
|
-
timeZone: TimeZoneSchema
|
|
22850
|
+
timeZone: TimeZoneSchema,
|
|
22851
|
+
/** Owners and admins: Home, from an installed app (null: back to ours). */
|
|
22852
|
+
homePage: WorkspaceHomePageSchema.nullable()
|
|
22198
22853
|
}).partial().strict().refine((patch) => Object.keys(patch).length > 0, "Nothing to update");
|
|
22199
22854
|
var WorkspaceResponseSchema = external_exports.object({ workspace: WorkspaceSchema });
|
|
22200
22855
|
var TRANSLITERATIONS = {
|
|
@@ -22267,10 +22922,13 @@ var WorkspaceMemberSchema = external_exports.object({
|
|
|
22267
22922
|
title: external_exports.string().default(""),
|
|
22268
22923
|
/** Their profile picture's address (null: initials), decision 145. */
|
|
22269
22924
|
picture: external_exports.string().nullable().default(null),
|
|
22270
|
-
joinedAt: external_exports.iso.datetime()
|
|
22925
|
+
joinedAt: external_exports.iso.datetime(),
|
|
22926
|
+
/** Their notifications are paused, or in quiet hours, until then (decision 194); null: not. */
|
|
22927
|
+
quietUntil: external_exports.iso.datetime().nullable().default(null)
|
|
22271
22928
|
});
|
|
22272
22929
|
var TitleSchema = external_exports.string().trim().max(60, "Keep the title under 60 characters.");
|
|
22273
22930
|
var UpdateMemberRequestSchema = external_exports.object({ title: TitleSchema });
|
|
22931
|
+
var ChangeRoleRequestSchema = external_exports.object({ role: WorkspaceRoleSchema }).strict();
|
|
22274
22932
|
var WorkspaceMemberListSchema = external_exports.object({ members: external_exports.array(WorkspaceMemberSchema) });
|
|
22275
22933
|
var MAX_PROFILE_PICTURE_BYTES = 2 * 1024 * 1024;
|
|
22276
22934
|
|
|
@@ -22521,227 +23179,67 @@ var ExportManifestSchema = external_exports.object({
|
|
|
22521
23179
|
scope: external_exports.enum(["shared", "space"]),
|
|
22522
23180
|
/** The space, for a space export. */
|
|
22523
23181
|
space: external_exports.object({
|
|
22524
|
-
id: external_exports.string(),
|
|
22525
|
-
kind: external_exports.enum(["general", "personal", "normal"]),
|
|
22526
|
-
name: external_exports.string().nullable(),
|
|
22527
|
-
description: external_exports.string(),
|
|
22528
|
-
visibility: external_exports.enum(["public", "private"])
|
|
22529
|
-
}).nullable().default(null),
|
|
22530
|
-
exportedAt: external_exports.iso.datetime(),
|
|
22531
|
-
exportedBy: external_exports.object({ name: external_exports.string(), email: external_exports.string() }),
|
|
22532
|
-
workspace: external_exports.object({
|
|
22533
|
-
id: external_exports.string(),
|
|
22534
|
-
name: external_exports.string(),
|
|
22535
|
-
slug: external_exports.string(),
|
|
22536
|
-
createdAt: external_exports.iso.datetime(),
|
|
22537
|
-
logo: external_exports.object({ key: external_exports.string(), contentType: external_exports.string() }).nullable()
|
|
22538
|
-
}),
|
|
22539
|
-
counts: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
|
|
22540
|
-
files: external_exports.number().int().nonnegative()
|
|
22541
|
-
});
|
|
22542
|
-
var ExportPersonSchema = external_exports.object({
|
|
22543
|
-
id: external_exports.string(),
|
|
22544
|
-
name: external_exports.string(),
|
|
22545
|
-
email: external_exports.string(),
|
|
22546
|
-
role: external_exports.enum(["owner", "admin", "member", "guest"])
|
|
22547
|
-
});
|
|
22548
|
-
var ExportPeopleSchema = external_exports.array(ExportPersonSchema);
|
|
22549
|
-
var ImportPreviewSchema = external_exports.object({
|
|
22550
|
-
importId: external_exports.string(),
|
|
22551
|
-
name: external_exports.string(),
|
|
22552
|
-
/** What it holds: a whole workspace, or one space (and which kind). */
|
|
22553
|
-
scope: external_exports.enum(["shared", "space"]).default("shared"),
|
|
22554
|
-
spaceKind: external_exports.enum(["general", "personal", "normal"]).nullable().default(null),
|
|
22555
|
-
exportedAt: external_exports.iso.datetime(),
|
|
22556
|
-
exportedBy: external_exports.string(),
|
|
22557
|
-
counts: external_exports.object({
|
|
22558
|
-
spaces: external_exports.number().int(),
|
|
22559
|
-
messages: external_exports.number().int(),
|
|
22560
|
-
files: external_exports.number().int(),
|
|
22561
|
-
agents: external_exports.number().int(),
|
|
22562
|
-
people: external_exports.number().int()
|
|
22563
|
-
})
|
|
22564
|
-
});
|
|
22565
|
-
var ImportRequestSchema = external_exports.object({
|
|
22566
|
-
name: WorkspaceNameSchema,
|
|
22567
|
-
slug: WorkspaceSlugSchema.optional(),
|
|
22568
|
-
database: external_exports.object({ uri: MongoUriSchema }).optional(),
|
|
22569
|
-
files: BucketSchema.optional()
|
|
22570
|
-
});
|
|
22571
|
-
var ImportResultSchema = external_exports.object({
|
|
22572
|
-
workspace: WorkspaceSchema,
|
|
22573
|
-
/** The other people from the export, to invite (their old messages keep their names). */
|
|
22574
|
-
people: external_exports.array(external_exports.object({ name: external_exports.string(), email: external_exports.string() }))
|
|
22575
|
-
});
|
|
22576
|
-
var SpaceImportRequestSchema = external_exports.object({
|
|
22577
|
-
/** For a new space: its name (the exported one when left out). */
|
|
22578
|
-
name: external_exports.string().trim().min(1).max(80).optional()
|
|
22579
|
-
});
|
|
22580
|
-
var SpaceImportResultSchema = external_exports.object({
|
|
22581
|
-
spaceId: external_exports.string(),
|
|
22582
|
-
/** Messages and files brought in. */
|
|
22583
|
-
messages: external_exports.number().int(),
|
|
22584
|
-
files: external_exports.number().int()
|
|
22585
|
-
});
|
|
22586
|
-
|
|
22587
|
-
// ../types/src/billing.ts
|
|
22588
|
-
var COMMON_CURRENCIES = [
|
|
22589
|
-
"USD",
|
|
22590
|
-
"EUR",
|
|
22591
|
-
"GBP",
|
|
22592
|
-
"NGN",
|
|
22593
|
-
"KES",
|
|
22594
|
-
"GHS",
|
|
22595
|
-
"ZAR",
|
|
22596
|
-
"CAD",
|
|
22597
|
-
"AUD",
|
|
22598
|
-
"CHF",
|
|
22599
|
-
"JPY",
|
|
22600
|
-
"INR",
|
|
22601
|
-
"BRL"
|
|
22602
|
-
];
|
|
22603
|
-
var CurrencySchema = external_exports.string().regex(/^[A-Z]{3}$/, "Use a three-letter currency code, like USD").refine((code) => knownCurrencies().has(code), "Unknown currency");
|
|
22604
|
-
var known = null;
|
|
22605
|
-
function knownCurrencies() {
|
|
22606
|
-
known ??= new Set(
|
|
22607
|
-
typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("currency") : COMMON_CURRENCIES
|
|
22608
|
-
);
|
|
22609
|
-
return known;
|
|
22610
|
-
}
|
|
22611
|
-
var PriceSchema = external_exports.number().min(0, "Prices can't be negative").max(1e6).transform((value) => Math.round(value * 1e4) / 1e4);
|
|
22612
|
-
var priced = external_exports.object({ enabled: external_exports.boolean(), price: PriceSchema });
|
|
22613
|
-
var ModelPriceSchema = external_exports.object({
|
|
22614
|
-
/** As agents name it: `provider/model`. */
|
|
22615
|
-
model: external_exports.string().trim().min(3).max(200),
|
|
22616
|
-
input: PriceSchema,
|
|
22617
|
-
/** Input read from the prompt cache. */
|
|
22618
|
-
cachedInput: PriceSchema,
|
|
22619
|
-
/** Input written to the prompt cache. */
|
|
22620
|
-
cacheWrite: PriceSchema,
|
|
22621
|
-
output: PriceSchema
|
|
22622
|
-
});
|
|
22623
|
-
var BillingSettingsSchema = external_exports.object({
|
|
22624
|
-
currency: CurrencySchema,
|
|
22625
|
-
/** Per person who used the workspace in the month. */
|
|
22626
|
-
seats: priced,
|
|
22627
|
-
/** Per GB-month in the deployment's bucket. */
|
|
22628
|
-
files: priced,
|
|
22629
|
-
/** Per GB-month in the deployment's MongoDB. */
|
|
22630
|
-
database: priced,
|
|
22631
|
-
/** Model cost (from `models`) plus a markup, for runs on the deployment's Gateway. */
|
|
22632
|
-
ai: external_exports.object({
|
|
22633
|
-
enabled: external_exports.boolean(),
|
|
22634
|
-
markupPercent: external_exports.number().min(0).max(1e3),
|
|
22635
|
-
models: external_exports.array(ModelPriceSchema).max(100).refine(
|
|
22636
|
-
(models) => new Set(models.map((m) => m.model)).size === models.length,
|
|
22637
|
-
"Each model once"
|
|
22638
|
-
)
|
|
22639
|
-
}),
|
|
22640
|
-
/** A flat amount per workspace per month (prorated from the day it was created). */
|
|
22641
|
-
deploymentFee: priced,
|
|
22642
|
-
/**
|
|
22643
|
-
* A support plan per workspace per month, opt-in (decision 74): workspaces
|
|
22644
|
-
* that turn it on pay it (prorated by day) and can ask the deployment for
|
|
22645
|
-
* help. Absent in settings saved before it existed: off.
|
|
22646
|
-
*/
|
|
22647
|
-
support: priced.default({ enabled: false, price: 0 }),
|
|
22648
|
-
/**
|
|
22649
|
-
* The deployment's Gateways (decision 151), per hour: a workspace's own
|
|
22650
|
-
* ("Managed for you") while it's awake, or the deployment's shared one while
|
|
22651
|
-
* the workspace is connected to it. Absent in older settings: off.
|
|
22652
|
-
*/
|
|
22653
|
-
gatewayHours: priced.default({ enabled: false, price: 0 }),
|
|
22654
|
-
/** A workspace's own Gateway's storage (its volume), per GB-month, asleep or awake. */
|
|
22655
|
-
gatewayStorage: priced.default({ enabled: false, price: 0 })
|
|
22656
|
-
});
|
|
22657
|
-
var BILLING_METERS = [
|
|
22658
|
-
"seats",
|
|
22659
|
-
"files",
|
|
22660
|
-
"database",
|
|
22661
|
-
"ai",
|
|
22662
|
-
"deploymentFee",
|
|
22663
|
-
"support",
|
|
22664
|
-
"gatewayHours",
|
|
22665
|
-
"gatewayStorage"
|
|
22666
|
-
];
|
|
22667
|
-
var StripeConnectionSchema = external_exports.object({
|
|
22668
|
-
connected: external_exports.boolean(),
|
|
22669
|
-
/** Test keys create test invoices that nobody really pays. */
|
|
22670
|
-
mode: external_exports.enum(["test", "live"]).nullable(),
|
|
22671
|
-
/** The key's last four characters, to recognise it. */
|
|
22672
|
-
keyHint: external_exports.string().nullable(),
|
|
22673
|
-
connectedAt: external_exports.iso.datetime().nullable()
|
|
22674
|
-
});
|
|
22675
|
-
var ConnectStripeRequestSchema = external_exports.object({
|
|
22676
|
-
secretKey: external_exports.string().trim().regex(
|
|
22677
|
-
/^(sk|rk)_(test|live)_[A-Za-z0-9]{10,}$/,
|
|
22678
|
-
"Use a Stripe secret key (sk_\u2026) or restricted key (rk_\u2026)"
|
|
22679
|
-
)
|
|
22680
|
-
});
|
|
22681
|
-
var AdminBillingSchema = external_exports.object({
|
|
22682
|
-
settings: BillingSettingsSchema,
|
|
22683
|
-
/** Models agents have run on this deployment's Gateways, to price. */
|
|
22684
|
-
modelsInUse: external_exports.array(external_exports.string()),
|
|
22685
|
-
stripe: StripeConnectionSchema
|
|
22686
|
-
});
|
|
22687
|
-
var BillLineSchema = external_exports.object({
|
|
22688
|
-
meter: external_exports.enum(BILLING_METERS),
|
|
22689
|
-
/**
|
|
22690
|
-
* billed: charged; notBilled: this deployment doesn't bill it;
|
|
22691
|
-
* own: the workspace brings this resource itself; notChosen: an opt-in plan
|
|
22692
|
-
* (support) the workspace doesn't have.
|
|
22693
|
-
*/
|
|
22694
|
-
status: external_exports.enum(["billed", "notBilled", "own", "notChosen"]),
|
|
22695
|
-
/** People, GB-months, tokens, or the share of the month (deployment fee, support plan). */
|
|
22696
|
-
quantity: external_exports.number().nonnegative(),
|
|
22697
|
-
/** Price per unit; null for AI (priced per model). */
|
|
22698
|
-
unitPrice: external_exports.number().nullable(),
|
|
22699
|
-
amount: external_exports.number().nonnegative()
|
|
22700
|
-
});
|
|
22701
|
-
var WorkspaceBillSchema = external_exports.object({
|
|
22702
|
-
currency: external_exports.string(),
|
|
22703
|
-
lines: external_exports.array(BillLineSchema),
|
|
22704
|
-
/** AI amount per model (null: the model has no price set). */
|
|
22705
|
-
aiByModel: external_exports.array(external_exports.object({ model: external_exports.string(), amount: external_exports.number().nullable() })),
|
|
22706
|
-
/** Models used but not priced: their tokens aren't charged. */
|
|
22707
|
-
unpricedModels: external_exports.array(external_exports.string()),
|
|
22708
|
-
total: external_exports.number().nonnegative(),
|
|
22709
|
-
/** True for the current month: amounts grow until it ends. */
|
|
22710
|
-
toDate: external_exports.boolean()
|
|
23182
|
+
id: external_exports.string(),
|
|
23183
|
+
kind: external_exports.enum(["general", "personal", "normal"]),
|
|
23184
|
+
name: external_exports.string().nullable(),
|
|
23185
|
+
description: external_exports.string(),
|
|
23186
|
+
visibility: external_exports.enum(["public", "private"])
|
|
23187
|
+
}).nullable().default(null),
|
|
23188
|
+
exportedAt: external_exports.iso.datetime(),
|
|
23189
|
+
exportedBy: external_exports.object({ name: external_exports.string(), email: external_exports.string() }),
|
|
23190
|
+
workspace: external_exports.object({
|
|
23191
|
+
id: external_exports.string(),
|
|
23192
|
+
name: external_exports.string(),
|
|
23193
|
+
slug: external_exports.string(),
|
|
23194
|
+
createdAt: external_exports.iso.datetime(),
|
|
23195
|
+
logo: external_exports.object({ key: external_exports.string(), contentType: external_exports.string() }).nullable()
|
|
23196
|
+
}),
|
|
23197
|
+
counts: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
|
|
23198
|
+
files: external_exports.number().int().nonnegative()
|
|
22711
23199
|
});
|
|
22712
|
-
var
|
|
22713
|
-
var StatementSchema = external_exports.object({
|
|
23200
|
+
var ExportPersonSchema = external_exports.object({
|
|
22714
23201
|
id: external_exports.string(),
|
|
22715
|
-
|
|
22716
|
-
|
|
22717
|
-
|
|
22718
|
-
|
|
22719
|
-
|
|
22720
|
-
|
|
22721
|
-
|
|
22722
|
-
|
|
22723
|
-
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
|
|
22728
|
-
|
|
22729
|
-
|
|
22730
|
-
|
|
22731
|
-
|
|
22732
|
-
|
|
23202
|
+
name: external_exports.string(),
|
|
23203
|
+
email: external_exports.string(),
|
|
23204
|
+
role: external_exports.enum(["owner", "admin", "member", "guest"])
|
|
23205
|
+
});
|
|
23206
|
+
var ExportPeopleSchema = external_exports.array(ExportPersonSchema);
|
|
23207
|
+
var ImportPreviewSchema = external_exports.object({
|
|
23208
|
+
importId: external_exports.string(),
|
|
23209
|
+
name: external_exports.string(),
|
|
23210
|
+
/** What it holds: a whole workspace, or one space (and which kind). */
|
|
23211
|
+
scope: external_exports.enum(["shared", "space"]).default("shared"),
|
|
23212
|
+
spaceKind: external_exports.enum(["general", "personal", "normal"]).nullable().default(null),
|
|
23213
|
+
exportedAt: external_exports.iso.datetime(),
|
|
23214
|
+
exportedBy: external_exports.string(),
|
|
23215
|
+
counts: external_exports.object({
|
|
23216
|
+
spaces: external_exports.number().int(),
|
|
23217
|
+
messages: external_exports.number().int(),
|
|
23218
|
+
files: external_exports.number().int(),
|
|
23219
|
+
agents: external_exports.number().int(),
|
|
23220
|
+
people: external_exports.number().int()
|
|
22733
23221
|
})
|
|
22734
23222
|
});
|
|
22735
|
-
var
|
|
22736
|
-
|
|
22737
|
-
|
|
22738
|
-
|
|
22739
|
-
|
|
22740
|
-
|
|
22741
|
-
|
|
22742
|
-
|
|
22743
|
-
|
|
22744
|
-
)
|
|
23223
|
+
var ImportRequestSchema = external_exports.object({
|
|
23224
|
+
name: WorkspaceNameSchema,
|
|
23225
|
+
slug: WorkspaceSlugSchema.optional(),
|
|
23226
|
+
database: external_exports.object({ uri: MongoUriSchema }).optional(),
|
|
23227
|
+
files: BucketSchema.optional()
|
|
23228
|
+
});
|
|
23229
|
+
var ImportResultSchema = external_exports.object({
|
|
23230
|
+
workspace: WorkspaceSchema,
|
|
23231
|
+
/** The other people from the export, to invite (their old messages keep their names). */
|
|
23232
|
+
people: external_exports.array(external_exports.object({ name: external_exports.string(), email: external_exports.string() }))
|
|
23233
|
+
});
|
|
23234
|
+
var SpaceImportRequestSchema = external_exports.object({
|
|
23235
|
+
/** For a new space: its name (the exported one when left out). */
|
|
23236
|
+
name: external_exports.string().trim().min(1).max(80).optional()
|
|
23237
|
+
});
|
|
23238
|
+
var SpaceImportResultSchema = external_exports.object({
|
|
23239
|
+
spaceId: external_exports.string(),
|
|
23240
|
+
/** Messages and files brought in. */
|
|
23241
|
+
messages: external_exports.number().int(),
|
|
23242
|
+
files: external_exports.number().int()
|
|
22745
23243
|
});
|
|
22746
23244
|
|
|
22747
23245
|
// ../types/src/usage.ts
|
|
@@ -23131,7 +23629,11 @@ var ConnectorToolSchema = external_exports.object({
|
|
|
23131
23629
|
/** A tool its server doesn't describe, which an owner says only reads. */
|
|
23132
23630
|
markedReadOnly: external_exports.boolean(),
|
|
23133
23631
|
/** Agents may use it (only tools that read, or that an owner says only read). */
|
|
23134
|
-
enabled: external_exports.boolean()
|
|
23632
|
+
enabled: external_exports.boolean(),
|
|
23633
|
+
/** It shows a view in conversations (MCP Apps, decision 213). */
|
|
23634
|
+
view: external_exports.boolean().default(false),
|
|
23635
|
+
/** Only its views call it, not agents. */
|
|
23636
|
+
viewsOnly: external_exports.boolean().default(false)
|
|
23135
23637
|
});
|
|
23136
23638
|
var McpConnectorSchema = external_exports.object({
|
|
23137
23639
|
id: external_exports.string(),
|
|
@@ -23163,7 +23665,19 @@ var McpConnectorSchema = external_exports.object({
|
|
|
23163
23665
|
addedAt: external_exports.string(),
|
|
23164
23666
|
checkedAt: external_exports.string().nullable()
|
|
23165
23667
|
});
|
|
23166
|
-
var
|
|
23668
|
+
var ConnectorPresetSchema = external_exports.object({
|
|
23669
|
+
id: external_exports.string(),
|
|
23670
|
+
name: external_exports.string(),
|
|
23671
|
+
url: external_exports.string(),
|
|
23672
|
+
auth: external_exports.enum(["oauth", "header"]),
|
|
23673
|
+
headerName: external_exports.string().nullable(),
|
|
23674
|
+
/** How its key is written ("Bearer github_pat_…"). */
|
|
23675
|
+
keyHint: external_exports.string().nullable()
|
|
23676
|
+
});
|
|
23677
|
+
var McpConnectorListSchema = external_exports.object({
|
|
23678
|
+
connectors: external_exports.array(McpConnectorSchema),
|
|
23679
|
+
presets: external_exports.array(ConnectorPresetSchema).default([])
|
|
23680
|
+
});
|
|
23167
23681
|
var HeaderNameSchema = external_exports.string().trim().regex(/^[A-Za-z0-9-]{1,64}$/, "A header's name: letters, digits and dashes.").refine(
|
|
23168
23682
|
(name) => !["host", "content-length", "content-type", "accept", "connection"].includes(
|
|
23169
23683
|
name.toLowerCase()
|
|
@@ -23219,6 +23733,574 @@ var MyConnectorSchema = external_exports.object({
|
|
|
23219
23733
|
var MyConnectorListSchema = external_exports.object({ connectors: external_exports.array(MyConnectorSchema) });
|
|
23220
23734
|
var SetMyConnectorKeyRequestSchema = external_exports.object({ value: external_exports.string().trim().min(1, "Enter your key.").max(4e3) }).strict();
|
|
23221
23735
|
|
|
23736
|
+
// ../types/src/marketplace.ts
|
|
23737
|
+
var LISTING_KINDS = ["agent", "app"];
|
|
23738
|
+
var ListingKindSchema = external_exports.enum(LISTING_KINDS);
|
|
23739
|
+
var LISTING_CATEGORIES = [
|
|
23740
|
+
"productivity",
|
|
23741
|
+
"research",
|
|
23742
|
+
"writing",
|
|
23743
|
+
"support",
|
|
23744
|
+
"sales",
|
|
23745
|
+
"marketing",
|
|
23746
|
+
"engineering",
|
|
23747
|
+
"operations",
|
|
23748
|
+
"finance",
|
|
23749
|
+
"people",
|
|
23750
|
+
"education",
|
|
23751
|
+
"personal"
|
|
23752
|
+
];
|
|
23753
|
+
var ListingCategorySchema = external_exports.enum(LISTING_CATEGORIES);
|
|
23754
|
+
var LISTED_AGENT = "@self";
|
|
23755
|
+
var LISTED_TABBY = "@tabby";
|
|
23756
|
+
var LISTED_ADDER = "@adder";
|
|
23757
|
+
var LISTED_TABS = {
|
|
23758
|
+
conversations: "@conversations",
|
|
23759
|
+
docs: "@docs",
|
|
23760
|
+
tasks: "@tasks"
|
|
23761
|
+
};
|
|
23762
|
+
var listedAppTab = (app) => `@app:${app.id}/${app.tab}`;
|
|
23763
|
+
var AGENT_PLACEHOLDERS = [LISTED_AGENT, LISTED_TABBY];
|
|
23764
|
+
var TAB_PLACEHOLDERS = Object.values(LISTED_TABS);
|
|
23765
|
+
var ASSIGNEE_PLACEHOLDERS = [LISTED_AGENT, LISTED_TABBY, LISTED_ADDER];
|
|
23766
|
+
var ListedAssigneesSchema = external_exports.array(external_exports.enum([LISTED_AGENT, LISTED_TABBY, LISTED_ADDER])).max(3).default([LISTED_AGENT]);
|
|
23767
|
+
var ListedSkillSchema = external_exports.discriminatedUnion("source", [
|
|
23768
|
+
external_exports.object({
|
|
23769
|
+
source: external_exports.literal("builtin"),
|
|
23770
|
+
name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "A skill's name."),
|
|
23771
|
+
displayName: external_exports.string().trim().min(1).max(80)
|
|
23772
|
+
}),
|
|
23773
|
+
external_exports.object({
|
|
23774
|
+
source: external_exports.literal("clawhub"),
|
|
23775
|
+
ref: ClawHubRefSchema,
|
|
23776
|
+
displayName: external_exports.string().trim().min(1).max(80)
|
|
23777
|
+
})
|
|
23778
|
+
]);
|
|
23779
|
+
var ListedConnectorSchema = external_exports.object({
|
|
23780
|
+
name: external_exports.string().trim().min(1).max(40),
|
|
23781
|
+
url: external_exports.url({ protocol: /^https$/, message: "A connector's https:// address." }).max(500),
|
|
23782
|
+
auth: external_exports.enum(["none", "header", "oauth"]),
|
|
23783
|
+
/** With a header: its name (its value is asked for when it's added). */
|
|
23784
|
+
headerName: external_exports.string().regex(/^[A-Za-z0-9-]{1,64}$/).nullable().default(null),
|
|
23785
|
+
identity: ConnectorIdentitySchema.default("workspace"),
|
|
23786
|
+
/** OAuth: what its sign-in asks for (null: what its server suggests, or our default for it). */
|
|
23787
|
+
scope: external_exports.string().trim().max(500).nullable().default(null),
|
|
23788
|
+
/** What it's for, for whoever adds it. */
|
|
23789
|
+
description: external_exports.string().trim().max(300).default(""),
|
|
23790
|
+
/** Its tools the agent may use, by name (the rest stay off). */
|
|
23791
|
+
tools: external_exports.array(external_exports.string().max(200)).max(500).default([])
|
|
23792
|
+
});
|
|
23793
|
+
var ListedAppSchema = external_exports.object({
|
|
23794
|
+
/** Its manifest's `id`. */
|
|
23795
|
+
id: external_exports.string().min(3).max(64),
|
|
23796
|
+
name: external_exports.string().trim().min(1).max(40),
|
|
23797
|
+
manifestUrl: external_exports.url({ protocol: /^https?$/, message: "The manifest's address." }).max(500),
|
|
23798
|
+
/** Which of its tabs goes in the space: `listedAppTab()` names it. */
|
|
23799
|
+
tab: external_exports.string().min(1).max(40),
|
|
23800
|
+
/** What it's for, for whoever adds it. */
|
|
23801
|
+
description: external_exports.string().trim().max(300).default("")
|
|
23802
|
+
});
|
|
23803
|
+
var ListedWorkflowSchema = external_exports.object({
|
|
23804
|
+
key: WorkflowStepIdSchema,
|
|
23805
|
+
name: external_exports.string().trim().min(1).max(120),
|
|
23806
|
+
description: external_exports.string().max(2e3).default(""),
|
|
23807
|
+
steps: external_exports.array(WorkflowStepSchema).min(1).max(30)
|
|
23808
|
+
});
|
|
23809
|
+
var ListedSeriesSchema = external_exports.object({
|
|
23810
|
+
title: external_exports.string().trim().min(1).max(200),
|
|
23811
|
+
description: external_exports.string().max(4e3).default(""),
|
|
23812
|
+
assignees: ListedAssigneesSchema,
|
|
23813
|
+
recurrence: RecurrenceSchema,
|
|
23814
|
+
time: ClockTimeSchema,
|
|
23815
|
+
/** Its results are also posted in a conversation (`@conversations`). */
|
|
23816
|
+
postTo: external_exports.literal(LISTED_TABS.conversations).nullable().default(null),
|
|
23817
|
+
approveResults: external_exports.boolean().default(false),
|
|
23818
|
+
workflowKey: WorkflowStepIdSchema.nullable().default(null)
|
|
23819
|
+
});
|
|
23820
|
+
var ListedTriggerSchema = external_exports.object({
|
|
23821
|
+
name: external_exports.string().trim().min(1).max(120),
|
|
23822
|
+
event: TriggerEventSchema,
|
|
23823
|
+
task: external_exports.object({
|
|
23824
|
+
title: external_exports.string().trim().min(1).max(200),
|
|
23825
|
+
description: external_exports.string().max(4e3).default(""),
|
|
23826
|
+
assignees: ListedAssigneesSchema,
|
|
23827
|
+
workflowKey: WorkflowStepIdSchema.nullable().default(null)
|
|
23828
|
+
})
|
|
23829
|
+
});
|
|
23830
|
+
var AgentListingContentSchema = external_exports.object({
|
|
23831
|
+
agent: external_exports.object({
|
|
23832
|
+
name: external_exports.string().trim().min(1).max(40),
|
|
23833
|
+
title: external_exports.string().trim().max(60).default(""),
|
|
23834
|
+
// An agent's own limits, so whatever's listed can be added.
|
|
23835
|
+
description: external_exports.string().trim().min(1, "Say what it's for.").max(120),
|
|
23836
|
+
instructions: external_exports.string().max(MAX_AGENT_INSTRUCTIONS).default(""),
|
|
23837
|
+
/** One of the drawn faces; or "custom", with the listing's picture. */
|
|
23838
|
+
avatar: external_exports.enum([...AGENT_AVATARS, "custom"])
|
|
23839
|
+
}),
|
|
23840
|
+
skills: external_exports.array(ListedSkillSchema).max(30).default([]),
|
|
23841
|
+
connectors: external_exports.array(ListedConnectorSchema).max(10).default([]),
|
|
23842
|
+
apps: external_exports.array(ListedAppSchema).max(3).default([]),
|
|
23843
|
+
workflows: external_exports.array(ListedWorkflowSchema).max(10).default([]),
|
|
23844
|
+
series: external_exports.array(ListedSeriesSchema).max(10).default([]),
|
|
23845
|
+
triggers: external_exports.array(ListedTriggerSchema).max(10).default([])
|
|
23846
|
+
}).superRefine((content, ctx) => {
|
|
23847
|
+
for (const problem of portabilityProblems(content))
|
|
23848
|
+
ctx.addIssue({ code: "custom", ...problem });
|
|
23849
|
+
});
|
|
23850
|
+
function portabilityProblems(content) {
|
|
23851
|
+
const problems = [];
|
|
23852
|
+
const keys = new Set(content.workflows.map((w) => w.key));
|
|
23853
|
+
const appTabs = new Set((content.apps ?? []).map(listedAppTab));
|
|
23854
|
+
const agent = (id, path) => {
|
|
23855
|
+
if (!AGENT_PLACEHOLDERS.includes(id)) {
|
|
23856
|
+
problems.push({ message: "It can only use this agent or Tabby.", path });
|
|
23857
|
+
}
|
|
23858
|
+
};
|
|
23859
|
+
const tab = (id, path) => {
|
|
23860
|
+
if (!TAB_PLACEHOLDERS.includes(id) && !appTabs.has(id)) {
|
|
23861
|
+
problems.push({ message: "It can only use a conversation, Docs or Tasks tab.", path });
|
|
23862
|
+
}
|
|
23863
|
+
};
|
|
23864
|
+
const person = (id, path) => {
|
|
23865
|
+
if (!ASSIGNEE_PLACEHOLDERS.includes(id)) {
|
|
23866
|
+
problems.push({ message: "It can only be for this agent, Tabby or whoever adds it.", path });
|
|
23867
|
+
}
|
|
23868
|
+
};
|
|
23869
|
+
const workflow = (key, path) => {
|
|
23870
|
+
if (key !== null && !keys.has(key)) {
|
|
23871
|
+
problems.push({ message: "It names a workflow the listing doesn't have.", path });
|
|
23872
|
+
}
|
|
23873
|
+
};
|
|
23874
|
+
content.workflows.forEach((w, i) => {
|
|
23875
|
+
if (content.workflows.findIndex((other) => other.key === w.key) !== i) {
|
|
23876
|
+
problems.push({ message: "Workflows' keys must differ.", path: ["workflows", i, "key"] });
|
|
23877
|
+
}
|
|
23878
|
+
for (const step of allSteps(w.steps)) {
|
|
23879
|
+
const at = ["workflows", i, "steps", step.id];
|
|
23880
|
+
switch (step.kind) {
|
|
23881
|
+
case "agent":
|
|
23882
|
+
agent(step.agentId, at);
|
|
23883
|
+
break;
|
|
23884
|
+
case "post":
|
|
23885
|
+
agent(step.agentId, at);
|
|
23886
|
+
tab(step.tabId, at);
|
|
23887
|
+
break;
|
|
23888
|
+
case "create_task":
|
|
23889
|
+
tab(step.tabId, at);
|
|
23890
|
+
step.assigneeIds.forEach((id) => person(id, at));
|
|
23891
|
+
break;
|
|
23892
|
+
case "person":
|
|
23893
|
+
person(step.assigneeId, at);
|
|
23894
|
+
break;
|
|
23895
|
+
case "if":
|
|
23896
|
+
if (step.condition.op === "agent") agent(step.condition.agentId, at);
|
|
23897
|
+
break;
|
|
23898
|
+
case "app_action":
|
|
23899
|
+
if (!appTabs.has(step.tabId)) {
|
|
23900
|
+
problems.push({ message: "Its actions need an app the listing brings.", path: at });
|
|
23901
|
+
}
|
|
23902
|
+
break;
|
|
23903
|
+
}
|
|
23904
|
+
}
|
|
23905
|
+
});
|
|
23906
|
+
content.series.forEach((s, i) => workflow(s.workflowKey, ["series", i, "workflowKey"]));
|
|
23907
|
+
content.triggers.forEach((t, i) => {
|
|
23908
|
+
const at = ["triggers", i, "event"];
|
|
23909
|
+
const event = t.event;
|
|
23910
|
+
if (event.kind === "app") {
|
|
23911
|
+
if (!appTabs.has(event.tabId)) {
|
|
23912
|
+
problems.push({ message: "Its events need an app the listing brings.", path: at });
|
|
23913
|
+
}
|
|
23914
|
+
} else if (event.kind === "inbox") {
|
|
23915
|
+
problems.push({ message: "A personal trigger (someone's Inbox) can't be listed.", path: at });
|
|
23916
|
+
} else if (event.kind !== "webhook") tab(event.tabId, at);
|
|
23917
|
+
if (event.kind === "message" && event.fromId !== null) person(event.fromId, at);
|
|
23918
|
+
workflow(t.task.workflowKey, ["triggers", i, "task", "workflowKey"]);
|
|
23919
|
+
});
|
|
23920
|
+
return problems;
|
|
23921
|
+
}
|
|
23922
|
+
var ListingPublisherSchema = external_exports.object({
|
|
23923
|
+
/** The workspace that publishes it, or Tabs & Spaces. */
|
|
23924
|
+
name: external_exports.string(),
|
|
23925
|
+
/** Made by Tabs & Spaces (decision 167): kept in our repository, listed as it changes. */
|
|
23926
|
+
official: external_exports.boolean().default(false)
|
|
23927
|
+
});
|
|
23928
|
+
var ListingNeedsSchema = external_exports.object({
|
|
23929
|
+
skills: external_exports.number().int().nonnegative(),
|
|
23930
|
+
connectors: external_exports.number().int().nonnegative(),
|
|
23931
|
+
workflows: external_exports.number().int().nonnegative(),
|
|
23932
|
+
recurring: external_exports.number().int().nonnegative(),
|
|
23933
|
+
triggers: external_exports.number().int().nonnegative(),
|
|
23934
|
+
tabs: external_exports.number().int().nonnegative().default(0),
|
|
23935
|
+
/** An agent's apps (decision 178). */
|
|
23936
|
+
apps: external_exports.number().int().nonnegative().default(0),
|
|
23937
|
+
actions: external_exports.number().int().nonnegative().default(0),
|
|
23938
|
+
events: external_exports.number().int().nonnegative().default(0)
|
|
23939
|
+
});
|
|
23940
|
+
var ListingSummarySchema = external_exports.object({
|
|
23941
|
+
id: external_exports.string(),
|
|
23942
|
+
slug: external_exports.string(),
|
|
23943
|
+
kind: ListingKindSchema,
|
|
23944
|
+
name: external_exports.string(),
|
|
23945
|
+
/** Its job title (agents), or a tagline. */
|
|
23946
|
+
title: external_exports.string(),
|
|
23947
|
+
description: external_exports.string(),
|
|
23948
|
+
categories: external_exports.array(ListingCategorySchema),
|
|
23949
|
+
avatar: external_exports.string(),
|
|
23950
|
+
/** Its own picture's address, if it has one. */
|
|
23951
|
+
pictureUrl: external_exports.string().nullable(),
|
|
23952
|
+
publisher: ListingPublisherSchema,
|
|
23953
|
+
version: external_exports.number().int().positive(),
|
|
23954
|
+
installs: external_exports.number().int().nonnegative(),
|
|
23955
|
+
needs: ListingNeedsSchema,
|
|
23956
|
+
publishedAt: external_exports.iso.datetime(),
|
|
23957
|
+
updatedAt: external_exports.iso.datetime()
|
|
23958
|
+
});
|
|
23959
|
+
var ListingSearchSchema = external_exports.object({
|
|
23960
|
+
listings: external_exports.array(ListingSummarySchema),
|
|
23961
|
+
total: external_exports.number().int().nonnegative()
|
|
23962
|
+
});
|
|
23963
|
+
var ListingImageViewSchema = external_exports.object({
|
|
23964
|
+
id: external_exports.string(),
|
|
23965
|
+
url: external_exports.string(),
|
|
23966
|
+
caption: external_exports.string()
|
|
23967
|
+
});
|
|
23968
|
+
var ListingPage = ListingSummarySchema.extend({
|
|
23969
|
+
/** A longer account of it, in Markdown. */
|
|
23970
|
+
about: external_exports.string(),
|
|
23971
|
+
/** What changed in this version. */
|
|
23972
|
+
changes: external_exports.string(),
|
|
23973
|
+
/** Screenshots and pictures of it at work (decision 202), in order. */
|
|
23974
|
+
images: external_exports.array(ListingImageViewSchema).default([])
|
|
23975
|
+
});
|
|
23976
|
+
var AgentListingSchema = ListingPage.extend({
|
|
23977
|
+
kind: external_exports.literal("agent"),
|
|
23978
|
+
content: AgentListingContentSchema
|
|
23979
|
+
});
|
|
23980
|
+
var AppListingSchema = ListingPage.extend({
|
|
23981
|
+
kind: external_exports.literal("app"),
|
|
23982
|
+
content: external_exports.lazy(() => AppListingContentSchema)
|
|
23983
|
+
});
|
|
23984
|
+
var ListingSchema = external_exports.discriminatedUnion("kind", [AgentListingSchema, AppListingSchema]);
|
|
23985
|
+
var ListingResponseSchema = external_exports.object({ listing: ListingSchema });
|
|
23986
|
+
var ListingPictureSchema = external_exports.object({
|
|
23987
|
+
type: external_exports.enum(["image/png", "image/jpeg", "image/webp"]),
|
|
23988
|
+
base64: external_exports.string().max(35e4, "The picture is too big (256 kB at most).").regex(/^[A-Za-z0-9+/]+=*$/)
|
|
23989
|
+
});
|
|
23990
|
+
var MAX_LISTING_IMAGES = 6;
|
|
23991
|
+
var MAX_LISTING_IMAGE_BYTES = 1048576;
|
|
23992
|
+
var ListingImageIdSchema = external_exports.string().regex(/^[0-9a-f]{64}$/, "An image's id.");
|
|
23993
|
+
var ImageCaption = external_exports.string().trim().max(140, "A caption is 140 characters at most.").default("");
|
|
23994
|
+
var ListingImageSchema = external_exports.union([
|
|
23995
|
+
external_exports.object({
|
|
23996
|
+
type: external_exports.enum(["image/png", "image/jpeg", "image/webp"]),
|
|
23997
|
+
base64: external_exports.string().max(Math.ceil(MAX_LISTING_IMAGE_BYTES / 3) * 4, "An image is 1 MB at most.").regex(/^[A-Za-z0-9+/]+=*$/),
|
|
23998
|
+
caption: ImageCaption
|
|
23999
|
+
}).strict(),
|
|
24000
|
+
external_exports.object({ id: ListingImageIdSchema, caption: ImageCaption }).strict()
|
|
24001
|
+
]);
|
|
24002
|
+
var ListingImages = external_exports.array(ListingImageSchema).max(MAX_LISTING_IMAGES, `${MAX_LISTING_IMAGES} images at most.`).default([]);
|
|
24003
|
+
var PrivacyUrlSchema = external_exports.url({ protocol: /^https$/, message: "The privacy policy's address, starting https://." }).max(500);
|
|
24004
|
+
var AppListingContentSchema = external_exports.object({
|
|
24005
|
+
app: external_exports.object({
|
|
24006
|
+
/** Its manifest's `id`. */
|
|
24007
|
+
id: external_exports.string().min(3).max(64),
|
|
24008
|
+
name: external_exports.string().trim().min(1).max(40),
|
|
24009
|
+
/** A line about it. */
|
|
24010
|
+
title: external_exports.string().trim().max(60).default(""),
|
|
24011
|
+
description: external_exports.string().trim().min(1).max(300),
|
|
24012
|
+
// https, as installing requires (http only where a deployment allows private networks).
|
|
24013
|
+
manifestUrl: external_exports.url({ protocol: /^https?$/, message: "The manifest's address." }).max(500),
|
|
24014
|
+
/**
|
|
24015
|
+
* The manifest we reviewed (decision 203): installing from the listing refuses
|
|
24016
|
+
* another. Ours have none (we serve them, and change them as we deploy).
|
|
24017
|
+
*/
|
|
24018
|
+
manifestHash: ManifestHashSchema.optional(),
|
|
24019
|
+
/**
|
|
24020
|
+
* Its developer's privacy policy (decision 205): what happens to the data
|
|
24021
|
+
* the app is sent. Every workspace's app has one; ours are on our site.
|
|
24022
|
+
*/
|
|
24023
|
+
privacyUrl: PrivacyUrlSchema.optional()
|
|
24024
|
+
}),
|
|
24025
|
+
tabs: external_exports.array(
|
|
24026
|
+
external_exports.object({
|
|
24027
|
+
id: external_exports.string().max(40),
|
|
24028
|
+
name: external_exports.string().max(40),
|
|
24029
|
+
description: external_exports.string().max(200).default("")
|
|
24030
|
+
})
|
|
24031
|
+
).min(1).max(10),
|
|
24032
|
+
actions: external_exports.array(
|
|
24033
|
+
external_exports.object({
|
|
24034
|
+
name: external_exports.string().max(40),
|
|
24035
|
+
description: external_exports.string().max(300),
|
|
24036
|
+
changes: external_exports.boolean()
|
|
24037
|
+
})
|
|
24038
|
+
).max(20).default([]),
|
|
24039
|
+
events: external_exports.array(external_exports.object({ name: external_exports.string().max(40), description: external_exports.string().max(300) })).max(20).default([])
|
|
24040
|
+
});
|
|
24041
|
+
var DraftCommon = {
|
|
24042
|
+
categories: external_exports.array(ListingCategorySchema).min(1, "Choose a category.").max(3),
|
|
24043
|
+
about: external_exports.string().max(1e4).default(""),
|
|
24044
|
+
changes: external_exports.string().max(2e3).default(""),
|
|
24045
|
+
picture: ListingPictureSchema.nullable().default(null),
|
|
24046
|
+
images: ListingImages
|
|
24047
|
+
};
|
|
24048
|
+
var AgentListingDraftSchema = external_exports.object({
|
|
24049
|
+
kind: external_exports.literal("agent"),
|
|
24050
|
+
...DraftCommon,
|
|
24051
|
+
content: AgentListingContentSchema
|
|
24052
|
+
});
|
|
24053
|
+
var ListingDraftSchema = external_exports.discriminatedUnion("kind", [
|
|
24054
|
+
AgentListingDraftSchema,
|
|
24055
|
+
external_exports.object({ kind: external_exports.literal("app"), ...DraftCommon, content: AppListingContentSchema })
|
|
24056
|
+
]);
|
|
24057
|
+
var PublishedFrom = {
|
|
24058
|
+
/** Its listing, for a new version (one this workspace published). */
|
|
24059
|
+
listingId: external_exports.string().max(64).nullable().default(null),
|
|
24060
|
+
workspace: external_exports.object({ id: external_exports.string().min(1).max(64), name: external_exports.string().trim().min(1).max(120) }),
|
|
24061
|
+
/** Who sent it (we write to them about the review; never shown). */
|
|
24062
|
+
publishedBy: external_exports.object({ name: external_exports.string().trim().min(1).max(120), email: external_exports.email() }),
|
|
24063
|
+
/**
|
|
24064
|
+
* The publisher terms' version its sender accepted just now (decision 205;
|
|
24065
|
+
* null: the workspace accepted these terms before).
|
|
24066
|
+
*/
|
|
24067
|
+
acceptedTerms: external_exports.string().max(20).nullable().default(null)
|
|
24068
|
+
};
|
|
24069
|
+
var ControlPublishAppSchema = external_exports.object({
|
|
24070
|
+
kind: external_exports.literal("app"),
|
|
24071
|
+
...DraftCommon,
|
|
24072
|
+
manifestUrl: external_exports.url({ protocol: /^https?$/, message: "The manifest's address." }).max(500),
|
|
24073
|
+
manifestHash: ManifestHashSchema,
|
|
24074
|
+
privacyUrl: PrivacyUrlSchema,
|
|
24075
|
+
...PublishedFrom
|
|
24076
|
+
});
|
|
24077
|
+
var ControlPublishListingSchema = external_exports.discriminatedUnion("kind", [
|
|
24078
|
+
AgentListingDraftSchema.extend(PublishedFrom),
|
|
24079
|
+
ControlPublishAppSchema
|
|
24080
|
+
]);
|
|
24081
|
+
var ListingStatusSchema = external_exports.enum(["pending", "approved", "rejected", "removed"]);
|
|
24082
|
+
var PublishedListingSchema = external_exports.object({
|
|
24083
|
+
id: external_exports.string(),
|
|
24084
|
+
slug: external_exports.string(),
|
|
24085
|
+
kind: ListingKindSchema,
|
|
24086
|
+
name: external_exports.string(),
|
|
24087
|
+
/** The version everyone sees (null: none approved yet). */
|
|
24088
|
+
liveVersion: external_exports.number().int().positive().nullable(),
|
|
24089
|
+
/** The newest version and its review. */
|
|
24090
|
+
latest: external_exports.object({
|
|
24091
|
+
version: external_exports.number().int().positive(),
|
|
24092
|
+
status: external_exports.enum(["pending", "approved", "rejected"]),
|
|
24093
|
+
/** Why we didn't list it. */
|
|
24094
|
+
reason: external_exports.string().nullable(),
|
|
24095
|
+
submittedAt: external_exports.iso.datetime()
|
|
24096
|
+
}),
|
|
24097
|
+
/** Taken down by us (with why), or by the workspace. */
|
|
24098
|
+
removed: external_exports.object({ reason: external_exports.string(), at: external_exports.iso.datetime() }).nullable(),
|
|
24099
|
+
installs: external_exports.number().int().nonnegative()
|
|
24100
|
+
});
|
|
24101
|
+
var PublishedListingsSchema = external_exports.object({
|
|
24102
|
+
listings: external_exports.array(PublishedListingSchema),
|
|
24103
|
+
/**
|
|
24104
|
+
* The workspace's token (decision 203): an app's manifest names it in
|
|
24105
|
+
* `marketplace.verify` to say this workspace may publish it.
|
|
24106
|
+
*/
|
|
24107
|
+
publisherToken: external_exports.string().nullable().default(null),
|
|
24108
|
+
/** The publisher terms (decision 205), and the version this workspace accepted. */
|
|
24109
|
+
terms: external_exports.object({ version: external_exports.string(), url: external_exports.string(), accepted: external_exports.string().nullable() }).nullable().default(null)
|
|
24110
|
+
});
|
|
24111
|
+
var PublisherTermsSchema = external_exports.object({
|
|
24112
|
+
version: external_exports.string(),
|
|
24113
|
+
url: external_exports.string(),
|
|
24114
|
+
/** This workspace accepted this version. */
|
|
24115
|
+
accepted: external_exports.boolean()
|
|
24116
|
+
});
|
|
24117
|
+
var ListingStatusRequestSchema = external_exports.object({
|
|
24118
|
+
ids: external_exports.array(external_exports.string().min(1).max(64)).min(1).max(100)
|
|
24119
|
+
});
|
|
24120
|
+
var ListingStatusesSchema = external_exports.object({
|
|
24121
|
+
listings: external_exports.array(
|
|
24122
|
+
external_exports.object({
|
|
24123
|
+
id: external_exports.string(),
|
|
24124
|
+
/** Live, for anyone to add. */
|
|
24125
|
+
listed: external_exports.boolean(),
|
|
24126
|
+
/** Taken down by Tabs & Spaces, and why (its workspace taking it out isn't this). */
|
|
24127
|
+
takenDown: external_exports.object({ reason: external_exports.string(), at: external_exports.iso.datetime() }).nullable()
|
|
24128
|
+
})
|
|
24129
|
+
)
|
|
24130
|
+
});
|
|
24131
|
+
var PublishingItemSchema = external_exports.object({
|
|
24132
|
+
id: external_exports.string(),
|
|
24133
|
+
name: external_exports.string(),
|
|
24134
|
+
/** A line about it ("ClawHub: @acme/notes", "Every Friday at 16:00"). */
|
|
24135
|
+
detail: external_exports.string(),
|
|
24136
|
+
/** Ticked to start with. */
|
|
24137
|
+
suggested: external_exports.boolean(),
|
|
24138
|
+
/** Why it can't be listed (empty: it can). */
|
|
24139
|
+
problems: external_exports.array(external_exports.string())
|
|
24140
|
+
});
|
|
24141
|
+
var AgentPublishingSchema = external_exports.object({
|
|
24142
|
+
/** This deployment is registered with Tabs & Spaces (publishing needs it). */
|
|
24143
|
+
registered: external_exports.boolean(),
|
|
24144
|
+
/** The agent's listing, if it was published. */
|
|
24145
|
+
listing: PublishedListingSchema.nullable(),
|
|
24146
|
+
/** Its live version's words, to start a new version from. */
|
|
24147
|
+
previous: external_exports.object({
|
|
24148
|
+
categories: external_exports.array(ListingCategorySchema),
|
|
24149
|
+
about: external_exports.string(),
|
|
24150
|
+
/** Its images, kept by id unless they're taken out (decision 202). */
|
|
24151
|
+
images: external_exports.array(ListingImageViewSchema).default([])
|
|
24152
|
+
}).nullable(),
|
|
24153
|
+
/** Where the marketplace shows a listing (its slug follows). */
|
|
24154
|
+
listingBase: external_exports.string(),
|
|
24155
|
+
/** The publisher terms (null: not registered, or unknown). */
|
|
24156
|
+
terms: PublisherTermsSchema.nullable().default(null),
|
|
24157
|
+
skills: external_exports.array(PublishingItemSchema),
|
|
24158
|
+
connectors: external_exports.array(PublishingItemSchema),
|
|
24159
|
+
/** Spaces where it has workflows, recurring tasks or triggers. */
|
|
24160
|
+
spaces: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string() })),
|
|
24161
|
+
/** The space whose work is shown below (null: none). */
|
|
24162
|
+
spaceId: external_exports.string().nullable(),
|
|
24163
|
+
workflows: external_exports.array(PublishingItemSchema),
|
|
24164
|
+
series: external_exports.array(PublishingItemSchema),
|
|
24165
|
+
triggers: external_exports.array(PublishingItemSchema)
|
|
24166
|
+
});
|
|
24167
|
+
var PublishAgentRequestSchema = external_exports.object({
|
|
24168
|
+
categories: external_exports.array(ListingCategorySchema).min(1, "Choose a category.").max(3),
|
|
24169
|
+
about: external_exports.string().max(1e4).default(""),
|
|
24170
|
+
changes: external_exports.string().max(2e3).default(""),
|
|
24171
|
+
spaceId: external_exports.string().max(64).nullable().default(null),
|
|
24172
|
+
skills: external_exports.array(external_exports.string().max(200)).max(30).default([]),
|
|
24173
|
+
connectors: external_exports.array(external_exports.string().max(64)).max(10).default([]),
|
|
24174
|
+
workflows: external_exports.array(external_exports.string().max(64)).max(10).default([]),
|
|
24175
|
+
series: external_exports.array(external_exports.string().max(64)).max(10).default([]),
|
|
24176
|
+
triggers: external_exports.array(external_exports.string().max(64)).max(10).default([]),
|
|
24177
|
+
images: ListingImages,
|
|
24178
|
+
/** The publisher terms' version accepted now (decision 205; left out: accepted before). */
|
|
24179
|
+
acceptTerms: external_exports.string().max(20).optional()
|
|
24180
|
+
}).strict();
|
|
24181
|
+
var PublishedListingResponseSchema = external_exports.object({ listing: PublishedListingSchema });
|
|
24182
|
+
var AppPublishingSchema = external_exports.object({
|
|
24183
|
+
/** This deployment is registered with Tabs & Spaces (publishing needs it). */
|
|
24184
|
+
registered: external_exports.boolean(),
|
|
24185
|
+
/** The app's listing, if this workspace published it. */
|
|
24186
|
+
listing: PublishedListingSchema.nullable(),
|
|
24187
|
+
/** Its live version's words and images, to start a new version from. */
|
|
24188
|
+
previous: external_exports.object({
|
|
24189
|
+
categories: external_exports.array(ListingCategorySchema),
|
|
24190
|
+
about: external_exports.string(),
|
|
24191
|
+
images: external_exports.array(ListingImageViewSchema).default([]),
|
|
24192
|
+
privacyUrl: external_exports.string().nullable().default(null)
|
|
24193
|
+
}).nullable(),
|
|
24194
|
+
listingBase: external_exports.string(),
|
|
24195
|
+
terms: PublisherTermsSchema.nullable().default(null),
|
|
24196
|
+
/** What its manifest says to name this workspace (null: not registered, or unknown). */
|
|
24197
|
+
publisherToken: external_exports.string().nullable(),
|
|
24198
|
+
/** The installed manifest names it. */
|
|
24199
|
+
verified: external_exports.boolean(),
|
|
24200
|
+
/** Why it can't be sent yet, as the installed manifest stands. */
|
|
24201
|
+
problems: external_exports.array(external_exports.string())
|
|
24202
|
+
});
|
|
24203
|
+
var PublishAppRequestSchema = external_exports.object({
|
|
24204
|
+
categories: external_exports.array(ListingCategorySchema).min(1, "Choose a category.").max(3),
|
|
24205
|
+
about: external_exports.string().max(1e4).default(""),
|
|
24206
|
+
changes: external_exports.string().max(2e3).default(""),
|
|
24207
|
+
images: ListingImages,
|
|
24208
|
+
privacyUrl: PrivacyUrlSchema,
|
|
24209
|
+
acceptTerms: external_exports.string().max(20).optional()
|
|
24210
|
+
}).strict();
|
|
24211
|
+
var PublishingKeySchema = external_exports.object({
|
|
24212
|
+
id: external_exports.string(),
|
|
24213
|
+
/** Its first characters, to tell keys apart (the rest is never shown again). */
|
|
24214
|
+
prefix: external_exports.string(),
|
|
24215
|
+
createdBy: external_exports.object({ name: external_exports.string() }),
|
|
24216
|
+
createdAt: external_exports.iso.datetime(),
|
|
24217
|
+
lastUsedAt: external_exports.iso.datetime().nullable()
|
|
24218
|
+
});
|
|
24219
|
+
var PublishingKeysSchema = external_exports.object({ keys: external_exports.array(PublishingKeySchema) });
|
|
24220
|
+
var CreatedPublishingKeySchema = external_exports.object({
|
|
24221
|
+
key: PublishingKeySchema,
|
|
24222
|
+
/** Shown once: `tands publish` sends it (TANDS_PUBLISH_KEY). */
|
|
24223
|
+
secret: external_exports.string()
|
|
24224
|
+
});
|
|
24225
|
+
var KeyPublishRequestSchema = external_exports.object({ changes: external_exports.string().max(2e3).default("") }).strict();
|
|
24226
|
+
var KeyPublishResultSchema = external_exports.object({
|
|
24227
|
+
app: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
|
|
24228
|
+
listing: PublishedListingSchema,
|
|
24229
|
+
/** The installed manifest changed (checked for updates first). */
|
|
24230
|
+
updated: external_exports.boolean()
|
|
24231
|
+
});
|
|
24232
|
+
var MarketplaceBrowseSchema = external_exports.object({
|
|
24233
|
+
/** Off: its deployment's admins turned the marketplace off. */
|
|
24234
|
+
enabled: external_exports.boolean(),
|
|
24235
|
+
listings: external_exports.array(ListingSummarySchema),
|
|
24236
|
+
total: external_exports.number().int().nonnegative(),
|
|
24237
|
+
/** Listings this workspace has added: listing id → its agent. */
|
|
24238
|
+
added: external_exports.record(external_exports.string(), external_exports.string()),
|
|
24239
|
+
/** Workspace owners and admins add them (skills and connectors are theirs to set up). */
|
|
24240
|
+
canAdd: external_exports.boolean()
|
|
24241
|
+
});
|
|
24242
|
+
var MarketplaceListingSchema = external_exports.object({
|
|
24243
|
+
listing: ListingSchema,
|
|
24244
|
+
/** The agent it was added as, if it was. */
|
|
24245
|
+
addedAs: external_exports.string().nullable(),
|
|
24246
|
+
/** What the workspace has already (it's shared, not added twice). */
|
|
24247
|
+
has: external_exports.object({ skills: external_exports.array(external_exports.string()), connectors: external_exports.array(external_exports.string()) }),
|
|
24248
|
+
/**
|
|
24249
|
+
* How each of its connectors signs in here (by its place in the listing):
|
|
24250
|
+
* a known server (GitHub) uses OAuth where this deployment registered its
|
|
24251
|
+
* app, else each person's own key in `headerName` (decision 167).
|
|
24252
|
+
*/
|
|
24253
|
+
connectorAuth: external_exports.array(
|
|
24254
|
+
external_exports.object({
|
|
24255
|
+
auth: external_exports.enum(["none", "header", "oauth"]),
|
|
24256
|
+
headerName: external_exports.string().nullable(),
|
|
24257
|
+
keyHint: external_exports.string().nullable()
|
|
24258
|
+
})
|
|
24259
|
+
).default([]),
|
|
24260
|
+
canAdd: external_exports.boolean()
|
|
24261
|
+
});
|
|
24262
|
+
var AddListingRequestSchema = external_exports.object({
|
|
24263
|
+
/** Where its work goes (needed when it has some). */
|
|
24264
|
+
spaceId: external_exports.string().max(64).nullable().default(null),
|
|
24265
|
+
/** Its recurring tasks' time zone: the adder's. */
|
|
24266
|
+
timeZone: external_exports.string().min(1).max(64),
|
|
24267
|
+
/** Keys for its connectors that sign in with one, by the connector's place in the listing. */
|
|
24268
|
+
keys: external_exports.record(external_exports.string().regex(/^\d{1,2}$/), external_exports.string().trim().min(1).max(4e3)).default({})
|
|
24269
|
+
}).strict();
|
|
24270
|
+
var AddedStepSchema = external_exports.object({
|
|
24271
|
+
what: external_exports.enum([
|
|
24272
|
+
"agent",
|
|
24273
|
+
"picture",
|
|
24274
|
+
"skill",
|
|
24275
|
+
"connector",
|
|
24276
|
+
"space",
|
|
24277
|
+
"workflow",
|
|
24278
|
+
"series",
|
|
24279
|
+
"trigger",
|
|
24280
|
+
"app",
|
|
24281
|
+
"tab"
|
|
24282
|
+
]),
|
|
24283
|
+
name: external_exports.string(),
|
|
24284
|
+
ok: external_exports.boolean(),
|
|
24285
|
+
/** Why it didn't work (it can be done by hand). */
|
|
24286
|
+
message: external_exports.string().nullable()
|
|
24287
|
+
});
|
|
24288
|
+
var AddListingResultSchema = external_exports.object({
|
|
24289
|
+
/** The agent it was added as. */
|
|
24290
|
+
agent: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
|
|
24291
|
+
steps: external_exports.array(AddedStepSchema),
|
|
24292
|
+
/** Connectors waiting for an OAuth sign-in. */
|
|
24293
|
+
signIns: external_exports.array(external_exports.object({ connectorId: external_exports.string(), name: external_exports.string() }))
|
|
24294
|
+
});
|
|
24295
|
+
var AddAppListingRequestSchema = external_exports.object({ spaceId: external_exports.string().max(64).nullable().default(null) }).strict();
|
|
24296
|
+
var AddAppListingResultSchema = external_exports.object({
|
|
24297
|
+
/** The app, installed (or updated, if it was). */
|
|
24298
|
+
app: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
|
|
24299
|
+
/** Its tab, where it was added. */
|
|
24300
|
+
tab: external_exports.object({ spaceId: external_exports.string(), tabId: external_exports.string() }).nullable(),
|
|
24301
|
+
steps: external_exports.array(AddedStepSchema)
|
|
24302
|
+
});
|
|
24303
|
+
|
|
23222
24304
|
// src/harness.ts
|
|
23223
24305
|
import { createHash, generateKeyPairSync, randomBytes, sign } from "node:crypto";
|
|
23224
24306
|
import { createServer } from "node:http";
|
|
@@ -23254,6 +24336,7 @@ function checkManifest(json2, url2) {
|
|
|
23254
24336
|
manifest2.tabs.forEach((tab) => onOrigin(tab.url, `tabs.${tab.id}.url`));
|
|
23255
24337
|
for (const [name, action] of Object.entries(manifest2.actions ?? {})) {
|
|
23256
24338
|
onOrigin(action.url, `actions.${name}.url`);
|
|
24339
|
+
if (action.view) onOrigin(action.view.url, `actions.${name}.view.url`);
|
|
23257
24340
|
}
|
|
23258
24341
|
if (manifest2.icon) onOrigin(manifest2.icon, "icon");
|
|
23259
24342
|
}
|
|
@@ -23329,6 +24412,7 @@ function harnessPage() {
|
|
|
23329
24412
|
input, select, textarea { width: 100%; padding: 7px 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
|
|
23330
24413
|
button { padding: 7px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--canvas); cursor: pointer; }
|
|
23331
24414
|
button.primary { background: var(--accent); color: var(--canvas); border-color: var(--accent); }
|
|
24415
|
+
button[aria-pressed="true"] { background: var(--text); color: var(--canvas); border-color: var(--text); }
|
|
23332
24416
|
.frame { display: flex; flex-direction: column; }
|
|
23333
24417
|
.frame .bar { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--border); color: var(--muted); font-size: 12px; }
|
|
23334
24418
|
.frame .bar code { color: var(--text); }
|
|
@@ -23352,6 +24436,7 @@ function harnessPage() {
|
|
|
23352
24436
|
<strong>App harness</strong><span class="muted" id="appName"></span>
|
|
23353
24437
|
<span class="spacer"></span>
|
|
23354
24438
|
<button type="button" id="theme">Dark</button>
|
|
24439
|
+
<button type="button" id="readOnly" aria-pressed="false" title="As when its bill is unpaid: reads work, writes are refused">Read-only</button>
|
|
23355
24440
|
<button type="button" id="reset">Clear data</button>
|
|
23356
24441
|
</header>
|
|
23357
24442
|
<div id="problems" class="problems" hidden></div>
|
|
@@ -23395,6 +24480,8 @@ function harnessPage() {
|
|
|
23395
24480
|
const $ = (id) => document.getElementById(id);
|
|
23396
24481
|
const frame = $("frame");
|
|
23397
24482
|
let theme = "light";
|
|
24483
|
+
// The workspace read-only (an unpaid bill): the page is told, and writes are refused.
|
|
24484
|
+
let readOnly = false;
|
|
23398
24485
|
let info = null;
|
|
23399
24486
|
let origin = null;
|
|
23400
24487
|
|
|
@@ -23402,7 +24489,7 @@ const post = async (path, body) => {
|
|
|
23402
24489
|
const response = await fetch(path, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
|
|
23403
24490
|
return response.json();
|
|
23404
24491
|
};
|
|
23405
|
-
const who = () => Object.fromEntries(new FormData($("who")));
|
|
24492
|
+
const who = () => ({ ...Object.fromEntries(new FormData($("who"))), readOnly });
|
|
23406
24493
|
const send = (message) => frame.contentWindow?.postMessage({ tands: 1, ...message }, origin);
|
|
23407
24494
|
const reply = (id, out) =>
|
|
23408
24495
|
out && out.error ? send({ type: "error", id, code: out.error.code, message: out.error.message }) : send({ type: "data", id, result: out.result });
|
|
@@ -23505,6 +24592,11 @@ $("theme").addEventListener("click", () => {
|
|
|
23505
24592
|
$("theme").textContent = theme === "light" ? "Dark" : "Light";
|
|
23506
24593
|
send({ type: "theme", theme });
|
|
23507
24594
|
});
|
|
24595
|
+
$("readOnly").addEventListener("click", () => {
|
|
24596
|
+
readOnly = !readOnly;
|
|
24597
|
+
$("readOnly").setAttribute("aria-pressed", String(readOnly));
|
|
24598
|
+
send({ type: "readOnly", readOnly });
|
|
24599
|
+
});
|
|
23508
24600
|
$("reset").addEventListener("click", async () => { await post("/harness/reset", {}); void refresh(); });
|
|
23509
24601
|
void load().then(refresh);
|
|
23510
24602
|
setInterval(refresh, 2000);
|
|
@@ -23674,6 +24766,9 @@ function createMemoryStore() {
|
|
|
23674
24766
|
}
|
|
23675
24767
|
|
|
23676
24768
|
// src/harness.ts
|
|
24769
|
+
var READING = /* @__PURE__ */ new Set(["values.get", "values.list", "records.list", "records.get"]);
|
|
24770
|
+
var READ_ONLY_MESSAGE = "This workspace is read-only until its bill is paid.";
|
|
24771
|
+
var writes = (request) => !READING.has(String(request?.op));
|
|
23677
24772
|
var ACTION_TOKEN_SECONDS = 120;
|
|
23678
24773
|
var DATA_KEY_MS = 5 * 6e4;
|
|
23679
24774
|
var ACTION_TIMEOUT_MS = 1e4;
|
|
@@ -23722,7 +24817,12 @@ async function startHarness({
|
|
|
23722
24817
|
const spaceId = idFrom("s", who.spaceName || "Design");
|
|
23723
24818
|
return {
|
|
23724
24819
|
user: { id: idFrom("u", who.name || "Ada Lovelace"), name: who.name || "Ada Lovelace" },
|
|
23725
|
-
workspace: {
|
|
24820
|
+
workspace: {
|
|
24821
|
+
id: "dev-workspace",
|
|
24822
|
+
slug: "dev",
|
|
24823
|
+
name: "Harness workspace",
|
|
24824
|
+
readOnly: who.readOnly === true
|
|
24825
|
+
},
|
|
23726
24826
|
space: { id: spaceId, kind: who.spaceKind, name: who.spaceName || "Design" },
|
|
23727
24827
|
tab: { id: `${spaceId}-${who.appTabId}`, appTabId: who.appTabId },
|
|
23728
24828
|
app: { id: manifest2.id },
|
|
@@ -23757,7 +24857,7 @@ async function startHarness({
|
|
|
23757
24857
|
}
|
|
23758
24858
|
const isWho = (value) => {
|
|
23759
24859
|
const who = value;
|
|
23760
|
-
return typeof who?.name === "string" && typeof who.spaceName === "string" && typeof who.locale === "string" && typeof who.appTabId === "string" && ["normal", "general", "personal", "dm"].includes(String(who.spaceKind));
|
|
24860
|
+
return typeof who?.name === "string" && typeof who.spaceName === "string" && typeof who.locale === "string" && typeof who.appTabId === "string" && (who.readOnly === void 0 || typeof who.readOnly === "boolean") && ["normal", "general", "personal", "dm"].includes(String(who.spaceKind));
|
|
23761
24861
|
};
|
|
23762
24862
|
function logEvent(loaded, body, from, person) {
|
|
23763
24863
|
const manifest2 = loaded.manifest;
|
|
@@ -23887,6 +24987,9 @@ async function startHarness({
|
|
|
23887
24987
|
}
|
|
23888
24988
|
const loaded2 = await current();
|
|
23889
24989
|
if (!loaded2.manifest) return refused2(409, "BAD_MANIFEST", loaded2.problems.join(" "));
|
|
24990
|
+
if (claims.who.readOnly && (url2.pathname === "/api/apps/events" || writes(body))) {
|
|
24991
|
+
return refused2(423, "WORKSPACE_READ_ONLY", READ_ONLY_MESSAGE);
|
|
24992
|
+
}
|
|
23890
24993
|
if (url2.pathname === "/api/apps/events") {
|
|
23891
24994
|
const outcome2 = logEvent(loaded2, body, "server", claims.who.name);
|
|
23892
24995
|
return "error" in outcome2 ? send(outcome2.status, { error: outcome2.error }) : send(200, { result: outcome2.result });
|
|
@@ -23903,6 +25006,9 @@ async function startHarness({
|
|
|
23903
25006
|
return refused2(404, "NOT_FOUND", `${manifest2.name} has no tab \u201C${who.appTabId}\u201D.`);
|
|
23904
25007
|
}
|
|
23905
25008
|
const context = contextFor(who, manifest2);
|
|
25009
|
+
if (who.readOnly && (url2.pathname === "/harness/event" || url2.pathname === "/harness/data" && writes(body.request))) {
|
|
25010
|
+
return refused2(423, "WORKSPACE_READ_ONLY", READ_ONLY_MESSAGE);
|
|
25011
|
+
}
|
|
23906
25012
|
switch (url2.pathname) {
|
|
23907
25013
|
case "/harness/token": {
|
|
23908
25014
|
const tab = manifest2.tabs.find((one) => one.id === who.appTabId);
|
|
@@ -23948,6 +25054,49 @@ async function startHarness({
|
|
|
23948
25054
|
};
|
|
23949
25055
|
}
|
|
23950
25056
|
|
|
25057
|
+
// src/publish.ts
|
|
25058
|
+
async function publish({
|
|
25059
|
+
url: url2,
|
|
25060
|
+
key,
|
|
25061
|
+
changes = "",
|
|
25062
|
+
fetchImpl = fetch
|
|
25063
|
+
}) {
|
|
25064
|
+
let origin;
|
|
25065
|
+
try {
|
|
25066
|
+
origin = new URL(url2).origin;
|
|
25067
|
+
} catch {
|
|
25068
|
+
return { ok: false, message: `\u201C${url2}\u201D isn't a web address (TANDS_URL).` };
|
|
25069
|
+
}
|
|
25070
|
+
let response;
|
|
25071
|
+
try {
|
|
25072
|
+
response = await fetchImpl(`${origin}/api/publish/app`, {
|
|
25073
|
+
method: "POST",
|
|
25074
|
+
headers: { authorization: `Bearer ${key}`, "content-type": "application/json" },
|
|
25075
|
+
body: JSON.stringify({ changes }),
|
|
25076
|
+
signal: AbortSignal.timeout(6e4)
|
|
25077
|
+
});
|
|
25078
|
+
} catch (error62) {
|
|
25079
|
+
return {
|
|
25080
|
+
ok: false,
|
|
25081
|
+
message: `${origin} can't be reached: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
25082
|
+
};
|
|
25083
|
+
}
|
|
25084
|
+
const json2 = await response.json().catch(() => null);
|
|
25085
|
+
if (!response.ok || !json2?.app || !json2.listing) {
|
|
25086
|
+
return {
|
|
25087
|
+
ok: false,
|
|
25088
|
+
message: json2?.error?.message ?? `${origin} answered HTTP ${response.status}.`
|
|
25089
|
+
};
|
|
25090
|
+
}
|
|
25091
|
+
return {
|
|
25092
|
+
ok: true,
|
|
25093
|
+
app: json2.app,
|
|
25094
|
+
version: json2.listing.latest.version,
|
|
25095
|
+
live: json2.listing.liveVersion,
|
|
25096
|
+
updated: Boolean(json2.updated)
|
|
25097
|
+
};
|
|
25098
|
+
}
|
|
25099
|
+
|
|
23951
25100
|
// src/scaffold.ts
|
|
23952
25101
|
import { existsSync } from "node:fs";
|
|
23953
25102
|
import { copyFile, mkdir, readdir, writeFile } from "node:fs/promises";
|
|
@@ -24212,7 +25361,7 @@ your manifest's address. See https://developer.tabsandspaces.dev.
|
|
|
24212
25361
|
`;
|
|
24213
25362
|
|
|
24214
25363
|
// src/bin.ts
|
|
24215
|
-
var version2 = true ? "0.
|
|
25364
|
+
var version2 = true ? "0.3.0" : "dev";
|
|
24216
25365
|
var USAGE = `tands: developer tools for Tabs & Spaces apps
|
|
24217
25366
|
|
|
24218
25367
|
tands new <folder> [--name "My app"] [--id my-app]
|
|
@@ -24227,13 +25376,21 @@ var USAGE = `tands: developer tools for Tabs & Spaces apps
|
|
|
24227
25376
|
choose, with your data in memory, your events and your actions.
|
|
24228
25377
|
Default: http://localhost:5480/tands.json
|
|
24229
25378
|
|
|
25379
|
+
tands publish [--changes "What changed"]
|
|
25380
|
+
Sends a new version of your app to the marketplace for review. Its
|
|
25381
|
+
workspace checks it for updates first, then sends it with its listing's
|
|
25382
|
+
words and images. Needs TANDS_URL (the workspace's address) and
|
|
25383
|
+
TANDS_PUBLISH_KEY (a key from Settings \u2192 Apps \u2192 Publish\u2026 there).
|
|
25384
|
+
|
|
24230
25385
|
tands --version
|
|
24231
25386
|
|
|
24232
25387
|
Docs: https://developer.tabsandspaces.dev`;
|
|
24233
25388
|
async function main(argv, {
|
|
24234
25389
|
cwd = process.env.INIT_CWD ?? process.cwd(),
|
|
24235
|
-
out = (
|
|
24236
|
-
err = (
|
|
25390
|
+
out = (line2) => console.log(line2),
|
|
25391
|
+
err = (line2) => console.error(line2),
|
|
25392
|
+
env = process.env,
|
|
25393
|
+
fetchImpl = fetch
|
|
24237
25394
|
} = {}) {
|
|
24238
25395
|
const { values, positionals } = parseArgs({
|
|
24239
25396
|
args: argv,
|
|
@@ -24242,6 +25399,7 @@ async function main(argv, {
|
|
|
24242
25399
|
name: { type: "string" },
|
|
24243
25400
|
id: { type: "string" },
|
|
24244
25401
|
port: { type: "string" },
|
|
25402
|
+
changes: { type: "string" },
|
|
24245
25403
|
help: { type: "boolean", short: "h" },
|
|
24246
25404
|
version: { type: "boolean", short: "v" }
|
|
24247
25405
|
}
|
|
@@ -24334,6 +25492,29 @@ async function main(argv, {
|
|
|
24334
25492
|
return 1;
|
|
24335
25493
|
}
|
|
24336
25494
|
}
|
|
25495
|
+
case "publish": {
|
|
25496
|
+
const url2 = env.TANDS_URL?.trim();
|
|
25497
|
+
const key = env.TANDS_PUBLISH_KEY?.trim();
|
|
25498
|
+
if (!url2 || !key) {
|
|
25499
|
+
err("tands publish needs your workspace's address and a publishing key:");
|
|
25500
|
+
err(" TANDS_URL=https://your.workspace TANDS_PUBLISH_KEY=tas-pk-\u2026 npx tands publish");
|
|
25501
|
+
err("Make the key in the workspace: Settings \u2192 Apps \u2192 Publish\u2026 \u2192 Make a key.");
|
|
25502
|
+
return 1;
|
|
25503
|
+
}
|
|
25504
|
+
const sent = await publish({ url: url2, key, changes: values.changes ?? "", fetchImpl });
|
|
25505
|
+
if (!sent.ok) {
|
|
25506
|
+
err(sent.message);
|
|
25507
|
+
return 1;
|
|
25508
|
+
}
|
|
25509
|
+
out(
|
|
25510
|
+
`\u2713 Sent ${sent.app.name} (${sent.app.id}) version ${sent.version} to the marketplace for review.`
|
|
25511
|
+
);
|
|
25512
|
+
if (sent.updated) out(" Its workspace had an older manifest: it's up to date now.");
|
|
25513
|
+
out(
|
|
25514
|
+
sent.live ? ` Version ${sent.live} stays listed until it's reviewed; you'll get an email then.` : " You'll get an email when it's reviewed."
|
|
25515
|
+
);
|
|
25516
|
+
return 0;
|
|
25517
|
+
}
|
|
24337
25518
|
default:
|
|
24338
25519
|
err(`There's no command \u201C${command}\u201D.`);
|
|
24339
25520
|
out(USAGE);
|