@orthacms/copilot-server 0.0.0-reserve.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/index.d.ts +24 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +48 -0
  6. package/dist/lib/chat/application/appliers-registrar.d.ts +16 -0
  7. package/dist/lib/chat/application/appliers-registrar.d.ts.map +1 -0
  8. package/dist/lib/chat/application/appliers-registrar.js +50 -0
  9. package/dist/lib/chat/application/capability-profile.service.d.ts +43 -0
  10. package/dist/lib/chat/application/capability-profile.service.d.ts.map +1 -0
  11. package/dist/lib/chat/application/capability-profile.service.js +75 -0
  12. package/dist/lib/chat/application/content-type-summary.service.d.ts +32 -0
  13. package/dist/lib/chat/application/content-type-summary.service.d.ts.map +1 -0
  14. package/dist/lib/chat/application/content-type-summary.service.js +64 -0
  15. package/dist/lib/chat/application/decide-proposal.service.d.ts +80 -0
  16. package/dist/lib/chat/application/decide-proposal.service.d.ts.map +1 -0
  17. package/dist/lib/chat/application/decide-proposal.service.js +112 -0
  18. package/dist/lib/chat/application/dto/create-run.dto.d.ts +138 -0
  19. package/dist/lib/chat/application/dto/create-run.dto.d.ts.map +1 -0
  20. package/dist/lib/chat/application/dto/create-run.dto.js +253 -0
  21. package/dist/lib/chat/application/dto/decide-tool-permission.dto.d.ts +20 -0
  22. package/dist/lib/chat/application/dto/decide-tool-permission.dto.d.ts.map +1 -0
  23. package/dist/lib/chat/application/dto/decide-tool-permission.dto.js +44 -0
  24. package/dist/lib/chat/application/dto/extend-tool-permission.dto.d.ts +18 -0
  25. package/dist/lib/chat/application/dto/extend-tool-permission.dto.d.ts.map +1 -0
  26. package/dist/lib/chat/application/dto/extend-tool-permission.dto.js +33 -0
  27. package/dist/lib/chat/application/dto/list-conversations-query.dto.d.ts +18 -0
  28. package/dist/lib/chat/application/dto/list-conversations-query.dto.d.ts.map +1 -0
  29. package/dist/lib/chat/application/dto/list-conversations-query.dto.js +39 -0
  30. package/dist/lib/chat/application/dto/list-proposals-query.dto.d.ts +15 -0
  31. package/dist/lib/chat/application/dto/list-proposals-query.dto.d.ts.map +1 -0
  32. package/dist/lib/chat/application/dto/list-proposals-query.dto.js +41 -0
  33. package/dist/lib/chat/application/dto/update-conversation.dto.d.ts +68 -0
  34. package/dist/lib/chat/application/dto/update-conversation.dto.d.ts.map +1 -0
  35. package/dist/lib/chat/application/dto/update-conversation.dto.js +115 -0
  36. package/dist/lib/chat/application/proposal-applier.registry.d.ts +27 -0
  37. package/dist/lib/chat/application/proposal-applier.registry.d.ts.map +1 -0
  38. package/dist/lib/chat/application/proposal-applier.registry.js +62 -0
  39. package/dist/lib/chat/application/run-engine.service.d.ts +243 -0
  40. package/dist/lib/chat/application/run-engine.service.d.ts.map +1 -0
  41. package/dist/lib/chat/application/run-engine.service.js +1058 -0
  42. package/dist/lib/chat/application/summarize-tool-output.d.ts +15 -0
  43. package/dist/lib/chat/application/summarize-tool-output.d.ts.map +1 -0
  44. package/dist/lib/chat/application/summarize-tool-output.js +61 -0
  45. package/dist/lib/chat/application/system-prompt.d.ts +81 -0
  46. package/dist/lib/chat/application/system-prompt.d.ts.map +1 -0
  47. package/dist/lib/chat/application/system-prompt.js +477 -0
  48. package/dist/lib/chat/application/tool-permission.broker.d.ts +118 -0
  49. package/dist/lib/chat/application/tool-permission.broker.d.ts.map +1 -0
  50. package/dist/lib/chat/application/tool-permission.broker.js +221 -0
  51. package/dist/lib/chat/http/controllers/create-run.controller.d.ts +30 -0
  52. package/dist/lib/chat/http/controllers/create-run.controller.d.ts.map +1 -0
  53. package/dist/lib/chat/http/controllers/create-run.controller.js +159 -0
  54. package/dist/lib/chat/http/controllers/get-conversation.controller.d.ts +22 -0
  55. package/dist/lib/chat/http/controllers/get-conversation.controller.d.ts.map +1 -0
  56. package/dist/lib/chat/http/controllers/get-conversation.controller.js +50 -0
  57. package/dist/lib/chat/http/controllers/list-conversations.controller.d.ts +20 -0
  58. package/dist/lib/chat/http/controllers/list-conversations.controller.d.ts.map +1 -0
  59. package/dist/lib/chat/http/controllers/list-conversations.controller.js +47 -0
  60. package/dist/lib/chat/http/controllers/list-models.controller.d.ts +35 -0
  61. package/dist/lib/chat/http/controllers/list-models.controller.d.ts.map +1 -0
  62. package/dist/lib/chat/http/controllers/list-models.controller.js +48 -0
  63. package/dist/lib/chat/http/controllers/proposals.controller.d.ts +43 -0
  64. package/dist/lib/chat/http/controllers/proposals.controller.d.ts.map +1 -0
  65. package/dist/lib/chat/http/controllers/proposals.controller.js +98 -0
  66. package/dist/lib/chat/http/controllers/tool-permission.controller.d.ts +57 -0
  67. package/dist/lib/chat/http/controllers/tool-permission.controller.d.ts.map +1 -0
  68. package/dist/lib/chat/http/controllers/tool-permission.controller.js +116 -0
  69. package/dist/lib/chat/http/controllers/update-conversation.controller.d.ts +37 -0
  70. package/dist/lib/chat/http/controllers/update-conversation.controller.d.ts.map +1 -0
  71. package/dist/lib/chat/http/controllers/update-conversation.controller.js +108 -0
  72. package/dist/lib/chat/http/sse-stream.d.ts +41 -0
  73. package/dist/lib/chat/http/sse-stream.d.ts.map +1 -0
  74. package/dist/lib/chat/http/sse-stream.js +95 -0
  75. package/dist/lib/chat/infrastructure/persistence/conversation.repository.d.ts +159 -0
  76. package/dist/lib/chat/infrastructure/persistence/conversation.repository.d.ts.map +1 -0
  77. package/dist/lib/chat/infrastructure/persistence/conversation.repository.js +249 -0
  78. package/dist/lib/chat/infrastructure/persistence/derive-title.d.ts +13 -0
  79. package/dist/lib/chat/infrastructure/persistence/derive-title.d.ts.map +1 -0
  80. package/dist/lib/chat/infrastructure/persistence/derive-title.js +35 -0
  81. package/dist/lib/chat/infrastructure/persistence/proposal.repository.d.ts +86 -0
  82. package/dist/lib/chat/infrastructure/persistence/proposal.repository.d.ts.map +1 -0
  83. package/dist/lib/chat/infrastructure/persistence/proposal.repository.js +152 -0
  84. package/dist/lib/chat/infrastructure/schema/conversations.d.ts +189 -0
  85. package/dist/lib/chat/infrastructure/schema/conversations.d.ts.map +1 -0
  86. package/dist/lib/chat/infrastructure/schema/conversations.js +100 -0
  87. package/dist/lib/chat/infrastructure/schema/external-refs.d.ts +67 -0
  88. package/dist/lib/chat/infrastructure/schema/external-refs.d.ts.map +1 -0
  89. package/dist/lib/chat/infrastructure/schema/external-refs.js +28 -0
  90. package/dist/lib/chat/infrastructure/schema/index.d.ts +5 -0
  91. package/dist/lib/chat/infrastructure/schema/index.d.ts.map +1 -0
  92. package/dist/lib/chat/infrastructure/schema/index.js +12 -0
  93. package/dist/lib/chat/infrastructure/schema/messages.d.ts +264 -0
  94. package/dist/lib/chat/infrastructure/schema/messages.d.ts.map +1 -0
  95. package/dist/lib/chat/infrastructure/schema/messages.js +96 -0
  96. package/dist/lib/chat/infrastructure/schema/proposals.d.ts +328 -0
  97. package/dist/lib/chat/infrastructure/schema/proposals.d.ts.map +1 -0
  98. package/dist/lib/chat/infrastructure/schema/proposals.js +87 -0
  99. package/dist/lib/chat/infrastructure/schema/tool-calls.d.ts +203 -0
  100. package/dist/lib/chat/infrastructure/schema/tool-calls.d.ts.map +1 -0
  101. package/dist/lib/chat/infrastructure/schema/tool-calls.js +50 -0
  102. package/dist/lib/copilot.module.d.ts +30 -0
  103. package/dist/lib/copilot.module.d.ts.map +1 -0
  104. package/dist/lib/copilot.module.js +146 -0
  105. package/dist/lib/copilot.tokens.d.ts +34 -0
  106. package/dist/lib/copilot.tokens.d.ts.map +1 -0
  107. package/dist/lib/copilot.tokens.js +38 -0
  108. package/dist/lib/infrastructure/model-registry.d.ts +22 -0
  109. package/dist/lib/infrastructure/model-registry.d.ts.map +1 -0
  110. package/dist/lib/infrastructure/model-registry.js +54 -0
  111. package/dist/lib/skills/application/dto/create-skill.dto.d.ts +36 -0
  112. package/dist/lib/skills/application/dto/create-skill.dto.d.ts.map +1 -0
  113. package/dist/lib/skills/application/dto/create-skill.dto.js +106 -0
  114. package/dist/lib/skills/application/dto/update-skill.dto.d.ts +28 -0
  115. package/dist/lib/skills/application/dto/update-skill.dto.d.ts.map +1 -0
  116. package/dist/lib/skills/application/dto/update-skill.dto.js +96 -0
  117. package/dist/lib/skills/application/skill-catalog.service.d.ts +97 -0
  118. package/dist/lib/skills/application/skill-catalog.service.d.ts.map +1 -0
  119. package/dist/lib/skills/application/skill-catalog.service.js +157 -0
  120. package/dist/lib/skills/http/controllers/list-skills.controller.d.ts +19 -0
  121. package/dist/lib/skills/http/controllers/list-skills.controller.d.ts.map +1 -0
  122. package/dist/lib/skills/http/controllers/list-skills.controller.js +50 -0
  123. package/dist/lib/skills/http/controllers/manage-skills.controller.d.ts +64 -0
  124. package/dist/lib/skills/http/controllers/manage-skills.controller.d.ts.map +1 -0
  125. package/dist/lib/skills/http/controllers/manage-skills.controller.js +182 -0
  126. package/dist/lib/skills/infrastructure/persistence/skill.repository.d.ts +78 -0
  127. package/dist/lib/skills/infrastructure/persistence/skill.repository.d.ts.map +1 -0
  128. package/dist/lib/skills/infrastructure/persistence/skill.repository.js +116 -0
  129. package/dist/lib/skills/infrastructure/schema/index.d.ts +2 -0
  130. package/dist/lib/skills/infrastructure/schema/index.d.ts.map +1 -0
  131. package/dist/lib/skills/infrastructure/schema/index.js +6 -0
  132. package/dist/lib/skills/infrastructure/schema/skills.d.ts +212 -0
  133. package/dist/lib/skills/infrastructure/schema/skills.d.ts.map +1 -0
  134. package/dist/lib/skills/infrastructure/schema/skills.js +78 -0
  135. package/dist/lib/types/copilot-config.d.ts +55 -0
  136. package/dist/lib/types/copilot-config.d.ts.map +1 -0
  137. package/dist/lib/types/copilot-config.js +2 -0
  138. package/dist/lib/utils/copilot-plugin.d.ts +66 -0
  139. package/dist/lib/utils/copilot-plugin.d.ts.map +1 -0
  140. package/dist/lib/utils/copilot-plugin.js +87 -0
  141. package/migrations/0000_copilot_chat.sql +48 -0
  142. package/migrations/0001_proposals.sql +34 -0
  143. package/migrations/0002_drop_workspace_policies.sql +1 -0
  144. package/migrations/0003_conversation_allowed_tools.sql +1 -0
  145. package/migrations/0004_message_attachments.sql +1 -0
  146. package/migrations/0005_skills.sql +19 -0
  147. package/migrations/0006_conversation_model_choice.sql +1 -0
  148. package/migrations/meta/0000_snapshot.json +390 -0
  149. package/migrations/meta/0001_snapshot.json +657 -0
  150. package/migrations/meta/0002_snapshot.json +610 -0
  151. package/migrations/meta/0003_snapshot.json +617 -0
  152. package/migrations/meta/0004_snapshot.json +623 -0
  153. package/migrations/meta/0005_snapshot.json +771 -0
  154. package/migrations/meta/0006_snapshot.json +777 -0
  155. package/migrations/meta/_journal.json +55 -0
  156. package/package.json +46 -0
