@xfey/tutti 0.1.128 → 0.1.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat-assistant/diagnostics.d.ts +10 -1
- package/dist/chat-assistant/failure-messages.d.ts +4 -0
- package/dist/chat-assistant/failure-messages.js +57 -0
- package/dist/chat-assistant/failures.d.ts +16 -16
- package/dist/chat-assistant/failures.js +24 -80
- package/dist/chat-assistant/index.d.ts +4 -2
- package/dist/chat-assistant/index.js +33 -8
- package/dist/chat-assistant/language-context.d.ts +2 -0
- package/dist/chat-assistant/language-context.js +17 -14
- package/dist/chat-assistant/requests.d.ts +5 -1
- package/dist/chat-assistant/requests.js +9 -3
- package/dist/collaboration-state/context-sync-attempts.d.ts +9 -0
- package/dist/collaboration-state/context-sync-attempts.js +13 -0
- package/dist/communication-language/notice-locale.d.ts +4 -0
- package/dist/communication-language/notice-locale.js +14 -0
- package/dist/control-plane/context-sync-completion.d.ts +7 -0
- package/dist/control-plane/context-sync-completion.js +27 -0
- package/dist/control-plane/context-sync.d.ts +1 -0
- package/dist/control-plane/context-sync.js +23 -0
- package/dist/control-plane/index.d.ts +13 -4
- package/dist/control-plane/index.js +30 -23
- package/dist/control-plane/types.d.ts +2 -0
- package/dist/providers/invocation-progress.d.ts +6 -0
- package/dist/providers/invocation-progress.js +24 -0
- package/dist/providers/openai/app-server/read-only-procedure.js +1 -0
- package/dist/providers/openai/chat-assistant.js +2 -1
- package/dist/server-shell/cli/host-server-runtime.js +4 -1
- package/migrations/0026_context_sync_and_chat_locale.sql +12 -0
- package/migrations/README.md +2 -2
- package/package.json +1 -1
- package/web/assets/{homepage-motion-scene-BcMt0AVW.js → homepage-motion-scene-BHhw4CfM.js} +1 -1
- package/web/assets/{index-2eX37Jx6.js → index-5COc1Yku.js} +2 -2
- package/web/index.html +1 -1
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { type ActivityRef, type ClarificationRoundRef, type IdempotencyKey, type TaskId, type WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
2
2
|
import type { TrustedCollaborationAuthor } from "../collaboration-ingestion/types.js";
|
|
3
|
+
import type { WorkflowKind } from "@tutti/shared/domain";
|
|
3
4
|
import type { ExecutionStatusProjection, MessageProjection, ContextSyncDisposition, ContextSyncResult, RefreshScratchpadDisposition, RefreshScratchpadResult, RunSchedulerNowDisposition, RunSchedulerNowPayload, RetryTaskDisposition, RetryTaskPayload, RefreshReferenceSummariesDisposition, RefreshReferenceSummariesPayload, RefreshReferenceSummariesResult, SendClarificationRoundMessageDisposition, SendClarificationRoundMessagePayload, SendClarificationRoundMessageResult, SubmitClarificationRoundDisposition, SubmitClarificationRoundPayload, SubmitClarificationRoundResult, SubmitWorklistDisposition, SubmitWorklistPayload, SubmitWorklistResult, ProcedureLane } from "@tutti/shared/schemas/api";
|
|
4
|
-
import type { ContextSyncWorkflowTrigger } from "./workflows/index.js";
|
|
5
5
|
import type { ControlPlaneCommandResult, Phase5ControlPlaneOptions, StartupRecoveryOptions, StartupRecoveryResult } from "./types.js";
|
|
6
6
|
import { type ProjectBriefRefreshReason, type RefreshProjectBriefProjectionResult } from "./project-brief-refresh.js";
|
|
7
|
+
type ActiveActivity = {
|
|
8
|
+
activity_ref: ActivityRef;
|
|
9
|
+
activity_kind: "run" | "procedure";
|
|
10
|
+
lane?: ProcedureLane;
|
|
11
|
+
workflow_kind?: WorkflowKind;
|
|
12
|
+
workflow_ref?: WorkflowInvocationRef;
|
|
13
|
+
};
|
|
7
14
|
export type { ControlPlaneCommandResult, ControlPlaneLogger, Phase5ControlPlaneOptions, RunCorrectionContext, RunContinuationContext, RunDispatchContext, RunDispatchTrigger, RunPipelineInput, RunPipelineResolution, RunPipelineResolver, RunPipelineResult, RunPipelineRunner, StartupRecoveryOptions, StartupRecoveryResult, TrustedHumanAuthor, } from "./types.js";
|
|
8
15
|
export declare class Phase5ControlPlane {
|
|
9
16
|
private readonly engine;
|
|
@@ -14,6 +21,7 @@ export declare class Phase5ControlPlane {
|
|
|
14
21
|
private readonly resolveRunPipeline;
|
|
15
22
|
private readonly readMainlineStatus;
|
|
16
23
|
private readonly readActiveApproval;
|
|
24
|
+
private readonly hasPendingChatRequests;
|
|
17
25
|
private readonly logger;
|
|
18
26
|
private readonly projectContext;
|
|
19
27
|
private readonly runLifecycle;
|
|
@@ -46,9 +54,10 @@ export declare class Phase5ControlPlane {
|
|
|
46
54
|
}): Promise<RefreshProjectBriefProjectionResult>;
|
|
47
55
|
beginShutdown(): void;
|
|
48
56
|
dispose(): Promise<void>;
|
|
49
|
-
waitForRepoInspectionIdle(): Promise<void>;
|
|
57
|
+
waitForRepoInspectionIdle(onBlocked?: (blocker: ActiveActivity) => void): Promise<void>;
|
|
50
58
|
startTaskCompile(payload: SubmitWorklistPayload): ControlPlaneCommandResult<SubmitWorklistDisposition, SubmitWorklistResult>;
|
|
51
|
-
startContextSyncAnalysis(
|
|
59
|
+
startContextSyncAnalysis(): ControlPlaneCommandResult<ContextSyncDisposition, ContextSyncResult>;
|
|
60
|
+
private startContextSync;
|
|
52
61
|
startReferenceSummaryRefresh(payload?: RefreshReferenceSummariesPayload): ControlPlaneCommandResult<RefreshReferenceSummariesDisposition, RefreshReferenceSummariesResult>;
|
|
53
62
|
private tryStartPendingReferenceSummaryRefresh;
|
|
54
63
|
sendClarificationRoundMessage(roundId: ClarificationRoundRef, payload: SendClarificationRoundMessagePayload, author: TrustedCollaborationAuthor): ControlPlaneCommandResult<SendClarificationRoundMessageDisposition, SendClarificationRoundMessageResult>;
|
|
@@ -71,7 +80,7 @@ export declare class Phase5ControlPlane {
|
|
|
71
80
|
private handleRunTerminalTransition;
|
|
72
81
|
private tryRunTaskArrivalScheduler;
|
|
73
82
|
private maybeScheduleAfterRunCompletion;
|
|
74
|
-
|
|
83
|
+
notifyChatRequestsChanged(): void;
|
|
75
84
|
private scheduleContextSyncAfterWorklistCompletion;
|
|
76
85
|
private attemptContextSyncAfterWorklistCompletion;
|
|
77
86
|
private cancelPendingWorklistCompletionContextSync;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { readActiveClarificationProjection, readActiveTaskCompileContext, markScratchpadRefreshSucceeded, readPendingTaskCompileSubmission, readTaskDetailProjection, readTaskProjectionByActivityRef, readScratchpadSourceState,
|
|
1
|
+
import { readActiveClarificationProjection, readActiveTaskCompileContext, markScratchpadRefreshSucceeded, readPendingTaskCompileSubmission, readTaskDetailProjection, readTaskProjectionByActivityRef, readScratchpadSourceState, } from "../collaboration-state/index.js";
|
|
2
2
|
import { ProcedureEngine } from "../procedure-engine/index.js";
|
|
3
3
|
import { RunEngine } from "../run-engine/index.js";
|
|
4
4
|
import { WorkspaceOpsError, isReferenceFilePath, readReferenceSummaryTargets, } from "../workspace-ops/index.js";
|
|
5
5
|
import { publishProcedureTransition as publishProcedureTransitionEvent, publishRunResultRecorded as publishRunResultRecordedEvent, publishRunTransition as publishRunTransitionEvent, publishTaskRunStarted as publishTaskRunStartedEvent, } from "./event-publishers.js";
|
|
6
6
|
import { startContextSyncAnalysisProcedure } from "./context-sync.js";
|
|
7
|
+
import { pendingContextSyncCompletion } from "./context-sync-completion.js";
|
|
7
8
|
import { refreshProjectBriefProjection, } from "./project-brief-refresh.js";
|
|
8
9
|
import { startReferenceSummaryRefreshProcedure } from "./reference-summary-refresh.js";
|
|
9
10
|
import { runControlPlaneStartupRecovery } from "./startup-recovery.js";
|
|
@@ -30,6 +31,7 @@ export class Phase5ControlPlane {
|
|
|
30
31
|
resolveRunPipeline;
|
|
31
32
|
readMainlineStatus;
|
|
32
33
|
readActiveApproval;
|
|
34
|
+
hasPendingChatRequests;
|
|
33
35
|
logger;
|
|
34
36
|
projectContext;
|
|
35
37
|
runLifecycle;
|
|
@@ -53,6 +55,7 @@ export class Phase5ControlPlane {
|
|
|
53
55
|
this.resolveRunPipeline = options.resolveRunPipeline;
|
|
54
56
|
this.readMainlineStatus = options.readMainlineStatus;
|
|
55
57
|
this.readActiveApproval = options.readActiveApproval;
|
|
58
|
+
this.hasPendingChatRequests = options.hasPendingChatRequests ?? (() => false);
|
|
56
59
|
this.logger = options.logger;
|
|
57
60
|
this.projectContext = options.projectContext;
|
|
58
61
|
this.runLifecycle = options.runLifecycle;
|
|
@@ -177,13 +180,17 @@ export class Phase5ControlPlane {
|
|
|
177
180
|
this.beginShutdown();
|
|
178
181
|
return this.waitForIdle();
|
|
179
182
|
}
|
|
180
|
-
async waitForRepoInspectionIdle() {
|
|
183
|
+
async waitForRepoInspectionIdle(onBlocked) {
|
|
181
184
|
for (;;) {
|
|
182
185
|
const waits = [];
|
|
183
|
-
|
|
186
|
+
const run = this.readActiveRun();
|
|
187
|
+
const procedure = this.readActiveForegroundProcedure();
|
|
188
|
+
if (run !== null) {
|
|
189
|
+
onBlocked?.(run);
|
|
184
190
|
waits.push(this.runEngine.waitForIdle());
|
|
185
191
|
}
|
|
186
|
-
if (
|
|
192
|
+
if (procedure !== null) {
|
|
193
|
+
onBlocked?.(procedure);
|
|
187
194
|
waits.push(this.engine.waitForLaneIdle("foreground"));
|
|
188
195
|
}
|
|
189
196
|
if (waits.length === 0) {
|
|
@@ -233,15 +240,17 @@ export class Phase5ControlPlane {
|
|
|
233
240
|
shouldContinue: () => !this.closing,
|
|
234
241
|
});
|
|
235
242
|
}
|
|
236
|
-
startContextSyncAnalysis(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
243
|
+
startContextSyncAnalysis() {
|
|
244
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
245
|
+
return this.startContextSync({ kind: "manual" });
|
|
246
|
+
}
|
|
247
|
+
startContextSync(trigger, completionBatchKey) {
|
|
240
248
|
return startContextSyncAnalysisProcedure({
|
|
241
249
|
engine: this.engine,
|
|
242
250
|
store: this.store,
|
|
243
251
|
events: this.events,
|
|
244
252
|
trigger,
|
|
253
|
+
...(completionBatchKey === undefined ? {} : { completionBatchKey }),
|
|
245
254
|
resolveWorkflowRunner: this.resolveWorkflowRunner,
|
|
246
255
|
readActiveActivity: () => this.readSchedulerBlocker(),
|
|
247
256
|
projectContext: this.projectContext,
|
|
@@ -544,17 +553,13 @@ export class Phase5ControlPlane {
|
|
|
544
553
|
}
|
|
545
554
|
this.scheduleContextSyncAfterWorklistCompletion();
|
|
546
555
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
kind: "worklist_all_tasks_completed",
|
|
555
|
-
completed_task_count: tasks.length,
|
|
556
|
-
module_count: worklist.modules.length,
|
|
557
|
-
};
|
|
556
|
+
notifyChatRequestsChanged() {
|
|
557
|
+
if (this.closing || !this.store.db.open)
|
|
558
|
+
return;
|
|
559
|
+
if (this.hasPendingChatRequests())
|
|
560
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
561
|
+
else
|
|
562
|
+
this.scheduleContextSyncAfterWorklistCompletion();
|
|
558
563
|
}
|
|
559
564
|
scheduleContextSyncAfterWorklistCompletion() {
|
|
560
565
|
if (this.closing ||
|
|
@@ -563,7 +568,8 @@ export class Phase5ControlPlane {
|
|
|
563
568
|
return;
|
|
564
569
|
}
|
|
565
570
|
const sourceState = readScratchpadSourceState(this.store.db);
|
|
566
|
-
if (this.
|
|
571
|
+
if (pendingContextSyncCompletion(this.store.db) === undefined ||
|
|
572
|
+
this.hasPendingChatRequests() ||
|
|
567
573
|
sourceState.dirty_since !== undefined ||
|
|
568
574
|
sourceState.in_flight !== undefined ||
|
|
569
575
|
this.readSchedulerBlocker() !== null) {
|
|
@@ -579,15 +585,16 @@ export class Phase5ControlPlane {
|
|
|
579
585
|
if (this.closing || !this.store.db.open) {
|
|
580
586
|
return;
|
|
581
587
|
}
|
|
582
|
-
const
|
|
588
|
+
const completion = pendingContextSyncCompletion(this.store.db);
|
|
583
589
|
const sourceState = readScratchpadSourceState(this.store.db);
|
|
584
|
-
if (
|
|
590
|
+
if (completion === undefined ||
|
|
591
|
+
this.hasPendingChatRequests() ||
|
|
585
592
|
sourceState.dirty_since !== undefined ||
|
|
586
593
|
sourceState.in_flight !== undefined ||
|
|
587
594
|
this.readSchedulerBlocker() !== null) {
|
|
588
595
|
return;
|
|
589
596
|
}
|
|
590
|
-
void this.
|
|
597
|
+
void this.startContextSync(completion.trigger, completion.key);
|
|
591
598
|
}
|
|
592
599
|
cancelPendingWorklistCompletionContextSync() {
|
|
593
600
|
if (this.pendingWorklistCompletionContextSyncTimer === null) {
|
|
@@ -17,6 +17,8 @@ export type Phase5ControlPlaneOptions = {
|
|
|
17
17
|
mainline_clean: boolean;
|
|
18
18
|
};
|
|
19
19
|
readActiveApproval?: () => ActiveApprovalProjection;
|
|
20
|
+
/** Read-only Chat owner signal; does not merge Chat into the workflow state machine. */
|
|
21
|
+
hasPendingChatRequests?: () => boolean;
|
|
20
22
|
logger?: ControlPlaneLogger;
|
|
21
23
|
projectContext?: {
|
|
22
24
|
workspaceRoot: string;
|
|
@@ -3,8 +3,14 @@ export type ProviderInvocationProgress = {
|
|
|
3
3
|
invocation_ref?: string;
|
|
4
4
|
skill_count?: number;
|
|
5
5
|
completed_tool_count?: number;
|
|
6
|
+
turn_timeout_ms?: number;
|
|
7
|
+
notification_count?: number;
|
|
8
|
+
server_request_count?: number;
|
|
9
|
+
last_activity_age_ms?: number;
|
|
6
10
|
reason_code?: "provider_unavailable" | "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "file_read_not_observed" | "write_detected" | "secret_leak_detected" | "process_lifecycle_failed" | "admission_unavailable";
|
|
7
11
|
};
|
|
8
12
|
export type ProviderInvocationProgressObserver = (event: ProviderInvocationProgress) => void;
|
|
13
|
+
/** Copy only finite counters. Do not forward raw error details/methods/prose. */
|
|
14
|
+
export declare function providerInvocationFailureCounters(error: unknown, now?: number): Partial<ProviderInvocationProgress>;
|
|
9
15
|
export declare function reportProviderInvocationProgress(observer: ProviderInvocationProgressObserver | undefined, event: ProviderInvocationProgress): void;
|
|
10
16
|
//# sourceMappingURL=invocation-progress.d.ts.map
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/** Copy only finite counters. Do not forward raw error details/methods/prose. */
|
|
2
|
+
export function providerInvocationFailureCounters(error, now = Date.now()) {
|
|
3
|
+
if (typeof error !== "object" || error === null || !("details" in error))
|
|
4
|
+
return {};
|
|
5
|
+
const details = error.details;
|
|
6
|
+
if (typeof details !== "object" || details === null)
|
|
7
|
+
return {};
|
|
8
|
+
const source = details;
|
|
9
|
+
const counters = {};
|
|
10
|
+
for (const key of ["turn_timeout_ms", "notification_count", "completed_tool_count"]) {
|
|
11
|
+
const value = source[key];
|
|
12
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0)
|
|
13
|
+
counters[key] = value;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(source.server_request_methods))
|
|
16
|
+
counters.server_request_count = source.server_request_methods.length;
|
|
17
|
+
if (typeof source.last_activity_at === "string" &&
|
|
18
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(source.last_activity_at)) {
|
|
19
|
+
const age = now - Date.parse(source.last_activity_at);
|
|
20
|
+
if (Number.isSafeInteger(age) && age >= 0)
|
|
21
|
+
counters.last_activity_age_ms = age;
|
|
22
|
+
}
|
|
23
|
+
return counters;
|
|
24
|
+
}
|
|
1
25
|
export function reportProviderInvocationProgress(observer, event) {
|
|
2
26
|
try {
|
|
3
27
|
observer?.(event);
|
|
@@ -55,6 +55,7 @@ function readOnlyTimeoutDetails(input) {
|
|
|
55
55
|
const details = {
|
|
56
56
|
turn_timeout_ms: input.turnTimeoutMs,
|
|
57
57
|
notification_count: input.client.notifications.length,
|
|
58
|
+
completed_tool_count: structuredOutputDetails(input.client, "").completed_tool_count ?? 0,
|
|
58
59
|
server_request_methods: input.client.serverRequests.map(extractServerRequestMethod),
|
|
59
60
|
notification_methods: input.client.notifications
|
|
60
61
|
.map((notification) => notification.method)
|
|
@@ -3,7 +3,7 @@ import { readOpenAiApiKeyCredential } from "./credential-store.js";
|
|
|
3
3
|
import { resolveOpenAiProviderConfig } from "./provider-config.js";
|
|
4
4
|
import { openAiCredentialAccess, } from "./execution-access.js";
|
|
5
5
|
import { CodexAppServerReadOnlyProcedureError, runCodexAppServerReadOnlyProcedure, } from "./app-server/read-only-procedure.js";
|
|
6
|
-
import { reportProviderInvocationProgress } from "../invocation-progress.js";
|
|
6
|
+
import { reportProviderInvocationProgress, providerInvocationFailureCounters, } from "../invocation-progress.js";
|
|
7
7
|
import { getProjectUserSkillsRoot } from "../../skills/index.js";
|
|
8
8
|
export function createOpenAiReadOnlyChatAssistantModel(options) {
|
|
9
9
|
return {
|
|
@@ -42,6 +42,7 @@ export function createOpenAiReadOnlyChatAssistantModel(options) {
|
|
|
42
42
|
: { onLifecycleIncident: options.onLifecycleIncident }),
|
|
43
43
|
}).catch((error) => {
|
|
44
44
|
reportProviderInvocationProgress(input.onProgress, {
|
|
45
|
+
...providerInvocationFailureCounters(error),
|
|
45
46
|
stage: "provider_failed",
|
|
46
47
|
reason_code: error instanceof CodexAppServerReadOnlyProcedureError
|
|
47
48
|
? error.code
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { basename, join } from "node:path";
|
|
2
|
+
import { hasPendingChatRequests } from "../../chat-assistant/requests.js";
|
|
2
3
|
import { MAX_PROVIDER_MODEL_NAME_LENGTH, } from "@tutti/shared/schemas/api";
|
|
3
4
|
import { serializeRuntimeLogLine } from "@tutti/shared/utils";
|
|
4
5
|
import { completeRelayUpload, deliverRelayPlatformOutbound, RelayHostControlClientError, resolveRelayUpload, } from "@tutti/relay-client";
|
|
@@ -397,6 +398,7 @@ export async function startForegroundHostServer(options) {
|
|
|
397
398
|
events: workspaceEvents,
|
|
398
399
|
now,
|
|
399
400
|
logger: controlPlaneLogger,
|
|
401
|
+
hasPendingChatRequests: () => hasPendingChatRequests(store.db),
|
|
400
402
|
projectContext,
|
|
401
403
|
runLifecycle: {
|
|
402
404
|
started: () => artifactPreviewManager.beginWorkspaceUpdate(),
|
|
@@ -471,7 +473,8 @@ export async function startForegroundHostServer(options) {
|
|
|
471
473
|
return await resolution.model.answer(input);
|
|
472
474
|
},
|
|
473
475
|
},
|
|
474
|
-
waitForInspectionAvailability: () => controlPlane.waitForRepoInspectionIdle(),
|
|
476
|
+
waitForInspectionAvailability: (onBlocked) => controlPlane.waitForRepoInspectionIdle(onBlocked),
|
|
477
|
+
onRequestsChanged: () => controlPlane.notifyChatRequestsChanged(),
|
|
475
478
|
onScratchpadSourceChanged: (message) => controlPlane.notifyScratchpadSourceChanged(message),
|
|
476
479
|
...(platformOutboundCoordinator === undefined
|
|
477
480
|
? {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- A started automatic maintenance attempt is not automatically replayable.
|
|
2
|
+
-- Keys refer to task/result identities, not mutable repository HEAD or chat.
|
|
3
|
+
CREATE TABLE context_sync_completion_attempts (
|
|
4
|
+
batch_key TEXT PRIMARY KEY NOT NULL,
|
|
5
|
+
workflow_ref TEXT NOT NULL UNIQUE,
|
|
6
|
+
started_at TEXT NOT NULL
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
-- Static failure notices retain their language across queueing and recovery.
|
|
10
|
+
-- Older requests have no captured preference and retain the English fallback.
|
|
11
|
+
ALTER TABLE chat_requests ADD COLUMN notice_locale TEXT NOT NULL DEFAULT 'en'
|
|
12
|
+
CHECK (notice_locale IN ('en', 'zh-Hans', 'zh-Hant'));
|
package/migrations/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
## 当前 migrations
|
|
15
15
|
|
|
16
|
-
后续 `0021`/`0022`/`0023` 分别增加外部读取证据、clarification 投影 cursor 和协作语言 metadata。`0024_chat_requests.sql` 为普通 Chat 增加持久 FIFO、状态/阶段 CHECK、attempt/revision、原始与回复 message FK;不回填历史提问,不保存正文/prompt
|
|
16
|
+
后续 `0021`/`0022`/`0023` 分别增加外部读取证据、clarification 投影 cursor 和协作语言 metadata。`0024_chat_requests.sql` 为普通 Chat 增加持久 FIFO、状态/阶段 CHECK、attempt/revision、原始与回复 message FK;不回填历史提问,不保存正文/prompt。`0025_task_compile_requests.sql` 增加 Submit identity/明确关闭证据、command 关联、外部授权 requirement 与 Chat attempt→invocation 关联;仅回填 live pending/captured submission,不重建历史状态/command,不复制 token 或授权状态。最新 `0026_context_sync_and_chat_locale.sql` 新增自动整理 batch/workflow/start attempt 记录(不回填历史),以及 Chat 内部有限 notice locale(旧行默认英文,不改状态或 revision)。恢复仍由原 owner 负责,见 [请求状态与恢复](../../../docs/system/request-status-and-recovery.md)。
|
|
17
17
|
|
|
18
18
|
- `0001_init.sql`:初始化本地 `tutti.sqlite`,包含协作 truth records、store metadata、command idempotency、clarification replay hint、索引和关键 trigger。
|
|
19
19
|
- `0002_allow_sealed_round_successor_note.sql`:允许 Control Plane 在 sealed clarification round 内追加只读 Tutti successor 结论消息,同时继续禁止人类补充消息写入 sealed round。
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
## 当前实现状态
|
|
40
40
|
|
|
41
|
-
- 当前 Host migrations 已到 `
|
|
41
|
+
- 当前 Host migrations 已到 `0026_context_sync_and_chat_locale.sql`,后续表的 owner 见上方说明。`0014` 明确采用开发数据库重建策略,不提供旧 Scratchpad source/cursor 数据兼容;`0016`–`0017`不回填既有 internal Chat message/agent response 的 external mapping/outbound intent,`0018`保留旧 intent 并阻止历史 status 回填,`0019`无损加入 structured card content,`0020`加入独立 managed Reference recovery checkpoint;`0024`不回填历史 Chat 请求,`0025`只回填 live submission identity,`0026`不推断旧任务已完成过文档检查。
|
|
42
42
|
- SQLite adapter、migration runner、checksum 校验、store metadata 初始化、transaction helper 与 command recovery scan helper 已实现。
|
|
43
43
|
- 协作 repository 与 Control Plane 已实现第一批业务读写;Phase 7 首批已复用 `0001_init.sql` 中的 `tasks.latest_run_result_id`、`task_details.result_json` 与 `run_results` 表完成 Run result / checks / promotion 摘要持久化。Control Plane recovery resolver 与 task-bound continuation / retry 复用现有 schema;新 Run 的 accepted checkpoint 业务 truth 继续写入最终 Run result / task detail result,Git tag / commit trailer 承担 crash recovery evidence。Timeline 默认从 `tasks`、`run_results` 与历史主群聊 `refs.worklist_feedback` 投影任务级审计节点,当前 task terminal Chat feedback 写入 `refs.task_result` 消息;`project_timeline_events` 只保留缺少稳定 record 的轻量可观测性事件和历史 reconcile 兼容记录。project workspace、working diff 与 ignored runtime state 都不进入 SQLite truth。`provider_usage_events` 只保存 token 计数、调用来源、模型名、记录时间和可空 anchor,不保存 provider secret、prompt 或 raw response。store 基础设施本身已经可以创建并迁移 `tutti.sqlite`。
|
|
44
44
|
|
package/package.json
CHANGED
|
@@ -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-2eX37Jx6.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-5COc1Yku.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};
|