openmates 0.12.0-alpha.4 → 0.12.0-alpha.6

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.
@@ -1127,6 +1127,7 @@ var OpenMatesWsClient = class {
1127
1127
  let category = null;
1128
1128
  let modelName = null;
1129
1129
  let followUpSuggestions = [];
1130
+ let newChatSuggestions = [];
1130
1131
  const subChatEvents = [];
1131
1132
  const pendingSubChatHandlers = /* @__PURE__ */ new Set();
1132
1133
  const pendingMemoryRequestHandlers = /* @__PURE__ */ new Set();
@@ -1184,6 +1185,7 @@ var OpenMatesWsClient = class {
1184
1185
  category,
1185
1186
  modelName,
1186
1187
  followUpSuggestions,
1188
+ newChatSuggestions,
1187
1189
  embeds: [...embeds.values()],
1188
1190
  subChatEvents
1189
1191
  });
@@ -1203,6 +1205,7 @@ var OpenMatesWsClient = class {
1203
1205
  category,
1204
1206
  modelName,
1205
1207
  followUpSuggestions,
1208
+ newChatSuggestions,
1206
1209
  embeds: [...embeds.values()],
1207
1210
  subChatEvents
1208
1211
  });
@@ -1219,6 +1222,7 @@ var OpenMatesWsClient = class {
1219
1222
  category,
1220
1223
  modelName,
1221
1224
  followUpSuggestions,
1225
+ newChatSuggestions,
1222
1226
  embeds: [...embeds.values()],
1223
1227
  subChatEvents
1224
1228
  });
@@ -1391,7 +1395,7 @@ var OpenMatesWsClient = class {
1391
1395
  });
1392
1396
  return;
1393
1397
  }