@@ -0,0 +1,212 @@
1
+ /** Whether a skill applies to every run or only when someone attaches it. */
2
+ export declare const copilotSkillMode: import("drizzle-orm/pg-core").PgEnum<["manual", "always"]>;
3
+ /**
4
+ * One CMS-authored skill — a reusable instruction packet the copilot can run
5
+ * with, scoped to the workspace it was written in.
6
+ *
7
+ * **Workspace-scoped, not deployment-wide.** A skill is editorial guidance
8
+ * about a particular body of content, which is exactly what a workspace
9
+ * bounds; the deployment-wide case is served by the host's code-defined skills,
10
+ * which are reviewed in git and identical everywhere. That split also keeps the
11
+ * blast radius of the write permission inside one workspace.
12
+ *
13
+ * `instructions` is **prompt text, not content**. Writing here is authoring
14
+ * part of the system prompt for everyone in the workspace, which is why the
15
+ * write routes require `copilot:skills:manage` (admin-only) rather than a
16
+ * content permission — see ADR-0010.
17
+ */
18
+ export declare const copilotSkills: import("drizzle-orm/pg-core").PgTableWithColumns<{
19
+ name: "copilot_skills";
20
+ schema: undefined;
21
+ columns: {
22
+ id: import("drizzle-orm/pg-core").PgColumn<{
23
+ name: "id";
24
+ tableName: "copilot_skills";
25
+ dataType: "string";
26
+ columnType: "PgUUID";
27
+ data: string;
28
+ driverParam: string;
29
+ notNull: true;
30
+ hasDefault: true;
31
+ isPrimaryKey: true;
32
+ isAutoincrement: false;
33
+ hasRuntimeDefault: false;
34
+ enumValues: undefined;
35
+ baseColumn: never;
36
+ identity: undefined;
37
+ generated: undefined;
38
+ }, {}, {}>;
39
+ workspaceId: import("drizzle-orm/pg-core").PgColumn<{
40
+ name: "workspace_id";
41
+ tableName: "copilot_skills";
42
+ dataType: "string";
43
+ columnType: "PgUUID";
44
+ data: string;
45
+ driverParam: string;
46
+ notNull: true;
47
+ hasDefault: false;
48
+ isPrimaryKey: false;
49
+ isAutoincrement: false;
50
+ hasRuntimeDefault: false;
51
+ enumValues: undefined;
52
+ baseColumn: never;
53
+ identity: undefined;
54
+ generated: undefined;
55
+ }, {}, {}>;
56
+ name: import("drizzle-orm/pg-core").PgColumn<{
57
+ name: "name";
58
+ tableName: "copilot_skills";
59
+ dataType: "string";
60
+ columnType: "PgText";
61
+ data: string;
62
+ driverParam: string;
63
+ notNull: true;
64
+ hasDefault: false;
65
+ isPrimaryKey: false;
66
+ isAutoincrement: false;
67
+ hasRuntimeDefault: false;
68
+ enumValues: [string, ...string[]];
69
+ baseColumn: never;
70
+ identity: undefined;
71
+ generated: undefined;
72
+ }, {}, {}>;
73
+ title: import("drizzle-orm/pg-core").PgColumn<{
74
+ name: "title";
75
+ tableName: "copilot_skills";
76
+ dataType: "string";
77
+ columnType: "PgText";
78
+ data: string;
79
+ driverParam: string;
80
+ notNull: true;
81
+ hasDefault: false;
82
+ isPrimaryKey: false;
83
+ isAutoincrement: false;
84
+ hasRuntimeDefault: false;
85
+ enumValues: [string, ...string[]];
86
+ baseColumn: never;
87
+ identity: undefined;
88
+ generated: undefined;
89
+ }, {}, {}>;
90
+ description: import("drizzle-orm/pg-core").PgColumn<{
91
+ name: "description";
92
+ tableName: "copilot_skills";
93
+ dataType: "string";
94
+ columnType: "PgText";
95
+ data: string;
96
+ driverParam: string;
97
+ notNull: true;
98
+ hasDefault: false;
99
+ isPrimaryKey: false;
100
+ isAutoincrement: false;
101
+ hasRuntimeDefault: false;
102
+ enumValues: [string, ...string[]];
103
+ baseColumn: never;
104
+ identity: undefined;
105
+ generated: undefined;
106
+ }, {}, {}>;
107
+ instructions: import("drizzle-orm/pg-core").PgColumn<{
108
+ name: "instructions";
109
+ tableName: "copilot_skills";
110
+ dataType: "string";
111
+ columnType: "PgText";
112
+ data: string;
113
+ driverParam: string;
114
+ notNull: true;
115
+ hasDefault: false;
116
+ isPrimaryKey: false;
117
+ isAutoincrement: false;
118
+ hasRuntimeDefault: false;
119
+ enumValues: [string, ...string[]];
120
+ baseColumn: never;
121
+ identity: undefined;
122
+ generated: undefined;
123
+ }, {}, {}>;
124
+ mode: import("drizzle-orm/pg-core").PgColumn<{
125
+ name: "mode";
126
+ tableName: "copilot_skills";
127
+ dataType: "string";
128
+ columnType: "PgEnumColumn";
129
+ data: "always" | "manual";
130
+ driverParam: string;
131
+ notNull: true;
132
+ hasDefault: true;
133
+ isPrimaryKey: false;
134
+ isAutoincrement: false;
135
+ hasRuntimeDefault: false;
136
+ enumValues: ["manual", "always"];
137
+ baseColumn: never;
138
+ identity: undefined;
139
+ generated: undefined;
140
+ }, {}, {}>;
141
+ enabled: import("drizzle-orm/pg-core").PgColumn<{
142
+ name: "enabled";
143
+ tableName: "copilot_skills";
144
+ dataType: "boolean";
145
+ columnType: "PgBoolean";
146
+ data: boolean;
147
+ driverParam: boolean;
148
+ notNull: true;
149
+ hasDefault: true;
150
+ isPrimaryKey: false;
151
+ isAutoincrement: false;
152
+ hasRuntimeDefault: false;
153
+ enumValues: undefined;
154
+ baseColumn: never;
155
+ identity: undefined;
156
+ generated: undefined;
157
+ }, {}, {}>;
158
+ createdBy: import("drizzle-orm/pg-core").PgColumn<{
159
+ name: "created_by";
160
+ tableName: "copilot_skills";
161
+ dataType: "string";
162
+ columnType: "PgUUID";
163
+ data: string;
164
+ driverParam: string;
165
+ notNull: false;
166
+ hasDefault: false;
167
+ isPrimaryKey: false;
168
+ isAutoincrement: false;
169
+ hasRuntimeDefault: false;
170
+ enumValues: undefined;
171
+ baseColumn: never;
172
+ identity: undefined;
173
+ generated: undefined;
174
+ }, {}, {}>;
175
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
176
+ name: "created_at";
177
+ tableName: "copilot_skills";
178
+ dataType: "date";
179
+ columnType: "PgTimestamp";
180
+ data: Date;
181
+ driverParam: string;
182
+ notNull: true;
183
+ hasDefault: true;
184
+ isPrimaryKey: false;
185
+ isAutoincrement: false;
186
+ hasRuntimeDefault: false;
187
+ enumValues: undefined;
188
+ baseColumn: never;
189
+ identity: undefined;
190
+ generated: undefined;
191
+ }, {}, {}>;
192
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
193
+ name: "updated_at";
194
+ tableName: "copilot_skills";
195
+ dataType: "date";
196
+ columnType: "PgTimestamp";
197
+ data: Date;
198
+ driverParam: string;
199
+ notNull: true;
200
+ hasDefault: true;
201
+ isPrimaryKey: false;
202
+ isAutoincrement: false;
203
+ hasRuntimeDefault: false;
204
+ enumValues: undefined;
205
+ baseColumn: never;
206
+ identity: undefined;
207
+ generated: undefined;
208
+ }, {}, {}>;
209
+ };
210
+ dialect: "pg";
211
+ }>;
212
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../../../src/lib/skills/infrastructure/schema/skills.ts"],"names":[],"mappings":"AAcA,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,4DAG3B,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2DzB,CAAC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copilotSkills = exports.copilotSkillMode = void 0;
4
+ const pg_core_1 = require("drizzle-orm/pg-core");
5
+ const external_refs_1 = require("../../../chat/infrastructure/schema/external-refs");
6
+ /** Whether a skill applies to every run or only when someone attaches it. */
7
+ exports.copilotSkillMode = (0, pg_core_1.pgEnum)('copilot_skill_mode', [
8
+ 'manual',
9
+ 'always'
10
+ ]);
11
+ /**
12
+ * One CMS-authored skill — a reusable instruction packet the copilot can run
13
+ * with, scoped to the workspace it was written in.
14
+ *
15
+ * **Workspace-scoped, not deployment-wide.** A skill is editorial guidance
16
+ * about a particular body of content, which is exactly what a workspace
17
+ * bounds; the deployment-wide case is served by the host's code-defined skills,
18
+ * which are reviewed in git and identical everywhere. That split also keeps the
19
+ * blast radius of the write permission inside one workspace.
20
+ *
21
+ * `instructions` is **prompt text, not content**. Writing here is authoring
22
+ * part of the system prompt for everyone in the workspace, which is why the
23
+ * write routes require `copilot:skills:manage` (admin-only) rather than a
24
+ * content permission — see ADR-0010.
25
+ */
26
+ exports.copilotSkills = (0, pg_core_1.pgTable)('copilot_skills', {
27
+ /** Primary key. */
28
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
29
+ /** The workspace this skill belongs to. */
30
+ workspaceId: (0, pg_core_1.uuid)('workspace_id')
31
+ .notNull()
32
+ .references(() => external_refs_1.workspaces.id, { onDelete: 'cascade' }),
33
+ /**
34
+ * Machine name, unique within the workspace and refused if a
35
+ * code-defined skill already holds it. What a run request names.
36
+ */
37
+ name: (0, pg_core_1.text)('name').notNull(),
38
+ /** What a person reads in the picker and on a chip. */
39
+ title: (0, pg_core_1.text)('title').notNull(),
40
+ /**
41
+ * When to use it, written for the model. In the prompt for **every**
42
+ * enabled skill in the workspace, whether or not it is in force — which
43
+ * is what lets the model recommend one it has not been given.
44
+ */
45
+ description: (0, pg_core_1.text)('description').notNull(),
46
+ /** The body. Reaches the model only when the skill is in force. */
47
+ instructions: (0, pg_core_1.text)('instructions').notNull(),
48
+ /** `always` puts it in force on every run in this workspace. */
49
+ mode: (0, exports.copilotSkillMode)('mode').notNull().default('manual'),
50
+ /**
51
+ * Off without deleting. A disabled skill is absent from the catalogue
52
+ * rather than greyed out in it: the picker's job is to show what can be
53
+ * used, and the manage page reads the disabled ones separately.
54
+ */
55
+ enabled: (0, pg_core_1.boolean)('enabled').notNull().default(true),
56
+ /**
57
+ * Who wrote it — attribution only. `set null` rather than `cascade`,
58
+ * unlike the conversation tables: a thread is personal and goes with
59
+ * its owner, while a skill is workspace configuration that must survive
60
+ * the admin who happened to type it.
61
+ */
62
+ createdBy: (0, pg_core_1.uuid)('created_by').references(() => external_refs_1.users.id, {
63
+ onDelete: 'set null'
64
+ }),
65
+ /** Row creation timestamp. */
66
+ createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true })
67
+ .notNull()
68
+ .defaultNow(),
69
+ /** Last edit. Bumped on every write, unlike a conversation's. */
70
+ updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true })
71
+ .notNull()
72
+ .defaultNow()
73
+ }, (table) => [
74
+ // The uniqueness the resolver depends on: a run names a skill by
75
+ // `name`, so two rows sharing one in a workspace would make which
76
+ // instructions the model receives a matter of row order.
77
+ (0, pg_core_1.uniqueIndex)('copilot_skills_workspace_name_idx').on(table.workspaceId, table.name)
78
+ ]);
@@ -0,0 +1,55 @@
1
+ import type { RunLimits } from '@orthacms/copilot-domain';
2
+ /**
3
+ * The copilot plugin's host-supplied config.
4
+ *
5
+ * Deliberately **adapter-agnostic**: it names no provider kind and imports no
6
+ * adapter package, so adding a Bedrock or Vertex adapter is a new package and
7
+ * a line in the composition root — never a change here
8
+ * ([ADR-0004](../../../../../docs/adr/0004-model-agnostic-copilot-provider.md) §2).
9
+ *
10
+ * Provider *connection* settings therefore live with the host, next to the
11
+ * factories that consume them; each adapter exports its own config type. The
12
+ * routing handler, if any, is code in the composition root rather than config.
13
+ */
14
+ export interface CopilotPluginConfig {
15
+ /**
16
+ * The global kill switch. **Off by default**
17
+ * ([ADR-0005](../../../../../docs/adr/0005-copilot-authority-model.md) §10):
18
+ * enabling a hosted provider sends workspace content to a third party, and
19
+ * that is an operator's decision to make explicitly.
20
+ */
21
+ enabled: boolean;
22
+ /** Ceiling on a single model response, in tokens. */
23
+ maxOutputTokens: number;
24
+ /**
25
+ * Optional overrides for the run engine's ceilings. Omitted fields keep
26
+ * `DEFAULT_RUN_LIMITS`.
27
+ *
28
+ * `maxSteps` is the one an operator reaches for first — a smaller local
29
+ * model needs more tool round trips than a frontier one to answer the same
30
+ * question — but raising it alone rarely helps, because all three are
31
+ * checked in the same loop and a run that no longer runs out of steps runs
32
+ * out of seconds instead. Move them together. Raising them costs tokens
33
+ * rather than safety: every step is still authorized and audited, and a
34
+ * `propose` tool still records its row before it applies anything.
35
+ */
36
+ limits?: Partial<RunLimits>;
37
+ /**
38
+ * How long a parked run waits for the user to answer a permission request,
39
+ * in milliseconds — **for the whole run**, not per call. Defaults to
40
+ * {@link DEFAULT_RUN_DECISION_BUDGET_MS}.
41
+ *
42
+ * Configurable because the default was a bare five minutes with no warning,
43
+ * no countdown and nothing to press for more time, and five minutes to read
44
+ * a JSON argument block, decide, and click is not generous for a
45
+ * screen-magnifier or switch-access user (WCAG 2.2.1, `ORT-118`). The user
46
+ * can now extend it themselves from the prompt, which is what actually
47
+ * satisfies the criterion; this is the operator's floor underneath that.
48
+ *
49
+ * What the limit protects is a held connection, a live generator and a
50
+ * model context — the *operator's* cost, not the user's — so an operator
51
+ * who can afford more should be able to say so.
52
+ */
53
+ permissionDecisionBudgetMs?: number;
54
+ }
55
+ //# sourceMappingURL=copilot-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot-config.d.ts","sourceRoot":"","sources":["../../../src/lib/types/copilot-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B;;;;;;;;;;;;;;;OAeG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACvC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,66 @@
1
+ import type { ServerPlugin } from '@orthacms/bootstrap-server';
2
+ import { type ModelResolver, type SkillDefinition } from '@orthacms/copilot-domain';
3
+ import type { ProviderRegistration } from '../infrastructure/model-registry';
4
+ import type { CopilotPluginConfig } from '../types/copilot-config';
5
+ /** The copilot plugin shape, with its config attached. */
6
+ export type CopilotServerPluginDefinition = ServerPlugin & {
7
+ copilotConfig: CopilotPluginConfig;
8
+ };
9
+ /** Options the host passes to {@link CopilotPlugin}. */
10
+ export interface CopilotPluginOptions {
11
+ /**
12
+ * The model backends this deployment can reach, in preference order. Each
13
+ * entry pairs an operator-chosen name with an already-constructed adapter,
14
+ * so the plugin never learns which adapters exist — register two of the
15
+ * same kind (`ollama-fast`, `ollama-big`) freely.
16
+ *
17
+ * **The order is the setting.** The first entry serves any run that names
18
+ * no provider, and is what the admin's model picker opens on. There is no
19
+ * separate `defaultProvider` to name one of these — a name that could be
20
+ * misspelled, could point at a provider nobody registered, and had to be
21
+ * kept in step with this list on every change. A deployment that should
22
+ * not reach a backend does not register it.
23
+ */
24
+ providers: readonly ProviderRegistration[];
25
+ /** Optional custom handler picking a provider per run (plain code). */
26
+ resolve?: ModelResolver;
27
+ /**
28
+ * Skills defined **in code** — reusable instruction packets available in
29
+ * every workspace of this deployment.
30
+ *
31
+ * Here rather than in `config` for the same reason the providers are: the
32
+ * bodies are usually read off disk next to `plugins.ts`, and config is the
33
+ * typed view of the environment. A workspace can author its own alongside
34
+ * these in the CMS; a code skill wins a name collision, and is read-only in
35
+ * the admin.
36
+ */
37
+ skills?: readonly SkillDefinition[];
38
+ /** Host config (kill switch + output ceiling + run limits). */
39
+ config: CopilotPluginConfig;
40
+ }
41
+ /**
42
+ * Creates the copilot plugin. Register it **after** `WorkspacesPlugin` (runs
43
+ * are workspace-scoped) and `IdentityPlugin` (runs execute as the calling
44
+ * user, with the `copilot:use` permission checked by its guard). Model
45
+ * providers are constructed at the composition root and passed in here — the
46
+ * plugin never imports a vendor SDK, and never learns which adapters exist
47
+ * ([ADR-0004](../../../../../docs/adr/0004-model-agnostic-copilot-provider.md) §1).
48
+ *
49
+ * **Phase 1 ships the chat vertical slice**: the SSE run route, the bounded run
50
+ * engine, the capability profile, and the transcript tables this plugin now
51
+ * owns and migrates.
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * CopilotPlugin({
56
+ * providers: [
57
+ * { name: 'claude', provider: createAnthropicProvider(providers.claude) },
58
+ * { name: 'ollama', provider: createOpenAiProvider(providers.ollama) },
59
+ * { name: 'fake', provider: createFakeProvider() }
60
+ * ],
61
+ * config: config.plugins.copilot
62
+ * });
63
+ * ```
64
+ */
65
+ export declare function CopilotPlugin(options: CopilotPluginOptions): CopilotServerPluginDefinition;
66
+ //# sourceMappingURL=copilot-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot-plugin.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/copilot-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAEH,KAAK,aAAa,EAClB,KAAK,eAAe,EACvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,0DAA0D;AAC1D,MAAM,MAAM,6BAA6B,GAAG,YAAY,GAAG;IACvD,aAAa,EAAE,mBAAmB,CAAC;CACtC,CAAC;AAEF,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACjC;;;;;;;;;;;;OAYG;IACH,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3C,uEAAuE;IACvE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,+DAA+D;IAC/D,MAAM,EAAE,mBAAmB,CAAC;CAC/B;AAsDD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CACzB,OAAO,EAAE,oBAAoB,GAC9B,6BAA6B,CAa/B"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CopilotPlugin = CopilotPlugin;
4
+ const node_path_1 = require("node:path");
5
+ const copilot_domain_1 = require("@orthacms/copilot-domain");
6
+ const copilot_module_1 = require("../copilot.module");
7
+ /**
8
+ * Validate the wiring **eagerly** (like `ContentPlugin`'s registry and
9
+ * `I18nServerPlugin`'s locales): an empty provider list, or a provider
10
+ * declaring no models, is a misconfiguration that should fail at construction —
11
+ * before boot — rather than on the first chat message, where it is most
12
+ * expensive to diagnose.
13
+ *
14
+ * Name uniqueness is enforced by `buildModelRegistry`, which the module builds
15
+ * from the same list.
16
+ */
17
+ function assertOptions(options) {
18
+ const names = options.providers.map((entry) => entry.name);
19
+ if (names.length === 0) {
20
+ throw new Error('CopilotPlugin requires at least one model provider. Register one at the composition root, ' +
21
+ "e.g. `providers: [{ name: 'fake', provider: createFakeProvider() }]`.");
22
+ }
23
+ for (const entry of options.providers) {
24
+ if (entry.provider.models().length === 0) {
25
+ throw new Error(`Copilot model provider "${entry.name}" declares no models. Configure at least one.`);
26
+ }
27
+ }
28
+ if (options.config.maxOutputTokens <= 0) {
29
+ throw new Error(`CopilotPlugin's maxOutputTokens must be a positive number (got ${options.config.maxOutputTokens}).`);
30
+ }
31
+ // The ceilings, on the same terms. `maxSteps` is the one an operator
32
+ // reaches for (`COPILOT_MAX_STEPS`), and it was the only number in this
33
+ // config that could be set to something meaningless and still boot:
34
+ // `maxSteps: 0` makes `for (step = 0; step < 0; …)` skip the loop entirely,
35
+ // so the run yields `run-started` and then `done` with `max-steps` — no
36
+ // model call, no answer, and no assistant row at all, leaving a thread
37
+ // showing a question and silence. A typo'd env var should not be able to
38
+ // turn the copilot into that.
39
+ for (const [key, value] of Object.entries(options.config.limits ?? {})) {
40
+ if (value !== undefined && (!Number.isFinite(value) || value <= 0)) {
41
+ throw new Error(`CopilotPlugin's limits.${key} must be a positive number (got ${value}).`);
42
+ }
43
+ }
44
+ // Built here and thrown away: the module builds its own from the same list.
45
+ // The point is *when* — a malformed or duplicated skill fails at
46
+ // construction, like a mistyped provider name, rather than on the first
47
+ // chat message in the workspace that happened to use it.
48
+ (0, copilot_domain_1.buildSkillRegistry)(options.skills ?? []);
49
+ }
50
+ /**
51
+ * Creates the copilot plugin. Register it **after** `WorkspacesPlugin` (runs
52
+ * are workspace-scoped) and `IdentityPlugin` (runs execute as the calling
53
+ * user, with the `copilot:use` permission checked by its guard). Model
54
+ * providers are constructed at the composition root and passed in here — the
55
+ * plugin never imports a vendor SDK, and never learns which adapters exist
56
+ * ([ADR-0004](../../../../../docs/adr/0004-model-agnostic-copilot-provider.md) §1).
57
+ *
58
+ * **Phase 1 ships the chat vertical slice**: the SSE run route, the bounded run
59
+ * engine, the capability profile, and the transcript tables this plugin now
60
+ * owns and migrates.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * CopilotPlugin({
65
+ * providers: [
66
+ * { name: 'claude', provider: createAnthropicProvider(providers.claude) },
67
+ * { name: 'ollama', provider: createOpenAiProvider(providers.ollama) },
68
+ * { name: 'fake', provider: createFakeProvider() }
69
+ * ],
70
+ * config: config.plugins.copilot
71
+ * });
72
+ * ```
73
+ */
74
+ function CopilotPlugin(options) {
75
+ assertOptions(options);
76
+ return {
77
+ name: 'copilot',
78
+ module: copilot_module_1.CopilotModule.forRoot(options),
79
+ copilotConfig: options.config,
80
+ migrations: {
81
+ // Lazy — only called at migrate time. Source layout: src/lib/utils
82
+ // → ../../../migrations = <pkg>/migrations.
83
+ dir: () => (0, node_path_1.join)(__dirname, '../../../migrations'),
84
+ table: '__drizzle_migrations_copilot'
85
+ }
86
+ };
87
+ }
@@ -0,0 +1,48 @@
1
+ CREATE TYPE "public"."copilot_message_role" AS ENUM('user', 'assistant');--> statement-breakpoint
2
+ CREATE TABLE "copilot_conversations" (
3
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4
+ "user_id" uuid NOT NULL,
5
+ "workspace_id" uuid NOT NULL,
6
+ "title" text,
7
+ "surface" text DEFAULT 'chat' NOT NULL,
8
+ "archived" boolean DEFAULT false NOT NULL,
9
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
10
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
11
+ );
12
+ --> statement-breakpoint
13
+ CREATE TABLE "copilot_messages" (
14
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
15
+ "conversation_id" uuid NOT NULL,
16
+ "run_id" uuid NOT NULL,
17
+ "role" "copilot_message_role" NOT NULL,
18
+ "content" jsonb NOT NULL,
19
+ "model" text,
20
+ "provider" text,
21
+ "stop_reason" text,
22
+ "input_tokens" integer,
23
+ "output_tokens" integer,
24
+ "position" integer NOT NULL,
25
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
26
+ );
27
+ --> statement-breakpoint
28
+ CREATE TABLE "copilot_tool_calls" (
29
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
30
+ "conversation_id" uuid NOT NULL,
31
+ "run_id" uuid NOT NULL,
32
+ "call_id" text NOT NULL,
33
+ "name" text NOT NULL,
34
+ "input" jsonb,
35
+ "output_summary" text,
36
+ "ok" boolean NOT NULL,
37
+ "error" text,
38
+ "duration_ms" integer NOT NULL,
39
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
40
+ );
41
+ --> statement-breakpoint
42
+ ALTER TABLE "copilot_conversations" ADD CONSTRAINT "copilot_conversations_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
43
+ ALTER TABLE "copilot_conversations" ADD CONSTRAINT "copilot_conversations_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
44
+ ALTER TABLE "copilot_messages" ADD CONSTRAINT "copilot_messages_conversation_id_copilot_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."copilot_conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
45
+ ALTER TABLE "copilot_tool_calls" ADD CONSTRAINT "copilot_tool_calls_conversation_id_copilot_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."copilot_conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
46
+ CREATE INDEX "copilot_conversations_owner_idx" ON "copilot_conversations" USING btree ("user_id","workspace_id","updated_at");--> statement-breakpoint
47
+ CREATE INDEX "copilot_messages_thread_idx" ON "copilot_messages" USING btree ("conversation_id","position");--> statement-breakpoint
48
+ CREATE INDEX "copilot_tool_calls_run_idx" ON "copilot_tool_calls" USING btree ("run_id","created_at");
@@ -0,0 +1,34 @@
1
+ CREATE TABLE "copilot_proposals" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "conversation_id" uuid NOT NULL,
4
+ "run_id" uuid NOT NULL,
5
+ "tool_call_id" text NOT NULL,
6
+ "tool_name" text NOT NULL,
7
+ "kind" text NOT NULL,
8
+ "workspace_id" uuid NOT NULL,
9
+ "created_by" uuid NOT NULL,
10
+ "target" jsonb NOT NULL,
11
+ "patch" jsonb NOT NULL,
12
+ "summary" text NOT NULL,
13
+ "changes" jsonb,
14
+ "status" text DEFAULT 'pending' NOT NULL,
15
+ "decided_by" uuid,
16
+ "decided_at" timestamp with time zone,
17
+ "result" jsonb,
18
+ "error" text,
19
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
20
+ );
21
+ --> statement-breakpoint
22
+ CREATE TABLE "copilot_workspace_policies" (
23
+ "workspace_id" uuid PRIMARY KEY NOT NULL,
24
+ "auto_apply_tools" jsonb DEFAULT '[]'::jsonb NOT NULL,
25
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
26
+ );
27
+ --> statement-breakpoint
28
+ ALTER TABLE "copilot_proposals" ADD CONSTRAINT "copilot_proposals_conversation_id_copilot_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."copilot_conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
29
+ ALTER TABLE "copilot_proposals" ADD CONSTRAINT "copilot_proposals_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
30
+ ALTER TABLE "copilot_proposals" ADD CONSTRAINT "copilot_proposals_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
31
+ ALTER TABLE "copilot_proposals" ADD CONSTRAINT "copilot_proposals_decided_by_users_id_fk" FOREIGN KEY ("decided_by") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
32
+ ALTER TABLE "copilot_workspace_policies" ADD CONSTRAINT "copilot_workspace_policies_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
33
+ CREATE INDEX "copilot_proposals_workspace_idx" ON "copilot_proposals" USING btree ("workspace_id","status","created_at");--> statement-breakpoint
34
+ CREATE INDEX "copilot_proposals_run_idx" ON "copilot_proposals" USING btree ("run_id");
@@ -0,0 +1 @@
1
+ DROP TABLE "copilot_workspace_policies" CASCADE;
@@ -0,0 +1 @@
1
+ ALTER TABLE "copilot_conversations" ADD COLUMN "allowed_tools" jsonb DEFAULT '[]'::jsonb NOT NULL;
@@ -0,0 +1 @@
1
+ ALTER TABLE "copilot_messages" ADD COLUMN "attachments" jsonb;
@@ -0,0 +1,19 @@
1
+ CREATE TYPE "public"."copilot_skill_mode" AS ENUM('manual', 'always');--> statement-breakpoint
2
+ CREATE TABLE "copilot_skills" (
3
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4
+ "workspace_id" uuid NOT NULL,
5
+ "name" text NOT NULL,
6
+ "title" text NOT NULL,
7
+ "description" text NOT NULL,
8
+ "instructions" text NOT NULL,
9
+ "mode" "copilot_skill_mode" DEFAULT 'manual' NOT NULL,
10
+ "enabled" boolean DEFAULT true NOT NULL,
11
+ "created_by" uuid,
12
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
13
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ ALTER TABLE "copilot_messages" ADD COLUMN "skills" jsonb;--> statement-breakpoint
17
+ ALTER TABLE "copilot_skills" ADD CONSTRAINT "copilot_skills_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
18
+ ALTER TABLE "copilot_skills" ADD CONSTRAINT "copilot_skills_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
19
+ CREATE UNIQUE INDEX "copilot_skills_workspace_name_idx" ON "copilot_skills" USING btree ("workspace_id","name");
@@ -0,0 +1 @@
1
+ ALTER TABLE "copilot_conversations" ADD COLUMN "model_choice" text;