@minimalcorp/tsunagi 0.3.3 → 0.4.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/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_05n88to._.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{_0kflgfj._.js → _0pw3_r_._.js} +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{_0g79jqo._.js → _0rb6-mo._.js} +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0ts4rpp._.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_settings_page_tsx_0i6itlb._.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_04pfam-._.js → node_modules_03-rvdo._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0cv326~._.js → node_modules_06jdmu~._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0a57phw._.js → node_modules_0925te2._.js} +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0_huoqd._.js → node_modules_0e8uni7._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0tod6y8._.js → node_modules_0h4h_aw._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0h.vgyn._.js → node_modules_0nzbb9~._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0oip5a1._.js → node_modules_0q8yuvq._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_11-z65a._.js → node_modules_0r6t2tu._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_09d2oqj._.js → node_modules_0t6ysh_._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0krwgny._.js → node_modules_0vj~e_v._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0sn0lqb._.js → node_modules_0vq~hzy._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0l23gkf._.js → node_modules_0xzmx-x._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0npujym._.js → node_modules_0yb2sh9._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0q_5qo~._.js → node_modules_0yc~s8p._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0q_xfyl._.js → node_modules_0zi-gfw._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0ak_3rk._.js → node_modules_0zzdoud._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0xp9nhx._.js → node_modules_0~aiu12._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
- package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/09b_3duxnyfto.js +7 -0
- package/.next/standalone/apps/web/.next/static/chunks/{0z60ewb40i2ce.js → 0gxhy80~c0gvp.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/0i9h-39w91ybd.js +6 -0
- package/.next/standalone/apps/web/.next/static/chunks/{0b90ys7wq-p.4.css → 0pm0knaijueoc.css} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{0oricprxoxb_d.js → 0smdykrt42e.5.js} +10 -10
- package/.next/standalone/apps/web/.next/static/chunks/{149sia28cskw9.js → 0yp~t_.pozr-d.js} +6 -6
- package/.next/standalone/apps/web/.next/static/chunks/{0o6ggm7jrim25.js → 14zh2vf8ljbxo.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{053h220fng_68.js → 1624992q-gpj2.js} +10 -10
- package/.next/standalone/apps/web/package.json +1 -0
- package/README.md +1 -1
- package/dist/app.js +3 -3
- package/dist/plugin-lifecycle.d.ts +5 -3
- package/dist/plugin-lifecycle.js +40 -16
- package/dist/prisma/migrations/20261011000000_add_codex_support/migration.sql +20 -0
- package/dist/prisma/schema.prisma +9 -5
- package/dist/server/generated/prisma/browser.d.ts +2 -2
- package/dist/server/generated/prisma/client.d.ts +2 -2
- package/dist/server/generated/prisma/internal/class.d.ts +4 -4
- package/dist/server/generated/prisma/internal/class.js +4 -4
- package/dist/server/generated/prisma/internal/prismaNamespace.d.ts +41 -39
- package/dist/server/generated/prisma/internal/prismaNamespace.js +4 -2
- package/dist/server/generated/prisma/internal/prismaNamespaceBrowser.d.ts +5 -3
- package/dist/server/generated/prisma/internal/prismaNamespaceBrowser.js +4 -2
- package/dist/server/generated/prisma/models/AgentProfile.d.ts +972 -0
- package/dist/server/generated/prisma/models/Tab.d.ts +36 -1
- package/dist/server/generated/prisma/models.d.ts +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/lib/agent-profiles.d.ts +43 -0
- package/dist/server/lib/agent-profiles.js +127 -0
- package/dist/server/lib/agents/claude.d.ts +2 -0
- package/dist/server/lib/agents/claude.js +130 -0
- package/dist/server/lib/agents/cli.d.ts +14 -0
- package/dist/server/lib/agents/cli.js +57 -0
- package/dist/server/lib/agents/codex.d.ts +2 -0
- package/dist/server/lib/agents/codex.js +285 -0
- package/dist/server/lib/agents/index.d.ts +11 -0
- package/dist/server/lib/agents/index.js +19 -0
- package/dist/server/lib/agents/login-callback.d.ts +11 -0
- package/dist/server/lib/agents/login-callback.js +47 -0
- package/dist/server/lib/agents/types.d.ts +77 -0
- package/dist/server/lib/agents/types.js +8 -0
- package/dist/server/lib/pty-env-sync.js +1 -1
- package/dist/server/lib/pty-launch.d.ts +8 -10
- package/dist/server/lib/pty-launch.js +20 -58
- package/dist/server/lib/repositories/task.js +1 -0
- package/dist/server/lib/tab-todos.d.ts +5 -0
- package/dist/server/lib/tab-todos.js +13 -0
- package/dist/server/pty-manager.d.ts +7 -2
- package/dist/server/pty-manager.js +13 -0
- package/dist/server/routes/agent-profiles.d.ts +2 -0
- package/dist/server/routes/agent-profiles.js +193 -0
- package/dist/server/routes/env.js +2 -2
- package/dist/server/routes/hooks.d.ts +4 -19
- package/dist/server/routes/hooks.js +83 -73
- package/dist/server/routes/mcp.js +2 -2
- package/dist/server/routes/onboarding.js +19 -10
- package/dist/server/routes/tasks.js +4 -4
- package/dist/server/routes/terminal.js +47 -34
- package/dist/with-plugin.js +3 -3
- package/npm-shrinkwrap.json +12 -12
- package/package.json +1 -1
- package/tsunagi-marketplace/codex/tsunagi-task.md +120 -0
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0hnxatt._.js +0 -3
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_10gk93.._.js +0 -3
- package/.next/standalone/apps/web/.next/static/chunks/0crn03y2tj0lu.js +0 -6
- package/.next/standalone/apps/web/.next/static/chunks/0lvl3ec93cab_.js +0 -7
- package/dist/server/generated/prisma/models/ClaudeProfile.d.ts +0 -939
- package/dist/server/lib/claude-profiles.d.ts +0 -49
- package/dist/server/lib/claude-profiles.js +0 -168
- package/dist/server/routes/claude-profiles.d.ts +0 -2
- package/dist/server/routes/claude-profiles.js +0 -138
- /package/.next/standalone/apps/web/.next/static/{7x81GlNKt9yqIkeI7U1BX → ZcOuTrikuO_ZLaERk7FsW}/_buildManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{7x81GlNKt9yqIkeI7U1BX → ZcOuTrikuO_ZLaERk7FsW}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{7x81GlNKt9yqIkeI7U1BX → ZcOuTrikuO_ZLaERk7FsW}/_ssgManifest.js +0 -0
- /package/dist/server/generated/prisma/models/{ClaudeProfile.js → AgentProfile.js} +0 -0
|
@@ -29,6 +29,7 @@ export type TabMinAggregateOutputType = {
|
|
|
29
29
|
completedAt: Date | null;
|
|
30
30
|
todos: string | null;
|
|
31
31
|
unread: boolean | null;
|
|
32
|
+
agentSessionId: string | null;
|
|
32
33
|
updatedAt: Date | null;
|
|
33
34
|
};
|
|
34
35
|
export type TabMaxAggregateOutputType = {
|
|
@@ -42,6 +43,7 @@ export type TabMaxAggregateOutputType = {
|
|
|
42
43
|
completedAt: Date | null;
|
|
43
44
|
todos: string | null;
|
|
44
45
|
unread: boolean | null;
|
|
46
|
+
agentSessionId: string | null;
|
|
45
47
|
updatedAt: Date | null;
|
|
46
48
|
};
|
|
47
49
|
export type TabCountAggregateOutputType = {
|
|
@@ -55,6 +57,7 @@ export type TabCountAggregateOutputType = {
|
|
|
55
57
|
completedAt: number;
|
|
56
58
|
todos: number;
|
|
57
59
|
unread: number;
|
|
60
|
+
agentSessionId: number;
|
|
58
61
|
updatedAt: number;
|
|
59
62
|
_all: number;
|
|
60
63
|
};
|
|
@@ -75,6 +78,7 @@ export type TabMinAggregateInputType = {
|
|
|
75
78
|
completedAt?: true;
|
|
76
79
|
todos?: true;
|
|
77
80
|
unread?: true;
|
|
81
|
+
agentSessionId?: true;
|
|
78
82
|
updatedAt?: true;
|
|
79
83
|
};
|
|
80
84
|
export type TabMaxAggregateInputType = {
|
|
@@ -88,6 +92,7 @@ export type TabMaxAggregateInputType = {
|
|
|
88
92
|
completedAt?: true;
|
|
89
93
|
todos?: true;
|
|
90
94
|
unread?: true;
|
|
95
|
+
agentSessionId?: true;
|
|
91
96
|
updatedAt?: true;
|
|
92
97
|
};
|
|
93
98
|
export type TabCountAggregateInputType = {
|
|
@@ -101,6 +106,7 @@ export type TabCountAggregateInputType = {
|
|
|
101
106
|
completedAt?: true;
|
|
102
107
|
todos?: true;
|
|
103
108
|
unread?: true;
|
|
109
|
+
agentSessionId?: true;
|
|
104
110
|
updatedAt?: true;
|
|
105
111
|
_all?: true;
|
|
106
112
|
};
|
|
@@ -191,6 +197,7 @@ export type TabGroupByOutputType = {
|
|
|
191
197
|
completedAt: Date | null;
|
|
192
198
|
todos: string | null;
|
|
193
199
|
unread: boolean;
|
|
200
|
+
agentSessionId: string | null;
|
|
194
201
|
updatedAt: Date;
|
|
195
202
|
_count: TabCountAggregateOutputType | null;
|
|
196
203
|
_avg: TabAvgAggregateOutputType | null;
|
|
@@ -215,6 +222,7 @@ export type TabWhereInput = {
|
|
|
215
222
|
completedAt?: Prisma.DateTimeNullableFilter<"Tab"> | Date | string | null;
|
|
216
223
|
todos?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
217
224
|
unread?: Prisma.BoolFilter<"Tab"> | boolean;
|
|
225
|
+
agentSessionId?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
218
226
|
updatedAt?: Prisma.DateTimeFilter<"Tab"> | Date | string;
|
|
219
227
|
task?: Prisma.XOR<Prisma.TaskScalarRelationFilter, Prisma.TaskWhereInput>;
|
|
220
228
|
};
|
|
@@ -229,6 +237,7 @@ export type TabOrderByWithRelationInput = {
|
|
|
229
237
|
completedAt?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
230
238
|
todos?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
231
239
|
unread?: Prisma.SortOrder;
|
|
240
|
+
agentSessionId?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
232
241
|
updatedAt?: Prisma.SortOrder;
|
|
233
242
|
task?: Prisma.TaskOrderByWithRelationInput;
|
|
234
243
|
};
|
|
@@ -246,6 +255,7 @@ export type TabWhereUniqueInput = Prisma.AtLeast<{
|
|
|
246
255
|
completedAt?: Prisma.DateTimeNullableFilter<"Tab"> | Date | string | null;
|
|
247
256
|
todos?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
248
257
|
unread?: Prisma.BoolFilter<"Tab"> | boolean;
|
|
258
|
+
agentSessionId?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
249
259
|
updatedAt?: Prisma.DateTimeFilter<"Tab"> | Date | string;
|
|
250
260
|
task?: Prisma.XOR<Prisma.TaskScalarRelationFilter, Prisma.TaskWhereInput>;
|
|
251
261
|
}, "tabId">;
|
|
@@ -260,6 +270,7 @@ export type TabOrderByWithAggregationInput = {
|
|
|
260
270
|
completedAt?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
261
271
|
todos?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
262
272
|
unread?: Prisma.SortOrder;
|
|
273
|
+
agentSessionId?: Prisma.SortOrderInput | Prisma.SortOrder;
|
|
263
274
|
updatedAt?: Prisma.SortOrder;
|
|
264
275
|
_count?: Prisma.TabCountOrderByAggregateInput;
|
|
265
276
|
_avg?: Prisma.TabAvgOrderByAggregateInput;
|
|
@@ -281,6 +292,7 @@ export type TabScalarWhereWithAggregatesInput = {
|
|
|
281
292
|
completedAt?: Prisma.DateTimeNullableWithAggregatesFilter<"Tab"> | Date | string | null;
|
|
282
293
|
todos?: Prisma.StringNullableWithAggregatesFilter<"Tab"> | string | null;
|
|
283
294
|
unread?: Prisma.BoolWithAggregatesFilter<"Tab"> | boolean;
|
|
295
|
+
agentSessionId?: Prisma.StringNullableWithAggregatesFilter<"Tab"> | string | null;
|
|
284
296
|
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Tab"> | Date | string;
|
|
285
297
|
};
|
|
286
298
|
export type TabCreateInput = {
|
|
@@ -293,6 +305,7 @@ export type TabCreateInput = {
|
|
|
293
305
|
completedAt?: Date | string | null;
|
|
294
306
|
todos?: string | null;
|
|
295
307
|
unread?: boolean;
|
|
308
|
+
agentSessionId?: string | null;
|
|
296
309
|
updatedAt?: Date | string;
|
|
297
310
|
task: Prisma.TaskCreateNestedOneWithoutTabsInput;
|
|
298
311
|
};
|
|
@@ -307,6 +320,7 @@ export type TabUncheckedCreateInput = {
|
|
|
307
320
|
completedAt?: Date | string | null;
|
|
308
321
|
todos?: string | null;
|
|
309
322
|
unread?: boolean;
|
|
323
|
+
agentSessionId?: string | null;
|
|
310
324
|
updatedAt?: Date | string;
|
|
311
325
|
};
|
|
312
326
|
export type TabUpdateInput = {
|
|
@@ -319,6 +333,7 @@ export type TabUpdateInput = {
|
|
|
319
333
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
320
334
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
321
335
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
336
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
322
337
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
323
338
|
task?: Prisma.TaskUpdateOneRequiredWithoutTabsNestedInput;
|
|
324
339
|
};
|
|
@@ -333,6 +348,7 @@ export type TabUncheckedUpdateInput = {
|
|
|
333
348
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
334
349
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
335
350
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
351
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
336
352
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
337
353
|
};
|
|
338
354
|
export type TabCreateManyInput = {
|
|
@@ -346,6 +362,7 @@ export type TabCreateManyInput = {
|
|
|
346
362
|
completedAt?: Date | string | null;
|
|
347
363
|
todos?: string | null;
|
|
348
364
|
unread?: boolean;
|
|
365
|
+
agentSessionId?: string | null;
|
|
349
366
|
updatedAt?: Date | string;
|
|
350
367
|
};
|
|
351
368
|
export type TabUpdateManyMutationInput = {
|
|
@@ -358,6 +375,7 @@ export type TabUpdateManyMutationInput = {
|
|
|
358
375
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
359
376
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
360
377
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
378
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
361
379
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
362
380
|
};
|
|
363
381
|
export type TabUncheckedUpdateManyInput = {
|
|
@@ -371,6 +389,7 @@ export type TabUncheckedUpdateManyInput = {
|
|
|
371
389
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
372
390
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
373
391
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
392
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
374
393
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
375
394
|
};
|
|
376
395
|
export type TabListRelationFilter = {
|
|
@@ -392,6 +411,7 @@ export type TabCountOrderByAggregateInput = {
|
|
|
392
411
|
completedAt?: Prisma.SortOrder;
|
|
393
412
|
todos?: Prisma.SortOrder;
|
|
394
413
|
unread?: Prisma.SortOrder;
|
|
414
|
+
agentSessionId?: Prisma.SortOrder;
|
|
395
415
|
updatedAt?: Prisma.SortOrder;
|
|
396
416
|
};
|
|
397
417
|
export type TabAvgOrderByAggregateInput = {
|
|
@@ -408,6 +428,7 @@ export type TabMaxOrderByAggregateInput = {
|
|
|
408
428
|
completedAt?: Prisma.SortOrder;
|
|
409
429
|
todos?: Prisma.SortOrder;
|
|
410
430
|
unread?: Prisma.SortOrder;
|
|
431
|
+
agentSessionId?: Prisma.SortOrder;
|
|
411
432
|
updatedAt?: Prisma.SortOrder;
|
|
412
433
|
};
|
|
413
434
|
export type TabMinOrderByAggregateInput = {
|
|
@@ -421,6 +442,7 @@ export type TabMinOrderByAggregateInput = {
|
|
|
421
442
|
completedAt?: Prisma.SortOrder;
|
|
422
443
|
todos?: Prisma.SortOrder;
|
|
423
444
|
unread?: Prisma.SortOrder;
|
|
445
|
+
agentSessionId?: Prisma.SortOrder;
|
|
424
446
|
updatedAt?: Prisma.SortOrder;
|
|
425
447
|
};
|
|
426
448
|
export type TabSumOrderByAggregateInput = {
|
|
@@ -477,6 +499,7 @@ export type TabCreateWithoutTaskInput = {
|
|
|
477
499
|
completedAt?: Date | string | null;
|
|
478
500
|
todos?: string | null;
|
|
479
501
|
unread?: boolean;
|
|
502
|
+
agentSessionId?: string | null;
|
|
480
503
|
updatedAt?: Date | string;
|
|
481
504
|
};
|
|
482
505
|
export type TabUncheckedCreateWithoutTaskInput = {
|
|
@@ -489,6 +512,7 @@ export type TabUncheckedCreateWithoutTaskInput = {
|
|
|
489
512
|
completedAt?: Date | string | null;
|
|
490
513
|
todos?: string | null;
|
|
491
514
|
unread?: boolean;
|
|
515
|
+
agentSessionId?: string | null;
|
|
492
516
|
updatedAt?: Date | string;
|
|
493
517
|
};
|
|
494
518
|
export type TabCreateOrConnectWithoutTaskInput = {
|
|
@@ -525,6 +549,7 @@ export type TabScalarWhereInput = {
|
|
|
525
549
|
completedAt?: Prisma.DateTimeNullableFilter<"Tab"> | Date | string | null;
|
|
526
550
|
todos?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
527
551
|
unread?: Prisma.BoolFilter<"Tab"> | boolean;
|
|
552
|
+
agentSessionId?: Prisma.StringNullableFilter<"Tab"> | string | null;
|
|
528
553
|
updatedAt?: Prisma.DateTimeFilter<"Tab"> | Date | string;
|
|
529
554
|
};
|
|
530
555
|
export type TabCreateManyTaskInput = {
|
|
@@ -537,6 +562,7 @@ export type TabCreateManyTaskInput = {
|
|
|
537
562
|
completedAt?: Date | string | null;
|
|
538
563
|
todos?: string | null;
|
|
539
564
|
unread?: boolean;
|
|
565
|
+
agentSessionId?: string | null;
|
|
540
566
|
updatedAt?: Date | string;
|
|
541
567
|
};
|
|
542
568
|
export type TabUpdateWithoutTaskInput = {
|
|
@@ -549,6 +575,7 @@ export type TabUpdateWithoutTaskInput = {
|
|
|
549
575
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
550
576
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
551
577
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
578
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
552
579
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
553
580
|
};
|
|
554
581
|
export type TabUncheckedUpdateWithoutTaskInput = {
|
|
@@ -561,6 +588,7 @@ export type TabUncheckedUpdateWithoutTaskInput = {
|
|
|
561
588
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
562
589
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
563
590
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
591
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
564
592
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
565
593
|
};
|
|
566
594
|
export type TabUncheckedUpdateManyWithoutTaskInput = {
|
|
@@ -573,6 +601,7 @@ export type TabUncheckedUpdateManyWithoutTaskInput = {
|
|
|
573
601
|
completedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
|
|
574
602
|
todos?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
575
603
|
unread?: Prisma.BoolFieldUpdateOperationsInput | boolean;
|
|
604
|
+
agentSessionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
|
|
576
605
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
|
|
577
606
|
};
|
|
578
607
|
export type TabSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
|
@@ -586,6 +615,7 @@ export type TabSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = ru
|
|
|
586
615
|
completedAt?: boolean;
|
|
587
616
|
todos?: boolean;
|
|
588
617
|
unread?: boolean;
|
|
618
|
+
agentSessionId?: boolean;
|
|
589
619
|
updatedAt?: boolean;
|
|
590
620
|
task?: boolean | Prisma.TaskDefaultArgs<ExtArgs>;
|
|
591
621
|
}, ExtArgs["result"]["tab"]>;
|
|
@@ -600,6 +630,7 @@ export type TabSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extension
|
|
|
600
630
|
completedAt?: boolean;
|
|
601
631
|
todos?: boolean;
|
|
602
632
|
unread?: boolean;
|
|
633
|
+
agentSessionId?: boolean;
|
|
603
634
|
updatedAt?: boolean;
|
|
604
635
|
task?: boolean | Prisma.TaskDefaultArgs<ExtArgs>;
|
|
605
636
|
}, ExtArgs["result"]["tab"]>;
|
|
@@ -614,6 +645,7 @@ export type TabSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extension
|
|
|
614
645
|
completedAt?: boolean;
|
|
615
646
|
todos?: boolean;
|
|
616
647
|
unread?: boolean;
|
|
648
|
+
agentSessionId?: boolean;
|
|
617
649
|
updatedAt?: boolean;
|
|
618
650
|
task?: boolean | Prisma.TaskDefaultArgs<ExtArgs>;
|
|
619
651
|
}, ExtArgs["result"]["tab"]>;
|
|
@@ -628,9 +660,10 @@ export type TabSelectScalar = {
|
|
|
628
660
|
completedAt?: boolean;
|
|
629
661
|
todos?: boolean;
|
|
630
662
|
unread?: boolean;
|
|
663
|
+
agentSessionId?: boolean;
|
|
631
664
|
updatedAt?: boolean;
|
|
632
665
|
};
|
|
633
|
-
export type TabOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"tabId" | "taskId" | "order" | "status" | "mode" | "createdAt" | "startedAt" | "completedAt" | "todos" | "unread" | "updatedAt", ExtArgs["result"]["tab"]>;
|
|
666
|
+
export type TabOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"tabId" | "taskId" | "order" | "status" | "mode" | "createdAt" | "startedAt" | "completedAt" | "todos" | "unread" | "agentSessionId" | "updatedAt", ExtArgs["result"]["tab"]>;
|
|
634
667
|
export type TabInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
|
635
668
|
task?: boolean | Prisma.TaskDefaultArgs<ExtArgs>;
|
|
636
669
|
};
|
|
@@ -656,6 +689,7 @@ export type $TabPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
|
|
|
656
689
|
completedAt: Date | null;
|
|
657
690
|
todos: string | null;
|
|
658
691
|
unread: boolean;
|
|
692
|
+
agentSessionId: string | null;
|
|
659
693
|
updatedAt: Date;
|
|
660
694
|
}, ExtArgs["result"]["tab"]>;
|
|
661
695
|
composites: {};
|
|
@@ -1022,6 +1056,7 @@ export interface TabFieldRefs {
|
|
|
1022
1056
|
readonly completedAt: Prisma.FieldRef<"Tab", 'DateTime'>;
|
|
1023
1057
|
readonly todos: Prisma.FieldRef<"Tab", 'String'>;
|
|
1024
1058
|
readonly unread: Prisma.FieldRef<"Tab", 'Boolean'>;
|
|
1059
|
+
readonly agentSessionId: Prisma.FieldRef<"Tab", 'String'>;
|
|
1025
1060
|
readonly updatedAt: Prisma.FieldRef<"Tab", 'DateTime'>;
|
|
1026
1061
|
}
|
|
1027
1062
|
/**
|
|
@@ -2,6 +2,6 @@ export type * from './models/Repository.js';
|
|
|
2
2
|
export type * from './models/Task.js';
|
|
3
3
|
export type * from './models/Tab.js';
|
|
4
4
|
export type * from './models/EnvironmentVariable.js';
|
|
5
|
-
export type * from './models/
|
|
5
|
+
export type * from './models/AgentProfile.js';
|
|
6
6
|
export type * from './models/AppSetting.js';
|
|
7
7
|
export type * from './commonInputTypes.js';
|
package/dist/server/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { envRoutes } from './routes/env.js';
|
|
|
10
10
|
import { worktreesRoutes } from './routes/worktrees.js';
|
|
11
11
|
import { commandsRoutes } from './routes/commands.js';
|
|
12
12
|
import { onboardingRoutes } from './routes/onboarding.js';
|
|
13
|
-
import {
|
|
13
|
+
import { agentProfilesRoutes } from './routes/agent-profiles.js';
|
|
14
14
|
import { internalRoutes } from './routes/internal.js';
|
|
15
15
|
import { hooksRoutes } from './routes/hooks.js';
|
|
16
16
|
import { mcpRoutes } from './routes/mcp.js';
|
|
@@ -110,7 +110,7 @@ async function start() {
|
|
|
110
110
|
await fastify.register(worktreesRoutes, { prefix: '/api' });
|
|
111
111
|
await fastify.register(commandsRoutes, { prefix: '/api' });
|
|
112
112
|
await fastify.register(onboardingRoutes, { prefix: '/api' });
|
|
113
|
-
await fastify.register(
|
|
113
|
+
await fastify.register(agentProfilesRoutes, { prefix: '/api' });
|
|
114
114
|
await fastify.register(internalRoutes, { prefix: '/api' });
|
|
115
115
|
await fastify.register(hooksRoutes, { prefix: '/api' });
|
|
116
116
|
await fastify.register(mcpRoutes, { prefix: '/api' });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AgentAuthStatus, AgentProfile } from '@minimalcorp/tsunagi-shared';
|
|
2
|
+
import { type AgentAdapter } from './agents/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* エージェントのプロファイル(Claude: CLAUDE_CONFIG_DIR / Codex: CODEX_HOME)。
|
|
5
|
+
* タブで使うプロファイルの割り当ては予約キー(adapter.profile.envKey)に slug か DEFAULT_PROFILE を保存し、
|
|
6
|
+
* 環境変数と同じ global → owner → repo の継承で解決して PTY 起動時に設定ディレクトリへ変換する
|
|
7
|
+
* (resolveAgentProfileEnv)。
|
|
8
|
+
*/
|
|
9
|
+
/** ログイン用 PTY の sessionId の接頭辞(タブの PTY と区別する) */
|
|
10
|
+
export declare const LOGIN_SESSION_PREFIX = "agent-login-";
|
|
11
|
+
/** システム既定(設定ディレクトリの環境変数を付けず ~/.claude / ~/.codex を使う) */
|
|
12
|
+
export declare const DEFAULT_PROFILE = "default";
|
|
13
|
+
/** 汎用の環境変数として登録させないキー(認証はプロファイルで扱う) */
|
|
14
|
+
export declare const RESERVED_ENV_KEYS: string[];
|
|
15
|
+
export declare function getProfilesDir(agent: AgentAdapter): string;
|
|
16
|
+
/** プロファイルの設定ディレクトリ。システム既定は undefined */
|
|
17
|
+
export declare function getProfileConfigDir(agent: AgentAdapter, slug: string): string | undefined;
|
|
18
|
+
/** 空白を `-` にし、小文字にする(macOS のファイルシステムは大文字小文字を区別しないため) */
|
|
19
|
+
export declare function toProfileSlug(name: string): string;
|
|
20
|
+
/** プロファイル名の検証。問題があればエラーメッセージを返す */
|
|
21
|
+
export declare function validateProfileName(name: string): string | null;
|
|
22
|
+
export declare function listProfiles(agent: AgentAdapter): Promise<AgentProfile[]>;
|
|
23
|
+
export declare function profileExists(agent: AgentAdapter, slug: string): Promise<boolean>;
|
|
24
|
+
export declare function createProfile(agent: AgentAdapter, name: string): Promise<AgentProfile>;
|
|
25
|
+
/**
|
|
26
|
+
* プロファイルを削除する。ログイン情報(macOS の Keychain 等)を残さないよう先に logout し、
|
|
27
|
+
* このプロファイルを割り当てていたスコープは割り当てを外して親の設定を継承させる。
|
|
28
|
+
*/
|
|
29
|
+
export declare function deleteProfile(agent: AgentAdapter, slug: string): Promise<void>;
|
|
30
|
+
export declare function getProfileAuthStatus(agent: AgentAdapter, slug: string): Promise<AgentAuthStatus>;
|
|
31
|
+
/** ログイン用 PTY の環境変数(PtyManager.createSession の env / unsetKeys) */
|
|
32
|
+
export declare function loginPtyEnv(agent: AgentAdapter, slug: string): {
|
|
33
|
+
env: Record<string, string>;
|
|
34
|
+
unsetKeys: string[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* 継承解決済みの環境変数に含まれる各エージェントのプロファイル割り当てを設定ディレクトリに変換する。
|
|
38
|
+
* 予約キー自体は PTY に渡さない。
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveAgentProfileEnv(env: Record<string, string>): {
|
|
41
|
+
env: Record<string, string>;
|
|
42
|
+
unsetKeys: string[];
|
|
43
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { prisma } from './db.js';
|
|
4
|
+
import { getTsunagiDataDir } from './data-path.js';
|
|
5
|
+
import { AGENTS } from './agents/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* エージェントのプロファイル(Claude: CLAUDE_CONFIG_DIR / Codex: CODEX_HOME)。
|
|
8
|
+
* タブで使うプロファイルの割り当ては予約キー(adapter.profile.envKey)に slug か DEFAULT_PROFILE を保存し、
|
|
9
|
+
* 環境変数と同じ global → owner → repo の継承で解決して PTY 起動時に設定ディレクトリへ変換する
|
|
10
|
+
* (resolveAgentProfileEnv)。
|
|
11
|
+
*/
|
|
12
|
+
/** ログイン用 PTY の sessionId の接頭辞(タブの PTY と区別する) */
|
|
13
|
+
export const LOGIN_SESSION_PREFIX = 'agent-login-';
|
|
14
|
+
/** システム既定(設定ディレクトリの環境変数を付けず ~/.claude / ~/.codex を使う) */
|
|
15
|
+
export const DEFAULT_PROFILE = 'default';
|
|
16
|
+
/** 汎用の環境変数として登録させないキー(認証はプロファイルで扱う) */
|
|
17
|
+
export const RESERVED_ENV_KEYS = AGENTS.flatMap(({ profile }) => [
|
|
18
|
+
profile.envKey,
|
|
19
|
+
profile.configDirEnvKey,
|
|
20
|
+
...profile.authEnvKeys,
|
|
21
|
+
]);
|
|
22
|
+
const PROFILE_NAME_PATTERN = /^[A-Za-z0-9 _-]+$/;
|
|
23
|
+
export function getProfilesDir(agent) {
|
|
24
|
+
return path.join(getTsunagiDataDir(), `${agent.id}-profiles`);
|
|
25
|
+
}
|
|
26
|
+
/** プロファイルの設定ディレクトリ。システム既定は undefined */
|
|
27
|
+
export function getProfileConfigDir(agent, slug) {
|
|
28
|
+
if (slug === DEFAULT_PROFILE)
|
|
29
|
+
return undefined;
|
|
30
|
+
return path.join(getProfilesDir(agent), slug);
|
|
31
|
+
}
|
|
32
|
+
/** 空白を `-` にし、小文字にする(macOS のファイルシステムは大文字小文字を区別しないため) */
|
|
33
|
+
export function toProfileSlug(name) {
|
|
34
|
+
return name.trim().replace(/\s+/g, '-').toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
/** プロファイル名の検証。問題があればエラーメッセージを返す */
|
|
37
|
+
export function validateProfileName(name) {
|
|
38
|
+
const trimmed = name.trim();
|
|
39
|
+
if (!trimmed)
|
|
40
|
+
return 'Name is required';
|
|
41
|
+
if (!PROFILE_NAME_PATTERN.test(trimmed)) {
|
|
42
|
+
return 'Use only letters, numbers, spaces, "-" and "_"';
|
|
43
|
+
}
|
|
44
|
+
if (toProfileSlug(trimmed) === DEFAULT_PROFILE) {
|
|
45
|
+
return `"${DEFAULT_PROFILE}" is reserved`;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
export async function listProfiles(agent) {
|
|
50
|
+
const rows = await prisma.agentProfile.findMany({
|
|
51
|
+
where: { agent: agent.id },
|
|
52
|
+
orderBy: { createdAt: 'asc' },
|
|
53
|
+
});
|
|
54
|
+
return rows.map((row) => ({
|
|
55
|
+
agent: agent.id,
|
|
56
|
+
slug: row.slug,
|
|
57
|
+
name: row.name,
|
|
58
|
+
configDir: path.join(getProfilesDir(agent), row.slug),
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
export async function profileExists(agent, slug) {
|
|
62
|
+
if (slug === DEFAULT_PROFILE)
|
|
63
|
+
return true;
|
|
64
|
+
return (await prisma.agentProfile.count({ where: { agent: agent.id, slug } })) > 0;
|
|
65
|
+
}
|
|
66
|
+
export async function createProfile(agent, name) {
|
|
67
|
+
const error = validateProfileName(name);
|
|
68
|
+
if (error)
|
|
69
|
+
throw new Error(error);
|
|
70
|
+
const trimmed = name.trim();
|
|
71
|
+
const slug = toProfileSlug(trimmed);
|
|
72
|
+
if (await profileExists(agent, slug)) {
|
|
73
|
+
throw new Error(`Profile "${slug}" already exists`);
|
|
74
|
+
}
|
|
75
|
+
const configDir = path.join(getProfilesDir(agent), slug);
|
|
76
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
77
|
+
await prisma.agentProfile.create({ data: { agent: agent.id, slug, name: trimmed } });
|
|
78
|
+
return { agent: agent.id, slug, name: trimmed, configDir };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* プロファイルを削除する。ログイン情報(macOS の Keychain 等)を残さないよう先に logout し、
|
|
82
|
+
* このプロファイルを割り当てていたスコープは割り当てを外して親の設定を継承させる。
|
|
83
|
+
*/
|
|
84
|
+
export async function deleteProfile(agent, slug) {
|
|
85
|
+
const configDir = getProfileConfigDir(agent, slug);
|
|
86
|
+
if (!configDir)
|
|
87
|
+
throw new Error('The system default profile cannot be deleted');
|
|
88
|
+
await agent.profile.logout(configDir).catch(() => undefined);
|
|
89
|
+
await prisma.environmentVariable.deleteMany({
|
|
90
|
+
where: { key: agent.profile.envKey, value: slug },
|
|
91
|
+
});
|
|
92
|
+
await prisma.agentProfile.delete({ where: { agent_slug: { agent: agent.id, slug } } });
|
|
93
|
+
await fs.rm(configDir, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
export function getProfileAuthStatus(agent, slug) {
|
|
96
|
+
return agent.profile.getAuthStatus(getProfileConfigDir(agent, slug));
|
|
97
|
+
}
|
|
98
|
+
/** ログイン用 PTY の環境変数(PtyManager.createSession の env / unsetKeys) */
|
|
99
|
+
export function loginPtyEnv(agent, slug) {
|
|
100
|
+
const configDir = getProfileConfigDir(agent, slug);
|
|
101
|
+
if (!configDir)
|
|
102
|
+
return { env: {}, unsetKeys: [] };
|
|
103
|
+
return {
|
|
104
|
+
env: { [agent.profile.configDirEnvKey]: configDir },
|
|
105
|
+
unsetKeys: agent.profile.authEnvKeys,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 継承解決済みの環境変数に含まれる各エージェントのプロファイル割り当てを設定ディレクトリに変換する。
|
|
110
|
+
* 予約キー自体は PTY に渡さない。
|
|
111
|
+
*/
|
|
112
|
+
export function resolveAgentProfileEnv(env) {
|
|
113
|
+
const rest = { ...env };
|
|
114
|
+
const unsetKeys = [];
|
|
115
|
+
for (const agent of AGENTS) {
|
|
116
|
+
const { envKey, configDirEnvKey, authEnvKeys } = agent.profile;
|
|
117
|
+
const slug = rest[envKey];
|
|
118
|
+
delete rest[envKey];
|
|
119
|
+
const configDir = slug ? getProfileConfigDir(agent, slug) : undefined;
|
|
120
|
+
// システム既定: 外側 Terminal の環境のまま(普段ターミナルで CLI を使うときと同じ)
|
|
121
|
+
if (!configDir)
|
|
122
|
+
continue;
|
|
123
|
+
rest[configDirEnvKey] = configDir;
|
|
124
|
+
unsetKeys.push(...authEnvKeys);
|
|
125
|
+
}
|
|
126
|
+
return { env: rest, unsetKeys };
|
|
127
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { LOCAL_LLM_PROXY_URL, buildClaudeCommand, isLocalLlmMode } from '../claude-command.js';
|
|
2
|
+
import { ensureClaudeOnboardingCompleted, removeLocalModelFromUserSettings, watchUserSettingsForLocalModel, } from '../claude-config-guard.js';
|
|
3
|
+
import { LOCAL_LLM_UNSET_ENV_KEYS, LOCAL_MODEL_ALIAS, buildLocalLlmEnv } from '../local-llm-env.js';
|
|
4
|
+
import { ensureActiveLoaded, getLocalLlmSettings } from '../local-llm.js';
|
|
5
|
+
import { TODO_TOOL_NAMES, applyToolToTodos } from '../tab-todos.js';
|
|
6
|
+
import { agentCliEnv, runAgentCli } from './cli.js';
|
|
7
|
+
import { AgentLaunchError, } from './types.js';
|
|
8
|
+
const SIMPLE_EVENTS = {
|
|
9
|
+
// claudeが起動しただけ(まだプロンプト処理していない)
|
|
10
|
+
SessionStart: 'session-start',
|
|
11
|
+
UserPromptSubmit: 'prompt',
|
|
12
|
+
// ツール実行許可待ち
|
|
13
|
+
PermissionRequest: 'permission',
|
|
14
|
+
Stop: 'stop',
|
|
15
|
+
// APIエラーでターン終了
|
|
16
|
+
StopFailure: 'stop-failure',
|
|
17
|
+
// Escキー中断・Ctrl+C・/exit等
|
|
18
|
+
SessionEnd: 'session-end',
|
|
19
|
+
};
|
|
20
|
+
const claudeProfile = {
|
|
21
|
+
envKey: 'TSUNAGI_CLAUDE_PROFILE',
|
|
22
|
+
configDirEnvKey: 'CLAUDE_CONFIG_DIR',
|
|
23
|
+
// Claude Code が /login のログインより優先する認証情報
|
|
24
|
+
authEnvKeys: ['ANTHROPIC_API_KEY', 'CLAUDE_CODE_OAUTH_TOKEN'],
|
|
25
|
+
defaultConfigDir: '~/.claude',
|
|
26
|
+
loginCommand: 'claude auth login',
|
|
27
|
+
// `claude auth status --json` でログイン状態を取得する
|
|
28
|
+
async getAuthStatus(configDir) {
|
|
29
|
+
const env = agentCliEnv(claudeProfile, configDir);
|
|
30
|
+
try {
|
|
31
|
+
const { stdout } = await runAgentCli('claude', ['auth', 'status', '--json'], env);
|
|
32
|
+
const raw = JSON.parse(stdout);
|
|
33
|
+
const str = (v) => (typeof v === 'string' ? v : undefined);
|
|
34
|
+
return {
|
|
35
|
+
loggedIn: raw.loggedIn === true,
|
|
36
|
+
authMethod: str(raw.authMethod),
|
|
37
|
+
email: str(raw.email),
|
|
38
|
+
orgName: str(raw.orgName),
|
|
39
|
+
subscriptionType: str(raw.subscriptionType),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
// claude auth status は未ログイン時に非 0 で終了するが、stdout には JSON が出る
|
|
44
|
+
const stdout = err.stdout;
|
|
45
|
+
if (stdout) {
|
|
46
|
+
try {
|
|
47
|
+
const raw = JSON.parse(stdout);
|
|
48
|
+
return { loggedIn: raw.loggedIn === true, authMethod: raw.authMethod };
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// fallthrough
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { loggedIn: false, error: err instanceof Error ? err.message : String(err) };
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
// ログイン情報(macOS は Keychain)を残さないよう、プロファイル削除前に logout する
|
|
58
|
+
async logout(configDir) {
|
|
59
|
+
await runAgentCli('claude', ['auth', 'logout'], agentCliEnv(claudeProfile, configDir));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
export const claudeAdapter = {
|
|
63
|
+
id: 'claude',
|
|
64
|
+
label: 'Claude Code',
|
|
65
|
+
cli: 'claude',
|
|
66
|
+
// CLAUDE_CODE_PLUGIN_DIRS に対応した最初のバージョン(apps/cli の起動チェックと同じ)
|
|
67
|
+
minVersion: [2, 1, 280],
|
|
68
|
+
profile: claudeProfile,
|
|
69
|
+
// ローカルLLMタブ: Anthropic の代わりに tsunagi の中継口(→ Ollama / LM Studio)で claude を動かす。
|
|
70
|
+
// Anthropic の認証トークンは環境変数ごと取り除く
|
|
71
|
+
async resolveLaunchEnv(mode) {
|
|
72
|
+
if (!isLocalLlmMode(mode))
|
|
73
|
+
return { env: {}, unsetKeys: [] };
|
|
74
|
+
const { active, extraEnv } = await getLocalLlmSettings();
|
|
75
|
+
if (!active) {
|
|
76
|
+
throw new AgentLaunchError('ローカルLLMのモデルが未設定です。Settings で使用するモデルを選んでください', 400);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
env: buildLocalLlmEnv({
|
|
80
|
+
proxyUrl: LOCAL_LLM_PROXY_URL,
|
|
81
|
+
contextTokens: active.contextTokens,
|
|
82
|
+
extraEnv,
|
|
83
|
+
}),
|
|
84
|
+
unsetKeys: LOCAL_LLM_UNSET_ENV_KEYS,
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* claude logout で .claude.json の hasCompletedOnboarding がリセットされていると、次回 claude 起動時に
|
|
89
|
+
* オンボーディングウィザードが表示され --resume/--session-id を前提にした自動起動フローが止まるため補正する。
|
|
90
|
+
* 監視の取りこぼしに備え、中継口の名前が既定モデルに残っていないかも補正する。
|
|
91
|
+
* 対象はタブが使う Claude プロファイルの設定ディレクトリ
|
|
92
|
+
*/
|
|
93
|
+
async prepareLaunch(env) {
|
|
94
|
+
// PTY は外側 Terminal の環境を継承するため、プロファイル未指定なら外側の CLAUDE_CONFIG_DIR に従う
|
|
95
|
+
const configDir = env.CLAUDE_CONFIG_DIR ?? process.env.CLAUDE_CONFIG_DIR;
|
|
96
|
+
await ensureClaudeOnboardingCompleted(configDir);
|
|
97
|
+
await removeLocalModelFromUserSettings(LOCAL_MODEL_ALIAS, configDir);
|
|
98
|
+
watchUserSettingsForLocalModel(LOCAL_MODEL_ALIAS, configDir);
|
|
99
|
+
},
|
|
100
|
+
async buildCommand(tabId, mode) {
|
|
101
|
+
if (isLocalLlmMode(mode)) {
|
|
102
|
+
// 最初の発言を待たせないよう読み込みを始めておく(完了は待たない。未設定等のエラーは中継口がタブに返す)
|
|
103
|
+
ensureActiveLoaded().catch(() => undefined);
|
|
104
|
+
}
|
|
105
|
+
return buildClaudeCommand(tabId, mode);
|
|
106
|
+
},
|
|
107
|
+
// Claude のセッションIDはタブIDと同じ(--session-id / --resume で揃えている)
|
|
108
|
+
normalizeHook({ body }) {
|
|
109
|
+
const { hook_event_name: eventName, session_id: tabId } = body;
|
|
110
|
+
if (!tabId || !eventName)
|
|
111
|
+
return null;
|
|
112
|
+
const kind = SIMPLE_EVENTS[eventName];
|
|
113
|
+
if (kind)
|
|
114
|
+
return { tabId, kind };
|
|
115
|
+
if (eventName === 'PostToolUse') {
|
|
116
|
+
// ツール実行完了(PermissionRequest後のAllow含む)。TodoWrite / Task 系ツールなら todos も更新する
|
|
117
|
+
const { tool_name: toolName, tool_input: input, tool_response: response, } = body;
|
|
118
|
+
return {
|
|
119
|
+
tabId,
|
|
120
|
+
kind: 'tool-post',
|
|
121
|
+
toolName,
|
|
122
|
+
...(toolName !== undefined &&
|
|
123
|
+
TODO_TOOL_NAMES.has(toolName) && {
|
|
124
|
+
applyTodos: (current) => applyToolToTodos(current, toolName, input, response),
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
},
|
|
130
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentAvailability } from '@minimalcorp/tsunagi-shared';
|
|
2
|
+
import type { AgentAdapter, AgentProfileSpec } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* エージェント CLI を実行するときの環境変数。プロファイルのログインを見るよう設定ディレクトリを付け、
|
|
5
|
+
* ログインより優先される認証情報の環境変数は取り除く。システム既定は外側 Terminal の環境のまま
|
|
6
|
+
* (普段ターミナルで CLI を使うときと同じ)。
|
|
7
|
+
*/
|
|
8
|
+
export declare function agentCliEnv(profile: AgentProfileSpec, configDir: string | undefined): NodeJS.ProcessEnv;
|
|
9
|
+
export declare function runAgentCli(cli: string, args: string[], env: NodeJS.ProcessEnv): Promise<{
|
|
10
|
+
stdout: string;
|
|
11
|
+
stderr: string;
|
|
12
|
+
}>;
|
|
13
|
+
/** `<cli> --version` で導入状況を確認する */
|
|
14
|
+
export declare function getAgentAvailability(adapter: AgentAdapter): Promise<AgentAvailability>;
|