@teamscala/service-boot 0.23.344 → 0.23.346

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 (138) hide show
  1. package/package.json +1064 -1093
  2. package/src/two-phase-boot.ts +55 -2
  3. package/src/two-phase-health-gate-client-only.test.ts +77 -0
  4. package/src/two-phase-health-gate.test.ts +13 -2
  5. package/src/agreement-gate.d.ts +0 -19
  6. package/src/asset-cache-key.d.ts +0 -11
  7. package/src/asset-optimize.d.ts +0 -17
  8. package/src/asset-proxy.d.ts +0 -11
  9. package/src/asset-social-card.d.ts +0 -17
  10. package/src/attach-agreement-magic.d.ts +0 -20
  11. package/src/attach-portal-members.d.ts +0 -23
  12. package/src/attach-proposal-accept.d.ts +0 -26
  13. package/src/attach-proposal-magic.d.ts +0 -18
  14. package/src/attach-transfers-upload.d.ts +0 -27
  15. package/src/auth-gate.d.ts +0 -29
  16. package/src/bind-page-handler.d.ts +0 -18
  17. package/src/build-client-assets/input-hashing.d.ts +0 -25
  18. package/src/build-client-assets/source-candidates.d.ts +0 -27
  19. package/src/build-client-assets.d.ts +0 -50
  20. package/src/compose-page-title.d.ts +0 -41
  21. package/src/content-gate/access.d.ts +0 -15
  22. package/src/content-gate/config-types.d.ts +0 -99
  23. package/src/content-gate/gate.d.ts +0 -13
  24. package/src/content-gate/parse-cookie.d.ts +0 -9
  25. package/src/content-gate/token.d.ts +0 -48
  26. package/src/content-page-floor.d.ts +0 -39
  27. package/src/discover-blocks.d.ts +0 -28
  28. package/src/expand-roster.d.ts +0 -34
  29. package/src/fn-routers/agreement-completion-email.d.ts +0 -14
  30. package/src/fn-routers/agreement-send-router.d.ts +0 -82
  31. package/src/fn-routers/ai-health-router.d.ts +0 -35
  32. package/src/fn-routers/auth-router.d.ts +0 -47
  33. package/src/fn-routers/cache-admin-router.d.ts +0 -57
  34. package/src/fn-routers/chat-session-router.d.ts +0 -219
  35. package/src/fn-routers/email-defaults.d.ts +0 -1
  36. package/src/fn-routers/email-link-ttl.d.ts +0 -1
  37. package/src/fn-routers/index.d.ts +0 -18
  38. package/src/fn-routers/orchestrator-registration-router.d.ts +0 -60
  39. package/src/fn-routers/orchestrator-registration-router.ts +0 -77
  40. package/src/fn-routers/orchestrator-registration.live.test.ts +0 -70
  41. package/src/fn-routers/orchestrator-registration.test.ts +0 -23
  42. package/src/fn-routers/panel-data-router.d.ts +0 -19
  43. package/src/fn-routers/persist-chat-messages.d.ts +0 -36
  44. package/src/fn-routers/plans-router.d.ts +0 -25
  45. package/src/fn-routers/proposal-send-router.d.ts +0 -58
  46. package/src/fn-routers/public-agreement-router.d.ts +0 -289
  47. package/src/fn-routers/public-assessment-router.d.ts +0 -68
  48. package/src/fn-routers/public-gpt-session-router.d.ts +0 -143
  49. package/src/fn-routers/sign-in-flow-router.d.ts +0 -107
  50. package/src/fn-routers/task-sync-assign.d.ts +0 -307
  51. package/src/fn-routers/task-sync-brief.d.ts +0 -98
  52. package/src/fn-routers/task-sync-close.d.ts +0 -41
  53. package/src/fn-routers/task-sync-dispatch.d.ts +0 -47
  54. package/src/fn-routers/task-sync-dispatch.ts +0 -81
  55. package/src/fn-routers/task-sync-lane.d.ts +0 -49
  56. package/src/fn-routers/task-sync-lane.ts +0 -114
  57. package/src/fn-routers/task-sync-projection.d.ts +0 -144
  58. package/src/fn-routers/task-sync-rename.d.ts +0 -91
  59. package/src/fn-routers/task-sync-router.d.ts +0 -455
  60. package/src/fn-routers/task-sync-router.ts +0 -1075
  61. package/src/fn-routers/tasks-router.d.ts +0 -25
  62. package/src/fn-routers/user-preferences-router.d.ts +0 -77
  63. package/src/fn-routers/work-items-router.d.ts +0 -102
  64. package/src/gate-ttls.d.ts +0 -6
  65. package/src/gpt-gate.d.ts +0 -25
  66. package/src/handlers/bun-stable-watch.d.ts +0 -1
  67. package/src/handlers/pane-outbox-drain.d.ts +0 -1
  68. package/src/handlers/projects-digest.d.ts +0 -26
  69. package/src/handlers/prune-stale-data.d.ts +0 -30
  70. package/src/handlers/registry-stale-inactive-sweep.d.ts +0 -1
  71. package/src/handlers/scala-tools-currency-watch.d.ts +0 -1
  72. package/src/handlers/singleton-tools-currency-watch.d.ts +0 -1
  73. package/src/handlers/sweep-event-log.d.ts +0 -1
  74. package/src/handlers/sweep-host-cache.d.ts +0 -24
  75. package/src/handlers/upstream-issue-sync.d.ts +0 -1
  76. package/src/handlers/whatsapp-liveness-logic.d.ts +0 -34
  77. package/src/handlers/whatsapp-liveness.d.ts +0 -4
  78. package/src/hono-error-handler.d.ts +0 -25
  79. package/src/install-harness.d.ts +0 -45
  80. package/src/install-logging.d.ts +0 -34
  81. package/src/load-service-install-row.d.ts +0 -24
  82. package/src/load-service-prisma-client.d.ts +0 -18
  83. package/src/mount-orpc-router.d.ts +0 -15
  84. package/src/mount-server-packages.d.ts +0 -29
  85. package/src/mount.d.ts +0 -9
  86. package/src/mutable-app-ref.d.ts +0 -44
  87. package/src/page-route-shell-types.d.ts +0 -12
  88. package/src/page-server-orpc/audit-revert-router.d.ts +0 -37
  89. package/src/page-server-orpc/hub-mcp-client.d.ts +0 -12
  90. package/src/page-server-orpc/portal-diagnostics-router.d.ts +0 -49
  91. package/src/page-server-orpc/puck-pages-router.d.ts +0 -58
  92. package/src/page-server-orpc/server-client.d.ts +0 -16
  93. package/src/page-server-orpc/templates-router.d.ts +0 -34
  94. package/src/page-server-orpc/user-preferences-router.d.ts +0 -79
  95. package/src/pg-boss-handler-registry.d.ts +0 -27
  96. package/src/pg-boss-mount.d.ts +0 -42
  97. package/src/proposal-authorized-emails.d.ts +0 -28
  98. package/src/proposal-chat-inject.d.ts +0 -17
  99. package/src/proposal-gate.d.ts +0 -18
  100. package/src/read-html-template.d.ts +0 -38
  101. package/src/read-viewport-from-request.d.ts +0 -18
  102. package/src/readiness-gate.d.ts +0 -16
  103. package/src/register-api-routes.d.ts +0 -18
  104. package/src/register-crash-handlers.d.ts +0 -15
  105. package/src/register-page-routes.d.ts +0 -27
  106. package/src/register-page-server-client.d.ts +0 -11
  107. package/src/register-registry-page-route/ai-chat-prefetch.d.ts +0 -13
  108. package/src/register-registry-page-route/graph-cache.d.ts +0 -30
  109. package/src/register-registry-page-route/meta-title.d.ts +0 -2
  110. package/src/register-registry-page-route/proposal-approval-email-token.d.ts +0 -14
  111. package/src/register-registry-page-route/proposal-brand-stamping.d.ts +0 -28
  112. package/src/register-registry-page-route/resolve-page-data.d.ts +0 -1
  113. package/src/register-registry-page-route.d.ts +0 -27
  114. package/src/register-static-assets.d.ts +0 -13
  115. package/src/register-ws-routes.d.ts +0 -28
  116. package/src/resolve-app-base-url.d.ts +0 -13
  117. package/src/resolve-brand-favicon.d.ts +0 -28
  118. package/src/resolve-from-loader-config.d.ts +0 -32
  119. package/src/resolve-service-context.d.ts +0 -17
  120. package/src/resolve-service-port.d.ts +0 -75
  121. package/src/resolve-theme-mode.d.ts +0 -42
  122. package/src/resolvers/fetch-org-brand.d.ts +0 -2
  123. package/src/resolvers/portal-route-paths.d.ts +0 -39
  124. package/src/resolvers/website-by-host-map.d.ts +0 -12
  125. package/src/resource-chat-inject.d.ts +0 -46
  126. package/src/resource-not-found.d.ts +0 -60
  127. package/src/run-boot-hook-list.d.ts +0 -19
  128. package/src/run-boot-hooks.d.ts +0 -31
  129. package/src/scala-tools-currency-watchdog.d.ts +0 -10
  130. package/src/security-headers.d.ts +0 -12
  131. package/src/serve/serve.d.ts +0 -46
  132. package/src/serve/stamp-transport-identity.d.ts +0 -39
  133. package/src/server-error-page.d.ts +0 -29
  134. package/src/start-scheduled-jobs.d.ts +0 -18
  135. package/src/two-phase-boot.d.ts +0 -136
  136. package/src/types.d.ts +0 -46
  137. package/src/ui-service.d.ts +0 -46
  138. package/src/ws-boot-self-test.d.ts +0 -19
