gestalt-mobile 0.35.5 → 0.36.0

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.
Files changed (47) hide show
  1. package/README.md +60 -3
  2. package/dist/client/assets/index-9XMv2BvD.js +38 -0
  3. package/dist/client/assets/{index-CPQBJDsg.css → index-Bxv5Z2w4.css} +1 -1
  4. package/dist/client/index.html +2 -2
  5. package/dist/server/client/features/chat/activity-summary.js +71 -0
  6. package/dist/server/client/features/chat/chat-projection.js +722 -0
  7. package/dist/server/client/features/chat/message-store.js +30 -0
  8. package/dist/server/server/app.js +1 -1
  9. package/dist/server/server/cli.js +8 -0
  10. package/dist/server/server/composition.contracts.js +158 -6
  11. package/dist/server/server/composition.js +266 -56
  12. package/dist/server/server/features/autopilot/register-routes.js +2 -2
  13. package/dist/server/server/features/autopilot/toggle/endpoint.js +5 -1
  14. package/dist/server/server/features/catalog/get-bootstrap/use-case.js +5 -3
  15. package/dist/server/server/features/sessions/get-session/endpoint.js +1 -1
  16. package/dist/server/server/features/sessions/list-models/endpoint.js +16 -0
  17. package/dist/server/server/features/sessions/list-recent-threads/endpoint.js +8 -3
  18. package/dist/server/server/features/sessions/list-sessions/endpoint.js +1 -1
  19. package/dist/server/server/features/sessions/model/relay-session.js +2 -0
  20. package/dist/server/server/features/sessions/promote-recent-thread/endpoint.js +6 -2
  21. package/dist/server/server/features/sessions/promote-recent-thread/use-case.js +7 -2
  22. package/dist/server/server/features/sessions/register-routes.js +8 -3
  23. package/dist/server/server/features/sessions/respond-interaction/endpoint.js +1 -1
  24. package/dist/server/server/features/sessions/select-model/endpoint.js +1 -1
  25. package/dist/server/server/features/sessions/start-session/request.js +1 -0
  26. package/dist/server/server/features/sessions/start-session/use-case.js +21 -7
  27. package/dist/server/server/features/skills/list-available/endpoint.js +4 -2
  28. package/dist/server/server/platform/catalog/provider-model-catalog.js +15 -0
  29. package/dist/server/server/platform/kimi/kimi-activity-facts.js +88 -0
  30. package/dist/server/server/platform/kimi/kimi-errors.js +30 -0
  31. package/dist/server/server/platform/kimi/kimi-model-catalog.js +63 -0
  32. package/dist/server/server/platform/kimi/kimi-normalizer.js +196 -0
  33. package/dist/server/server/platform/kimi/kimi-recent-session-lister.js +68 -0
  34. package/dist/server/server/platform/kimi/kimi-server-request.js +143 -0
  35. package/dist/server/server/platform/kimi/kimi-session-runtime.js +653 -0
  36. package/dist/server/server/platform/kimi/kimi-share-dir.js +65 -0
  37. package/dist/server/server/platform/kimi/kimi-skill-catalog.js +79 -0
  38. package/dist/server/server/platform/kimi/kimi-skills-materializer.js +41 -0
  39. package/dist/server/server/platform/kimi/kimi-web-client.js +63 -0
  40. package/dist/server/server/platform/kimi/kimi-web-server-manager.js +215 -0
  41. package/dist/server/server/platform/kimi/kimi-ws-client.js +154 -0
  42. package/dist/server/server/platform/persistence/migrate.js +2 -0
  43. package/dist/server/server/platform/persistence/sqlite-session-repository.js +3 -2
  44. package/dist/server/server/platform/skills/cached-skill-catalog.js +0 -0
  45. package/dist/server/shared/contracts/llm-provider.js +6 -0
  46. package/package.json +4 -3
  47. package/dist/client/assets/index-SZM7lpix.js +0 -38
