@buoy-gg/scenarios 7.0.76 → 7.0.78
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 +6 -4
- package/lib/commonjs/components/RunProgressScreen.js +1 -1
- package/lib/commonjs/components/ScenarioDetailScreen.js +1 -1
- package/lib/commonjs/components/ScenarioRow.js +1 -1
- package/lib/commonjs/components/ScenariosBody.js +1 -1
- package/lib/commonjs/store/scenariosStore.js +1 -1
- package/lib/commonjs/sync/scenariosSyncAdapter.js +1 -1
- package/lib/commonjs/team/teamClient.js +1 -0
- package/lib/module/components/RunProgressScreen.js +1 -1
- package/lib/module/components/ScenarioDetailScreen.js +1 -1
- package/lib/module/components/ScenarioRow.js +1 -1
- package/lib/module/components/ScenariosBody.js +1 -1
- package/lib/module/store/scenariosStore.js +1 -1
- package/lib/module/sync/scenariosSyncAdapter.js +1 -1
- package/lib/module/team/teamClient.js +1 -0
- package/lib/typescript/components/ScenarioDetailScreen.d.ts +9 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/store/scenariosStore.d.ts +59 -1
- package/lib/typescript/sync/scenariosSyncAdapter.d.ts +86 -0
- package/lib/typescript/team/teamClient.d.ts +77 -0
- package/lib/typescript/types.d.ts +22 -1
- package/lib/web/index.mjs +2 -2
- package/package.json +6 -6
|
@@ -14,7 +14,15 @@ export interface ScenarioDetailScreenProps {
|
|
|
14
14
|
onExported?: () => void;
|
|
15
15
|
/** Opens the folder picker. Absent for scenarios that can't be re-filed. */
|
|
16
16
|
onMoveToFolder?: () => void;
|
|
17
|
+
/** Shares a device scenario with the team. Absent when this person isn't on a team. */
|
|
18
|
+
onShare?: () => void;
|
|
19
|
+
/** Takes a team scenario off the team's list. Present for its sharer and for admins. */
|
|
20
|
+
onRemoveFromTeam?: () => void;
|
|
21
|
+
/** A share or removal is on its way to buoy.gg. */
|
|
22
|
+
teamBusy?: boolean;
|
|
17
23
|
onBack: () => void;
|
|
18
24
|
}
|
|
19
|
-
|
|
25
|
+
/** Where a scenario came from, in words. */
|
|
26
|
+
export declare function sourceText(scenario: Scenario): string;
|
|
27
|
+
export declare function ScenarioDetailScreen({ scenario, onRun, onDelete, onDuplicate, onExported, onMoveToFolder, onShare, onRemoveFromTeam, teamBusy, onBack, }: ScenarioDetailScreenProps): import("react").JSX.Element;
|
|
20
28
|
//# sourceMappingURL=ScenarioDetailScreen.d.ts.map
|
|
@@ -21,7 +21,7 @@ export { condense, macroToSteps, describeTarget, selectorFor, humanizeTestID, ti
|
|
|
21
21
|
export type { MacroLane, MacroStep, RecordedAction, RecordedTouch, RecordingState, RecorderStatus, TouchTargetInfo, } from "./record/types";
|
|
22
22
|
export { scenariosSyncAdapter } from "./sync/scenariosSyncAdapter";
|
|
23
23
|
export { ScenariosToolView } from "./components/ScenariosToolView";
|
|
24
|
-
export { scenariosStore, setRemoteScenariosHandler, replaceScenariosFromSnapshot, MAX_DEVICE_SCENARIOS, type ScenariosState, type RunState, } from "./store/scenariosStore";
|
|
24
|
+
export { scenariosStore, setRemoteScenariosHandler, replaceScenariosFromSnapshot, MAX_DEVICE_SCENARIOS, type ScenariosState, type RunState, type TeamInfo, } from "./store/scenariosStore";
|
|
25
25
|
export { useScenariosState, useActiveScenario, useScenariosRunState, } from "./hooks/useScenarios";
|
|
26
26
|
export { defineScenario, type ScenarioDefinition } from "./defineScenario";
|
|
27
27
|
export { runScenario, revertEffects, preflight, STEP_TIMEOUT_MS, SCENARIO_TIMEOUT_MS, type DispatchToolAction, type PreflightResult, type PreflightContext, } from "./engine";
|
|
@@ -23,7 +23,26 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { dispatchToolAction } from "@buoy-gg/shared-ui";
|
|
25
25
|
import { type PreflightResult } from "../engine";
|
|
26
|
+
import { type TeamClientDeps, type TeamScenarioRow } from "../team/teamClient";
|
|
26
27
|
import type { ActiveScenario, DeactivateReport, RunReport, Scenario, ScenarioVarValue, StepReport } from "../types";
|
|
28
|
+
/** Tests swap the buoy.gg calls. Null puts the real ones back. */
|
|
29
|
+
export declare function setTeamClientDepsForTests(deps: TeamClientDeps | null): void;
|
|
30
|
+
/** One row from buoy.gg as a read-only `team` scenario. */
|
|
31
|
+
export declare function teamScenarioFromRow(row: TeamScenarioRow): Scenario;
|
|
32
|
+
/**
|
|
33
|
+
* The team list's state. `off` means there is no team list here (no sign-in
|
|
34
|
+
* on a team, or no app id) and `message` says why. `error` keeps the last list.
|
|
35
|
+
*/
|
|
36
|
+
export interface TeamInfo {
|
|
37
|
+
status: "idle" | "loading" | "ready" | "off" | "error";
|
|
38
|
+
message?: string;
|
|
39
|
+
/** Why it is `off`: no team sign-in, no app id, or buoy.gg said no. */
|
|
40
|
+
reason?: "no-team" | "no-app" | "refused";
|
|
41
|
+
/** The signed-in account, to tell which team scenarios are yours. */
|
|
42
|
+
you: string | null;
|
|
43
|
+
admin: boolean;
|
|
44
|
+
pulledAt?: number;
|
|
45
|
+
}
|
|
27
46
|
/** Device library cap — a phone is not a database. */
|
|
28
47
|
export declare const MAX_DEVICE_SCENARIOS = 100;
|
|
29
48
|
export interface RunState {
|
|
@@ -42,6 +61,9 @@ export interface ScenariosState {
|
|
|
42
61
|
device: Scenario[];
|
|
43
62
|
/** Authored remotely, inert until accepted. */
|
|
44
63
|
drafts: Scenario[];
|
|
64
|
+
/** Shared by this app's team, pulled from buoy.gg — read-only on device. */
|
|
65
|
+
team: Scenario[];
|
|
66
|
+
teamInfo: TeamInfo;
|
|
45
67
|
active: ActiveScenario | null;
|
|
46
68
|
runState: RunState | null;
|
|
47
69
|
lastDeactivateReport: DeactivateReport | null;
|
|
@@ -61,7 +83,11 @@ declare class ScenariosStore {
|
|
|
61
83
|
getState: () => ScenariosState;
|
|
62
84
|
subscribe: (listener: () => void) => (() => void);
|
|
63
85
|
private setState;
|
|
64
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* All runnable scenarios: code, then the team's, then this device's. An id
|
|
88
|
+
* clash goes the same way, so a scenario shared from this device shows once,
|
|
89
|
+
* as the team's copy.
|
|
90
|
+
*/
|
|
65
91
|
allScenarios(): Scenario[];
|
|
66
92
|
find(id: string): Scenario | undefined;
|
|
67
93
|
/**
|
|
@@ -78,6 +104,38 @@ declare class ScenariosStore {
|
|
|
78
104
|
private load;
|
|
79
105
|
private persistLibrary;
|
|
80
106
|
private persistActive;
|
|
107
|
+
private persistTeam;
|
|
108
|
+
private teamRows;
|
|
109
|
+
private teamPull;
|
|
110
|
+
/** The token and team the last pull went out with, to notice a new sign-in. */
|
|
111
|
+
private teamCredentialKey;
|
|
112
|
+
private credentialKey;
|
|
113
|
+
/**
|
|
114
|
+
* Account access changed (a sign-in, a sign-out, a new key). Pull again only
|
|
115
|
+
* when the team credential is a different one; other license events pass.
|
|
116
|
+
*/
|
|
117
|
+
onAccountChange(): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Pull the team's scenarios for this app from buoy.gg. Opening Scenarios
|
|
120
|
+
* calls this; a pull from the last 30 s counts unless `force` (Refresh).
|
|
121
|
+
* No team sign-in, or no app id: the team list goes away and says why.
|
|
122
|
+
* buoy.gg unreachable: the last list stays, with the reason.
|
|
123
|
+
*/
|
|
124
|
+
refreshTeam(options?: {
|
|
125
|
+
force?: boolean;
|
|
126
|
+
}): Promise<void>;
|
|
127
|
+
private pullTeam;
|
|
128
|
+
/**
|
|
129
|
+
* Share a scenario saved on this device with the team. A person's tap only:
|
|
130
|
+
* no tool action, MCP call or Desktop panel reaches this.
|
|
131
|
+
*/
|
|
132
|
+
shareWithTeam(id: string): Promise<Scenario>;
|
|
133
|
+
/** True in a dashboard that mirrors a device (Desktop). Sharing is the device's to do. */
|
|
134
|
+
isMirror(): boolean;
|
|
135
|
+
/** Whether this person may take a team scenario off the list: its sharer or an admin. */
|
|
136
|
+
canRemoveFromTeam(scenario: Scenario): boolean;
|
|
137
|
+
/** Take a team scenario off the team's list, for everyone. Sharer or admin, a person's tap only. */
|
|
138
|
+
removeFromTeam(id: string): Promise<void>;
|
|
81
139
|
/**
|
|
82
140
|
* Verify the active scenario's effects still exist. An override rule can be
|
|
83
141
|
* deleted from the Network tool, cleared by the launch guard, or lost to a
|
|
@@ -28,6 +28,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
28
28
|
};
|
|
29
29
|
createdAt: number;
|
|
30
30
|
updatedAt: number;
|
|
31
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
31
32
|
steps: (ScenarioStep | {
|
|
32
33
|
params: undefined;
|
|
33
34
|
paramsOmitted: boolean;
|
|
@@ -66,6 +67,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
66
67
|
};
|
|
67
68
|
createdAt: number;
|
|
68
69
|
updatedAt: number;
|
|
70
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
69
71
|
steps: (ScenarioStep | {
|
|
70
72
|
params: undefined;
|
|
71
73
|
paramsOmitted: boolean;
|
|
@@ -104,6 +106,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
104
106
|
};
|
|
105
107
|
createdAt: number;
|
|
106
108
|
updatedAt: number;
|
|
109
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
107
110
|
steps: (ScenarioStep | {
|
|
108
111
|
params: undefined;
|
|
109
112
|
paramsOmitted: boolean;
|
|
@@ -118,6 +121,46 @@ export declare const scenariosSyncAdapter: {
|
|
|
118
121
|
durability: import("..").Durability;
|
|
119
122
|
}[];
|
|
120
123
|
}[];
|
|
124
|
+
team: {
|
|
125
|
+
id: string;
|
|
126
|
+
name: string;
|
|
127
|
+
description: string | undefined;
|
|
128
|
+
version: number;
|
|
129
|
+
source: import("..").ScenarioSource;
|
|
130
|
+
author: string | undefined;
|
|
131
|
+
folder: string | undefined;
|
|
132
|
+
tags: string[] | undefined;
|
|
133
|
+
vars: import("..").ScenarioVar[];
|
|
134
|
+
stepCount: number;
|
|
135
|
+
expectedOutcome: string | undefined;
|
|
136
|
+
authoredAgainst: string | undefined;
|
|
137
|
+
verifiedAt: {
|
|
138
|
+
build: string;
|
|
139
|
+
at: number;
|
|
140
|
+
} | undefined;
|
|
141
|
+
unsavedToRepo: boolean | undefined;
|
|
142
|
+
usage: {
|
|
143
|
+
runs: number;
|
|
144
|
+
lastRunAt?: number;
|
|
145
|
+
};
|
|
146
|
+
createdAt: number;
|
|
147
|
+
updatedAt: number;
|
|
148
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
149
|
+
steps: (ScenarioStep | {
|
|
150
|
+
params: undefined;
|
|
151
|
+
paramsOmitted: boolean;
|
|
152
|
+
id: string;
|
|
153
|
+
tool: string;
|
|
154
|
+
action: string;
|
|
155
|
+
label?: string;
|
|
156
|
+
timeoutMs?: number;
|
|
157
|
+
})[];
|
|
158
|
+
stepLines: {
|
|
159
|
+
label: string;
|
|
160
|
+
durability: import("..").Durability;
|
|
161
|
+
}[];
|
|
162
|
+
}[];
|
|
163
|
+
teamInfo: import("..").TeamInfo;
|
|
121
164
|
active: import("..").ActiveScenario | null;
|
|
122
165
|
runState: import("..").RunState | null;
|
|
123
166
|
hasLoaded: boolean;
|
|
@@ -151,6 +194,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
151
194
|
};
|
|
152
195
|
createdAt: number;
|
|
153
196
|
updatedAt: number;
|
|
197
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
154
198
|
steps: (ScenarioStep | {
|
|
155
199
|
params: undefined;
|
|
156
200
|
paramsOmitted: boolean;
|
|
@@ -189,6 +233,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
189
233
|
};
|
|
190
234
|
createdAt: number;
|
|
191
235
|
updatedAt: number;
|
|
236
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
192
237
|
steps: (ScenarioStep | {
|
|
193
238
|
params: undefined;
|
|
194
239
|
paramsOmitted: boolean;
|
|
@@ -227,6 +272,46 @@ export declare const scenariosSyncAdapter: {
|
|
|
227
272
|
};
|
|
228
273
|
createdAt: number;
|
|
229
274
|
updatedAt: number;
|
|
275
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
276
|
+
steps: (ScenarioStep | {
|
|
277
|
+
params: undefined;
|
|
278
|
+
paramsOmitted: boolean;
|
|
279
|
+
id: string;
|
|
280
|
+
tool: string;
|
|
281
|
+
action: string;
|
|
282
|
+
label?: string;
|
|
283
|
+
timeoutMs?: number;
|
|
284
|
+
})[];
|
|
285
|
+
stepLines: {
|
|
286
|
+
label: string;
|
|
287
|
+
durability: import("..").Durability;
|
|
288
|
+
}[];
|
|
289
|
+
}[];
|
|
290
|
+
team: {
|
|
291
|
+
id: string;
|
|
292
|
+
name: string;
|
|
293
|
+
description: string | undefined;
|
|
294
|
+
version: number;
|
|
295
|
+
source: import("..").ScenarioSource;
|
|
296
|
+
author: string | undefined;
|
|
297
|
+
folder: string | undefined;
|
|
298
|
+
tags: string[] | undefined;
|
|
299
|
+
vars: import("..").ScenarioVar[];
|
|
300
|
+
stepCount: number;
|
|
301
|
+
expectedOutcome: string | undefined;
|
|
302
|
+
authoredAgainst: string | undefined;
|
|
303
|
+
verifiedAt: {
|
|
304
|
+
build: string;
|
|
305
|
+
at: number;
|
|
306
|
+
} | undefined;
|
|
307
|
+
unsavedToRepo: boolean | undefined;
|
|
308
|
+
usage: {
|
|
309
|
+
runs: number;
|
|
310
|
+
lastRunAt?: number;
|
|
311
|
+
};
|
|
312
|
+
createdAt: number;
|
|
313
|
+
updatedAt: number;
|
|
314
|
+
team: import("../types").ScenarioTeamInfo | undefined;
|
|
230
315
|
steps: (ScenarioStep | {
|
|
231
316
|
params: undefined;
|
|
232
317
|
paramsOmitted: boolean;
|
|
@@ -241,6 +326,7 @@ export declare const scenariosSyncAdapter: {
|
|
|
241
326
|
durability: import("..").Durability;
|
|
242
327
|
}[];
|
|
243
328
|
}[];
|
|
329
|
+
teamInfo: import("..").TeamInfo;
|
|
244
330
|
active: import("..").ActiveScenario | null;
|
|
245
331
|
runState: import("..").RunState | null;
|
|
246
332
|
hasLoaded: boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Scenarios for teams: the three calls to buoy.gg (SHARED_SCENARIOS_PLAN.md).
|
|
3
|
+
*
|
|
4
|
+
* A device sends the token it already holds, a sign-in or the dev token from
|
|
5
|
+
* `buoy login`, plus this app's id. buoy.gg keeps one row per team, app and
|
|
6
|
+
* scenario. Bot keys and plain license keys get no team list.
|
|
7
|
+
*/
|
|
8
|
+
import type { Scenario } from "../types";
|
|
9
|
+
export interface TeamScenarioRow {
|
|
10
|
+
id: string;
|
|
11
|
+
app: string;
|
|
12
|
+
scenario: Scenario;
|
|
13
|
+
version: number;
|
|
14
|
+
sharedBy: {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
};
|
|
18
|
+
sharedAt: number;
|
|
19
|
+
updatedAt: number;
|
|
20
|
+
}
|
|
21
|
+
export interface TeamPullResult {
|
|
22
|
+
scenarios: TeamScenarioRow[];
|
|
23
|
+
/** The caller's account id. */
|
|
24
|
+
you: string;
|
|
25
|
+
admin: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Why a call didn't happen or didn't work:
|
|
29
|
+
* - `no-team`: no sign-in on a Business team (or a plain key).
|
|
30
|
+
* - `no-app`: Buoy can't tell which app this is.
|
|
31
|
+
* - `network`: buoy.gg couldn't be reached.
|
|
32
|
+
* - `refused`: buoy.gg said no; `message` says why.
|
|
33
|
+
*/
|
|
34
|
+
export type TeamFailure = {
|
|
35
|
+
ok: false;
|
|
36
|
+
code: "no-team" | "no-app" | "network" | "refused";
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
export type TeamCall<T> = {
|
|
40
|
+
ok: true;
|
|
41
|
+
value: T;
|
|
42
|
+
} | TeamFailure;
|
|
43
|
+
export interface TeamClientDeps {
|
|
44
|
+
credential: () => {
|
|
45
|
+
token: string;
|
|
46
|
+
origin: string;
|
|
47
|
+
team: string;
|
|
48
|
+
appId: string | null;
|
|
49
|
+
} | null;
|
|
50
|
+
appId: () => string | null;
|
|
51
|
+
fetch: (url: string, init: {
|
|
52
|
+
method: string;
|
|
53
|
+
headers: Record<string, string>;
|
|
54
|
+
body: string;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
}) => Promise<{
|
|
57
|
+
status: number;
|
|
58
|
+
json(): Promise<unknown>;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
export declare const NO_TEAM_MESSAGE = "Sign in with a Business team account to share scenarios with your team.";
|
|
62
|
+
export declare const NO_APP_MESSAGE = "Buoy can't tell which app this is. Pass signIn={{ appId }} to FloatingDevTools to name it.";
|
|
63
|
+
export declare function defaultTeamClientDeps(): TeamClientDeps;
|
|
64
|
+
/** The app this device's team list belongs to: the one its sign-in names, else the one core found. */
|
|
65
|
+
export declare function teamAppId(deps: TeamClientDeps): string | null;
|
|
66
|
+
/** The team's scenarios for this app. */
|
|
67
|
+
export declare function pullTeamScenarios(deps?: TeamClientDeps): Promise<TeamCall<TeamPullResult>>;
|
|
68
|
+
/**
|
|
69
|
+
* Fields that only mean something on this device. They never leave it:
|
|
70
|
+
* how often it ran here, when someone here last checked it, where it came from.
|
|
71
|
+
*/
|
|
72
|
+
export declare function forSharing(scenario: Scenario): Omit<Scenario, "usage" | "source" | "verifiedAt" | "team">;
|
|
73
|
+
/** Share one scenario with the team. A person's tap only: no tool action calls this. */
|
|
74
|
+
export declare function shareTeamScenario(scenario: Scenario, deps?: TeamClientDeps): Promise<TeamCall<TeamScenarioRow>>;
|
|
75
|
+
/** Take one scenario off the team's list. Only its sharer or a team admin may. */
|
|
76
|
+
export declare function removeTeamScenario(id: string, deps?: TeamClientDeps): Promise<TeamCall<true>>;
|
|
77
|
+
//# sourceMappingURL=teamClient.d.ts.map
|
|
@@ -48,8 +48,21 @@ export interface ScenarioStep {
|
|
|
48
48
|
* - `device` — saved on this device; editable, deletable, exportable.
|
|
49
49
|
* - `draft` — authored remotely (MCP/desktop) and INERT until a human accepts it
|
|
50
50
|
* on-device. A draft never runs and never appears as a Run target.
|
|
51
|
+
* - `team` — shared by someone on this app's Business team, pulled from
|
|
52
|
+
* buoy.gg. Read-only on device, like `code`; runs like any other.
|
|
51
53
|
*/
|
|
52
|
-
export type ScenarioSource = "code" | "device" | "draft";
|
|
54
|
+
export type ScenarioSource = "code" | "device" | "draft" | "team";
|
|
55
|
+
/** Who shared a team scenario, and when. Only on `team` scenarios. */
|
|
56
|
+
export interface ScenarioTeamInfo {
|
|
57
|
+
sharedBy: {
|
|
58
|
+
id: string;
|
|
59
|
+
label: string;
|
|
60
|
+
};
|
|
61
|
+
sharedAt: number;
|
|
62
|
+
updatedAt: number;
|
|
63
|
+
/** The app it was shared from, which is this app. */
|
|
64
|
+
app: string;
|
|
65
|
+
}
|
|
53
66
|
export interface Scenario {
|
|
54
67
|
id: string;
|
|
55
68
|
/** Placeholders allowed: "Out-of-stock item at store {{storeId}}". */
|
|
@@ -99,6 +112,8 @@ export interface Scenario {
|
|
|
99
112
|
runs: number;
|
|
100
113
|
lastRunAt?: number;
|
|
101
114
|
};
|
|
115
|
+
/** Set on `team` scenarios. */
|
|
116
|
+
team?: ScenarioTeamInfo;
|
|
102
117
|
}
|
|
103
118
|
/**
|
|
104
119
|
* An effect a run actually applied. Recorded per-step AS IT SUCCEEDS, so a
|
|
@@ -153,6 +168,12 @@ export interface ActiveScenario {
|
|
|
153
168
|
effects: AppliedEffect[];
|
|
154
169
|
/** Epoch ms after which the runner auto-deactivates. */
|
|
155
170
|
expiresAt?: number;
|
|
171
|
+
/**
|
|
172
|
+
* The undo steps as they were when it ran. A team scenario can change or
|
|
173
|
+
* go away while it is on, and undo must still run the steps that match
|
|
174
|
+
* what was applied.
|
|
175
|
+
*/
|
|
176
|
+
undoSteps?: ScenarioStep[];
|
|
156
177
|
}
|
|
157
178
|
export interface StepReport {
|
|
158
179
|
id: string;
|