@xfey/tutti 0.1.89 → 0.1.90

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.
@@ -5,6 +5,7 @@ export type CodexAppServerRuntimeTelemetryOptions = {
5
5
  activityRef: ActivityRef;
6
6
  stageId?: string;
7
7
  startedAt?: string;
8
+ workspaceRoot?: string;
8
9
  actionMinVisibleMs?: number;
9
10
  now?: () => Date;
10
11
  onSnapshot?: (snapshot: ExecutionRuntimeSnapshot) => void;
@@ -1,5 +1,9 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { classifyViewerPath, redactAndTruncateText } from "@tutti/shared/utils";
1
3
  import { extractCodexAppServerTokenUsage } from "../token-usage.js";
2
4
  const DEFAULT_ACTION_MIN_VISIBLE_MS = 1_000;
5
+ const MAX_ACTION_DETAIL_LENGTH = 160;
6
+ const MAX_ACTION_PATH_LENGTH = 120;
3
7
  function isRecord(value) {
4
8
  return typeof value === "object" && value !== null && !Array.isArray(value);
5
9
  }
@@ -13,65 +17,201 @@ function itemId(item) {
13
17
  return typeof item.id === "string" && item.id !== "" ? item.id : undefined;
14
18
  }
15
19
  const CHECK_COMMAND_PATTERN = /(?:^|[\s;&|])(?:(?:npm|pnpm|yarn|bun)\s+(?:(?:run|exec|x)\s+)?(?:test|lint|check|typecheck|build)|(?:npx|pnpm\s+exec|yarn\s+exec|bunx)\s+(?:vitest|jest|eslint|tsc|biome|prettier)|pytest|vitest|jest|cargo\s+(?:test|check|clippy|build)|go\s+test|dotnet\s+(?:test|build)|gradle\w*\s+(?:test|check|build)|make\s+(?:test|check|lint|build)|tsc(?:\s|$)|eslint(?:\s|$)|biome\s+check|ruff\s+check|mypy(?:\s|$)|swift\s+test|xcodebuild(?:\s|$))/iu;
16
- function commandActionFromItem(item) {
20
+ function boundedDetail(value) {
21
+ const detail = redactAndTruncateText(value.trim().replace(/\s+/gu, " "), MAX_ACTION_DETAIL_LENGTH);
22
+ return detail === "" ? undefined : detail;
23
+ }
24
+ function safeProjectPath(value, workspaceRoot) {
25
+ if (typeof value !== "string" || value.trim() === "") {
26
+ return undefined;
27
+ }
28
+ const rawPath = value.trim();
29
+ let candidate = rawPath;
30
+ if (isAbsolute(rawPath)) {
31
+ if (workspaceRoot === undefined) {
32
+ return undefined;
33
+ }
34
+ candidate = relative(resolve(workspaceRoot), resolve(rawPath));
35
+ }
36
+ const classification = classifyViewerPath(candidate);
37
+ if (classification.kind === "rejected" ||
38
+ classification.path_kind === "root" ||
39
+ classification.normalized_path === "") {
40
+ return undefined;
41
+ }
42
+ return redactAndTruncateText(classification.normalized_path, MAX_ACTION_PATH_LENGTH);
43
+ }
44
+ function firstSafePath(records, workspaceRoot, keys = ["path"]) {
45
+ for (const record of records) {
46
+ for (const key of keys) {
47
+ const path = safeProjectPath(record[key], workspaceRoot);
48
+ if (path !== undefined) {
49
+ return path;
50
+ }
51
+ }
52
+ }
53
+ return undefined;
54
+ }
55
+ function safeToolName(item) {
56
+ for (const key of ["tool", "toolName", "name"]) {
57
+ const value = item[key];
58
+ if (typeof value === "string" && value.length <= 64 && /^[A-Za-z0-9@._:/-]+$/u.test(value)) {
59
+ return value;
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ function commandCheckDetail(commands) {
65
+ const command = commands.join(" ");
66
+ const workspace = /--workspace(?:=|\s+)(@?[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)?)/iu.exec(command)?.[1];
67
+ const target = workspace === undefined ? "the project" : workspace;
68
+ if (/(?:^|[\s:./_-])(?:test|tests|pytest|vitest|jest)(?:$|[\s:./_-])/iu.test(command)) {
69
+ return {
70
+ detail: workspace === undefined ? "Running project tests" : `Running tests for ${target}`,
71
+ completionDetail: "Reviewing test results",
72
+ };
73
+ }
74
+ if (/(?:typecheck|\btsc\b|\bmypy\b)/iu.test(command)) {
75
+ return {
76
+ detail: `Checking types for ${target}`,
77
+ completionDetail: "Reviewing type-check results",
78
+ };
79
+ }
80
+ if (/(?:lint|eslint|biome|prettier|ruff|clippy)/iu.test(command)) {
81
+ return {
82
+ detail: `Checking code quality for ${target}`,
83
+ completionDetail: "Reviewing code-quality results",
84
+ };
85
+ }
86
+ if (/(?:^|[\s:./_-])build(?:$|[\s:./_-])|xcodebuild/iu.test(command)) {
87
+ return {
88
+ detail: workspace === undefined ? "Building the project" : `Building ${workspace}`,
89
+ completionDetail: "Reviewing the build result",
90
+ };
91
+ }
92
+ return {
93
+ detail: "Running project checks",
94
+ completionDetail: "Reviewing check results",
95
+ };
96
+ }
97
+ function commandActionFromItem(item, workspaceRoot) {
17
98
  const commandActions = Array.isArray(item.commandActions)
18
99
  ? item.commandActions.filter(isRecord)
19
100
  : [];
20
101
  const commands = [item.command, ...commandActions.map((action) => action.command)].filter((command) => typeof command === "string");
21
102
  if (commands.some((command) => CHECK_COMMAND_PATTERN.test(command))) {
22
- return "running_checks";
103
+ const check = commandCheckDetail(commands);
104
+ return {
105
+ action: "running_checks",
106
+ detail: check.detail,
107
+ completionDetail: check.completionDetail,
108
+ };
23
109
  }
24
110
  const actionTypes = commandActions
25
111
  .map((action) => action.type)
26
112
  .filter((type) => typeof type === "string");
27
113
  if (actionTypes.some((type) => type === "search" || type === "listFiles")) {
28
- return "searching_codebase";
114
+ const path = firstSafePath(commandActions, workspaceRoot, ["path", "name"]);
115
+ return {
116
+ action: "searching_codebase",
117
+ ...(path === undefined ? {} : { detail: `Searching in ${path}` }),
118
+ completionDetail: "Reviewing search results",
119
+ };
29
120
  }
30
121
  if (actionTypes.includes("read")) {
31
- return "reading_files";
122
+ const path = firstSafePath(commandActions, workspaceRoot, ["path", "name"]);
123
+ return {
124
+ action: "reading_files",
125
+ ...(path === undefined ? {} : { detail: `Reading ${path}` }),
126
+ completionDetail: path === undefined ? "Reviewing project context" : `Reviewing ${path}`,
127
+ };
32
128
  }
33
- return "running_command";
129
+ return {
130
+ action: "running_command",
131
+ completionDetail: "Reviewing command output",
132
+ };
34
133
  }
35
- function actionFromItem(item) {
134
+ function fileChangeSignal(item, workspaceRoot) {
135
+ const changes = Array.isArray(item.changes) ? item.changes.filter(isRecord) : [];
136
+ const path = firstSafePath([item, ...changes], workspaceRoot);
137
+ return {
138
+ action: "editing_files",
139
+ ...(path === undefined ? {} : { detail: `Editing ${path}` }),
140
+ completionDetail: path === undefined ? "Reviewing the latest changes" : `Reviewing changes to ${path}`,
141
+ };
142
+ }
143
+ function actionFromItem(item, workspaceRoot) {
36
144
  switch (item.type) {
37
145
  case "reasoning":
38
146
  case "contextCompaction":
39
- return "analyzing_task";
147
+ return { action: "analyzing_task" };
40
148
  case "plan":
41
- return "planning";
149
+ return { action: "planning" };
42
150
  case "commandExecution":
43
- return commandActionFromItem(item);
151
+ return commandActionFromItem(item, workspaceRoot);
44
152
  case "fileChange":
45
- return "editing_files";
46
- case "imageView":
47
- return "reading_files";
48
- case "mcpToolCall":
49
- case "dynamicToolCall":
153
+ return fileChangeSignal(item, workspaceRoot);
154
+ case "imageView": {
155
+ const path = firstSafePath([item], workspaceRoot);
156
+ return {
157
+ action: "reading_files",
158
+ detail: path === undefined ? "Inspecting a project visual" : `Inspecting ${path}`,
159
+ completionDetail: "Reviewing the project visual",
160
+ };
161
+ }
162
+ case "webSearch":
163
+ return {
164
+ action: "using_tool",
165
+ detail: "Searching the web",
166
+ completionDetail: "Reviewing web search results",
167
+ };
50
168
  case "collabAgentToolCall":
51
169
  case "subAgentActivity":
52
- case "webSearch":
170
+ return {
171
+ action: "using_tool",
172
+ detail: "Coordinating a sub-agent",
173
+ completionDetail: "Reviewing the sub-agent result",
174
+ };
53
175
  case "imageGeneration":
54
- return "using_tool";
176
+ return {
177
+ action: "using_tool",
178
+ detail: "Generating an image",
179
+ completionDetail: "Reviewing the generated image",
180
+ };
181
+ case "mcpToolCall":
182
+ case "dynamicToolCall": {
183
+ const tool = safeToolName(item);
184
+ return {
185
+ action: "using_tool",
186
+ ...(tool === undefined ? {} : { detail: `Using ${tool}` }),
187
+ completionDetail: "Reviewing tool output",
188
+ };
189
+ }
55
190
  default:
56
191
  return undefined;
57
192
  }
58
193
  }
59
- function actionFromNotificationMethod(notification) {
194
+ function actionFromNotificationMethod(notification, workspaceRoot) {
60
195
  const method = notification.method;
61
196
  if (method === "turn/started" || method.startsWith("item/reasoning/")) {
62
- return "analyzing_task";
197
+ return { action: "analyzing_task" };
63
198
  }
64
199
  if (method === "turn/plan/updated" || method.startsWith("item/plan/")) {
65
- return "planning";
200
+ return { action: "planning" };
66
201
  }
67
202
  if (method === "turn/diff/updated" || method.startsWith("item/fileChange/")) {
68
- return "editing_files";
203
+ const params = isRecord(notification.params) ? notification.params : {};
204
+ const rawPaths = params.paths;
205
+ const paths = Array.isArray(rawPaths)
206
+ ? rawPaths.map((path) => ({ path }))
207
+ : [];
208
+ return fileChangeSignal({ ...params, changes: paths }, workspaceRoot);
69
209
  }
70
210
  if (method === "turn/completed") {
71
- return "preparing_result";
211
+ return { action: "preparing_result" };
72
212
  }
73
213
  if (method.startsWith("item/mcpToolCall/")) {
74
- return "using_tool";
214
+ return { action: "using_tool", completionDetail: "Reviewing tool output" };
75
215
  }
76
216
  return undefined;
77
217
  }
@@ -107,19 +247,23 @@ export function createCodexAppServerRuntimeObserver(options) {
107
247
  let latest;
108
248
  let timer;
109
249
  let lastEmittedAt;
110
- let lastEmittedAction;
250
+ let lastEmittedActionKey;
111
251
  let pendingSnapshot;
252
+ let lastCompletedDetail;
112
253
  let itemOrder = 0;
113
254
  const activeItems = new Map();
114
255
  const waitingRequests = new Set();
115
256
  const actionMinVisibleMs = Math.max(0, options.actionMinVisibleMs ?? DEFAULT_ACTION_MIN_VISIBLE_MS);
116
257
  const now = options.now ?? (() => new Date());
258
+ const snapshotActionKey = (snapshot) => snapshot?.current_action === undefined
259
+ ? undefined
260
+ : `${snapshot.current_action}\u0000${snapshot.current_action_detail ?? ""}`;
117
261
  const emit = (snapshot = latest) => {
118
262
  if (snapshot === undefined || options.onSnapshot === undefined) {
119
263
  return;
120
264
  }
121
265
  lastEmittedAt = Date.now();
122
- lastEmittedAction = snapshot.current_action;
266
+ lastEmittedActionKey = snapshotActionKey(snapshot);
123
267
  options.onSnapshot(snapshot);
124
268
  };
125
269
  const publishPendingSnapshot = () => {
@@ -127,7 +271,7 @@ export function createCodexAppServerRuntimeObserver(options) {
127
271
  pendingSnapshot = undefined;
128
272
  emit(snapshot);
129
273
  if (latest?.current_action !== undefined &&
130
- latest.current_action !== lastEmittedAction) {
274
+ snapshotActionKey(latest) !== lastEmittedActionKey) {
131
275
  pendingSnapshot = latest;
132
276
  schedulePendingSnapshot();
133
277
  }
@@ -157,23 +301,26 @@ export function createCodexAppServerRuntimeObserver(options) {
157
301
  publishPendingSnapshot();
158
302
  }, Math.max(1, actionMinVisibleMs - elapsed));
159
303
  };
160
- const scheduleActionEmit = () => {
304
+ const scheduleActionEmit = (preservePendingAction) => {
161
305
  if (options.onSnapshot === undefined || latest?.current_action === undefined) {
162
306
  return;
163
307
  }
164
308
  if (pendingSnapshot !== undefined) {
165
- if (latest.current_action !== lastEmittedAction) {
309
+ if (preservePendingAction) {
310
+ return;
311
+ }
312
+ if (snapshotActionKey(latest) !== lastEmittedActionKey) {
166
313
  pendingSnapshot = latest;
167
314
  }
168
315
  return;
169
316
  }
170
- if (latest.current_action === lastEmittedAction) {
317
+ if (snapshotActionKey(latest) === lastEmittedActionKey) {
171
318
  return;
172
319
  }
173
320
  pendingSnapshot = latest;
174
321
  schedulePendingSnapshot();
175
322
  };
176
- const update = (patch, scheduleAction = patch.currentAction !== undefined) => {
323
+ const update = (patch, scheduleAction = patch.currentAction !== undefined, preservePendingAction = false) => {
177
324
  if (patch.currentAction === undefined && patch.tokenUsage === undefined) {
178
325
  return;
179
326
  }
@@ -184,16 +331,31 @@ export function createCodexAppServerRuntimeObserver(options) {
184
331
  ...(options.startedAt === undefined ? {} : { started_at: options.startedAt }),
185
332
  ...(latest?.token_usage === undefined ? {} : { token_usage: latest.token_usage }),
186
333
  ...(latest?.current_action === undefined ? {} : { current_action: latest.current_action }),
334
+ ...(latest?.current_action_detail === undefined
335
+ ? {}
336
+ : { current_action_detail: latest.current_action_detail }),
187
337
  updated_at: updatedAt,
188
338
  };
189
339
  if (patch.tokenUsage !== undefined) {
190
340
  latest.token_usage = runtimeTokenUsage(patch.tokenUsage);
191
341
  }
192
342
  if (patch.currentAction !== undefined) {
193
- latest.current_action = patch.currentAction;
343
+ latest.current_action = patch.currentAction.action;
344
+ const detail = patch.currentAction.detail === undefined
345
+ ? undefined
346
+ : boundedDetail(patch.currentAction.detail);
347
+ if (detail === undefined) {
348
+ delete latest.current_action_detail;
349
+ }
350
+ else {
351
+ latest.current_action_detail = detail;
352
+ }
353
+ }
354
+ if (!scheduleAction && pendingSnapshot !== undefined) {
355
+ pendingSnapshot = latest;
194
356
  }
195
357
  if (scheduleAction) {
196
- scheduleActionEmit();
358
+ scheduleActionEmit(preservePendingAction);
197
359
  }
198
360
  };
199
361
  const currentItemAction = () => {
@@ -203,14 +365,18 @@ export function createCodexAppServerRuntimeObserver(options) {
203
365
  current = item;
204
366
  }
205
367
  }
206
- return current?.action;
368
+ return current;
207
369
  };
370
+ const fallbackAction = () => ({
371
+ action: "analyzing_task",
372
+ ...(lastCompletedDetail === undefined ? {} : { detail: lastCompletedDetail }),
373
+ });
208
374
  const resumeCurrentAction = () => {
209
375
  update({
210
376
  currentAction: waitingRequests.size > 0
211
- ? "waiting_for_approval"
212
- : (currentItemAction() ?? "analyzing_task"),
213
- });
377
+ ? { action: "waiting_for_approval" }
378
+ : (currentItemAction() ?? fallbackAction()),
379
+ }, true, true);
214
380
  };
215
381
  return {
216
382
  notification: (notification) => {
@@ -228,10 +394,15 @@ export function createCodexAppServerRuntimeObserver(options) {
228
394
  if (notification.method === "item/started") {
229
395
  const item = itemFromNotification(notification);
230
396
  const id = item === undefined ? undefined : itemId(item);
231
- const action = item === undefined ? undefined : actionFromItem(item);
397
+ let action = item === undefined ? undefined : actionFromItem(item, options.workspaceRoot);
398
+ if (action?.action === "analyzing_task" &&
399
+ action.detail === undefined &&
400
+ lastCompletedDetail !== undefined) {
401
+ action = { ...action, detail: lastCompletedDetail };
402
+ }
232
403
  if (id !== undefined && action !== undefined) {
233
404
  itemOrder += 1;
234
- activeItems.set(id, { action, order: itemOrder });
405
+ activeItems.set(id, { ...action, order: itemOrder });
235
406
  if (waitingRequests.size === 0) {
236
407
  update({ currentAction: action });
237
408
  }
@@ -241,12 +412,27 @@ export function createCodexAppServerRuntimeObserver(options) {
241
412
  if (notification.method === "item/completed") {
242
413
  const item = itemFromNotification(notification);
243
414
  const id = item === undefined ? undefined : itemId(item);
415
+ const completed = id === undefined ? undefined : activeItems.get(id);
244
416
  if (id !== undefined && activeItems.delete(id)) {
417
+ if (completed?.completionDetail !== undefined) {
418
+ lastCompletedDetail = completed.completionDetail;
419
+ }
245
420
  resumeCurrentAction();
246
421
  }
247
422
  return;
248
423
  }
249
- const currentAction = actionFromNotificationMethod(notification);
424
+ let currentAction = actionFromNotificationMethod(notification, options.workspaceRoot);
425
+ const activeAction = currentItemAction();
426
+ if (currentAction !== undefined &&
427
+ currentAction.detail === undefined &&
428
+ activeAction?.action === currentAction.action) {
429
+ currentAction = activeAction;
430
+ }
431
+ if (currentAction?.action === "analyzing_task" &&
432
+ currentAction.detail === undefined &&
433
+ lastCompletedDetail !== undefined) {
434
+ currentAction = { ...currentAction, detail: lastCompletedDetail };
435
+ }
250
436
  if (currentAction !== undefined && waitingRequests.size === 0) {
251
437
  update({ currentAction });
252
438
  }
@@ -259,7 +445,7 @@ export function createCodexAppServerRuntimeObserver(options) {
259
445
  if (key !== undefined) {
260
446
  waitingRequests.add(key);
261
447
  }
262
- update({ currentAction: "waiting_for_approval" });
448
+ update({ currentAction: { action: "waiting_for_approval" } });
263
449
  },
264
450
  flush: () => {
265
451
  if (timer !== undefined) {
@@ -267,7 +453,8 @@ export function createCodexAppServerRuntimeObserver(options) {
267
453
  timer = undefined;
268
454
  }
269
455
  pendingSnapshot = undefined;
270
- if (latest?.current_action !== undefined && latest.current_action !== lastEmittedAction) {
456
+ if (latest?.current_action !== undefined &&
457
+ snapshotActionKey(latest) !== lastEmittedActionKey) {
271
458
  emit();
272
459
  }
273
460
  },
@@ -120,6 +120,7 @@ export async function runWorkspaceWriteTask(options, input) {
120
120
  runtimeTelemetry: {
121
121
  activityRef: input.activity_ref,
122
122
  stageId: "provider_task_run",
123
+ workspaceRoot: options.workspaceRoot,
123
124
  onSnapshot: (snapshot) => input.on_stage?.({
124
125
  stage: "provider_task_run",
125
126
  summary: "running Codex task implementation.",
@@ -203,6 +203,7 @@ export declare const HOST_PROJECT_EXECUTION_OPENAPI_ROUTES: ({
203
203
  total_tokens: import("@sinclair/typebox").TInteger;
204
204
  }>>;
205
205
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
206
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
206
207
  }>>;
207
208
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
208
209
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -1277,6 +1277,7 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
1277
1277
  total_tokens: import("@sinclair/typebox").TInteger;
1278
1278
  }>>;
1279
1279
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
1280
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1280
1281
  }>>;
1281
1282
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
1282
1283
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -832,6 +832,7 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
832
832
  total_tokens: import("@sinclair/typebox").TInteger;
833
833
  }>>;
834
834
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
835
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
835
836
  }>>;
836
837
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
837
838
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -2551,6 +2552,7 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
2551
2552
  total_tokens: import("@sinclair/typebox").TInteger;
2552
2553
  }>>;
2553
2554
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
2555
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
2554
2556
  }>>;
2555
2557
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
2556
2558
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -1241,6 +1241,7 @@ export declare const BootstrapResponseSchema: {
1241
1241
  total_tokens: import("@sinclair/typebox").TInteger;
1242
1242
  }>>;
1243
1243
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
1244
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1244
1245
  }>>;
1245
1246
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
1246
1247
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -29,6 +29,7 @@ export declare const ExecutionRuntimeSnapshotSchema: import("@sinclair/typebox")
29
29
  total_tokens: import("@sinclair/typebox").TInteger;
30
30
  }>>;
31
31
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
32
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
32
33
  }>;
33
34
  export declare const ExecutionStatusProjectionSchema: import("@sinclair/typebox").TObject<{
34
35
  status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"idle">, import("@sinclair/typebox").TLiteral<"running">, import("@sinclair/typebox").TLiteral<"pending">, import("@sinclair/typebox").TLiteral<"failed">]>;
@@ -76,6 +77,7 @@ export declare const ExecutionStatusProjectionSchema: import("@sinclair/typebox"
76
77
  total_tokens: import("@sinclair/typebox").TInteger;
77
78
  }>>;
78
79
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
80
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
79
81
  }>>;
80
82
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
81
83
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -213,6 +215,7 @@ export declare const ExecutionStatusChangedEventPayloadSchema: import("@sinclair
213
215
  total_tokens: import("@sinclair/typebox").TInteger;
214
216
  }>>;
215
217
  current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
218
+ current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
216
219
  }>>;
217
220
  blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
218
221
  kind: import("@sinclair/typebox").TLiteral<"clarification">;
@@ -50,6 +50,7 @@ export const ExecutionRuntimeSnapshotSchema = Type.Object({
50
50
  updated_at: Type.Optional(IsoDateTimeStringSchema),
51
51
  token_usage: Type.Optional(ExecutionRuntimeTokenUsageSchema),
52
52
  current_action: Type.Optional(ExecutionRuntimeActionSchema),
53
+ current_action_detail: Type.Optional(Type.String({ minLength: 1, maxLength: 160 })),
53
54
  }, { additionalProperties: false });
54
55
  export const ExecutionStatusProjectionSchema = Type.Object({
55
56
  status: ExecutionStatusKindSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfey/tutti",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1 +1 @@
1
- import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./index-BxgVVqiQ.js";var w=e(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),T=e(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),E=x();function D(e){return{"--reveal":e}}function O(e,t,n){let r=(e,t)=>Number.parseInt(e.slice(t,t+2),16),i=i=>Math.round(r(e,i)+(r(t,i)-r(e,i))*n).toString(16).padStart(2,`0`);return`#${i(1)}${i(3)}${i(5)}`}function k(e){let t=r((e-p.runEnd)/(p.executionComplete-p.runEnd));return t+t*t-t*t*t}function A({progress:e,children:t,className:n=``}){return(0,E.jsx)(`div`,{className:`scene-reveal ${n}`,style:D(e),children:t})}function j({progress:e,author:t,avatar:n,tone:r,timestamp:i,online:a=!1,assets:o,children:s}){return(0,E.jsxs)(`article`,{className:`scene-message`,style:D(e),children:[(0,E.jsx)(`span`,{className:`scene-avatar is-${r} ${n===`tutti`?`is-tutti`:``} ${a?`is-online`:``}`,"aria-hidden":`true`,children:n===`tutti`?(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.tuttiAvatarSrc,alt:``}):(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.humanAvatars[n],alt:``})}),(0,E.jsxs)(`div`,{className:`scene-message-copy`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`strong`,{children:t}),(0,E.jsx)(`span`,{children:i})]}),(0,E.jsx)(`p`,{children:s})]})]})}function M({time:e,assets:r}){let i=e>=p.artifactLive,a=e>=p.artifactClick,o=e>=p.runEnd&&e<p.executionComplete,u=d(e,p.runEnd,19.2),f=d(e,p.artifactLive,30.92);return(0,E.jsxs)(`aside`,{className:`scene-sidebar`,children:[(0,E.jsx)(`button`,{className:`scene-brand`,type:`button`,"aria-label":`Tutti`,tabIndex:-1,children:(0,E.jsx)(`img`,{src:r.logoSrc,alt:``})}),(0,E.jsxs)(`div`,{className:`scene-nav-stack`,children:[(0,E.jsxs)(`nav`,{className:`scene-nav`,"aria-label":`Workspace pages`,children:[(0,E.jsx)(`button`,{className:a?``:`is-active`,type:`button`,"aria-label":`Chat`,tabIndex:-1,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Worklist`,tabIndex:-1,children:(0,E.jsx)(b,{"aria-hidden":`true`})}),(0,E.jsxs)(`button`,{className:a?`is-active`:``,type:`button`,"aria-label":`Artifacts`,tabIndex:-1,children:[(0,E.jsx)(l,{"aria-hidden":`true`}),i?(0,E.jsx)(`span`,{className:`scene-live-pill`,style:D(f),children:`Live`}):null]}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`References`,tabIndex:-1,children:(0,E.jsx)(C,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Skills`,tabIndex:-1,children:(0,E.jsx)(s,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Timeline`,tabIndex:-1,children:(0,E.jsx)(t,{"aria-hidden":`true`})})]}),o?(0,E.jsx)(`button`,{className:`scene-status-entry is-running`,style:D(u),type:`button`,"aria-label":`Task running`,tabIndex:-1,children:(0,E.jsx)(n,{"aria-hidden":`true`})}):null]}),(0,E.jsx)(`button`,{className:`scene-settings`,type:`button`,"aria-label":`Settings`,tabIndex:-1,children:(0,E.jsx)(h,{"aria-hidden":`true`})})]})}function N({time:e,assets:t}){let n=d(e,30.35,30.92);return(0,E.jsxs)(`section`,{className:`scene-panel scene-chat-panel`,children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h2`,{children:`Morrow Studio`}),(0,E.jsx)(`p`,{children:`Ceramics storefront`})]}),(0,E.jsxs)(`span`,{className:`scene-members`,"aria-hidden":`true`,children:[(0,E.jsx)(`i`,{className:`is-green`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.fey,alt:``})}),(0,E.jsx)(`i`,{className:`is-blue`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.avery,alt:``})}),(0,E.jsx)(`i`,{className:`is-yellow`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.jun,alt:``})})]})]}),(0,E.jsxs)(`div`,{className:`scene-chat-stream`,children:[(0,E.jsx)(j,{progress:d(e,1.35,2.05),author:`Fey`,avatar:`fey`,tone:`green`,timestamp:`10:12`,online:!0,assets:t,children:`🏺 Let's build an online shop for our ceramics studio.`}),(0,E.jsx)(j,{progress:d(e,2.65,3.35),author:`Avery`,avatar:`avery`,tone:`blue`,timestamp:`10:13`,online:!0,assets:t,children:`✨ Keep it warm, minimal, and editorial.`}),(0,E.jsx)(j,{progress:d(e,3.95,4.65),author:`Jun`,avatar:`jun`,tone:`yellow`,timestamp:`10:14`,online:!0,assets:t,children:`🎨 Let people preview every piece in different glazes.`}),(0,E.jsx)(j,{progress:d(e,5.25,5.95),author:`Tutti`,avatar:`tutti`,tone:`green`,timestamp:`10:15`,assets:t,children:`Got it — I'll put it together. ✨`}),(0,E.jsxs)(`article`,{className:`scene-task-result`,style:D(n),children:[(0,E.jsx)(`span`,{className:`scene-task-result-rail`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`scene-task-result-icon`,"aria-hidden":`true`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{children:`Task completed`}),(0,E.jsx)(`strong`,{children:`Build ceramics storefront`}),(0,E.jsx)(`small`,{children:`Storefront`}),(0,E.jsx)(`p`,{children:`Warm editorial shopping and glaze previews are ready in Artifacts.`})]}),(0,E.jsx)(i,{className:`scene-task-result-chevron`,"aria-hidden":`true`})]})]}),(0,E.jsxs)(`div`,{className:`scene-composer`,"aria-hidden":`true`,children:[(0,E.jsx)(`span`,{children:`Write a message`}),(0,E.jsx)(T,{})]})]})}function P({progress:e,icon:t,children:n}){return(0,E.jsxs)(`div`,{className:`scene-scratchpad-row`,style:D(e),children:[(0,E.jsx)(`span`,{"aria-hidden":`true`,children:t}),(0,E.jsx)(`p`,{children:n})]})}function F({time:e}){return(0,E.jsxs)(`section`,{className:`scene-panel scene-scratchpad-panel`,style:{"--scratchpad-collapse":d(e,p.runEnd,19.18)},children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(v,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Scratchpad`})]}),(0,E.jsxs)(`div`,{className:`scene-scratchpad-body`,children:[(0,E.jsxs)(A,{progress:d(e,8.95,10),className:`scene-scratchpad-intro`,children:[(0,E.jsx)(`h3`,{children:`Ceramics storefront`}),(0,E.jsx)(`p`,{children:`A warm, editorial storefront for a small-batch studio, centered on tactile product discovery.`})]}),(0,E.jsx)(A,{progress:d(e,9.85,10.65),className:`scene-scratchpad-label`,children:`Confirmed`}),(0,E.jsx)(P,{progress:d(e,10.4,11.25),icon:(0,E.jsx)(S,{}),children:`Product-first editorial layout with generous space`}),(0,E.jsx)(P,{progress:d(e,11.2,12.05),icon:(0,E.jsx)(S,{}),children:`Warm neutrals with quiet serif headlines`}),(0,E.jsx)(P,{progress:d(e,12,12.85),icon:(0,E.jsx)(S,{}),children:`Keep the collection small, curated, and story-led`}),(0,E.jsx)(A,{progress:d(e,12.75,13.55),className:`scene-scratchpad-label`,children:`Requested feature`}),(0,E.jsx)(P,{progress:d(e,13.3,14.2),icon:(0,E.jsx)(o,{}),children:`Preview every piece in clay, sage, and ink glazes`})]}),(0,E.jsxs)(`footer`,{className:`scene-scratchpad-footer`,style:D(d(e,15.7,16.8)),children:[(0,E.jsxs)(`span`,{className:`scene-writing-mark`,children:[(0,E.jsx)(`strong`,{children:`Updated`}),(0,E.jsx)(`span`,{children:`just now`})]}),(0,E.jsxs)(`button`,{className:`scene-run-button`,type:`button`,tabIndex:-1,children:[(0,E.jsx)(f,{"aria-hidden":`true`}),(0,E.jsx)(`span`,{children:`Run`})]})]})]})}function I(e,t){let n=Math.max(0,Math.floor((e-t)*50/5)*5);return`${Math.floor(n/60)}m${(n%60).toString().padStart(2,`0`)}s`}function L({time:e,scoreSrc:t}){let r=d(e,18.92,19.2),i=_(e),a=i.id===`complete`,o={prepare:p.runEnd,implement:p.executionPrepareEnd,validate:p.executionImplementEnd,update:p.executionValidateEnd,complete:p.executionComplete}[i.id],s=d(e,o,o+.32),c=k(e);return(0,E.jsx)(`div`,{className:`scene-execution`,style:{"--reveal":r,"--stage-reveal":s},children:(0,E.jsxs)(`article`,{className:`homepage-motion-panel homepage-motion-execution-panel homepage-motion-execution-card is-score-${a?`complete`:`running`}`,children:[(0,E.jsx)(`header`,{className:`homepage-motion-panel-header`,children:(0,E.jsxs)(`div`,{className:`homepage-motion-panel-title`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,"aria-hidden":`true`,children:(0,E.jsx)(y,{})}),(0,E.jsx)(`h3`,{children:`Tutti is working on`})]})}),(0,E.jsxs)(`div`,{className:`homepage-motion-execution-body`,children:[(0,E.jsxs)(`div`,{className:`homepage-motion-execution-step homepage-motion-execution-stage is-${a?`complete`:`running`} has-marker`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-marker ${a?`is-done`:`is-running`}`,"aria-hidden":`true`,children:a?(0,E.jsx)(S,{}):(0,E.jsx)(n,{})}),(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-content homepage-motion-execution-stage-copy`,children:(0,E.jsxs)(`span`,{className:`homepage-motion-execution-step-title`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-label`,children:i.label}),a?null:(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-elapsed`,children:` (${I(e,o)})`})]})},i.id)]}),(0,E.jsx)(`div`,{className:`homepage-motion-running-score ${a?`is-complete`:``}`,role:`img`,"aria-label":`Ode to Joy score phrase`,children:(0,E.jsx)(`div`,{className:`homepage-motion-score-passage`,style:{"--score-translate-x":`${-395.3*c}px`},"aria-hidden":`true`,children:(0,E.jsx)(`img`,{src:t,alt:``,draggable:!1})})})]})]})})}function R({color:e,variant:t=`vase`,className:n=``}){let r={"--ceramic-color":e};return t===`cup`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-cup ${n}`,viewBox:`0 0 260 260`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M54 64h132l-9 126c-2 26-20 42-46 42h-22c-26 0-44-16-46-42Z`}),(0,E.jsx)(`path`,{className:`ceramic-outline`,d:`M186 92h18c34 0 34 72 1 76h-27`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`120`,cy:`64`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M78 90c5 62 4 91 20 114`})]}):t===`bowl`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-bowl ${n}`,viewBox:`0 0 300 220`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`150`,cy:`55`,rx:`116`,ry:`24`}),(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M34 55c8 82 45 132 116 132S258 137 266 55c-42 25-190 25-232 0Z`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M72 82c18 45 40 70 70 82`}),(0,E.jsx)(`path`,{className:`ceramic-base`,d:`M112 185h76`})]}):(0,E.jsxs)(`svg`,{className:`ceramic-object is-vase ${n}`,viewBox:`0 0 320 420`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M116 56c7 38-17 61-36 96-31 56-28 157 5 199 33 42 117 42 150 0 33-42 36-143 5-199-19-35-43-58-36-96Z`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`160`,cy:`56`,rx:`44`,ry:`12`}),(0,E.jsx)(`ellipse`,{className:`ceramic-base`,cx:`160`,cy:`365`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M108 153c-25 64-23 145 1 185`})]})}function z({time:e}){let t=d(e,p.artifactClick,33.25),n=d(e,34.25,34.52),r=d(e,34.88,35.15),i=d(e,35.55,35.82),a=g(e),o=O(`#d9cbb4`,`#c56f4f`,n);e>=34.88&&(o=O(`#c56f4f`,`#6f9275`,r)),e>=35.55&&(o=O(`#6f9275`,`#243a46`,i));let s=e>=35.55?`ink`:e>=34.88?`sage`:e>=34.25?`clay`:null,c={"--artifact-scroll":a};return(0,E.jsxs)(`section`,{className:`scene-panel scene-artifact-panel`,style:D(t),children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(l,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Artifacts`}),(0,E.jsx)(`span`,{className:`scene-ready-tag`,children:`Ready`})]}),(0,E.jsx)(`div`,{className:`scene-artifact-canvas`,children:(0,E.jsxs)(`div`,{className:`artifact-page-frame`,style:c,children:[(0,E.jsxs)(`div`,{className:`artifact-page-nav`,children:[(0,E.jsx)(`strong`,{children:`Morrow`}),(0,E.jsx)(`span`,{children:`Objects · Journal · Studio`})]}),(0,E.jsxs)(`section`,{className:`artifact-hero`,children:[(0,E.jsxs)(`div`,{className:`artifact-hero-copy`,children:[(0,E.jsx)(`span`,{className:`artifact-eyebrow`,children:`Hand-finished in small batches`}),(0,E.jsx)(`h3`,{children:`Objects for slower days.`}),(0,E.jsx)(`p`,{children:`Quiet forms, warm glazes, and useful pieces made to live with.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Explore the collection`})]}),(0,E.jsxs)(`div`,{className:`artifact-hero-object`,children:[(0,E.jsx)(R,{color:o}),(0,E.jsxs)(`div`,{className:`artifact-glaze-picker`,"aria-label":`Glaze preview`,children:[(0,E.jsx)(`span`,{children:`Glaze`}),(0,E.jsx)(`i`,{className:s===`clay`?`is-active is-clay`:`is-clay`}),(0,E.jsx)(`i`,{className:s===`sage`?`is-active is-sage`:`is-sage`}),(0,E.jsx)(`i`,{className:s===`ink`?`is-active is-ink`:`is-ink`})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-collection`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`span`,{children:`Selected pieces`}),(0,E.jsx)(`p`,{children:`Everyday forms shaped for the rituals around them.`})]}),(0,E.jsxs)(`div`,{className:`artifact-product-grid`,children:[(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#b9785f`,variant:`cup`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Low cup`}),(0,E.jsx)(`span`,{children:`Rust glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#819283`,variant:`vase`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Field vase`}),(0,E.jsx)(`span`,{children:`Sage glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#d5c7af`,variant:`bowl`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Gather bowl`}),(0,E.jsx)(`span`,{children:`Flax glaze`})]})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-studio`,children:[(0,E.jsx)(`span`,{children:`Made by hand · Meant for every day`}),(0,E.jsx)(`h3`,{children:`Useful things can still feel special.`}),(0,E.jsx)(`p`,{children:`We make a small number of considered objects, slowly and close to home.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Visit the studio`})]}),(0,E.jsxs)(`footer`,{className:`artifact-page-footer`,children:[(0,E.jsx)(`strong`,{children:`Morrow Ceramics`}),(0,E.jsx)(`span`,{className:`artifact-built-with`,children:`Built with Tutti.`}),(0,E.jsx)(`span`,{children:`Small batch · Est. 2026`})]})]})})]})}function B(e,t,n){return e+(t-e)*n}function V(e,t,n,r,i){let a=d(e,t,n,m);return{x:B(r.x,i.x,a),y:B(r.y,i.y,a)}}function H(e,t,n){return e<t||e>n?0:Math.sin(Math.PI*((e-t)/(n-t)))}function U(e){if(e>=p.runCursorStart&&e<18.92){let t=V(e,p.runCursorStart,p.runCursorArrive,{x:86,y:76},{x:94.25,y:94.2});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,p.runClickStart,p.runEnd)}}if(e>=31&&e<33.45){let t=V(e,31,32.22,{x:50,y:58},{x:4,y:22.85});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,32.28,32.6)}}return{visible:!1,x:50,y:50,clickPulse:0}}function W({time:e,assets:t}){let n=u(e),r=U(e),i=a(e),o=d(e,.08,1.05,m);return(0,E.jsx)(`div`,{className:`motion-scene`,role:`img`,"aria-label":`Tutti workflow animation from team discussion to a generated ceramics storefront`,style:{opacity:i,visibility:i<=.001?`hidden`:`visible`},children:(0,E.jsxs)(`div`,{className:`motion-stage`,style:{opacity:o,transform:`translate(50%, 50%) scale(${n.scale}) translate(${-n.centerX*100}%, ${-n.centerY*100}%)`},children:[(0,E.jsx)(M,{time:e,assets:t}),(0,E.jsxs)(`div`,{className:`scene-workspace-layer`,children:[(0,E.jsx)(N,{time:e,assets:t}),(0,E.jsx)(F,{time:e}),(0,E.jsx)(L,{time:e,scoreSrc:t.scoreSrc})]}),(0,E.jsx)(z,{time:e}),(0,E.jsxs)(`span`,{className:`scene-cursor ${r.visible?`is-visible`:``}`,style:{left:`${r.x}%`,top:`${r.y}%`,"--click-pulse":r.clickPulse},"aria-hidden":`true`,children:[(0,E.jsx)(w,{}),(0,E.jsx)(`i`,{})]})]})})}export{W as HomepageMotionScene};
1
+ import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./index-DHn0faN9.js";var w=e(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),T=e(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),E=x();function D(e){return{"--reveal":e}}function O(e,t,n){let r=(e,t)=>Number.parseInt(e.slice(t,t+2),16),i=i=>Math.round(r(e,i)+(r(t,i)-r(e,i))*n).toString(16).padStart(2,`0`);return`#${i(1)}${i(3)}${i(5)}`}function k(e){let t=r((e-p.runEnd)/(p.executionComplete-p.runEnd));return t+t*t-t*t*t}function A({progress:e,children:t,className:n=``}){return(0,E.jsx)(`div`,{className:`scene-reveal ${n}`,style:D(e),children:t})}function j({progress:e,author:t,avatar:n,tone:r,timestamp:i,online:a=!1,assets:o,children:s}){return(0,E.jsxs)(`article`,{className:`scene-message`,style:D(e),children:[(0,E.jsx)(`span`,{className:`scene-avatar is-${r} ${n===`tutti`?`is-tutti`:``} ${a?`is-online`:``}`,"aria-hidden":`true`,children:n===`tutti`?(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.tuttiAvatarSrc,alt:``}):(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.humanAvatars[n],alt:``})}),(0,E.jsxs)(`div`,{className:`scene-message-copy`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`strong`,{children:t}),(0,E.jsx)(`span`,{children:i})]}),(0,E.jsx)(`p`,{children:s})]})]})}function M({time:e,assets:r}){let i=e>=p.artifactLive,a=e>=p.artifactClick,o=e>=p.runEnd&&e<p.executionComplete,u=d(e,p.runEnd,19.2),f=d(e,p.artifactLive,30.92);return(0,E.jsxs)(`aside`,{className:`scene-sidebar`,children:[(0,E.jsx)(`button`,{className:`scene-brand`,type:`button`,"aria-label":`Tutti`,tabIndex:-1,children:(0,E.jsx)(`img`,{src:r.logoSrc,alt:``})}),(0,E.jsxs)(`div`,{className:`scene-nav-stack`,children:[(0,E.jsxs)(`nav`,{className:`scene-nav`,"aria-label":`Workspace pages`,children:[(0,E.jsx)(`button`,{className:a?``:`is-active`,type:`button`,"aria-label":`Chat`,tabIndex:-1,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Worklist`,tabIndex:-1,children:(0,E.jsx)(b,{"aria-hidden":`true`})}),(0,E.jsxs)(`button`,{className:a?`is-active`:``,type:`button`,"aria-label":`Artifacts`,tabIndex:-1,children:[(0,E.jsx)(l,{"aria-hidden":`true`}),i?(0,E.jsx)(`span`,{className:`scene-live-pill`,style:D(f),children:`Live`}):null]}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`References`,tabIndex:-1,children:(0,E.jsx)(C,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Skills`,tabIndex:-1,children:(0,E.jsx)(s,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Timeline`,tabIndex:-1,children:(0,E.jsx)(t,{"aria-hidden":`true`})})]}),o?(0,E.jsx)(`button`,{className:`scene-status-entry is-running`,style:D(u),type:`button`,"aria-label":`Task running`,tabIndex:-1,children:(0,E.jsx)(n,{"aria-hidden":`true`})}):null]}),(0,E.jsx)(`button`,{className:`scene-settings`,type:`button`,"aria-label":`Settings`,tabIndex:-1,children:(0,E.jsx)(h,{"aria-hidden":`true`})})]})}function N({time:e,assets:t}){let n=d(e,30.35,30.92);return(0,E.jsxs)(`section`,{className:`scene-panel scene-chat-panel`,children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h2`,{children:`Morrow Studio`}),(0,E.jsx)(`p`,{children:`Ceramics storefront`})]}),(0,E.jsxs)(`span`,{className:`scene-members`,"aria-hidden":`true`,children:[(0,E.jsx)(`i`,{className:`is-green`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.fey,alt:``})}),(0,E.jsx)(`i`,{className:`is-blue`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.avery,alt:``})}),(0,E.jsx)(`i`,{className:`is-yellow`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.jun,alt:``})})]})]}),(0,E.jsxs)(`div`,{className:`scene-chat-stream`,children:[(0,E.jsx)(j,{progress:d(e,1.35,2.05),author:`Fey`,avatar:`fey`,tone:`green`,timestamp:`10:12`,online:!0,assets:t,children:`🏺 Let's build an online shop for our ceramics studio.`}),(0,E.jsx)(j,{progress:d(e,2.65,3.35),author:`Avery`,avatar:`avery`,tone:`blue`,timestamp:`10:13`,online:!0,assets:t,children:`✨ Keep it warm, minimal, and editorial.`}),(0,E.jsx)(j,{progress:d(e,3.95,4.65),author:`Jun`,avatar:`jun`,tone:`yellow`,timestamp:`10:14`,online:!0,assets:t,children:`🎨 Let people preview every piece in different glazes.`}),(0,E.jsx)(j,{progress:d(e,5.25,5.95),author:`Tutti`,avatar:`tutti`,tone:`green`,timestamp:`10:15`,assets:t,children:`Got it — I'll put it together. ✨`}),(0,E.jsxs)(`article`,{className:`scene-task-result`,style:D(n),children:[(0,E.jsx)(`span`,{className:`scene-task-result-rail`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`scene-task-result-icon`,"aria-hidden":`true`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{children:`Task completed`}),(0,E.jsx)(`strong`,{children:`Build ceramics storefront`}),(0,E.jsx)(`small`,{children:`Storefront`}),(0,E.jsx)(`p`,{children:`Warm editorial shopping and glaze previews are ready in Artifacts.`})]}),(0,E.jsx)(i,{className:`scene-task-result-chevron`,"aria-hidden":`true`})]})]}),(0,E.jsxs)(`div`,{className:`scene-composer`,"aria-hidden":`true`,children:[(0,E.jsx)(`span`,{children:`Write a message`}),(0,E.jsx)(T,{})]})]})}function P({progress:e,icon:t,children:n}){return(0,E.jsxs)(`div`,{className:`scene-scratchpad-row`,style:D(e),children:[(0,E.jsx)(`span`,{"aria-hidden":`true`,children:t}),(0,E.jsx)(`p`,{children:n})]})}function F({time:e}){return(0,E.jsxs)(`section`,{className:`scene-panel scene-scratchpad-panel`,style:{"--scratchpad-collapse":d(e,p.runEnd,19.18)},children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(v,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Scratchpad`})]}),(0,E.jsxs)(`div`,{className:`scene-scratchpad-body`,children:[(0,E.jsxs)(A,{progress:d(e,8.95,10),className:`scene-scratchpad-intro`,children:[(0,E.jsx)(`h3`,{children:`Ceramics storefront`}),(0,E.jsx)(`p`,{children:`A warm, editorial storefront for a small-batch studio, centered on tactile product discovery.`})]}),(0,E.jsx)(A,{progress:d(e,9.85,10.65),className:`scene-scratchpad-label`,children:`Confirmed`}),(0,E.jsx)(P,{progress:d(e,10.4,11.25),icon:(0,E.jsx)(S,{}),children:`Product-first editorial layout with generous space`}),(0,E.jsx)(P,{progress:d(e,11.2,12.05),icon:(0,E.jsx)(S,{}),children:`Warm neutrals with quiet serif headlines`}),(0,E.jsx)(P,{progress:d(e,12,12.85),icon:(0,E.jsx)(S,{}),children:`Keep the collection small, curated, and story-led`}),(0,E.jsx)(A,{progress:d(e,12.75,13.55),className:`scene-scratchpad-label`,children:`Requested feature`}),(0,E.jsx)(P,{progress:d(e,13.3,14.2),icon:(0,E.jsx)(o,{}),children:`Preview every piece in clay, sage, and ink glazes`})]}),(0,E.jsxs)(`footer`,{className:`scene-scratchpad-footer`,style:D(d(e,15.7,16.8)),children:[(0,E.jsxs)(`span`,{className:`scene-writing-mark`,children:[(0,E.jsx)(`strong`,{children:`Updated`}),(0,E.jsx)(`span`,{children:`just now`})]}),(0,E.jsxs)(`button`,{className:`scene-run-button`,type:`button`,tabIndex:-1,children:[(0,E.jsx)(f,{"aria-hidden":`true`}),(0,E.jsx)(`span`,{children:`Run`})]})]})]})}function I(e,t){let n=Math.max(0,Math.floor((e-t)*50/5)*5);return`${Math.floor(n/60)}m${(n%60).toString().padStart(2,`0`)}s`}function L({time:e,scoreSrc:t}){let r=d(e,18.92,19.2),i=_(e),a=i.id===`complete`,o={prepare:p.runEnd,implement:p.executionPrepareEnd,validate:p.executionImplementEnd,update:p.executionValidateEnd,complete:p.executionComplete}[i.id],s=d(e,o,o+.32),c=k(e);return(0,E.jsx)(`div`,{className:`scene-execution`,style:{"--reveal":r,"--stage-reveal":s},children:(0,E.jsxs)(`article`,{className:`homepage-motion-panel homepage-motion-execution-panel homepage-motion-execution-card is-score-${a?`complete`:`running`}`,children:[(0,E.jsx)(`header`,{className:`homepage-motion-panel-header`,children:(0,E.jsxs)(`div`,{className:`homepage-motion-panel-title`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,"aria-hidden":`true`,children:(0,E.jsx)(y,{})}),(0,E.jsx)(`h3`,{children:`Tutti is working on`})]})}),(0,E.jsxs)(`div`,{className:`homepage-motion-execution-body`,children:[(0,E.jsxs)(`div`,{className:`homepage-motion-execution-step homepage-motion-execution-stage is-${a?`complete`:`running`} has-marker`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-marker ${a?`is-done`:`is-running`}`,"aria-hidden":`true`,children:a?(0,E.jsx)(S,{}):(0,E.jsx)(n,{})}),(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-content homepage-motion-execution-stage-copy`,children:(0,E.jsxs)(`span`,{className:`homepage-motion-execution-step-title`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-label`,children:i.label}),a?null:(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-elapsed`,children:` (${I(e,o)})`})]})},i.id)]}),(0,E.jsx)(`div`,{className:`homepage-motion-running-score ${a?`is-complete`:``}`,role:`img`,"aria-label":`Ode to Joy score phrase`,children:(0,E.jsx)(`div`,{className:`homepage-motion-score-passage`,style:{"--score-translate-x":`${-395.3*c}px`},"aria-hidden":`true`,children:(0,E.jsx)(`img`,{src:t,alt:``,draggable:!1})})})]})]})})}function R({color:e,variant:t=`vase`,className:n=``}){let r={"--ceramic-color":e};return t===`cup`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-cup ${n}`,viewBox:`0 0 260 260`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M54 64h132l-9 126c-2 26-20 42-46 42h-22c-26 0-44-16-46-42Z`}),(0,E.jsx)(`path`,{className:`ceramic-outline`,d:`M186 92h18c34 0 34 72 1 76h-27`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`120`,cy:`64`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M78 90c5 62 4 91 20 114`})]}):t===`bowl`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-bowl ${n}`,viewBox:`0 0 300 220`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`150`,cy:`55`,rx:`116`,ry:`24`}),(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M34 55c8 82 45 132 116 132S258 137 266 55c-42 25-190 25-232 0Z`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M72 82c18 45 40 70 70 82`}),(0,E.jsx)(`path`,{className:`ceramic-base`,d:`M112 185h76`})]}):(0,E.jsxs)(`svg`,{className:`ceramic-object is-vase ${n}`,viewBox:`0 0 320 420`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M116 56c7 38-17 61-36 96-31 56-28 157 5 199 33 42 117 42 150 0 33-42 36-143 5-199-19-35-43-58-36-96Z`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`160`,cy:`56`,rx:`44`,ry:`12`}),(0,E.jsx)(`ellipse`,{className:`ceramic-base`,cx:`160`,cy:`365`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M108 153c-25 64-23 145 1 185`})]})}function z({time:e}){let t=d(e,p.artifactClick,33.25),n=d(e,34.25,34.52),r=d(e,34.88,35.15),i=d(e,35.55,35.82),a=g(e),o=O(`#d9cbb4`,`#c56f4f`,n);e>=34.88&&(o=O(`#c56f4f`,`#6f9275`,r)),e>=35.55&&(o=O(`#6f9275`,`#243a46`,i));let s=e>=35.55?`ink`:e>=34.88?`sage`:e>=34.25?`clay`:null,c={"--artifact-scroll":a};return(0,E.jsxs)(`section`,{className:`scene-panel scene-artifact-panel`,style:D(t),children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(l,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Artifacts`}),(0,E.jsx)(`span`,{className:`scene-ready-tag`,children:`Ready`})]}),(0,E.jsx)(`div`,{className:`scene-artifact-canvas`,children:(0,E.jsxs)(`div`,{className:`artifact-page-frame`,style:c,children:[(0,E.jsxs)(`div`,{className:`artifact-page-nav`,children:[(0,E.jsx)(`strong`,{children:`Morrow`}),(0,E.jsx)(`span`,{children:`Objects · Journal · Studio`})]}),(0,E.jsxs)(`section`,{className:`artifact-hero`,children:[(0,E.jsxs)(`div`,{className:`artifact-hero-copy`,children:[(0,E.jsx)(`span`,{className:`artifact-eyebrow`,children:`Hand-finished in small batches`}),(0,E.jsx)(`h3`,{children:`Objects for slower days.`}),(0,E.jsx)(`p`,{children:`Quiet forms, warm glazes, and useful pieces made to live with.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Explore the collection`})]}),(0,E.jsxs)(`div`,{className:`artifact-hero-object`,children:[(0,E.jsx)(R,{color:o}),(0,E.jsxs)(`div`,{className:`artifact-glaze-picker`,"aria-label":`Glaze preview`,children:[(0,E.jsx)(`span`,{children:`Glaze`}),(0,E.jsx)(`i`,{className:s===`clay`?`is-active is-clay`:`is-clay`}),(0,E.jsx)(`i`,{className:s===`sage`?`is-active is-sage`:`is-sage`}),(0,E.jsx)(`i`,{className:s===`ink`?`is-active is-ink`:`is-ink`})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-collection`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`span`,{children:`Selected pieces`}),(0,E.jsx)(`p`,{children:`Everyday forms shaped for the rituals around them.`})]}),(0,E.jsxs)(`div`,{className:`artifact-product-grid`,children:[(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#b9785f`,variant:`cup`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Low cup`}),(0,E.jsx)(`span`,{children:`Rust glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#819283`,variant:`vase`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Field vase`}),(0,E.jsx)(`span`,{children:`Sage glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#d5c7af`,variant:`bowl`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Gather bowl`}),(0,E.jsx)(`span`,{children:`Flax glaze`})]})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-studio`,children:[(0,E.jsx)(`span`,{children:`Made by hand · Meant for every day`}),(0,E.jsx)(`h3`,{children:`Useful things can still feel special.`}),(0,E.jsx)(`p`,{children:`We make a small number of considered objects, slowly and close to home.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Visit the studio`})]}),(0,E.jsxs)(`footer`,{className:`artifact-page-footer`,children:[(0,E.jsx)(`strong`,{children:`Morrow Ceramics`}),(0,E.jsx)(`span`,{className:`artifact-built-with`,children:`Built with Tutti.`}),(0,E.jsx)(`span`,{children:`Small batch · Est. 2026`})]})]})})]})}function B(e,t,n){return e+(t-e)*n}function V(e,t,n,r,i){let a=d(e,t,n,m);return{x:B(r.x,i.x,a),y:B(r.y,i.y,a)}}function H(e,t,n){return e<t||e>n?0:Math.sin(Math.PI*((e-t)/(n-t)))}function U(e){if(e>=p.runCursorStart&&e<18.92){let t=V(e,p.runCursorStart,p.runCursorArrive,{x:86,y:76},{x:94.25,y:94.2});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,p.runClickStart,p.runEnd)}}if(e>=31&&e<33.45){let t=V(e,31,32.22,{x:50,y:58},{x:4,y:22.85});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,32.28,32.6)}}return{visible:!1,x:50,y:50,clickPulse:0}}function W({time:e,assets:t}){let n=u(e),r=U(e),i=a(e),o=d(e,.08,1.05,m);return(0,E.jsx)(`div`,{className:`motion-scene`,role:`img`,"aria-label":`Tutti workflow animation from team discussion to a generated ceramics storefront`,style:{opacity:i,visibility:i<=.001?`hidden`:`visible`},children:(0,E.jsxs)(`div`,{className:`motion-stage`,style:{opacity:o,transform:`translate(50%, 50%) scale(${n.scale}) translate(${-n.centerX*100}%, ${-n.centerY*100}%)`},children:[(0,E.jsx)(M,{time:e,assets:t}),(0,E.jsxs)(`div`,{className:`scene-workspace-layer`,children:[(0,E.jsx)(N,{time:e,assets:t}),(0,E.jsx)(F,{time:e}),(0,E.jsx)(L,{time:e,scoreSrc:t.scoreSrc})]}),(0,E.jsx)(z,{time:e}),(0,E.jsxs)(`span`,{className:`scene-cursor ${r.visible?`is-visible`:``}`,style:{left:`${r.x}%`,top:`${r.y}%`,"--click-pulse":r.clickPulse},"aria-hidden":`true`,children:[(0,E.jsx)(w,{}),(0,E.jsx)(`i`,{})]})]})})}export{W as HomepageMotionScene};