@@ -0,0 +1,143 @@
1
+ /*
2
+ * Copyright (C) 2026 Dyne.org foundation
3
+ * Designed by Denis Roio <jaromil@dyne.org>
4
+ * SPDX-License-Identifier: AGPL-3.0-or-later
5
+ */
6
+ function safeId(value) {
7
+ return typeof value === 'string' && value.length > 0 && value.length <= 256 ? value : undefined;
8
+ }
9
+ function bounded(value, max = 1_000) {
10
+ if (typeof value !== 'string')
11
+ return '';
12
+ return value.slice(0, max);
13
+ }
14
+ function displayText(display) {
15
+ if (!display || typeof display !== 'object')
16
+ return '';
17
+ const record = display;
18
+ for (const key of ['command', 'path', 'detail', 'description', 'text']) {
19
+ if (typeof record[key] === 'string')
20
+ return bounded(record[key], 500);
21
+ }
22
+ try {
23
+ return bounded(JSON.stringify(display), 500);
24
+ }
25
+ catch {
26
+ return '';
27
+ }
28
+ }
29
+ /** Command-shaped approvals steer to commandExecution; file mutations to fileChange. */
30
+ export function approvalToServerRequest(id, item) {
31
+ const approvalId = safeId(item.approval_id);
32
+ if (!approvalId)
33
+ return null;
34
+ const toolName = (item.tool_name ?? '').toLowerCase();
35
+ const fileLike = /file|write|edit|patch|str_replace|apply|notebook/.test(toolName);
36
+ const detail = displayText(item.tool_input_display);
37
+ return {
38
+ id,
39
+ method: fileLike ? 'item/fileChange/requestApproval' : 'item/commandExecution/requestApproval',
40
+ params: {
41
+ itemId: approvalId,
42
+ ...(item.tool_name ? { toolName: bounded(item.tool_name, 128) } : {}),
43
+ ...(item.action ? { reason: bounded(item.action, 256) } : {}),
44
+ ...(detail ? { [fileLike ? 'changes' : 'command']: detail } : {}),
45
+ },
46
+ };
47
+ }
48
+ export function questionToServerRequest(id, item) {
49
+ const questionId = safeId(item.question_id);
50
+ if (!questionId)
51
+ return null;
52
+ const questions = (item.questions ?? []).flatMap((question) => {
53
+ if (!safeId(question.id) || typeof question.question !== 'string')
54
+ return [];
55
+ return [
56
+ {
57
+ id: question.id,
58
+ question: bounded(question.question, 1_000),
59
+ ...(question.header ? { header: bounded(question.header, 200) } : {}),
60
+ ...(question.body ? { body: bounded(question.body, 2_000) } : {}),
61
+ ...(question.options && question.options.length
62
+ ? {
63
+ options: question.options.flatMap((option) => safeId(option.id) && typeof option.label === 'string'
64
+ ? [
65
+ {
66
+ id: option.id,
67
+ label: bounded(option.label, 200),
68
+ ...(option.description
69
+ ? { description: bounded(option.description, 500) }
70
+ : {}),
71
+ },
72
+ ]
73
+ : []),
74
+ }
75
+ : {}),
76
+ },
77
+ ];
78
+ });
79
+ return {
80
+ id,
81
+ method: 'item/tool/requestUserInput',
82
+ params: { questions },
83
+ };
84
+ }
85
+ /** Translates a relay approval decision into a kimi approval decision. */
86
+ export function kimiApprovalDecision(value) {
87
+ if (value === 'accept' || value === 'acceptForSession')
88
+ return 'approved';
89
+ if (value === 'decline')
90
+ return 'rejected';
91
+ if (value === 'cancel')
92
+ return 'cancelled';
93
+ return null;
94
+ }
95
+ /**
96
+ * Translates a relay userInput response (`{answers: {<qid>: {answers: string[]}}}`)
97
+ * into kimi's question answers map. An answer matching an option id or label
98
+ * becomes a single choice; anything else becomes free text.
99
+ */
100
+ export function kimiQuestionAnswers(item, value) {
101
+ if (!value || typeof value !== 'object')
102
+ return null;
103
+ const answers = value.answers;
104
+ if (!answers || typeof answers !== 'object' || Array.isArray(answers))
105
+ return null;
106
+ const result = {};
107
+ for (const [questionId, rawAnswer] of Object.entries(answers)) {
108
+ const reply = rawAnswer && typeof rawAnswer === 'object' ? rawAnswer : {};
109
+ const texts = Array.isArray(reply.answers)
110
+ ? reply.answers.filter((entry) => typeof entry === 'string')
111
+ : [];
112
+ if (!texts.length) {
113
+ result[questionId] = { kind: 'skipped' };
114
+ continue;
115
+ }
116
+ const question = (item.questions ?? []).find((candidate) => candidate.id === questionId);
117
+ const option = question?.options?.find((candidate) => candidate.id === texts[0] || candidate.label === texts[0]);
118
+ result[questionId] = option
119
+ ? { kind: 'single', option_id: option.id }
120
+ : { kind: 'other', text: texts.join('\n').slice(0, 4_000) };
121
+ }
122
+ return Object.keys(result).length ? result : null;
123
+ }
124
+ export function decodeApprovalItems(data) {
125
+ const items = data?.items;
126
+ if (!Array.isArray(items))
127
+ return [];
128
+ return items.filter((item) => {
129
+ if (!item || typeof item !== 'object')
130
+ return false;
131
+ return safeId(item.approval_id) !== undefined;
132
+ });
133
+ }
134
+ export function decodeQuestionItems(data) {
135
+ const items = data?.items;
136
+ if (!Array.isArray(items))
137
+ return [];
138
+ return items.filter((item) => {
139
+ if (!item || typeof item !== 'object')
140
+ return false;
141
+ return safeId(item.question_id) !== undefined;
142
+ });
143
+ }