@@ -1,219 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * ORPC procedures for the AUTHENTICATED AI-chat conversation lifecycle —
7
- * the org+user-keyed sibling of publicGptSessionRouter (which is contact-
8
- * linked for anonymous public GPT visitors). One signed-in user chatting
9
- * with one agent in one org owns a thread of `conversations` rows; this
10
- * router createOrRestore-s the active one, saves turns, archives+news on
11
- * clear, lists past threads, and loads a specific thread.
12
- *
13
- * Identity: the USER is resolved from the ORPC session context (`authed`
14
- * middleware → `context.user.id`); the ORGANISATION is supplied by the
15
- * client (it is the URL :orgId for org-scoped apps like scala-projects —
16
- * the session does not carry it) and VERIFIED — the caller must be a
17
- * member of that organisation, else FORBIDDEN. A caller cannot read or
18
- * write another user's threads (ownership is user_id) or another org's
19
- * (createOrRestore/list are membership-scoped to the supplied org).
20
- *
21
- * This restores the capability the portal AI chat lost when the June
22
- * chat-engine migration severed `usePortalConversationId` + the
23
- * `portalConversation` router (capability-named `chatSession` here per
24
- * name-by-capability; the host-named orphan was deleted in the same change).
25
- *
26
- * Persistence model: the chat client owns writes via onMessagesPersist →
27
- * saveMessages, and sends clientPersists:true so handle-chat-stream skips its
28
- * own persistChatRun (single writer, no double-persist). Verbatim UIMessage
29
- * parts are stored in messages.channel_data.parts so multi-step (tool-using)
30
- * turns round-trip losslessly (apps/chat.md messages-stored-as-uimessage-verbatim).
31
- */
32
- import * as v from "valibot";
33
- import { type Context } from "./auth-router.ts";
34
- export declare const chatSessionRouter: {
35
- createOrRestore: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
36
- headers: Headers;
37
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
38
- prisma: any;
39
- user: import("./auth-router.ts").User;
40
- orgId: string | null | undefined;
41
- }>, v.ObjectSchema<{
42
- readonly agentId: v.StringSchema<undefined>;
43
- readonly organisationId: v.StringSchema<undefined>;
44
- /**
45
- * SSR-only: the real user's id, passed by the AiChat serverLoader. The
46
- * in-process server client is system-authed (context.user.id === "system"),
47
- * so without this the conversation is created under user_id="system" and
48
- * the real user's saveMessages hits assertOwns → FORBIDDEN. Only honoured
49
- * when the caller is the system user (server-side SSR), never from a
50
- * client-side ORPC call.
51
- */
52
- readonly userId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
53
- }, undefined>, import("@orpc/contract").Schema<{
54
- conversationId: any;
55
- model: any;
56
- messages: {
57
- id: any;
58
- role: any;
59
- content: any;
60
- parts: unknown[] | undefined;
61
- metadata: Record<string, unknown> | undefined;
62
- created_at: any;
63
- occurred_at: any;
64
- }[];
65
- tokenTotals: {
66
- inputTokens: number;
67
- outputTokens: number;
68
- };
69
- hasMore: boolean;
70
- }, {
71
- conversationId: any;
72
- model: any;
73
- messages: {
74
- id: any;
75
- role: any;
76
- content: any;
77
- parts: unknown[] | undefined;
78
- metadata: Record<string, unknown> | undefined;
79
- created_at: any;
80
- occurred_at: any;
81
- }[];
82
- tokenTotals: {
83
- inputTokens: number;
84
- outputTokens: number;
85
- };
86
- hasMore: boolean;
87
- }>, Record<never, never>, Record<never, never>>;
88
- loadEarlier: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
89
- headers: Headers;
90
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
91
- prisma: any;
92
- user: import("./auth-router.ts").User;
93
- orgId: string | null | undefined;
94
- }>, v.ObjectSchema<{
95
- readonly conversationId: v.StringSchema<undefined>;
96
- /** Cursor: the occurred_at (ISO) of the oldest currently-loaded message. */
97
- readonly before: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
98
- /** Cap; defaults to RECENT_MESSAGE_LIMIT, clamped to it. */
99
- readonly limit: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
100
- }, undefined>, import("@orpc/contract").Schema<{
101
- messages: {
102
- id: any;
103
- role: any;
104
- content: any;
105
- parts: unknown[] | undefined;
106
- metadata: Record<string, unknown> | undefined;
107
- created_at: any;
108
- occurred_at: any;
109
- }[];
110
- hasMore: boolean;
111
- }, {
112
- messages: {
113
- id: any;
114
- role: any;
115
- content: any;
116
- parts: unknown[] | undefined;
117
- metadata: Record<string, unknown> | undefined;
118
- created_at: any;
119
- occurred_at: any;
120
- }[];
121
- hasMore: boolean;
122
- }>, Record<never, never>, Record<never, never>>;
123
- saveMessages: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
124
- headers: Headers;
125
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
126
- prisma: any;
127
- user: import("./auth-router.ts").User;
128
- orgId: string | null | undefined;
129
- }>, v.ObjectSchema<{
130
- readonly conversationId: v.StringSchema<undefined>;
131
- readonly messages: v.ArraySchema<v.ObjectSchema<{
132
- readonly id: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
133
- readonly role: v.StringSchema<undefined>;
134
- readonly content: v.StringSchema<undefined>;
135
- readonly parts: v.OptionalSchema<v.ArraySchema<v.AnySchema, undefined>, undefined>;
136
- readonly metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.AnySchema, undefined>, undefined>;
137
- }, undefined>, undefined>;
138
- }, undefined>, import("@orpc/contract").Schema<{
139
- success: boolean;
140
- }, {
141
- success: boolean;
142
- }>, Record<never, never>, Record<never, never>>;
143
- clear: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
144
- headers: Headers;
145
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
146
- prisma: any;
147
- user: import("./auth-router.ts").User;
148
- orgId: string | null | undefined;
149
- }>, v.ObjectSchema<{
150
- readonly conversationId: v.StringSchema<undefined>;
151
- }, undefined>, import("@orpc/contract").Schema<{
152
- conversationId: any;
153
- messages: never[];
154
- tokenTotals: {
155
- inputTokens: number;
156
- outputTokens: number;
157
- };
158
- }, {
159
- conversationId: any;
160
- messages: never[];
161
- tokenTotals: {
162
- inputTokens: number;
163
- outputTokens: number;
164
- };
165
- }>, Record<never, never>, Record<never, never>>;
166
- list: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
167
- headers: Headers;
168
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
169
- prisma: any;
170
- user: import("./auth-router.ts").User;
171
- orgId: string | null | undefined;
172
- }>, v.ObjectSchema<{
173
- readonly agentId: v.StringSchema<undefined>;
174
- readonly organisationId: v.StringSchema<undefined>;
175
- }, undefined>, import("@orpc/contract").Schema<{
176
- conversations: any;
177
- }, {
178
- conversations: any;
179
- }>, Record<never, never>, Record<never, never>>;
180
- load: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
181
- headers: Headers;
182
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
183
- prisma: any;
184
- user: import("./auth-router.ts").User;
185
- orgId: string | null | undefined;
186
- }>, v.ObjectSchema<{
187
- readonly conversationId: v.StringSchema<undefined>;
188
- }, undefined>, import("@orpc/contract").Schema<{
189
- conversationId: any;
190
- messages: {
191
- id: any;
192
- role: any;
193
- content: any;
194
- parts: unknown[] | undefined;
195
- metadata: Record<string, unknown> | undefined;
196
- created_at: any;
197
- occurred_at: any;
198
- }[];
199
- tokenTotals: {
200
- inputTokens: number;
201
- outputTokens: number;
202
- };
203
- }, {
204
- conversationId: any;
205
- messages: {
206
- id: any;
207
- role: any;
208
- content: any;
209
- parts: unknown[] | undefined;
210
- metadata: Record<string, unknown> | undefined;
211
- created_at: any;
212
- occurred_at: any;
213
- }[];
214
- tokenTotals: {
215
- inputTokens: number;
216
- outputTokens: number;
217
- };
218
- }>, Record<never, never>, Record<never, never>>;
219
- };
@@ -1 +0,0 @@
1
- export declare function getDefaultEmailSender(): Promise<string>;
@@ -1 +0,0 @@
1
- export declare function getEmailLinkTtlMs(): Promise<number>;
@@ -1,18 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Composes auth, tasks, work-items, plans, chat-session, public-gpt-session,
7
- * public-agreement, and user-preferences routers into the `fn` namespace and
8
- * registers it via registerCustomRouter.
9
- * Called at boot by registerFnRouters() — invoked before any ORPC dispatch.
10
- *
11
- * Also exposes the `regions` namespace on the client /api/rpc mount: a single
12
- * `loadPage` procedure (reusing puckPagesRouter.loadFromWebsite) so a client
13
- * RegionPageSwap can fetch a region's Puck page on demand and render it into a
14
- * slot — the no-reload half of `region-views-are-pages` (every region is a Puck
15
- * page; switching a view loads a different page's content). loadById is NOT
16
- * exposed (website+path is the client-facing contract, not raw page ids).
17
- */
18
- export declare function registerFnRouters(): void;
@@ -1,60 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * One transaction for the permanent Orchestrator registration. Database
7
- * uniqueness is the correctness boundary; every identity row is upserted
8
- * inside one transaction and callers cannot supply a project/session id.
9
- */
10
- import { type Context } from "./auth-router.ts";
11
- import * as v from "valibot";
12
- declare const input: v.ObjectSchema<{
13
- readonly runtime_slug: v.StringSchema<undefined>;
14
- }, undefined>;
15
- export type OrchestratorRegistrationRequest = v.InferOutput<typeof input>;
16
- export declare function buildOrchestratorSpawnPayload(input: {
17
- workItemId: string;
18
- launchCommentId: string;
19
- cliSessionId: string;
20
- slug: string;
21
- }): {
22
- workItemId: string;
23
- launchCommentId: string;
24
- cliSessionId: string;
25
- slug: string;
26
- };
27
- export declare function ensureOrchestratorRegistration(request: OrchestratorRegistrationRequest, context: Context): Promise<{
28
- projectId: string;
29
- taskId: string;
30
- sessionId: string;
31
- launchCommentId: string;
32
- runtime: string;
33
- slug: string | undefined;
34
- }>;
35
- export declare const orchestratorRegistrationRouter: {
36
- ensure: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
37
- headers: Headers;
38
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
39
- prisma: any;
40
- user: import("./auth-router.ts").User;
41
- orgId: string | null | undefined;
42
- }>, v.ObjectSchema<{
43
- readonly runtime_slug: v.StringSchema<undefined>;
44
- }, undefined>, import("@orpc/contract").Schema<{
45
- projectId: string;
46
- taskId: string;
47
- sessionId: string;
48
- launchCommentId: string;
49
- runtime: string;
50
- slug: string | undefined;
51
- }, {
52
- projectId: string;
53
- taskId: string;
54
- sessionId: string;
55
- launchCommentId: string;
56
- runtime: string;
57
- slug: string | undefined;
58
- }>, Record<never, never>, Record<never, never>>;
59
- };
60
- export {};
@@ -1,77 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * One transaction for the permanent Orchestrator registration. Database
7
- * uniqueness is the correctness boundary; every identity row is upserted
8
- * inside one transaction and callers cannot supply a project/session id.
9
- */
10
- import { authed, type Context } from "./auth-router.ts";
11
- import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
12
- import type { PrismaClient } from "@teamscala/db/client";
13
- import * as v from "valibot";
14
-
15
- const input = v.object({ runtime_slug: v.string() });
16
- const registryConfig = v.looseObject({
17
- enabled: v.optional(v.boolean()), model: v.optional(v.string()), reasoning_effort: v.optional(v.string()), picker_option_slug: v.optional(v.string()),
18
- });
19
-
20
- export type OrchestratorRegistrationRequest = v.InferOutput<typeof input>;
21
-
22
- export function buildOrchestratorSpawnPayload(input: {
23
- workItemId: string;
24
- launchCommentId: string;
25
- cliSessionId: string;
26
- slug: string;
27
- }) {
28
- return {
29
- workItemId: input.workItemId,
30
- launchCommentId: input.launchCommentId,
31
- cliSessionId: input.cliSessionId,
32
- slug: input.slug,
33
- };
34
- }
35
-
36
- export async function ensureOrchestratorRegistration(
37
- request: OrchestratorRegistrationRequest,
38
- context: Context,
39
- ) {
40
- const runtime = await loadRegistryConfig("agent_runtime", request.runtime_slug, registryConfig);
41
- if (runtime.enabled === false || runtime.model !== "gpt-5.6-sol" || runtime.reasoning_effort !== "high" || !runtime.picker_option_slug) throw new Error("requested runtime is not the registry-backed Sol High Orchestrator runtime");
42
- const user = context.user as { id: string; name?: string | null; displayName?: string | null; organisationId?: string | null };
43
- const organisationId = context.orgId || user.organisationId;
44
- if (!organisationId) throw new Error("Orchestrator registration requires an organisation");
45
- return await (context.prisma as PrismaClient).$transaction(async (tx) => {
46
- const initiative = await tx.work_items.findFirst({ where: { organisation_id: organisationId, kind: "initiative", kind_data: { path: ["tree"], equals: "agent_work" } } });
47
- if (!initiative) throw new Error("agent-work initiative is not registered");
48
- const developerName = user.displayName?.trim() || user.name?.trim() || "Developer";
49
- const project = await tx.work_items.upsert({
50
- where: { organisation_id_parent_id_assignee_id: { organisation_id: organisationId, parent_id: initiative.id, assignee_id: user.id } },
51
- create: { kind: "project", parent_id: initiative.id, organisation_id: organisationId, title: `Developer session — ${developerName}`, owner_id: user.id, assignee_id: user.id, created_by: user.id, kind_data: { project_type: "developer_session" } },
52
- update: { title: `Developer session — ${developerName}`, owner_id: user.id, assignee_id: user.id },
53
- });
54
- await tx.work_item_roles.upsert({ where: { work_item_id_user_id_role: { work_item_id: project.id, user_id: user.id, role: "assignee" } }, create: { work_item_id: project.id, user_id: user.id, role: "assignee", organisation_id: organisationId, created_by: user.id }, update: {} });
55
- const task = await tx.work_items.upsert({
56
- where: { parent_id_title: { parent_id: project.id, title: "Orchestrator" } },
57
- create: { kind: "task", parent_id: project.id, organisation_id: organisationId, title: "Orchestrator", owner_id: user.id, assignee_id: user.id, created_by: user.id },
58
- update: { owner_id: user.id, assignee_id: user.id },
59
- });
60
- const session = await tx.cli_sessions.upsert({
61
- where: { work_item_id: task.id },
62
- create: { authority: "operator", role: "orchestrator", cli_kind: "codex", picker_option_slug: runtime.picker_option_slug, runtime_slug: request.runtime_slug, provider: "codex", model: runtime.model, source_adapter: "orchestrator", label: "Orchestrator", lifecycle_state: "registering", host_route: {}, restore_metadata: {}, adapter_metadata: { project_id: project.id, work_item_id: task.id }, work_item_id: task.id },
63
- update: { picker_option_slug: runtime.picker_option_slug, runtime_slug: request.runtime_slug, model: runtime.model, closed_at: null, lifecycle_state: "registering" },
64
- });
65
- const startupBrief = `You are the permanent Orchestrator for developer project “${project.title}” (${project.id}). Coordinate all work through the canonical work_items and comments surfaces. Every tab is a child task, every prompt and reply is a comment, and cli_sessions is runtime identity only. Dispatch implementation through the fleet and reconcile durable outcomes; never create a parallel task, message, or session source.`;
66
- const launchComment = await tx.comments.upsert({ where: { work_item_id_system_key: { work_item_id: task.id, system_key: "orchestrator-startup" } }, update: { source_cli_session_id: session.id, sender_role: "orchestrator", sender_name: "Orchestrator" }, create: { work_item_id: task.id, content: startupBrief, system_key: "orchestrator-startup", source_cli_session_id: session.id, sender_role: "orchestrator", sender_name: "Orchestrator" } });
67
- await tx.cli_session_transitions.upsert({ where: { session_id_idempotency_key: { session_id: session.id, idempotency_key: `register:${project.id}` } }, create: { session_id: session.id, idempotency_key: `register:${project.id}`, from_state: null, to_state: "registering", trigger_event: "atomic-registration", metadata_json: { work_item_id: task.id } }, update: {} });
68
- await tx.host_commands.upsert({ where: { command_idempotency_key: { command: "picker_spawn_tab", idempotency_key: `orchestrator-visible:${project.id}` } }, update: {}, create: { command: "picker_spawn_tab", idempotency_key: `orchestrator-visible:${project.id}`, payload: buildOrchestratorSpawnPayload({ workItemId: task.id, launchCommentId: launchComment.id, cliSessionId: session.id, slug: runtime.picker_option_slug }), originator: { role: "orchestrator", session_id: session.id } } });
69
- return { projectId: project.id, taskId: task.id, sessionId: session.id, launchCommentId: launchComment.id, runtime: request.runtime_slug, slug: runtime.picker_option_slug };
70
- });
71
- }
72
-
73
- export const orchestratorRegistrationRouter = {
74
- ensure: authed.input(input).handler(async ({ input: request, context }) => {
75
- return ensureOrchestratorRegistration(request, context);
76
- }),
77
- };
@@ -1,70 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Real database concurrency acceptance for the canonical developer-session
7
- * registration. Run with PM_FLEET_LIVE_TEST=1 and a PM_FLEET_TEST_USER_ID
8
- * (plus PM_FLEET_TEST_ORG_ID when the user has more than one membership).
9
- */
10
- import { describe, expect, it } from "bun:test";
11
- import { createDbClient } from "@teamscala/db/create-db-client";
12
- import { registerPrismaClient } from "@teamscala/db/prisma-registry";
13
- import { ensureOrchestratorRegistration } from "./orchestrator-registration-router.ts";
14
- import type { Context } from "./auth-router.ts";
15
-
16
- const live = process.env.PM_FLEET_LIVE_TEST === "1";
17
-
18
- describe.skipIf(!live)("canonical Orchestrator registration — live database", () => {
19
- it("concurrent callers converge on one project, task, comment, runtime, transition, and spawn intent", async () => {
20
- const userId = process.env.PM_FLEET_TEST_USER_ID;
21
- if (!userId) throw new Error("PM_FLEET_TEST_USER_ID is required for the live concurrency acceptance");
22
- const db = await createDbClient({ serviceName: "service-boot-pm-fleet-live", maxConnections: 10 });
23
- try {
24
- registerPrismaClient(db.prisma as never);
25
- const user = await db.prisma.user.findUniqueOrThrow({ where: { id: userId }, select: { id: true, name: true } });
26
- const organisationId = process.env.PM_FLEET_TEST_ORG_ID;
27
- if (!organisationId) throw new Error("PM_FLEET_TEST_ORG_ID is required for the live concurrency acceptance");
28
- const context: Context = { user: { id: user.id, name: user.name, organisationId }, orgId: organisationId, prisma: db.prisma, headers: new Headers() };
29
- const results = await Promise.all(Array.from({ length: 8 }, () => ensureOrchestratorRegistration({ runtime_slug: "codex-acp" }, context)));
30
- const projectIds = new Set(results.map((result) => result.projectId));
31
- const taskIds = new Set(results.map((result) => result.taskId));
32
- const sessionIds = new Set(results.map((result) => result.sessionId));
33
- expect(projectIds.size).toBe(1);
34
- expect(taskIds.size).toBe(1);
35
- expect(sessionIds.size).toBe(1);
36
- const projectId = results[0]?.projectId;
37
- const taskId = results[0]?.taskId;
38
- const sessionId = results[0]?.sessionId;
39
- expect(await db.prisma.work_items.count({ where: { id: projectId, parent: { kind: "initiative", kind_data: { path: ["tree"], equals: "agent_work" } } } })).toBe(1);
40
- expect(await db.prisma.work_items.count({ where: { id: taskId, parent_id: projectId, kind: "task", title: "Orchestrator" } })).toBe(1);
41
- const startupComments = await db.prisma.comments.findMany({
42
- where: { work_item_id: taskId, system_key: "orchestrator-startup" },
43
- select: { id: true, source_cli_session_id: true, sender_role: true, sender_name: true },
44
- });
45
- expect(startupComments).toHaveLength(1);
46
- expect(startupComments[0]).toMatchObject({
47
- id: results[0]?.launchCommentId,
48
- source_cli_session_id: sessionId,
49
- sender_role: "orchestrator",
50
- sender_name: "Orchestrator",
51
- });
52
- expect(await db.prisma.cli_sessions.count({ where: { id: sessionId, work_item_id: taskId, role: "orchestrator", closed_at: null } })).toBe(1);
53
- expect(await db.prisma.cli_session_transitions.count({ where: { session_id: sessionId, idempotency_key: `register:${projectId}` } })).toBe(1);
54
- const spawnIntents = await db.prisma.host_commands.findMany({
55
- where: { command: "picker_spawn_tab", idempotency_key: `orchestrator-visible:${projectId}` },
56
- select: { payload: true },
57
- });
58
- expect(spawnIntents).toHaveLength(1);
59
- expect(spawnIntents[0]?.payload).toMatchObject({
60
- workItemId: taskId,
61
- launchCommentId: results[0]?.launchCommentId,
62
- cliSessionId: sessionId,
63
- slug: results[0]?.slug,
64
- });
65
- expect(Object.keys(spawnIntents[0]?.payload as Record<string, unknown>).sort()).toEqual(["cliSessionId", "launchCommentId", "slug", "workItemId"]);
66
- } finally {
67
- await db.disconnect();
68
- }
69
- });
70
- });
@@ -1,23 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { buildOrchestratorSpawnPayload } from "./orchestrator-registration-router.ts";
3
-
4
- describe("orchestrator spawn intent", () => {
5
- it("uses the generated Rust slug contract and carries no alternate launch input", () => {
6
- const payload = buildOrchestratorSpawnPayload({
7
- workItemId: "task-1",
8
- launchCommentId: "comment-1",
9
- cliSessionId: "session-1",
10
- slug: "codex-sol-acp-client",
11
- });
12
- expect(payload).toEqual({
13
- workItemId: "task-1",
14
- launchCommentId: "comment-1",
15
- cliSessionId: "session-1",
16
- slug: "codex-sol-acp-client",
17
- });
18
- expect(payload).not.toHaveProperty("pickerOptionSlug");
19
- expect(payload).not.toHaveProperty("initialPrompt");
20
- expect(payload).not.toHaveProperty("windowName");
21
- expect(Object.keys(payload).sort()).toEqual(["cliSessionId", "launchCommentId", "slug", "workItemId"]);
22
- });
23
- });
@@ -1,19 +0,0 @@
1
- import * as v from "valibot";
2
- interface Context {
3
- prisma: {
4
- builda_websites: {
5
- findFirst: (args: unknown) => Promise<{
6
- organisation_id?: string | null;
7
- } | null>;
8
- };
9
- };
10
- }
11
- export declare const resolvePanelDataHandler: import("@orpc/server").DecoratedProcedure<Context & Record<never, never>, Context, v.ObjectSchema<{
12
- readonly panelSlug: v.StringSchema<undefined>;
13
- readonly websiteSlug: v.StringSchema<undefined>;
14
- /** Tenant orgId (preferred over the website's organisation_id, which is
15
- * the platform org on a multi-tenant portal — not the tenant). The
16
- * caller (RegionPageSwap) threads this from __PAGE_DATA__.orgId. */
17
- readonly orgId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
18
- }, undefined>, import("@orpc/contract").Schema<Record<string, unknown> | null, Record<string, unknown> | null>, Record<never, never>, Record<never, never>>;
19
- export {};
@@ -1,36 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The ONE chat-message write surface for the session routers. Both the authed
7
- * (chatSession) and public (publicGptSession) saveMessages procedures persist
8
- * turns through here — they differ only in IDENTITY/ownership (user_id vs
9
- * contact_email, resolved in the router before calling this), never in the
10
- * write itself. Keeping the write in two routers was literal duplication
11
- * (no-duplicate-canonical-units) and is why the stable-id fix had to be applied
12
- * twice.
13
- *
14
- * Upserts each message on its SDK UIMessage id so a re-save of a turn (a retry,
15
- * a reconnect after a network drop, or a stray dual-write) updates the one row
16
- * in place instead of inserting a duplicate (chat-message-ids-server-stable);
17
- * falls back to create only for legacy id-less callers. occurred_at is stamped
18
- * with a 1ms step preserving array order so same-second saves restore in order.
19
- */
20
- export interface ChatMessageInput {
21
- id?: string;
22
- role: string;
23
- content: string;
24
- parts?: unknown[];
25
- /** The SDK UIMessage `metadata` — carries per-message token usage
26
- * (`inputTokens`/`outputTokens`/`contextWindow`/`model`) the stream attaches
27
- * via `messageMetadata`. Persisted so the context-usage gauge can rehydrate
28
- * on reload and budget-enforcement can read per-message token counts; without
29
- * it the save dropped the usage and the gauge came back blank on refresh. */
30
- metadata?: Record<string, unknown> | null;
31
- }
32
- export declare function persistChatMessages(prisma: any, opts: {
33
- conversationId: string;
34
- organisationId: string | null;
35
- messages: ChatMessageInput[];
36
- }): Promise<void>;
@@ -1,25 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * ORPC procedures for plan creation with tasks and subtasks.
7
- * Extracted from @teamscala/orpc/fn-router — primitives tier must not
8
- * contain application-specific work_items logic.
9
- */
10
- import { type Context } from "./auth-router.ts";
11
- export declare const plansRouter: {
12
- save: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
13
- headers: Headers;
14
- resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
15
- prisma: any;
16
- user: import("./auth-router.ts").User;
17
- orgId: string | null | undefined;
18
- }>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<{
19
- success: boolean;
20
- data: any;
21
- }, {
22
- success: boolean;
23
- data: any;
24
- }>, Record<never, never>, Record<never, never>>;
25
- };
@@ -1,58 +0,0 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The proposal SEND router — the proposal twin of agreement-send-router. An
7
- * authed portal caller POSTs {proposalId, baseUrl} to email the proposal's CRM
8
- * contact a per-recipient magic-link (no email gate, no OTP — see
9
- * attach-proposal-magic.ts) to view their proposal. Resend-backed.
10
- */
11
- import * as v from "valibot";
12
- interface User {
13
- id: string;
14
- organisationId: string | null;
15
- }
16
- interface Context {
17
- user: User | null | undefined;
18
- headers: Headers;
19
- resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
20
- prisma: any;
21
- }
22
- export declare const proposalSendRouter: {
23
- send: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
24
- headers: Headers;
25
- resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
26
- prisma: any;
27
- user: User;
28
- }>, v.ObjectSchema<{
29
- readonly proposalId: v.StringSchema<undefined>;
30
- /** Public base URL of the proposals site, e.g. https://proposals-dev.scala.business (no trailing slash). */
31
- readonly baseUrl: v.StringSchema<undefined>;
32
- }, undefined>, import("@orpc/contract").Schema<{
33
- ok: false;
34
- error: string;
35
- sentAt?: undefined;
36
- url?: undefined;
37
- email?: undefined;
38
- } | {
39
- error?: undefined;
40
- ok: true;
41
- sentAt: string;
42
- url: string;
43
- email: string;
44
- }, {
45
- ok: false;
46
- error: string;
47
- sentAt?: undefined;
48
- url?: undefined;
49
- email?: undefined;
50
- } | {
51
- error?: undefined;
52
- ok: true;
53
- sentAt: string;
54
- url: string;
55
- email: string;
56
- }>, Record<never, never>, Record<never, never>>;
57
- };
58
- export {};