gestalt-mobile 0.12.0 → 0.14.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.
- package/README.md +42 -11
- package/dist/client/assets/index-C5qFcFUg.css +1 -0
- package/dist/client/assets/index-tMyOolAm.js +24 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-ext-400-normal-Bh0R7Dhr.woff +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-ext-400-normal-C_uLvvQ5.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-ByoDsISC.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/client/assets/syne-greek-600-normal-BJs4kvyH.woff +0 -0
- package/dist/client/assets/syne-greek-600-normal-BpFII5Ja.woff2 +0 -0
- package/dist/client/assets/syne-latin-600-normal-BiwQbQXw.woff2 +0 -0
- package/dist/client/assets/syne-latin-600-normal-dRu9QuIh.woff +0 -0
- package/dist/client/assets/syne-latin-ext-600-normal-DEzBMW8B.woff +0 -0
- package/dist/client/assets/syne-latin-ext-600-normal-ZnizrDKU.woff2 +0 -0
- package/dist/client/index.html +3 -2
- package/dist/server/server/app.js +22 -227
- package/dist/server/server/cli.js +3 -1
- package/dist/server/server/composition.js +25 -26
- package/dist/server/server/features/auth/application/ceremony-attempts.js +22 -0
- package/dist/server/server/features/auth/devices/revoke/endpoint.js +3 -1
- package/dist/server/server/features/auth/domain/errors.js +7 -0
- package/dist/server/server/features/auth/enrollment-tickets/endpoint.js +7 -2
- package/dist/server/server/features/auth/enrollment-tickets/status/endpoint.js +3 -1
- package/dist/server/server/features/auth/http/cookies.js +20 -0
- package/dist/server/server/features/auth/login/options/endpoint.js +22 -20
- package/dist/server/server/features/auth/login/verify/endpoint.js +6 -14
- package/dist/server/server/features/auth/logout/endpoint.js +2 -6
- package/dist/server/server/features/auth/register/options/endpoint.js +43 -11
- package/dist/server/server/features/auth/register/verify/endpoint.js +74 -18
- package/dist/server/server/features/auth/register-routes.js +41 -0
- package/dist/server/server/features/git/checkout-branch/endpoint.js +1 -1
- package/dist/server/server/features/git/clone-repository/endpoint.js +1 -1
- package/dist/server/server/features/git/register-routes.js +34 -0
- package/dist/server/server/features/plans/application/measurement-snapshot.js +1 -1
- package/dist/server/server/features/plans/get-measurement/endpoint.js +1 -3
- package/dist/server/server/features/plans/register-routes.js +22 -0
- package/dist/server/server/features/sessions/interaction/kind.js +7 -1
- package/dist/server/server/features/sessions/list-recent-threads/endpoint.js +3 -1
- package/dist/server/server/features/sessions/model/relay-session.js +3 -1
- package/dist/server/server/features/sessions/promote-recent-thread/endpoint.js +1 -1
- package/dist/server/server/features/sessions/register-routes.js +138 -0
- package/dist/server/server/features/sessions/respond-interaction/endpoint.js +1 -1
- package/dist/server/server/features/sessions/select-model/endpoint.js +1 -1
- package/dist/server/server/features/sessions/start-session/endpoint.js +5 -2
- package/dist/server/server/features/sessions/start-session/use-case.js +1 -1
- package/dist/server/server/features/sessions/start-turn/endpoint.js +2 -1
- package/dist/server/server/features/skills/delete-profile/endpoint.js +12 -3
- package/dist/server/server/features/skills/list-available/endpoint.js +24 -6
- package/dist/server/server/features/skills/list-profiles/endpoint.js +29 -5
- package/dist/server/server/features/skills/model/skill-profile.js +23 -3
- package/dist/server/server/features/skills/register-routes.js +17 -0
- package/dist/server/server/features/skills/replace-profile/endpoint.js +20 -5
- package/dist/server/server/platform/auth/simple-webauthn-adapter.js +23 -3
- package/dist/server/server/platform/auth/sqlite-authorization-store.js +29 -6
- package/dist/server/server/platform/catalog/profile-command.js +8 -1
- package/dist/server/server/platform/codex/normalizer.js +50 -6
- package/dist/server/server/platform/codex/protocol-compatibility.js +19 -1
- package/dist/server/server/platform/codex/server-request.js +2 -0
- package/dist/server/server/platform/codex/session-runtime.js +235 -126
- package/dist/server/server/platform/codex/thread-plan-name.js +5 -2
- package/dist/server/server/platform/http/problem-handler.js +10 -0
- package/dist/server/server/platform/http/problem-reply.js +13 -0
- package/dist/server/server/platform/plans/filesystem-plan-status-source.js +11 -6
- package/dist/server/server/platform/plans/filesystem-workspace-plan-catalog.js +4 -1
- package/dist/server/server/platform/plans/plan-measurement-command.js +4 -1
- package/dist/server/server/platform/skills/codex-skill-catalog.js +29 -7
- package/dist/server/server/platform/skills/filesystem-skill-profile-store.js +5 -1
- package/dist/server/shared/contracts/quiz.js +30 -9
- package/package.json +4 -1
- package/dist/client/assets/index-B7KwEjTE.js +0 -19
- package/dist/client/assets/index-CMs5ZzxJ.css +0 -1
- package/dist/server/server/features/plans/application/native-plan-alignment.js +0 -39
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { resolve } from 'node:path';
|
|
8
|
-
import { availableSkillSchema } from '../../features/skills/model/skill-profile.js';
|
|
8
|
+
import { availableSkillSchema, } from '../../features/skills/model/skill-profile.js';
|
|
9
9
|
import { SkillProfileError } from '../../features/skills/model/errors.js';
|
|
10
10
|
import { launchCodexAppServer } from '../codex/codex-process-launcher.js';
|
|
11
11
|
const optionalString = z.preprocess((value) => (value === null ? undefined : value), z.string().optional());
|
|
@@ -19,12 +19,25 @@ const toolSchema = z.object({
|
|
|
19
19
|
url: optionalString,
|
|
20
20
|
});
|
|
21
21
|
const wireSkillSchema = z.object({
|
|
22
|
-
name: z.string(),
|
|
23
|
-
|
|
22
|
+
name: z.string(),
|
|
23
|
+
description: z.string(),
|
|
24
|
+
shortDescription: optionalString,
|
|
25
|
+
interface: optionalObject(z.object({
|
|
26
|
+
displayName: optionalString,
|
|
27
|
+
shortDescription: optionalString,
|
|
28
|
+
iconSmall: optionalString,
|
|
29
|
+
iconLarge: optionalString,
|
|
30
|
+
brandColor: optionalString,
|
|
31
|
+
defaultPrompt: optionalString,
|
|
32
|
+
})),
|
|
24
33
|
dependencies: optionalObject(z.object({ tools: optionalObject(z.array(toolSchema)) })),
|
|
25
|
-
path: z.string(),
|
|
34
|
+
path: z.string(),
|
|
35
|
+
scope: optionalString,
|
|
36
|
+
enabled: z.boolean(),
|
|
37
|
+
});
|
|
38
|
+
const resultSchema = z.object({
|
|
39
|
+
data: z.array(z.object({ cwd: z.string(), skills: z.array(wireSkillSchema), errors: z.array(z.unknown()) })),
|
|
26
40
|
});
|
|
27
|
-
const resultSchema = z.object({ data: z.array(z.object({ cwd: z.string(), skills: z.array(wireSkillSchema), errors: z.array(z.unknown()) })) });
|
|
28
41
|
/** Short-lived Codex app-server adapter: initialize, discover, and always terminate. */
|
|
29
42
|
export class CodexSkillCatalog {
|
|
30
43
|
profile;
|
|
@@ -58,7 +71,14 @@ export class CodexSkillCatalog {
|
|
|
58
71
|
});
|
|
59
72
|
return {
|
|
60
73
|
skills,
|
|
61
|
-
errors: entry.errors.map((error) => ({
|
|
74
|
+
errors: entry.errors.map((error) => ({
|
|
75
|
+
message: typeof error === 'object' &&
|
|
76
|
+
error !== null &&
|
|
77
|
+
'message' in error &&
|
|
78
|
+
typeof error.message === 'string'
|
|
79
|
+
? error.message
|
|
80
|
+
: 'Codex skill discovery error.',
|
|
81
|
+
})),
|
|
62
82
|
};
|
|
63
83
|
}
|
|
64
84
|
catch (error) {
|
|
@@ -75,7 +95,9 @@ export class CodexSkillCatalog {
|
|
|
75
95
|
try {
|
|
76
96
|
return await Promise.race([
|
|
77
97
|
promise,
|
|
78
|
-
new Promise((_, reject) => {
|
|
98
|
+
new Promise((_, reject) => {
|
|
99
|
+
timer = setTimeout(() => reject(new Error('timeout')), this.timeoutMs);
|
|
100
|
+
}),
|
|
79
101
|
]);
|
|
80
102
|
}
|
|
81
103
|
finally {
|
|
@@ -55,7 +55,11 @@ export class FilesystemSkillProfileStore {
|
|
|
55
55
|
const destination = join(root, `${name}.yml`);
|
|
56
56
|
const temporary = join(root, `.${name}.${randomUUID()}.tmp`);
|
|
57
57
|
try {
|
|
58
|
-
await writeFile(temporary, serializeSkillProfileYaml(profile), {
|
|
58
|
+
await writeFile(temporary, serializeSkillProfileYaml(profile), {
|
|
59
|
+
encoding: 'utf8',
|
|
60
|
+
mode: 0o600,
|
|
61
|
+
flag: 'wx',
|
|
62
|
+
});
|
|
59
63
|
await rename(temporary, destination);
|
|
60
64
|
}
|
|
61
65
|
finally {
|
|
@@ -26,7 +26,12 @@ export const gestaltQuizDynamicTool = {
|
|
|
26
26
|
additionalProperties: false,
|
|
27
27
|
required: ['id', 'header', 'question', 'choices', 'allowCustom'],
|
|
28
28
|
properties: {
|
|
29
|
-
id: {
|
|
29
|
+
id: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
minLength: 1,
|
|
32
|
+
maxLength: 64,
|
|
33
|
+
pattern: '^[A-Za-z][A-Za-z0-9_-]*$',
|
|
34
|
+
},
|
|
30
35
|
header: { type: 'string', minLength: 1, maxLength: 120 },
|
|
31
36
|
question: { type: 'string', minLength: 1, maxLength: 600 },
|
|
32
37
|
choices: {
|
|
@@ -61,7 +66,9 @@ export function parseQuiz(value, minimumChoices = 2) {
|
|
|
61
66
|
if (questions.some((question) => question === null))
|
|
62
67
|
return null;
|
|
63
68
|
const parsed = questions;
|
|
64
|
-
return new Set(parsed.map((question) => question.id)).size === parsed.length
|
|
69
|
+
return new Set(parsed.map((question) => question.id)).size === parsed.length
|
|
70
|
+
? { questions: parsed }
|
|
71
|
+
: null;
|
|
65
72
|
}
|
|
66
73
|
/** Maps Codex's experimental native request shape into the common quiz value. */
|
|
67
74
|
export function mapNativeUserInputToQuiz(value) {
|
|
@@ -87,7 +94,9 @@ export function toQuizToolResponse(answers) {
|
|
|
87
94
|
{
|
|
88
95
|
type: 'input_text',
|
|
89
96
|
text: JSON.stringify({
|
|
90
|
-
answers: Object.fromEntries(answers
|
|
97
|
+
answers: Object.fromEntries(answers
|
|
98
|
+
.filter((answer) => answer.answer.trim())
|
|
99
|
+
.map((answer) => [answer.id, answer.answer])),
|
|
91
100
|
}),
|
|
92
101
|
},
|
|
93
102
|
],
|
|
@@ -98,7 +107,10 @@ export function isQuizToolResponseForQuiz(quiz, value) {
|
|
|
98
107
|
if (!isRecord(value) || value.success !== true || !Array.isArray(value.contentItems))
|
|
99
108
|
return false;
|
|
100
109
|
const item = value.contentItems[0];
|
|
101
|
-
if (value.contentItems.length !== 1 ||
|
|
110
|
+
if (value.contentItems.length !== 1 ||
|
|
111
|
+
!isRecord(item) ||
|
|
112
|
+
item.type !== 'input_text' ||
|
|
113
|
+
typeof item.text !== 'string')
|
|
102
114
|
return false;
|
|
103
115
|
try {
|
|
104
116
|
const response = parseQuizResponse(JSON.parse(item.text));
|
|
@@ -109,9 +121,14 @@ export function isQuizToolResponseForQuiz(quiz, value) {
|
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
function parseQuestion(value, minimumChoices) {
|
|
112
|
-
if (!isRecord(value) ||
|
|
124
|
+
if (!isRecord(value) ||
|
|
125
|
+
!Array.isArray(value.choices) ||
|
|
126
|
+
value.choices.length < minimumChoices ||
|
|
127
|
+
value.choices.length > 5)
|
|
113
128
|
return null;
|
|
114
|
-
if (!isQuestionId(value.id) ||
|
|
129
|
+
if (!isQuestionId(value.id) ||
|
|
130
|
+
!isBoundedText(value.header, 120) ||
|
|
131
|
+
!isBoundedText(value.question, 600))
|
|
115
132
|
return null;
|
|
116
133
|
if (typeof value.allowCustom !== 'boolean')
|
|
117
134
|
return null;
|
|
@@ -128,7 +145,9 @@ function parseQuestion(value, minimumChoices) {
|
|
|
128
145
|
};
|
|
129
146
|
}
|
|
130
147
|
function parseChoice(value) {
|
|
131
|
-
if (!isRecord(value) ||
|
|
148
|
+
if (!isRecord(value) ||
|
|
149
|
+
!isBoundedText(value.label, 160) ||
|
|
150
|
+
!isBoundedText(value.description, 600))
|
|
132
151
|
return null;
|
|
133
152
|
return { label: value.label, description: value.description };
|
|
134
153
|
}
|
|
@@ -136,13 +155,15 @@ function parseQuizResponse(value) {
|
|
|
136
155
|
if (!isRecord(value) || !isRecord(value.answers))
|
|
137
156
|
return null;
|
|
138
157
|
const entries = Object.entries(value.answers);
|
|
139
|
-
if (entries.length === 0 ||
|
|
158
|
+
if (entries.length === 0 ||
|
|
159
|
+
entries.some(([id, answer]) => !isQuestionId(id) || !isBoundedText(answer, 2_000)))
|
|
140
160
|
return null;
|
|
141
161
|
return { answers: Object.fromEntries(entries) };
|
|
142
162
|
}
|
|
143
163
|
function isCompleteQuizResponse(quiz, response) {
|
|
144
164
|
const ids = Object.keys(response.answers);
|
|
145
|
-
if (ids.length !== quiz.questions.length ||
|
|
165
|
+
if (ids.length !== quiz.questions.length ||
|
|
166
|
+
ids.some((id) => !quiz.questions.some((question) => question.id === id)))
|
|
146
167
|
return false;
|
|
147
168
|
return quiz.questions.every((question) => {
|
|
148
169
|
const answer = response.answers[question.id];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gestalt-mobile",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Mobile-first web relay for durable Codex development sessions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"format": "prettier --write .",
|
|
46
46
|
"format:check": "prettier --check .",
|
|
47
47
|
"test": "vitest run",
|
|
48
|
+
"audit:prod": "npm audit --omit=dev --audit-level=high",
|
|
48
49
|
"test:open-profile-smoke": "tsx scripts/open-profile-smoke.ts",
|
|
49
50
|
"test:watch": "vitest",
|
|
50
51
|
"test:package": "node scripts/smoke-packed-cli.mjs",
|
|
@@ -57,6 +58,8 @@
|
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@fastify/cookie": "11.1.2",
|
|
59
60
|
"@fastify/static": "^10.1.0",
|
|
61
|
+
"@fontsource/jetbrains-mono": "5.2.7",
|
|
62
|
+
"@fontsource/syne": "5.2.7",
|
|
60
63
|
"@simplewebauthn/browser": "13.3.0",
|
|
61
64
|
"@simplewebauthn/server": "13.3.2",
|
|
62
65
|
"fastify": "^5.10.0",
|