@ottocode/server 0.1.259 → 0.1.261
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/package.json +4 -3
- package/src/index.ts +5 -4
- package/src/openapi/register.ts +92 -0
- package/src/openapi/route.ts +22 -0
- package/src/routes/ask.ts +210 -99
- package/src/routes/auth.ts +1701 -626
- package/src/routes/branch.ts +281 -90
- package/src/routes/config/agents.ts +79 -32
- package/src/routes/config/cwd.ts +46 -14
- package/src/routes/config/debug.ts +159 -30
- package/src/routes/config/defaults.ts +182 -64
- package/src/routes/config/main.ts +109 -73
- package/src/routes/config/models.ts +304 -137
- package/src/routes/config/providers.ts +462 -166
- package/src/routes/config/utils.ts +2 -2
- package/src/routes/doctor.ts +395 -161
- package/src/routes/files.ts +650 -260
- package/src/routes/git/branch.ts +143 -52
- package/src/routes/git/commit.ts +347 -141
- package/src/routes/git/diff.ts +239 -116
- package/src/routes/git/init.ts +103 -23
- package/src/routes/git/pull.ts +167 -65
- package/src/routes/git/push.ts +222 -117
- package/src/routes/git/remote.ts +401 -100
- package/src/routes/git/staging.ts +502 -141
- package/src/routes/git/status.ts +171 -78
- package/src/routes/mcp.ts +1129 -404
- package/src/routes/openapi.ts +27 -4
- package/src/routes/ottorouter.ts +1221 -389
- package/src/routes/provider-usage.ts +153 -36
- package/src/routes/research.ts +817 -370
- package/src/routes/root.ts +50 -6
- package/src/routes/session-approval.ts +228 -54
- package/src/routes/session-files.ts +265 -134
- package/src/routes/session-messages.ts +330 -150
- package/src/routes/session-stream.ts +83 -2
- package/src/routes/sessions.ts +1830 -780
- package/src/routes/skills.ts +849 -161
- package/src/routes/terminals.ts +469 -103
- package/src/routes/tunnel.ts +394 -118
- package/src/runtime/agent/runner-reasoning.ts +38 -3
- package/src/runtime/agent/runner.ts +1 -0
- package/src/runtime/ask/service.ts +1 -0
- package/src/runtime/message/compaction-limits.ts +3 -3
- package/src/runtime/provider/reasoning.ts +18 -7
- package/src/runtime/session/db-operations.ts +4 -3
- package/src/runtime/utils/token.ts +7 -2
- package/src/tools/adapter.ts +21 -0
- package/src/openapi/paths/ask.ts +0 -81
- package/src/openapi/paths/auth.ts +0 -687
- package/src/openapi/paths/branch.ts +0 -102
- package/src/openapi/paths/config.ts +0 -485
- package/src/openapi/paths/doctor.ts +0 -165
- package/src/openapi/paths/files.ts +0 -236
- package/src/openapi/paths/git.ts +0 -690
- package/src/openapi/paths/mcp.ts +0 -339
- package/src/openapi/paths/messages.ts +0 -103
- package/src/openapi/paths/ottorouter.ts +0 -594
- package/src/openapi/paths/provider-usage.ts +0 -59
- package/src/openapi/paths/research.ts +0 -227
- package/src/openapi/paths/session-approval.ts +0 -93
- package/src/openapi/paths/session-extras.ts +0 -336
- package/src/openapi/paths/session-files.ts +0 -91
- package/src/openapi/paths/sessions.ts +0 -210
- package/src/openapi/paths/skills.ts +0 -377
- package/src/openapi/paths/stream.ts +0 -26
- package/src/openapi/paths/terminals.ts +0 -226
- package/src/openapi/paths/tunnel.ts +0 -163
- package/src/openapi/spec.ts +0 -73
package/src/routes/branch.ts
CHANGED
|
@@ -8,100 +8,291 @@ import {
|
|
|
8
8
|
getParentSession,
|
|
9
9
|
} from '../runtime/session/branch.ts';
|
|
10
10
|
import { serializeError } from '../runtime/errors/api-error.ts';
|
|
11
|
+
import { openApiRoute } from '../openapi/route.ts';
|
|
11
12
|
|
|
12
13
|
export function registerBranchRoutes(app: Hono) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
openApiRoute(
|
|
15
|
+
app,
|
|
16
|
+
{
|
|
17
|
+
method: 'post',
|
|
18
|
+
path: '/v1/sessions/{sessionId}/branch',
|
|
19
|
+
tags: ['sessions'],
|
|
20
|
+
operationId: 'createBranch',
|
|
21
|
+
summary: 'Create a branch from a session message',
|
|
22
|
+
parameters: [
|
|
23
|
+
{
|
|
24
|
+
in: 'path',
|
|
25
|
+
name: 'sessionId',
|
|
26
|
+
required: true,
|
|
27
|
+
schema: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
in: 'query',
|
|
33
|
+
name: 'project',
|
|
34
|
+
required: false,
|
|
35
|
+
schema: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
},
|
|
38
|
+
description:
|
|
39
|
+
'Project root override (defaults to current working directory).',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
requestBody: {
|
|
43
|
+
required: true,
|
|
44
|
+
content: {
|
|
45
|
+
'application/json': {
|
|
46
|
+
schema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
fromMessageId: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
},
|
|
52
|
+
provider: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
},
|
|
55
|
+
model: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
},
|
|
58
|
+
agent: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
},
|
|
61
|
+
title: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ['fromMessageId'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
responses: {
|
|
71
|
+
'201': {
|
|
72
|
+
description: 'Created',
|
|
73
|
+
content: {
|
|
74
|
+
'application/json': {
|
|
75
|
+
schema: {
|
|
76
|
+
$ref: '#/components/schemas/Session',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
'400': {
|
|
82
|
+
description: 'Bad Request',
|
|
83
|
+
content: {
|
|
84
|
+
'application/json': {
|
|
85
|
+
schema: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
error: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
required: ['error'],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
async (c) => {
|
|
100
|
+
try {
|
|
101
|
+
const sessionId = c.req.param('sessionId');
|
|
102
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
103
|
+
const cfg = await loadConfig(projectRoot);
|
|
104
|
+
const db = await getDb(cfg.projectRoot);
|
|
105
|
+
|
|
106
|
+
const body = (await c.req.json().catch(() => ({}))) as Record<
|
|
107
|
+
string,
|
|
108
|
+
unknown
|
|
109
|
+
>;
|
|
110
|
+
|
|
111
|
+
const fromMessageId = body.fromMessageId;
|
|
112
|
+
if (typeof fromMessageId !== 'string' || !fromMessageId.trim()) {
|
|
113
|
+
return c.json({ error: 'fromMessageId is required' }, 400);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const provider =
|
|
117
|
+
typeof body.provider === 'string' &&
|
|
118
|
+
hasConfiguredProvider(cfg, body.provider)
|
|
119
|
+
? body.provider
|
|
120
|
+
: undefined;
|
|
121
|
+
|
|
122
|
+
const model =
|
|
123
|
+
typeof body.model === 'string' && body.model.trim()
|
|
124
|
+
? body.model.trim()
|
|
125
|
+
: undefined;
|
|
126
|
+
|
|
127
|
+
const agent =
|
|
128
|
+
typeof body.agent === 'string' && body.agent.trim()
|
|
129
|
+
? body.agent.trim()
|
|
130
|
+
: undefined;
|
|
131
|
+
|
|
132
|
+
const title =
|
|
133
|
+
typeof body.title === 'string' && body.title.trim()
|
|
134
|
+
? body.title.trim()
|
|
135
|
+
: undefined;
|
|
136
|
+
|
|
137
|
+
const result = await createBranch({
|
|
138
|
+
db,
|
|
139
|
+
parentSessionId: sessionId,
|
|
140
|
+
fromMessageId: fromMessageId.trim(),
|
|
141
|
+
provider,
|
|
142
|
+
model,
|
|
143
|
+
agent,
|
|
144
|
+
title,
|
|
145
|
+
projectPath: cfg.projectRoot,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return c.json(result, 201);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
logger.error('Failed to create branch', err);
|
|
151
|
+
const errorResponse = serializeError(err);
|
|
152
|
+
return c.json(errorResponse, errorResponse.error.status || 400);
|
|
28
153
|
}
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
openApiRoute(
|
|
158
|
+
app,
|
|
159
|
+
{
|
|
160
|
+
method: 'get',
|
|
161
|
+
path: '/v1/sessions/{sessionId}/branches',
|
|
162
|
+
tags: ['sessions'],
|
|
163
|
+
operationId: 'listBranches',
|
|
164
|
+
summary: 'List branches of a session',
|
|
165
|
+
parameters: [
|
|
166
|
+
{
|
|
167
|
+
in: 'path',
|
|
168
|
+
name: 'sessionId',
|
|
169
|
+
required: true,
|
|
170
|
+
schema: {
|
|
171
|
+
type: 'string',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
in: 'query',
|
|
176
|
+
name: 'project',
|
|
177
|
+
required: false,
|
|
178
|
+
schema: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
},
|
|
181
|
+
description:
|
|
182
|
+
'Project root override (defaults to current working directory).',
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
responses: {
|
|
186
|
+
'200': {
|
|
187
|
+
description: 'OK',
|
|
188
|
+
content: {
|
|
189
|
+
'application/json': {
|
|
190
|
+
schema: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {
|
|
193
|
+
branches: {
|
|
194
|
+
type: 'array',
|
|
195
|
+
items: {
|
|
196
|
+
$ref: '#/components/schemas/Session',
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
required: ['branches'],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
async (c) => {
|
|
208
|
+
try {
|
|
209
|
+
const sessionId = c.req.param('sessionId');
|
|
210
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
211
|
+
const cfg = await loadConfig(projectRoot);
|
|
212
|
+
const db = await getDb(cfg.projectRoot);
|
|
29
213
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
typeof body.model === 'string' && body.model.trim()
|
|
38
|
-
? body.model.trim()
|
|
39
|
-
: undefined;
|
|
40
|
-
|
|
41
|
-
const agent =
|
|
42
|
-
typeof body.agent === 'string' && body.agent.trim()
|
|
43
|
-
? body.agent.trim()
|
|
44
|
-
: undefined;
|
|
45
|
-
|
|
46
|
-
const title =
|
|
47
|
-
typeof body.title === 'string' && body.title.trim()
|
|
48
|
-
? body.title.trim()
|
|
49
|
-
: undefined;
|
|
50
|
-
|
|
51
|
-
const result = await createBranch({
|
|
52
|
-
db,
|
|
53
|
-
parentSessionId: sessionId,
|
|
54
|
-
fromMessageId: fromMessageId.trim(),
|
|
55
|
-
provider,
|
|
56
|
-
model,
|
|
57
|
-
agent,
|
|
58
|
-
title,
|
|
59
|
-
projectPath: cfg.projectRoot,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return c.json(result, 201);
|
|
63
|
-
} catch (err) {
|
|
64
|
-
logger.error('Failed to create branch', err);
|
|
65
|
-
const errorResponse = serializeError(err);
|
|
66
|
-
return c.json(errorResponse, errorResponse.error.status || 400);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
app.get('/v1/sessions/:sessionId/branches', async (c) => {
|
|
71
|
-
try {
|
|
72
|
-
const sessionId = c.req.param('sessionId');
|
|
73
|
-
const projectRoot = c.req.query('project') || process.cwd();
|
|
74
|
-
const cfg = await loadConfig(projectRoot);
|
|
75
|
-
const db = await getDb(cfg.projectRoot);
|
|
76
|
-
|
|
77
|
-
const branches = await listBranches(db, sessionId, cfg.projectRoot);
|
|
78
|
-
|
|
79
|
-
return c.json({ branches });
|
|
80
|
-
} catch (err) {
|
|
81
|
-
logger.error('Failed to list branches', err);
|
|
82
|
-
const errorResponse = serializeError(err);
|
|
83
|
-
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
app.get('/v1/sessions/:sessionId/parent', async (c) => {
|
|
88
|
-
try {
|
|
89
|
-
const sessionId = c.req.param('sessionId');
|
|
90
|
-
const projectRoot = c.req.query('project') || process.cwd();
|
|
91
|
-
const cfg = await loadConfig(projectRoot);
|
|
92
|
-
const db = await getDb(cfg.projectRoot);
|
|
93
|
-
|
|
94
|
-
const parent = await getParentSession(db, sessionId, cfg.projectRoot);
|
|
95
|
-
|
|
96
|
-
if (!parent) {
|
|
97
|
-
return c.json({ parent: null });
|
|
214
|
+
const branches = await listBranches(db, sessionId, cfg.projectRoot);
|
|
215
|
+
|
|
216
|
+
return c.json({ branches });
|
|
217
|
+
} catch (err) {
|
|
218
|
+
logger.error('Failed to list branches', err);
|
|
219
|
+
const errorResponse = serializeError(err);
|
|
220
|
+
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
98
221
|
}
|
|
222
|
+
},
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
openApiRoute(
|
|
226
|
+
app,
|
|
227
|
+
{
|
|
228
|
+
method: 'get',
|
|
229
|
+
path: '/v1/sessions/{sessionId}/parent',
|
|
230
|
+
tags: ['sessions'],
|
|
231
|
+
operationId: 'getParentSession',
|
|
232
|
+
summary: 'Get parent session of a branch',
|
|
233
|
+
parameters: [
|
|
234
|
+
{
|
|
235
|
+
in: 'path',
|
|
236
|
+
name: 'sessionId',
|
|
237
|
+
required: true,
|
|
238
|
+
schema: {
|
|
239
|
+
type: 'string',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
in: 'query',
|
|
244
|
+
name: 'project',
|
|
245
|
+
required: false,
|
|
246
|
+
schema: {
|
|
247
|
+
type: 'string',
|
|
248
|
+
},
|
|
249
|
+
description:
|
|
250
|
+
'Project root override (defaults to current working directory).',
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
responses: {
|
|
254
|
+
'200': {
|
|
255
|
+
description: 'OK',
|
|
256
|
+
content: {
|
|
257
|
+
'application/json': {
|
|
258
|
+
schema: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
properties: {
|
|
261
|
+
parent: {
|
|
262
|
+
nullable: true,
|
|
263
|
+
allOf: [
|
|
264
|
+
{
|
|
265
|
+
$ref: '#/components/schemas/Session',
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
required: ['parent'],
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
async (c) => {
|
|
278
|
+
try {
|
|
279
|
+
const sessionId = c.req.param('sessionId');
|
|
280
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
281
|
+
const cfg = await loadConfig(projectRoot);
|
|
282
|
+
const db = await getDb(cfg.projectRoot);
|
|
99
283
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
284
|
+
const parent = await getParentSession(db, sessionId, cfg.projectRoot);
|
|
285
|
+
|
|
286
|
+
if (!parent) {
|
|
287
|
+
return c.json({ parent: null });
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return c.json({ parent });
|
|
291
|
+
} catch (err) {
|
|
292
|
+
logger.error('Failed to get parent session', err);
|
|
293
|
+
const errorResponse = serializeError(err);
|
|
294
|
+
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
);
|
|
107
298
|
}
|
|
@@ -4,43 +4,90 @@ import type { EmbeddedAppConfig } from '../../index.ts';
|
|
|
4
4
|
import { logger } from '@ottocode/sdk';
|
|
5
5
|
import { serializeError } from '../../runtime/errors/api-error.ts';
|
|
6
6
|
import { discoverAllAgents, getDefault } from './utils.ts';
|
|
7
|
+
import { openApiRoute } from '../../openapi/route.ts';
|
|
7
8
|
|
|
8
9
|
export function registerAgentsRoute(app: Hono) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
openApiRoute(
|
|
11
|
+
app,
|
|
12
|
+
{
|
|
13
|
+
method: 'get',
|
|
14
|
+
path: '/v1/config/agents',
|
|
15
|
+
tags: ['config'],
|
|
16
|
+
operationId: 'getAgents',
|
|
17
|
+
summary: 'Get available agents',
|
|
18
|
+
parameters: [
|
|
19
|
+
{
|
|
20
|
+
in: 'query',
|
|
21
|
+
name: 'project',
|
|
22
|
+
required: false,
|
|
23
|
+
schema: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
},
|
|
26
|
+
description:
|
|
27
|
+
'Project root override (defaults to current working directory).',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
responses: {
|
|
31
|
+
'200': {
|
|
32
|
+
description: 'OK',
|
|
33
|
+
content: {
|
|
34
|
+
'application/json': {
|
|
35
|
+
schema: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
agents: {
|
|
39
|
+
type: 'array',
|
|
40
|
+
items: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
default: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ['agents', 'default'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
async (c) => {
|
|
56
|
+
try {
|
|
57
|
+
const embeddedConfig = (
|
|
58
|
+
c as unknown as {
|
|
59
|
+
get: (key: 'embeddedConfig') => EmbeddedAppConfig | undefined;
|
|
60
|
+
}
|
|
61
|
+
).get('embeddedConfig');
|
|
62
|
+
|
|
63
|
+
if (embeddedConfig) {
|
|
64
|
+
const agents = embeddedConfig.agents
|
|
65
|
+
? Object.keys(embeddedConfig.agents)
|
|
66
|
+
: ['general', 'build', 'plan', 'init'];
|
|
67
|
+
return c.json({
|
|
68
|
+
agents,
|
|
69
|
+
default: getDefault(
|
|
70
|
+
embeddedConfig.agent,
|
|
71
|
+
embeddedConfig.defaults?.agent,
|
|
72
|
+
'general',
|
|
73
|
+
),
|
|
74
|
+
});
|
|
14
75
|
}
|
|
15
|
-
).get('embeddedConfig');
|
|
16
76
|
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
77
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
78
|
+
const cfg = await loadConfig(projectRoot);
|
|
79
|
+
|
|
80
|
+
const allAgents = await discoverAllAgents(cfg.projectRoot);
|
|
81
|
+
|
|
21
82
|
return c.json({
|
|
22
|
-
agents,
|
|
23
|
-
default:
|
|
24
|
-
embeddedConfig.agent,
|
|
25
|
-
embeddedConfig.defaults?.agent,
|
|
26
|
-
'general',
|
|
27
|
-
),
|
|
83
|
+
agents: allAgents,
|
|
84
|
+
default: cfg.defaults.agent,
|
|
28
85
|
});
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logger.error('Failed to get agents', error);
|
|
88
|
+
const errorResponse = serializeError(error);
|
|
89
|
+
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
29
90
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const cfg = await loadConfig(projectRoot);
|
|
33
|
-
|
|
34
|
-
const allAgents = await discoverAllAgents(cfg.projectRoot);
|
|
35
|
-
|
|
36
|
-
return c.json({
|
|
37
|
-
agents: allAgents,
|
|
38
|
-
default: cfg.defaults.agent,
|
|
39
|
-
});
|
|
40
|
-
} catch (error) {
|
|
41
|
-
logger.error('Failed to get agents', error);
|
|
42
|
-
const errorResponse = serializeError(error);
|
|
43
|
-
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
91
|
+
},
|
|
92
|
+
);
|
|
46
93
|
}
|
package/src/routes/config/cwd.ts
CHANGED
|
@@ -2,20 +2,52 @@ import type { Hono } from 'hono';
|
|
|
2
2
|
import { basename } from 'node:path';
|
|
3
3
|
import { logger } from '@ottocode/sdk';
|
|
4
4
|
import { serializeError } from '../../runtime/errors/api-error.ts';
|
|
5
|
+
import { openApiRoute } from '../../openapi/route.ts';
|
|
5
6
|
|
|
6
7
|
export function registerCwdRoute(app: Hono) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
openApiRoute(
|
|
9
|
+
app,
|
|
10
|
+
{
|
|
11
|
+
method: 'get',
|
|
12
|
+
path: '/v1/config/cwd',
|
|
13
|
+
tags: ['config'],
|
|
14
|
+
operationId: 'getCwd',
|
|
15
|
+
summary: 'Get current working directory info',
|
|
16
|
+
responses: {
|
|
17
|
+
'200': {
|
|
18
|
+
description: 'OK',
|
|
19
|
+
content: {
|
|
20
|
+
'application/json': {
|
|
21
|
+
schema: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
cwd: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
},
|
|
27
|
+
dirName: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
required: ['cwd', 'dirName'],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
(c) => {
|
|
39
|
+
try {
|
|
40
|
+
const cwd = process.cwd();
|
|
41
|
+
const dirName = basename(cwd);
|
|
42
|
+
return c.json({
|
|
43
|
+
cwd,
|
|
44
|
+
dirName,
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error('Failed to get current working directory', error);
|
|
48
|
+
const errorResponse = serializeError(error);
|
|
49
|
+
return c.json(errorResponse, errorResponse.error.status || 500);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
);
|
|
21
53
|
}
|