1394
- if (type === "post_processing_metadata") {
1398
+ if (type === "post_processing_completed" || type === "post_processing_metadata") {
1395
1399
  if (p.chat_id !== chatId) return;
1396
1400
  const rawSuggestions = p.follow_up_request_suggestions;
1397
1401
  if (Array.isArray(rawSuggestions) && rawSuggestions.length > 0) {
@@ -1399,6 +1403,12 @@ var OpenMatesWsClient = class {
1399
1403
  (s) => typeof s === "string" && s.length > 0
1400
1404
  );
1401
1405
  }
1406
+ const rawNewChatSuggestions = p.new_chat_request_suggestions;
1407
+ if (Array.isArray(rawNewChatSuggestions) && rawNewChatSuggestions.length > 0) {
1408
+ newChatSuggestions = rawNewChatSuggestions.filter(
1409
+ (s) => typeof s === "string" && s.length > 0
1410
+ );
1411
+ }
1402
1412
  if (aiResponseDone) {
1403
1413
  if (postProcessingTimer) {
1404
1414
  clearTimeout(postProcessingTimer);
@@ -1426,6 +1436,7 @@ var OpenMatesWsClient = class {
1426
1436
  category,
1427
1437
  modelName,
1428
1438
  followUpSuggestions,
1439
+ newChatSuggestions,
1429
1440
  embeds: [...embeds.values()],
1430
1441
  subChatEvents
1431
1442
  });
@@ -2550,6 +2561,9 @@ var MATE_NAMES = {
2550
2561
  general_knowledge: "George",
2551
2562
  onboarding_support: "Suki"
2552
2563
  };
2564
+ function stripLegacySuggestionPrefix(text) {
2565
+ return text.replace(/^\s*\[[^\]]+\]\s*/, "").trim();
2566
+ }
2553
2567
  var CLOUD_API_URL = "https://api.openmates.org";
2554
2568
  var DEFAULT_API_URL = process.env.OPENMATES_API_URL ?? CLOUD_API_URL;
2555
2569
  var SETTINGS_GET_RATE_LIMIT_RETRY_MS = 61e3;
@@ -3444,13 +3458,10 @@ var OpenMatesClient = class _OpenMatesClient {
3444
3458
  masterKey
3445
3459
  );
3446
3460
  if (!plaintext) continue;
3447
- const { body, appId, skillId } = parseNewChatSuggestionText(plaintext);
3448
3461
  results.push({
3449
3462
  id: typeof raw.id === "string" ? raw.id : String(raw.id ?? ""),
3450
3463
  chatId: typeof raw.chat_id === "string" ? raw.chat_id : null,
3451
- body,
3452
- appId,
3453
- skillId,
3464
+ body: stripLegacySuggestionPrefix(plaintext),
3454
3465
  createdAt: typeof raw.created_at === "number" ? raw.created_at : 0
3455
3466
  });
3456
3467
  if (results.length >= limit) break;
@@ -3466,7 +3477,11 @@ var OpenMatesClient = class _OpenMatesClient {
3466
3477
  * Mirrors: chat_actions_store.ts / FollowUpSuggestions.svelte (web app)
3467
3478
  */
3468
3479
  async getChatFollowUpSuggestions(chatId) {
3469
- const cache = await this.ensureSynced();
3480
+ const cachedMatch = loadSyncCache()?.chats.find(
3481
+ (c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
3482
+ );
3483
+ const refreshChatId = String(cachedMatch?.details.id ?? chatId);
3484
+ const cache = await this.ensureSynced(true, [refreshChatId]);
3470
3485
  const masterKey = this.getMasterKeyBytes();
3471
3486
  const found = cache.chats.find(
3472
3487
  (c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
@@ -3486,9 +3501,7 @@ var OpenMatesClient = class _OpenMatesClient {
3486
3501
  try {
3487
3502
  const parsed = JSON.parse(plaintext);
3488
3503
  if (Array.isArray(parsed)) {
3489
- return parsed.filter(
3490
- (s) => typeof s === "string" && s.length > 0
3491
- );
3504
+ return parsed.filter((s) => typeof s === "string" && s.length > 0).map(stripLegacySuggestionPrefix).filter((s) => s.length > 0);
3492
3505
  }
3493
3506
  } catch {
3494
3507
  }
@@ -3917,6 +3930,14 @@ var OpenMatesClient = class _OpenMatesClient {
3917
3930
  chatKeyBytes,
3918
3931
  fallbackMessageId: persistedAssistantMessageId
3919
3932
  });
3933
+ await this.persistPostProcessingMetadata({
3934
+ ws,
3935
+ chatId,
3936
+ chatKeyBytes,
3937
+ followUpSuggestions: resp.followUpSuggestions,
3938
+ newChatSuggestions: resp.newChatSuggestions,
3939
+ encryptedChatKey
3940
+ });
3920
3941
  clearSyncCache();
3921
3942
  }
3922
3943
  } finally {
@@ -4057,6 +4078,33 @@ var OpenMatesClient = class _OpenMatesClient {
4057
4078
  processed.add(embed.embed_id);
4058
4079
  }
4059
4080
  }
4081
+ async persistPostProcessingMetadata(params) {
4082
+ const encryptedFollowUps = params.followUpSuggestions.length > 0 ? await encryptWithAesGcmCombined(
4083
+ JSON.stringify(params.followUpSuggestions.slice(0, 18)),
4084
+ params.chatKeyBytes
4085
+ ) : "";
4086
+ const masterKey = this.getMasterKeyBytes();
4087
+ const encryptedNewChatSuggestions = await Promise.all(
4088
+ params.newChatSuggestions.slice(0, 6).map(
4089
+ (suggestion) => encryptWithAesGcmCombined(suggestion, masterKey)
4090
+ )
4091
+ );
4092
+ if (!encryptedFollowUps && encryptedNewChatSuggestions.length === 0) return;
4093
+ await params.ws.sendAsync("update_post_processing_metadata", {
4094
+ chat_id: params.chatId,
4095
+ encrypted_follow_up_suggestions: encryptedFollowUps,
4096
+ encrypted_new_chat_suggestions: encryptedNewChatSuggestions,
4097
+ encrypted_chat_key: params.encryptedChatKey ?? ""
4098
+ });
4099
+ await params.ws.waitForMessage(
4100
+ "post_processing_metadata_stored",
4101
+ (payload) => {
4102
+ const p = payload;
4103
+ return p.chat_id === params.chatId;
4104
+ },
4105
+ 2e4
4106
+ );
4107
+ }
4060
4108
  /**
4061
4109
  * Delete a chat by ID.
4062
4110
  *
@@ -5475,7 +5523,7 @@ Required: ${schema.required.join(", ")}`
5475
5523
  async refreshWsToken() {
5476
5524
  const session = this.requireSession();
5477
5525
  try {
5478
- const res = await this.http.post("/v1/auth/session", {}, this.getCliRequestHeaders());
5526
+ const res = await this.http.post("/v1/auth/session", { session_id: session.sessionId }, this.getCliRequestHeaders());
5479
5527
  if (res.ok && res.data.ws_token) {
5480
5528
  session.wsToken = res.data.ws_token;
5481
5529
  }
@@ -5491,8 +5539,9 @@ Required: ${schema.required.join(", ")}`
5491
5539
  * The sync cache stores encrypted data — decryption is always on-demand.
5492
5540
  * SECURITY: decrypted user content is NEVER written to disk.
5493
5541
  */
5494
- async ensureSynced(forceRefresh = false) {
5495
- if (!forceRefresh && isSyncCacheFresh()) {
5542
+ async ensureSynced(forceRefresh = false, refreshChatIds = []) {
5543
+ const refreshChatIdSet = new Set(refreshChatIds.filter(Boolean));
5544
+ if (!forceRefresh && refreshChatIdSet.size === 0 && isSyncCacheFresh()) {
5496
5545
  const cache2 = loadSyncCache();
5497
5546
  if (cache2) return cache2;
5498
5547
  }
@@ -5505,6 +5554,7 @@ Required: ${schema.required.join(", ")}`
5505
5554
  const id = String(chat.details.id ?? "");
5506
5555
  if (!id) continue;
5507
5556
  clientChatIds.push(id);
5557
+ if (refreshChatIdSet.has(id)) continue;
5508
5558
  clientChatVersions[id] = {
5509
5559
  messages_v: getClientMessagesVersionForSync(chat),
5510
5560
  title_v: typeof chat.details.title_v === "number" ? chat.details.title_v : 0,
@@ -5777,21 +5827,6 @@ function parseYamlLikeContent(raw) {
5777
5827
  flush();
5778
5828
  return result;
5779
5829
  }
5780
- function parseNewChatSuggestionText(text) {
5781
- const prefixMatch = /^\[([a-z0-9_-]+(?:-[a-z0-9_]+)?)\]\s*/.exec(text);
5782
- if (!prefixMatch) {
5783
- return { body: text.trim(), appId: null, skillId: null };
5784
- }
5785
- const raw = prefixMatch[1];
5786
- const body = text.slice(prefixMatch[0].length).trim();
5787
- const dashIdx = raw.indexOf("-");
5788
- if (dashIdx === -1) {
5789
- return { body, appId: raw, skillId: null };
5790
- }
5791
- const appId = raw.slice(0, dashIdx);
5792
- const skillId = raw.slice(dashIdx + 1);
5793
- return { body, appId, skillId };
5794
- }
5795
5830
  function filenameFromContentDisposition(header2) {
5796
5831
  if (!header2) return null;
5797
5832
  const encoded = /filename\*=UTF-8''([^;]+)/i.exec(header2)?.[1];
@@ -23072,10 +23107,16 @@ var en_default = {
23072
23107
  text: "Clone and analyze a repo's architecture."
23073
23108
  }
23074
23109
  },
23110
+ project_planner: {
23111
+ text: "Project planner",
23112
+ description: {
23113
+ text: "Turn coding ideas into scoped plans, tasks, acceptance criteria, and verification steps."
23114
+ }
23115
+ },
23075
23116
  research_solutions: {
23076
23117
  text: "Research solutions",
23077
23118
  description: {
23078
- text: "Research what tech fits your requirements."
23119
+ text: "Compare technical options and choose the best fit for your requirements."
23079
23120
  }
23080
23121
  },
23081
23122
  code_walkthrough: {
@@ -23090,6 +23131,12 @@ var en_default = {
23090
23131
  text: "Get help setting up software or infra."
23091
23132
  }
23092
23133
  },
23134
+ learn_by_building: {
23135
+ text: "Learn by building",
23136
+ description: {
23137
+ text: "Learn a programming topic through a small real project with guided checkpoints."
23138
+ }
23139
+ },
23093
23140
  refactor_code: {
23094
23141
  text: "Refactor code",
23095
23142
  description: {
@@ -24218,6 +24265,32 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
24218
24265
  }
24219
24266
  }
24220
24267
  },
24268
+ calendar: {
24269
+ get_events: {
24270
+ text: "Get Events",
24271
+ description: {
24272
+ text: "Read events, agendas, availability, and event details from a connected calendar."
24273
+ }
24274
+ },
24275
+ create_event: {
24276
+ text: "Create Event",
24277
+ description: {
24278
+ text: "Create a calendar event after you approve the proposed details."
24279
+ }
24280
+ },
24281
+ update_event: {
24282
+ text: "Update Event",
24283
+ description: {
24284
+ text: "Update an existing calendar event after permission checks."
24285
+ }
24286
+ },
24287
+ delete_event: {
24288
+ text: "Delete Event",
24289
+ description: {
24290
+ text: "Delete calendar events only after explicit permission or an allowed automation rule."
24291
+ }
24292
+ }
24293
+ },
24221
24294
  code: {
24222
24295
  get_docs: {
24223
24296
  text: "Get docs",
@@ -25177,6 +25250,12 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
25177
25250
  }
25178
25251
  }
25179
25252
  },
25253
+ calendar: {
25254
+ text: "Calendar",
25255
+ description: {
25256
+ text: "Connect your calendar so mates can read, create, update, and delete events with your permission."
25257
+ }
25258
+ },
25180
25259
  social_media: {
25181
25260
  text: "Social Media",
25182
25261
  description: {
@@ -25562,6 +25641,70 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
25562
25641
  text: "Rejected memories request."
25563
25642
  }
25564
25643
  },
25644
+ connected_account_permissions: {
25645
+ title: {
25646
+ text: "Connected account approval"
25647
+ },
25648
+ question: {
25649
+ text: "Allow this chat to use your connected account for this {action} action?"
25650
+ },
25651
+ approve: {
25652
+ text: "Approve once"
25653
+ },
25654
+ loading: {
25655
+ text: "Approving..."
25656
+ }
25657
+ },
25658
+ connected_account_receipts: {
25659
+ completed: {
25660
+ text: "{action} completed."
25661
+ },
25662
+ undone: {
25663
+ text: "Action undone."
25664
+ },
25665
+ rejected: {
25666
+ text: "{action} rejected."
25667
+ },
25668
+ cancelled: {
25669
+ text: "{action} cancelled."
25670
+ },
25671
+ failed: {
25672
+ text: "{action} could not be completed."
25673
+ },
25674
+ undo: {
25675
+ text: "Undo"
25676
+ },
25677
+ undoing: {
25678
+ text: "Undoing..."
25679
+ },
25680
+ undo_started: {
25681
+ text: "Undo completed"
25682
+ },
25683
+ undo_failed: {
25684
+ text: "Could not undo this action."
25685
+ },
25686
+ undo_available: {
25687
+ text: "Undo is available."
25688
+ },
25689
+ action_read: {
25690
+ text: "Calendar read"
25691
+ },
25692
+ action_write: {
25693
+ text: "Calendar write"
25694
+ },
25695
+ action_update: {
25696
+ text: "Calendar update"
25697
+ },
25698
+ action_delete: {
25699
+ text: "Calendar delete"
25700
+ },
25701
+ action_undo: {
25702
+ text: "Calendar undo"
25703
+ },
25704
+ action_unknown: {
25705
+ text: "Connected account action"
25706
+ }
25707
+ },
25565
25708
  report_bad_answer: {
25566
25709
  button_text: {
25567
25710
  text: "Report bad answer"
@@ -25747,79 +25890,79 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
25747
25890
  },
25748
25891
  new_chat_suggestions: {
25749
25892
  quantum_computing: {
25750
- text: "[study] Teach me about quantum computing in simple terms"
25893
+ text: "Teach me about quantum computing in simple terms"
25751
25894
  },
25752
25895
  plan_trip_japan: {
25753
- text: "[travel] Help me plan a 7-day trip to Japan"
25896
+ text: "Help me plan a 7-day trip to Japan"
25754
25897
  },
25755
25898
  ai_news: {
25756
- text: "[news-search] What's the latest news about AI developments?"
25899
+ text: "What's the latest news about AI developments?"
25757
25900
  },
25758
25901
  photosynthesis: {
25759
- text: "[study] Explain how photosynthesis works"
25902
+ text: "Explain how photosynthesis works"
25760
25903
  },
25761
25904
  professional_email: {
25762
- text: "[mail] Help me write a professional email"
25905
+ text: "Help me write a professional email"
25763
25906
  },
25764
25907
  healthy_breakfast: {
25765
- text: "[nutrition] What are some healthy breakfast ideas?"
25908
+ text: "What are some healthy breakfast ideas?"
25766
25909
  },
25767
25910
  blockchain: {
25768
- text: "[web-search] Explain blockchain technology"
25911
+ text: "Explain blockchain technology"
25769
25912
  },
25770
25913
  learn_spanish: {
25771
- text: "[study] Help me learn Spanish basics"
25914
+ text: "Help me learn Spanish basics"
25772
25915
  },
25773
25916
  ml_vs_ai: {
25774
- text: "[web-search] What's the difference between machine learning and AI?"
25917
+ text: "What's the difference between machine learning and AI?"
25775
25918
  },
25776
25919
  improve_productivity: {
25777
- text: "[life_coaching] How do I improve my productivity?"
25920
+ text: "How do I improve my productivity?"
25778
25921
  },
25779
25922
  theory_relativity: {
25780
- text: "[study] Explain the theory of relativity"
25923
+ text: "Explain the theory of relativity"
25781
25924
  },
25782
25925
  workout_plan: {
25783
- text: "[fitness] Help me create a workout plan"
25926
+ text: "Help me create a workout plan"
25784
25927
  },
25785
25928
  cybersecurity: {
25786
- text: "[web-search] What are the best practices for cybersecurity?"
25929
+ text: "What are the best practices for cybersecurity?"
25787
25930
  },
25788
25931
  learn_coding: {
25789
- text: "[code] How do I start learning to code?"
25932
+ text: "How do I start learning to code?"
25790
25933
  },
25791
25934
  stock_market: {
25792
- text: "[web-search] Explain how the stock market works"
25935
+ text: "Explain how the stock market works"
25793
25936
  },
25794
25937
  cover_letter: {
25795
- text: "[mail] Help me write a cover letter"
25938
+ text: "Help me write a cover letter"
25796
25939
  },
25797
25940
  writing_prompts: {
25798
- text: "[books] What are some creative writing prompts?"
25941
+ text: "What are some creative writing prompts?"
25799
25942
  },
25800
25943
  carbon_footprint: {
25801
- text: "[web-search] How do I reduce my carbon footprint?"
25944
+ text: "How do I reduce my carbon footprint?"
25802
25945
  },
25803
25946
  internet_history: {
25804
- text: "[web-search] Explain the history of the Internet"
25947
+ text: "Explain the history of the Internet"
25805
25948
  },
25806
25949
  meal_prep: {
25807
- text: "[nutrition] Help me plan a healthy meal prep"
25950
+ text: "Help me plan a healthy meal prep"
25808
25951
  },
25809
25952
  discover_web_search: {
25810
- text: "[web-search] What's happening in the world today?"
25953
+ text: "What's happening in the world today?"
25811
25954
  },
25812
25955
  discover_image_generate: {
25813
- text: "[images-generate] Generate an image of a mountain sunset"
25956
+ text: "Generate an image of a mountain sunset"
25814
25957
  },
25815
25958
  discover_news_search: {
25816
- text: "[news-search] Find the latest AI news"
25959
+ text: "Find the latest AI news"
25817
25960
  },
25818
25961
  discover_video_search: {
25819
- text: "[videos-search] Find tutorial videos on Python programming"
25962
+ text: "Find tutorial videos on Python programming"
25820
25963
  },
25821
25964
  discover_math_calculate: {
25822
- text: "[math-calculate] Solve: what is 15% of 240?"
25965
+ text: "Solve: what is 15% of 240?"
25823
25966
  }
25824
25967
  },
25825
25968
  quick_tips: {
@@ -30932,6 +31075,18 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
30932
31075
  text: "Refine issues by adding details and clarity."
30933
31076
  }
30934
31077
  },
31078
+ code_learn_by_building: {
31079
+ text: "Learn by building",
31080
+ description: {
31081
+ text: "Learn a programming topic through a small real project with guided checkpoints."
31082
+ },
31083
+ process: {
31084
+ text: "- Determines the user's current skill level, target technology, learning goal, and preferred pace\n- Chooses or helps define a small project that demonstrates the topic without becoming too large\n- Teaches concepts immediately before they are used in the project\n- Gives one build step at a time with expected output, self-checks, and optional quiz questions\n- Adapts the pace based on the user's answers and saves useful learning preferences when appropriate"
31085
+ },
31086
+ systemprompt: {
31087
+ text: "You are Learn by Building, a patient programming mentor who teaches through practical project work.\n\nYour job is to help the user learn a coding topic by building something real in small steps. First determine the user's current level, target technology, learning goal, preferred pace, and project idea. If they do not have a project idea, suggest a small project that demonstrates the concept without becoming too large.\n\nTeach concepts immediately before they are needed, then give a small build task, expected outcome, and quick self-check. Ask occasional understanding checks or short quiz questions, but keep momentum toward a working project. Adapt explanations to the user's skill level and connect new ideas to their preferred technologies and want-to-learn memories when available.\n\nDo not dump a complete finished app unless the user explicitly asks. Favor guided iteration, code reading, debugging, and reflection so the user learns how and why the solution works."
31088
+ }
31089
+ },
30935
31090
  code_learn_new_tech: {
30936
31091
  text: "Learn new tech",
30937
31092
  description: {
@@ -30947,6 +31102,18 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
30947
31102
  text: "Plan a project and create requirement docs."
30948
31103
  }
30949
31104
  },
31105
+ code_project_planner: {
31106
+ text: "Project planner",
31107
+ description: {
31108
+ text: "Turn coding ideas into scoped plans, tasks, acceptance criteria, and verification steps."
31109
+ },
31110
+ process: {
31111
+ text: "- Clarifies the goal, target users, current stack, constraints, non-goals, and definition of success\n- Identifies unknowns, assumptions, risks, permissions, and likely implementation boundaries\n- Breaks the work into small, independently testable tasks with dependencies and handoff notes\n- Defines acceptance criteria and a verification ladder before coding begins\n- Recommends a durable spec-driven-development artifact only for complex or high-risk work"
31112
+ },
31113
+ systemprompt: {
31114
+ text: "You are Project Planner, a senior software product engineer helping the user turn coding intent into an actionable, testable plan.\n\nYour job is to reduce ambiguity before implementation. Start by understanding the goal, users, constraints, existing codebase or stack, non-goals, risks, and what success should look like. Ask only the highest-value clarifying questions; do not interrogate the user when enough context exists to draft a useful plan.\n\nProduce practical plans that an agentic coding workflow can execute safely. Include scope, assumptions, tasks, dependencies, acceptance criteria, verification steps, and risk/permission notes. For complex or high-risk work, recommend a durable spec-driven-development artifact, but keep the user-facing language simple and explain why the added structure is worth it.\n\nDo not write implementation code unless the user explicitly asks to move from planning into implementation. When asked to continue, hand off to a step-by-step build flow with the smallest independently verifiable next task."
31115
+ }
31116
+ },
30950
31117
  code_refactor_code: {
30951
31118
  text: "Refactor code",
30952
31119
  description: {
@@ -30959,7 +31126,13 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
30959
31126
  code_research_solutions: {
30960
31127
  text: "Research solutions",
30961
31128
  description: {
30962
- text: "Research what tech fits your requirements."
31129
+ text: "Compare technical options and choose the best fit for your requirements."
31130
+ },
31131
+ process: {
31132
+ text: "- Clarifies requirements, constraints, current stack, team skill level, budget, and deployment needs\n- Finds current documentation and credible source material when API or framework details matter\n- Compares options across fit, complexity, maturity, cost, lock-in, security, operations, and migration effort\n- Calls out unknowns, failure modes, and validation work before recommending a path\n- Ends with a clear recommendation, fallback option, decision record, and first safe validation step"
31133
+ },
31134
+ systemprompt: {
31135
+ text: "You are Research Solutions, a senior software architect and technical researcher.\n\nYour job is to help the user choose the right technical approach for a coding problem. Begin by extracting the requirements, constraints, current stack, must-haves, nice-to-haves, maturity needs, hosting/deployment limits, budget, team skill level, and migration constraints.\n\nPrefer current official documentation and credible source material for framework/library/API details. Compare options across fit, complexity, maintenance burden, ecosystem maturity, lock-in, security/privacy, cost, operational risk, and migration path. Be explicit about uncertainty and avoid recommending trendy tools without matching them to the user's constraints.\n\nEnd with a concrete recommendation, the main tradeoffs, a fallback option, and the first safe validation step. If the user asks to implement, transition to a small, testable implementation plan instead of attempting a broad rewrite."
30963
31136
  }
30964
31137
  },
30965
31138
  code_setup_infrastructure: {
@@ -35244,6 +35417,47 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
35244
35417
  text: "Content type not found."
35245
35418
  }
35246
35419
  },
35420
+ connected_accounts: {
35421
+ title: {
35422
+ text: "Connected accounts"
35423
+ },
35424
+ description: {
35425
+ text: "Connect provider accounts so mates can ask for permission before using private app data."
35426
+ },
35427
+ google_calendar_title: {
35428
+ text: "Google Calendar"
35429
+ },
35430
+ loading: {
35431
+ text: "Checking connected accounts..."
35432
+ },
35433
+ connected_count: {
35434
+ text: "{count} connected"
35435
+ },
35436
+ not_connected: {
35437
+ text: "Not connected yet."
35438
+ },
35439
+ connect_button: {
35440
+ text: "Connect Google Calendar"
35441
+ },
35442
+ finalizing: {
35443
+ text: "Encrypting and saving your connected account..."
35444
+ },
35445
+ connected_success: {
35446
+ text: "Google Calendar connected. Your token was encrypted before saving."
35447
+ },
35448
+ sign_in_required: {
35449
+ text: "Sign in again before connecting Google Calendar."
35450
+ },
35451
+ load_error: {
35452
+ text: "Could not load connected accounts."
35453
+ },
35454
+ start_error: {
35455
+ text: "Could not start Google Calendar connection."
35456
+ },
35457
+ finalize_error: {
35458
+ text: "Could not finish connecting Google Calendar."
35459
+ }
35460
+ },
35247
35461
  focus_modes: {
35248
35462
  title: {
35249
35463
  text: "Focus Modes"
@@ -44297,9 +44511,8 @@ function printNewChatSuggestionsList(suggestions) {
44297
44511
  );
44298
44512
  }
44299
44513
  function printNewChatSuggestion(s, index) {
44300
- const appLabel = s.skillId ? `\x1B[36m[${s.appId}-${s.skillId}]\x1B[0m ` : s.appId ? `\x1B[36m[${s.appId}]\x1B[0m ` : "";
44301
44514
  const escapedBody = s.body.replace(/"/g, '\\"');
44302
- process.stdout.write(`\x1B[1m${index}.\x1B[0m ${appLabel}${s.body}
44515
+ process.stdout.write(`\x1B[1m${index}.\x1B[0m ${s.body}
44303
44516
  `);
44304
44517
  process.stdout.write(
44305
44518
  ` \x1B[2mopenmates chats new "${escapedBody}"\x1B[0m
@@ -44958,7 +45171,6 @@ export {
44958
45171
  MATE_NAMES,
44959
45172
  deriveAppUrl,
44960
45173
  OpenMatesClient,
44961
- parseNewChatSuggestionText,
44962
45174
  defaultCloneBranchForVersion,
44963
45175
  serializeToYaml,
44964
45176
  getExtForLang
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getExtForLang,
4
4
  serializeToYaml
5
- } from "./chunk-MWM6T3MG.js";
5
+ } from "./chunk-MCVRDNDO.js";
6
6
  import "./chunk-AXNRPVLE.js";
7
7
  export {
8
8
  getExtForLang,
package/dist/index.d.ts CHANGED
@@ -392,17 +392,11 @@ declare const MATE_NAMES: Record<string, string>;
392
392
  *
393
393
  * Mirrors the format used by NewChatSuggestions.svelte in the web app.
394
394
  * The `body` text is the plain text to insert into the message input.
395
- * The optional `appId` and `skillId` are parsed from the `[app-skill]` prefix
396
- * (e.g. "[web-search] What's the weather today?" → appId="web", skillId="search").
397
395
  */
398
396
  interface DecryptedNewChatSuggestion {
399
397
  id: string;
400
398
  chatId: string | null;
401
399
  body: string;
402
- /** App ID if the suggestion has an [app-skill] or [app] prefix. */
403
- appId: string | null;
404
- /** Skill ID if the suggestion has an [app-skill] prefix. */
405
- skillId: string | null;
406
400
  createdAt: number;
407
401
  }
408
402
  /** A decrypted memory entry as returned to CLI callers. */
@@ -672,6 +666,7 @@ declare class OpenMatesClient {
672
666
  }>;
673
667
  }>;
674
668
  private persistStreamedEmbeds;
669
+ private persistPostProcessingMetadata;
675
670
  /**
676
671
  * Delete a chat by ID.
677
672
  *
@@ -927,7 +922,7 @@ declare class OpenMatesClient {
927
922
  * The sync cache stores encrypted data — decryption is always on-demand.
928
923
  * SECURITY: decrypted user content is NEVER written to disk.
929
924
  */
930
- ensureSynced(forceRefresh?: boolean): Promise<SyncCache>;
925
+ ensureSynced(forceRefresh?: boolean, refreshChatIds?: string[]): Promise<SyncCache>;
931
926
  private prompt;
932
927
  private waitForPairAuthorization;
933
928
  private installPairExitListener;
@@ -963,23 +958,7 @@ interface DocsSearchResult {
963
958
  title: string;
964
959
  snippet: string;
965
960
  }
966
- /**
967
- * Parse the [app-skill] or [app] prefix from a new-chat suggestion text.
968
- *
969
- * Mirrors parseSuggestion() in NewChatSuggestions.svelte (web app).
970
- *
971
- * Examples:
972
- * "[web-search] What's the weather today?" → { body: "What's the weather today?", appId: "web", skillId: "search" }
973
- * "[images-generate] Draw a cat" → { body: "Draw a cat", appId: "images", skillId: "generate" }
974
- * "[web] Open my bookmarks" → { body: "Open my bookmarks", appId: "web", skillId: null }
975
- * "How do I fix this bug?" → { body: "How do I fix this bug?", appId: null, skillId: null }
976
- */
977
- declare function parseNewChatSuggestionText(text: string): {
978
- body: string;
979
- appId: string | null;
980
- skillId: string | null;
981
- };
982
961
 
983
962
  declare function defaultCloneBranchForVersion(version: string): string | null;
984
963
 
985
- export { type AuthMethodsStatus, type BackupCodesResult, type BankTransferOrderDetails, type BankTransferStatus, type CachedChat, type CachedNewChatSuggestion, type ChatListPage, type CliSignupResult, type DecryptedEmbed, type DecryptedMemoryEntry, type DecryptedMessage, type DecryptedNewChatSuggestion, type DocsFile, type DocsFolder, type DocsSearchResult, type DocsTree, type GiftCardBankTransferStatus, MATE_NAMES, MEMORY_TYPE_REGISTRY, type MemoryFieldDef, type MemoryTypeDef, OpenMatesClient, type OpenMatesClientOptions, type OpenMatesSession, type SyncCache, type TotpSetupStartResult, defaultCloneBranchForVersion, deriveAppUrl, parseNewChatSuggestionText };
964
+ export { type AuthMethodsStatus, type BackupCodesResult, type BankTransferOrderDetails, type BankTransferStatus, type CachedChat, type CachedNewChatSuggestion, type ChatListPage, type CliSignupResult, type DecryptedEmbed, type DecryptedMemoryEntry, type DecryptedMessage, type DecryptedNewChatSuggestion, type DocsFile, type DocsFolder, type DocsSearchResult, type DocsTree, type GiftCardBankTransferStatus, MATE_NAMES, MEMORY_TYPE_REGISTRY, type MemoryFieldDef, type MemoryTypeDef, OpenMatesClient, type OpenMatesClientOptions, type OpenMatesSession, type SyncCache, type TotpSetupStartResult, defaultCloneBranchForVersion, deriveAppUrl };
package/dist/index.js CHANGED
@@ -5,9 +5,8 @@ import {
5
5
  defaultCloneBranchForVersion,
6
6
  deriveAppUrl,
7
7
  getExtForLang,
8
- parseNewChatSuggestionText,
9
8
  serializeToYaml
10
- } from "./chunk-MWM6T3MG.js";
9
+ } from "./chunk-MCVRDNDO.js";
11
10
  import "./chunk-AXNRPVLE.js";
12
11
  export {
13
12
  MATE_NAMES,
@@ -16,6 +15,5 @@ export {
16
15
  defaultCloneBranchForVersion,
17
16
  deriveAppUrl,
18
17
  getExtForLang,
19
- parseNewChatSuggestionText,
20
18
  serializeToYaml
21
19
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmates",
3
- "version": "0.12.0-alpha.4",
3
+ "version": "0.12.0-alpha.6",
4
4
  "description": "OpenMates CLI and SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",