@mindstudio-ai/remy 0.1.242 → 0.1.244

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/headless.js CHANGED
@@ -557,24 +557,31 @@ function getOrgContext() {
557
557
  function renderOrgContextBlock() {
558
558
  const ctx = cached;
559
559
  const auth = ctx?.auth;
560
- if (!auth || !auth.delegatedAvailable && !auth.requireDelegatedOnly) {
560
+ const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
561
+ const hasDesignSystem = !!ctx?.designSystem;
562
+ if (!hasAuth && !hasDesignSystem) {
561
563
  return "";
562
564
  }
563
- const lines = ["<org_auth_context>"];
565
+ const lines = ["<org_context>"];
564
566
  if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
565
567
  lines.push(`This app is owned by the organization "${ctx.org.name}".`);
566
568
  }
567
- if (auth.delegatedAvailable) {
569
+ if (auth?.delegatedAvailable) {
568
570
  lines.push(
569
571
  '"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
570
572
  );
571
573
  }
572
- if (auth.requireDelegatedOnly) {
574
+ if (auth?.requireDelegatedOnly) {
573
575
  lines.push(
574
576
  "This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
575
577
  );
576
578
  }
577
- lines.push("</org_auth_context>");
579
+ if (hasDesignSystem) {
580
+ lines.push(
581
+ "This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
582
+ );
583
+ }
584
+ lines.push("</org_context>");
578
585
  return lines.join("\n");
579
586
  }
580
587
 
@@ -3314,6 +3321,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
3314
3321
  let currentToolNames = "";
3315
3322
  let lastUsage;
3316
3323
  let lastProviderMetadata;
3324
+ let lastModelId;
3317
3325
  const statusWatcher = startStatusWatcher({
3318
3326
  apiConfig,
3319
3327
  getContext: () => {
@@ -3427,6 +3435,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
3427
3435
  llmCalls: 1
3428
3436
  };
3429
3437
  lastProviderMetadata = event.providerMetadata;
3438
+ lastModelId = event.modelId;
3430
3439
  recordUsage({
3431
3440
  ts: Date.now(),
3432
3441
  requestId,
@@ -3465,7 +3474,8 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
3465
3474
  role: "assistant",
3466
3475
  content: contentBlocks,
3467
3476
  ...lastUsage ? { usage: lastUsage } : {},
3468
- ...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {}
3477
+ ...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {},
3478
+ model: lastModelId ?? model
3469
3479
  });
3470
3480
  const toolCalls = contentBlocks.filter(
3471
3481
  (b) => b.type === "tool"
@@ -7059,6 +7069,7 @@ async function runTurn(params) {
7059
7069
  apiConfig,
7060
7070
  system,
7061
7071
  model,
7072
+ buildModel,
7062
7073
  onboardingState,
7063
7074
  signal,
7064
7075
  onEvent,
@@ -7070,15 +7081,24 @@ async function runTurn(params) {
7070
7081
  } = params;
7071
7082
  const tools2 = getToolDefinitions(onboardingState);
7072
7083
  const excludeToolsFromClearing = tools2.filter((t) => !CLEARABLE_TOOLS.has(t.name)).map((t) => t.name);
7084
+ const buildModelOverride = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
7085
+ const baseline = resolveModel("parent", state.models, model);
7086
+ const parentModel = buildModelOverride ?? baseline;
7087
+ const modelOverride = buildModelOverride && buildModelOverride !== baseline ? { from: baseline } : void 0;
7073
7088
  log13.info("Turn started", {
7074
7089
  requestId,
7075
7090
  model,
7091
+ buildModel: buildModelOverride,
7076
7092
  toolCount: tools2.length,
7077
7093
  ...attachments && attachments.length > 0 && {
7078
7094
  attachmentCount: attachments.length
7079
7095
  }
7080
7096
  });
7081
- onEvent({ type: "turn_started" });
7097
+ onEvent({
7098
+ type: "turn_started",
7099
+ model: parentModel,
7100
+ ...modelOverride && { modelOverride }
7101
+ });
7082
7102
  const hasText = userMessage.trim().length > 0;
7083
7103
  const hasAttachments = attachments && attachments.length > 0;
7084
7104
  if (!hasText && !hasAttachments) {
@@ -7145,6 +7165,7 @@ async function runTurn(params) {
7145
7165
  const toolInputAccumulators = /* @__PURE__ */ new Map();
7146
7166
  let stopReason = "end_turn";
7147
7167
  let turnProviderMetadata;
7168
+ let turnModelId;
7148
7169
  let subAgentText = "";
7149
7170
  let currentToolNames = "";
7150
7171
  const statusWatcher = isFirstMessage ? { stop() {
@@ -7226,7 +7247,6 @@ async function runTurn(params) {
7226
7247
  onEvent({ type: "tool_input_delta", id, name, result: content });
7227
7248
  }
7228
7249
  }
7229
- const parentModel = resolveModel("parent", state.models, model);
7230
7250
  try {
7231
7251
  for await (const event of streamChatWithRetry(
7232
7252
  {
@@ -7346,6 +7366,7 @@ async function runTurn(params) {
7346
7366
  case "done":
7347
7367
  stopReason = event.stopReason;
7348
7368
  turnProviderMetadata = event.providerMetadata;
7369
+ turnModelId = event.modelId;
7349
7370
  turnLlmCalls++;
7350
7371
  lastCallInputTokens = event.usage.inputTokens;
7351
7372
  lastCallCacheCreation = event.usage.cacheCreationTokens ?? 0;
@@ -7406,7 +7427,9 @@ async function runTurn(params) {
7406
7427
  },
7407
7428
  ...turnProviderMetadata && {
7408
7429
  providerMetadata: turnProviderMetadata
7409
- }
7430
+ },
7431
+ model: turnModelId ?? parentModel,
7432
+ ...modelOverride && { modelOverride }
7410
7433
  });
7411
7434
  }
7412
7435
  onEvent({ type: "turn_cancelled" });
@@ -7424,7 +7447,9 @@ async function runTurn(params) {
7424
7447
  cacheReadTokens: turnCacheRead || void 0,
7425
7448
  llmCalls: turnLlmCalls
7426
7449
  },
7427
- ...turnProviderMetadata && { providerMetadata: turnProviderMetadata }
7450
+ ...turnProviderMetadata && { providerMetadata: turnProviderMetadata },
7451
+ model: turnModelId ?? parentModel,
7452
+ ...modelOverride && { modelOverride }
7428
7453
  });
7429
7454
  }
7430
7455
  const toolCalls = getToolCalls(contentBlocks);
@@ -8219,7 +8244,14 @@ var HeadlessSession = class {
8219
8244
  const rid = this.currentRequestId;
8220
8245
  switch (e.type) {
8221
8246
  case "turn_started":
8222
- this.emit("turn_started", {}, rid);
8247
+ this.emit(
8248
+ "turn_started",
8249
+ {
8250
+ ...e.model && { model: e.model },
8251
+ ...e.modelOverride && { modelOverride: e.modelOverride }
8252
+ },
8253
+ rid
8254
+ );
8223
8255
  return;
8224
8256
  case "user_message":
8225
8257
  this.emit(
@@ -8423,7 +8455,9 @@ var HeadlessSession = class {
8423
8455
  userMessage = resolved.message;
8424
8456
  }
8425
8457
  const isHidden = !!parsed.hidden;
8426
- applyPlanFileSideEffect(parsed.text ?? "");
8458
+ const rawText = parsed.text ?? "";
8459
+ applyPlanFileSideEffect(rawText);
8460
+ const buildModel = hasSentinel(rawText, "approvePlan") ? parsed.buildModel : void 0;
8427
8461
  const onboardingState = parsed.onboardingState ?? "onboardingFinished";
8428
8462
  this.currentOnboardingState = onboardingState;
8429
8463
  const system = buildSystemPrompt(
@@ -8452,6 +8486,7 @@ var HeadlessSession = class {
8452
8486
  apiConfig: this.config,
8453
8487
  system,
8454
8488
  model: this.opts.model,
8489
+ buildModel,
8455
8490
  onboardingState,
8456
8491
  requestId,
8457
8492
  signal: this.currentAbort.signal,
package/dist/index.js CHANGED
@@ -3884,6 +3884,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
3884
3884
  let currentToolNames = "";
3885
3885
  let lastUsage;
3886
3886
  let lastProviderMetadata;
3887
+ let lastModelId;
3887
3888
  const statusWatcher = startStatusWatcher({
3888
3889
  apiConfig,
3889
3890
  getContext: () => {
@@ -3997,6 +3998,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
3997
3998
  llmCalls: 1
3998
3999
  };
3999
4000
  lastProviderMetadata = event.providerMetadata;
4001
+ lastModelId = event.modelId;
4000
4002
  recordUsage({
4001
4003
  ts: Date.now(),
4002
4004
  requestId,
@@ -4035,7 +4037,8 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
4035
4037
  role: "assistant",
4036
4038
  content: contentBlocks,
4037
4039
  ...lastUsage ? { usage: lastUsage } : {},
4038
- ...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {}
4040
+ ...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {},
4041
+ model: lastModelId ?? model
4039
4042
  });
4040
4043
  const toolCalls = contentBlocks.filter(
4041
4044
  (b) => b.type === "tool"
@@ -5715,24 +5718,31 @@ function getOrgContext() {
5715
5718
  function renderOrgContextBlock() {
5716
5719
  const ctx = cached;
5717
5720
  const auth = ctx?.auth;
5718
- if (!auth || !auth.delegatedAvailable && !auth.requireDelegatedOnly) {
5721
+ const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
5722
+ const hasDesignSystem = !!ctx?.designSystem;
5723
+ if (!hasAuth && !hasDesignSystem) {
5719
5724
  return "";
5720
5725
  }
5721
- const lines = ["<org_auth_context>"];
5726
+ const lines = ["<org_context>"];
5722
5727
  if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
5723
5728
  lines.push(`This app is owned by the organization "${ctx.org.name}".`);
5724
5729
  }
5725
- if (auth.delegatedAvailable) {
5730
+ if (auth?.delegatedAvailable) {
5726
5731
  lines.push(
5727
5732
  '"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
5728
5733
  );
5729
5734
  }
5730
- if (auth.requireDelegatedOnly) {
5735
+ if (auth?.requireDelegatedOnly) {
5731
5736
  lines.push(
5732
5737
  "This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
5733
5738
  );
5734
5739
  }
5735
- lines.push("</org_auth_context>");
5740
+ if (hasDesignSystem) {
5741
+ lines.push(
5742
+ "This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
5743
+ );
5744
+ }
5745
+ lines.push("</org_context>");
5736
5746
  return lines.join("\n");
5737
5747
  }
5738
5748
  var log9, cached;
@@ -7502,6 +7512,7 @@ async function runTurn(params) {
7502
7512
  apiConfig,
7503
7513
  system,
7504
7514
  model,
7515
+ buildModel,
7505
7516
  onboardingState,
7506
7517
  signal,
7507
7518
  onEvent,
@@ -7513,15 +7524,24 @@ async function runTurn(params) {
7513
7524
  } = params;
7514
7525
  const tools2 = getToolDefinitions(onboardingState);
7515
7526
  const excludeToolsFromClearing = tools2.filter((t) => !CLEARABLE_TOOLS.has(t.name)).map((t) => t.name);
7527
+ const buildModelOverride = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
7528
+ const baseline = resolveModel("parent", state.models, model);
7529
+ const parentModel = buildModelOverride ?? baseline;
7530
+ const modelOverride = buildModelOverride && buildModelOverride !== baseline ? { from: baseline } : void 0;
7516
7531
  log12.info("Turn started", {
7517
7532
  requestId,
7518
7533
  model,
7534
+ buildModel: buildModelOverride,
7519
7535
  toolCount: tools2.length,
7520
7536
  ...attachments && attachments.length > 0 && {
7521
7537
  attachmentCount: attachments.length
7522
7538
  }
7523
7539
  });
7524
- onEvent({ type: "turn_started" });
7540
+ onEvent({
7541
+ type: "turn_started",
7542
+ model: parentModel,
7543
+ ...modelOverride && { modelOverride }
7544
+ });
7525
7545
  const hasText = userMessage.trim().length > 0;
7526
7546
  const hasAttachments = attachments && attachments.length > 0;
7527
7547
  if (!hasText && !hasAttachments) {
@@ -7588,6 +7608,7 @@ async function runTurn(params) {
7588
7608
  const toolInputAccumulators = /* @__PURE__ */ new Map();
7589
7609
  let stopReason = "end_turn";
7590
7610
  let turnProviderMetadata;
7611
+ let turnModelId;
7591
7612
  let subAgentText = "";
7592
7613
  let currentToolNames = "";
7593
7614
  const statusWatcher = isFirstMessage ? { stop() {
@@ -7669,7 +7690,6 @@ async function runTurn(params) {
7669
7690
  onEvent({ type: "tool_input_delta", id, name, result: content });
7670
7691
  }
7671
7692
  }
7672
- const parentModel = resolveModel("parent", state.models, model);
7673
7693
  try {
7674
7694
  for await (const event of streamChatWithRetry(
7675
7695
  {
@@ -7789,6 +7809,7 @@ async function runTurn(params) {
7789
7809
  case "done":
7790
7810
  stopReason = event.stopReason;
7791
7811
  turnProviderMetadata = event.providerMetadata;
7812
+ turnModelId = event.modelId;
7792
7813
  turnLlmCalls++;
7793
7814
  lastCallInputTokens = event.usage.inputTokens;
7794
7815
  lastCallCacheCreation = event.usage.cacheCreationTokens ?? 0;
@@ -7849,7 +7870,9 @@ async function runTurn(params) {
7849
7870
  },
7850
7871
  ...turnProviderMetadata && {
7851
7872
  providerMetadata: turnProviderMetadata
7852
- }
7873
+ },
7874
+ model: turnModelId ?? parentModel,
7875
+ ...modelOverride && { modelOverride }
7853
7876
  });
7854
7877
  }
7855
7878
  onEvent({ type: "turn_cancelled" });
@@ -7867,7 +7890,9 @@ async function runTurn(params) {
7867
7890
  cacheReadTokens: turnCacheRead || void 0,
7868
7891
  llmCalls: turnLlmCalls
7869
7892
  },
7870
- ...turnProviderMetadata && { providerMetadata: turnProviderMetadata }
7893
+ ...turnProviderMetadata && { providerMetadata: turnProviderMetadata },
7894
+ model: turnModelId ?? parentModel,
7895
+ ...modelOverride && { modelOverride }
7871
7896
  });
7872
7897
  }
7873
7898
  const toolCalls = getToolCalls(contentBlocks);
@@ -9108,7 +9133,14 @@ var init_headless = __esm({
9108
9133
  const rid = this.currentRequestId;
9109
9134
  switch (e.type) {
9110
9135
  case "turn_started":
9111
- this.emit("turn_started", {}, rid);
9136
+ this.emit(
9137
+ "turn_started",
9138
+ {
9139
+ ...e.model && { model: e.model },
9140
+ ...e.modelOverride && { modelOverride: e.modelOverride }
9141
+ },
9142
+ rid
9143
+ );
9112
9144
  return;
9113
9145
  case "user_message":
9114
9146
  this.emit(
@@ -9312,7 +9344,9 @@ var init_headless = __esm({
9312
9344
  userMessage = resolved.message;
9313
9345
  }
9314
9346
  const isHidden = !!parsed.hidden;
9315
- applyPlanFileSideEffect(parsed.text ?? "");
9347
+ const rawText = parsed.text ?? "";
9348
+ applyPlanFileSideEffect(rawText);
9349
+ const buildModel = hasSentinel(rawText, "approvePlan") ? parsed.buildModel : void 0;
9316
9350
  const onboardingState = parsed.onboardingState ?? "onboardingFinished";
9317
9351
  this.currentOnboardingState = onboardingState;
9318
9352
  const system = buildSystemPrompt(
@@ -9341,6 +9375,7 @@ var init_headless = __esm({
9341
9375
  apiConfig: this.config,
9342
9376
  system,
9343
9377
  model: this.opts.model,
9378
+ buildModel,
9344
9379
  onboardingState,
9345
9380
  requestId,
9346
9381
  signal: this.currentAbort.signal,
@@ -34,7 +34,7 @@ Remy apps can have and manage their own users. Auth is opt-in: configure it in t
34
34
  - `email-code` — 6-digit code sent via email
35
35
  - `sms-code` — 6-digit code sent via SMS
36
36
  - `api-key` — programmatic access via `Authorization: Bearer sk_...` header. Resolves to a user with full RBAC.
37
- - `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<org_auth_context>` block signals availability. See *Organization-Managed Sign-In* above.
37
+ - `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<org_context>` block signals availability. See *Organization-Managed Sign-In* above.
38
38
  - **`auth.table.name`** — name of the `defineTable` table that holds user records.
39
39
  - **`auth.table.columns`** — maps platform-managed fields to column names in the developer's table.
40
40
  - `email` — required if `email-code` is in methods
@@ -135,12 +135,12 @@ const user = await auth.verifySmsCode(verificationId, '123456');
135
135
 
136
136
  ## Organization-Managed Sign-In ("Sign in with Remy")
137
137
 
138
- Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<org_auth_context>` block (near the end) stating the organization name and whether delegated sign-in is available. Sign in with Remy is a way to make authentication seamless for internal apps - it should not be used for public-facing applications. The app owner will need to add users to their workspace's team on the Remy platform and those users will need Remy accounts for it to work.
138
+ Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<org_context>` block (near the end); for org-managed sign-in it states the organization name and whether delegated sign-in is available. Sign in with Remy is a way to make authentication seamless for internal apps - it should not be used for public-facing applications. The app owner will need to add users to their workspace's team on the Remy platform and those users will need Remy accounts for it to work.
139
139
 
140
140
  - **When it says "Sign in with Remy" is available** — offer delegated sign-in: a **"Continue with {Org}"** button wired to the `remy` method (see *Sign in with Remy (delegated)* below). Use the exact organization name from the block for the label. For an org-owned app this is usually the primary sign-in — the members already have platform identities, so a verification-code form is redundant.
141
141
  - **When it says the organization requires delegated sign-in** — `remy` is the *only* human method: do not add `email-code` or `sms-code`. Those are blocked at the platform edge for the org's apps, so building them yields a login that can't work.
142
142
 
143
- When no `<org_auth_context>` block is present — the common case — do not build it or offer to build it. This is an auth scheme for enterprises building internal apps only, and it requires a Remy enterprise plan to use. When enabled, the platform decides who the user is (like "Sign in with Google"); the app just starts the flow and reads the result.
143
+ When the `<org_context>` block is absent, or present without a delegated-sign-in line — the common case — do not build it or offer to build it. This is an auth scheme for enterprises building internal apps only, and it requires a Remy enterprise plan to use. When enabled, the platform decides who the user is (like "Sign in with Google"); the app just starts the flow and reads the result.
144
144
 
145
145
  ```typescript
146
146
  // "Continue with {Org}" button — must be triggered by a user gesture (click).
@@ -399,7 +399,7 @@ Consult the `visualDesignExpert` to help you work through authentication at a hi
399
399
  ### Rules for Building Auth Screens
400
400
  **Auth modes:** Think about which mode(s) makes the most sense for the type of app you are building. Consumer apps likely to be used on mobile should probably tend toward SMS auth as the default - business apps used on desktop make more sense to use email verification - or allow both, there's no harm in giving the user choice!
401
401
 
402
- **"Continue with {Org}" (delegated):** When `<org_auth_context>` says delegated sign-in is available, a single "Continue with {Org}" button is the primary path — often the *only* one — and there's no verification-code step to design at all (the platform handles it). Give the button real weight in the branded login moment rather than treating it as a secondary option, and use the exact organization name. If the org also allows code methods, delegated goes first with the code form beneath. On return from the handshake (and on dashboard launch), render a brief "Completing sign-in…" state driven by `auth.authStatus === 'authenticating'` — never the login form — so a successful sign-in doesn't flash the logged-out screen.
402
+ **"Continue with {Org}" (delegated):** When the `<org_context>` block says delegated sign-in is available, a single "Continue with {Org}" button is the primary path — often the *only* one — and there's no verification-code step to design at all (the platform handles it). Give the button real weight in the branded login moment rather than treating it as a secondary option, and use the exact organization name. If the org also allows code methods, delegated goes first with the code form beneath. On return from the handshake (and on dashboard launch), render a brief "Completing sign-in…" state driven by `auth.authStatus === 'authenticating'` — never the login form — so a successful sign-in doesn't flash the logged-out screen.
403
403
 
404
404
  **Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, a beautiful animation and auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert. Make sure there is no layout shift when loading in the success/error states - loading spinners must never pop in below the input and shift the content, for example.
405
405
 
@@ -20,7 +20,7 @@ Login and signup screens set the tone for the user's entire experience with the
20
20
 
21
21
  Authentication moments must feel natural and intuitive - they should not feel jarring or surprising. Take care to integrate them into the entire experience when building. Remy apps support SMS code verification, email verification, delegated "Sign in with Remy", or a combination, depending on how the app is configured.
22
22
 
23
- **"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <org_auth_context> - it should not be used for public-facing apps.
23
+ **"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <org_context> - it should not be used for public-facing apps.
24
24
 
25
25
  **Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert.
26
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.242",
3
+ "version": "0.1.244",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",