@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,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copilotProposals = void 0;
4
+ const pg_core_1 = require("drizzle-orm/pg-core");
5
+ const conversations_1 = require("./conversations");
6
+ const external_refs_1 = require("./external-refs");
7
+ /**
8
+ * **The accept boundary** — one row per change the copilot proposed
9
+ * ([ADR-0005](../../../../../../docs/adr/0005-copilot-authority-model.md) §5).
10
+ *
11
+ * Every mutating tool writes here first and a human decides; a workspace that
12
+ * opted a tool into auto-apply still gets the row, accepted in the same breath.
13
+ * That is what makes a direct apply "undoable, never invisible" rather than a
14
+ * write with no paper trail — the row records what was proposed, by which run,
15
+ * on whose behalf, and who decided.
16
+ *
17
+ * `target` and `patch` are opaque jsonb on purpose: their shape belongs to the
18
+ * applier that declared the `kind`, and teaching this table about content
19
+ * entries would make the copilot the thing that changes when content does.
20
+ */
21
+ exports.copilotProposals = (0, pg_core_1.pgTable)('copilot_proposals', {
22
+ /** Primary key. */
23
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
24
+ /** The thread the proposal was made in. */
25
+ conversationId: (0, pg_core_1.uuid)('conversation_id')
26
+ .notNull()
27
+ .references(() => conversations_1.copilotConversations.id, { onDelete: 'cascade' }),
28
+ /** The run that produced it — provenance on the eventual effect. */
29
+ runId: (0, pg_core_1.uuid)('run_id').notNull(),
30
+ /**
31
+ * The provider-assigned tool-call id, so a proposal joins to its row in
32
+ * `copilot_tool_calls` and the UI can attach the card to the step that
33
+ * produced it.
34
+ */
35
+ toolCallId: (0, pg_core_1.text)('tool_call_id').notNull(),
36
+ /**
37
+ * The tool that proposed it. Load-bearing rather than descriptive:
38
+ * accepting re-resolves the capability profile and requires this tool to
39
+ * still be offered to the accepting user, so "you may accept what you
40
+ * could have proposed" needs no second permission model.
41
+ */
42
+ toolName: (0, pg_core_1.text)('tool_name').notNull(),
43
+ /** Which applier carries it out, e.g. `content.entry.update`. */
44
+ kind: (0, pg_core_1.text)('kind').notNull(),
45
+ /** The workspace it belongs to. */
46
+ workspaceId: (0, pg_core_1.uuid)('workspace_id')
47
+ .notNull()
48
+ .references(() => external_refs_1.workspaces.id, { onDelete: 'cascade' }),
49
+ /** The user the run acted as — never a copilot identity. */
50
+ createdBy: (0, pg_core_1.uuid)('created_by')
51
+ .notNull()
52
+ .references(() => external_refs_1.users.id, { onDelete: 'cascade' }),
53
+ /** Where the change lands; shape owned by the applier. */
54
+ target: (0, pg_core_1.jsonb)('target').notNull(),
55
+ /** The change itself; shape owned by the applier's use-case. */
56
+ patch: (0, pg_core_1.jsonb)('patch').notNull(),
57
+ /** One line naming the change — the card's title. */
58
+ summary: (0, pg_core_1.text)('summary').notNull(),
59
+ /** Per-field before/after for the review diff, when field-shaped. */
60
+ changes: (0, pg_core_1.jsonb)('changes'),
61
+ /** `pending` | `accepted` | `rejected`. */
62
+ status: (0, pg_core_1.text)('status').notNull().default('pending'),
63
+ /** Who decided. Null while pending. */
64
+ decidedBy: (0, pg_core_1.uuid)('decided_by').references(() => external_refs_1.users.id, {
65
+ onDelete: 'set null'
66
+ }),
67
+ /** When they decided. Null while pending. */
68
+ decidedAt: (0, pg_core_1.timestamp)('decided_at', { withTimezone: true }),
69
+ /** What the applier reported — the entity id and any detail. */
70
+ result: (0, pg_core_1.jsonb)('result'),
71
+ /**
72
+ * Why the last accept failed, when one did. The proposal stays
73
+ * `pending`, so a transient failure is retryable and a permanent one is
74
+ * legible — rather than stranding the row in a fourth state nobody
75
+ * clears.
76
+ */
77
+ error: (0, pg_core_1.text)('error'),
78
+ /** Row creation timestamp. */
79
+ createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true })
80
+ .notNull()
81
+ .defaultNow()
82
+ }, (table) => [
83
+ // "What is waiting for me in this workspace?" — the review queue.
84
+ (0, pg_core_1.index)('copilot_proposals_workspace_idx').on(table.workspaceId, table.status, table.createdAt),
85
+ // "What did this run propose?" — the transcript's card lookup.
86
+ (0, pg_core_1.index)('copilot_proposals_run_idx').on(table.runId)
87
+ ]);
@@ -0,0 +1,203 @@
1
+ /**
2
+ * What actually touched data — **the security-review surface**
3
+ * ([ADR-0005](../../../../../../docs/adr/0005-copilot-authority-model.md), consequences:
4
+ * "Security review has one surface: `copilot_tool_calls` joined to the activity
5
+ * log"). One row per attempted call, written whether it succeeded, failed, or
6
+ * was refused by the authorize step, because a refused call is exactly the
7
+ * event a reviewer is looking for.
8
+ */
9
+ export declare const copilotToolCalls: import("drizzle-orm/pg-core").PgTableWithColumns<{
10
+ name: "copilot_tool_calls";
11
+ schema: undefined;
12
+ columns: {
13
+ id: import("drizzle-orm/pg-core").PgColumn<{
14
+ name: "id";
15
+ tableName: "copilot_tool_calls";
16
+ dataType: "string";
17
+ columnType: "PgUUID";
18
+ data: string;
19
+ driverParam: string;
20
+ notNull: true;
21
+ hasDefault: true;
22
+ isPrimaryKey: true;
23
+ isAutoincrement: false;
24
+ hasRuntimeDefault: false;
25
+ enumValues: undefined;
26
+ baseColumn: never;
27
+ identity: undefined;
28
+ generated: undefined;
29
+ }, {}, {}>;
30
+ conversationId: import("drizzle-orm/pg-core").PgColumn<{
31
+ name: "conversation_id";
32
+ tableName: "copilot_tool_calls";
33
+ dataType: "string";
34
+ columnType: "PgUUID";
35
+ data: string;
36
+ driverParam: string;
37
+ notNull: true;
38
+ hasDefault: false;
39
+ isPrimaryKey: false;
40
+ isAutoincrement: false;
41
+ hasRuntimeDefault: false;
42
+ enumValues: undefined;
43
+ baseColumn: never;
44
+ identity: undefined;
45
+ generated: undefined;
46
+ }, {}, {}>;
47
+ runId: import("drizzle-orm/pg-core").PgColumn<{
48
+ name: "run_id";
49
+ tableName: "copilot_tool_calls";
50
+ dataType: "string";
51
+ columnType: "PgUUID";
52
+ data: string;
53
+ driverParam: string;
54
+ notNull: true;
55
+ hasDefault: false;
56
+ isPrimaryKey: false;
57
+ isAutoincrement: false;
58
+ hasRuntimeDefault: false;
59
+ enumValues: undefined;
60
+ baseColumn: never;
61
+ identity: undefined;
62
+ generated: undefined;
63
+ }, {}, {}>;
64
+ callId: import("drizzle-orm/pg-core").PgColumn<{
65
+ name: "call_id";
66
+ tableName: "copilot_tool_calls";
67
+ dataType: "string";
68
+ columnType: "PgText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {}>;
81
+ name: import("drizzle-orm/pg-core").PgColumn<{
82
+ name: "name";
83
+ tableName: "copilot_tool_calls";
84
+ dataType: "string";
85
+ columnType: "PgText";
86
+ data: string;
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: false;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: [string, ...string[]];
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {}>;
98
+ input: import("drizzle-orm/pg-core").PgColumn<{
99
+ name: "input";
100
+ tableName: "copilot_tool_calls";
101
+ dataType: "json";
102
+ columnType: "PgJsonb";
103
+ data: unknown;
104
+ driverParam: unknown;
105
+ notNull: false;
106
+ hasDefault: false;
107
+ isPrimaryKey: false;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: undefined;
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {}>;
115
+ outputSummary: import("drizzle-orm/pg-core").PgColumn<{
116
+ name: "output_summary";
117
+ tableName: "copilot_tool_calls";
118
+ dataType: "string";
119
+ columnType: "PgText";
120
+ data: string;
121
+ driverParam: string;
122
+ notNull: false;
123
+ hasDefault: false;
124
+ isPrimaryKey: false;
125
+ isAutoincrement: false;
126
+ hasRuntimeDefault: false;
127
+ enumValues: [string, ...string[]];
128
+ baseColumn: never;
129
+ identity: undefined;
130
+ generated: undefined;
131
+ }, {}, {}>;
132
+ ok: import("drizzle-orm/pg-core").PgColumn<{
133
+ name: "ok";
134
+ tableName: "copilot_tool_calls";
135
+ dataType: "boolean";
136
+ columnType: "PgBoolean";
137
+ data: boolean;
138
+ driverParam: boolean;
139
+ notNull: true;
140
+ hasDefault: false;
141
+ isPrimaryKey: false;
142
+ isAutoincrement: false;
143
+ hasRuntimeDefault: false;
144
+ enumValues: undefined;
145
+ baseColumn: never;
146
+ identity: undefined;
147
+ generated: undefined;
148
+ }, {}, {}>;
149
+ error: import("drizzle-orm/pg-core").PgColumn<{
150
+ name: "error";
151
+ tableName: "copilot_tool_calls";
152
+ dataType: "string";
153
+ columnType: "PgText";
154
+ data: string;
155
+ driverParam: string;
156
+ notNull: false;
157
+ hasDefault: false;
158
+ isPrimaryKey: false;
159
+ isAutoincrement: false;
160
+ hasRuntimeDefault: false;
161
+ enumValues: [string, ...string[]];
162
+ baseColumn: never;
163
+ identity: undefined;
164
+ generated: undefined;
165
+ }, {}, {}>;
166
+ durationMs: import("drizzle-orm/pg-core").PgColumn<{
167
+ name: "duration_ms";
168
+ tableName: "copilot_tool_calls";
169
+ dataType: "number";
170
+ columnType: "PgInteger";
171
+ data: number;
172
+ driverParam: string | number;
173
+ notNull: true;
174
+ hasDefault: false;
175
+ isPrimaryKey: false;
176
+ isAutoincrement: false;
177
+ hasRuntimeDefault: false;
178
+ enumValues: undefined;
179
+ baseColumn: never;
180
+ identity: undefined;
181
+ generated: undefined;
182
+ }, {}, {}>;
183
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
184
+ name: "created_at";
185
+ tableName: "copilot_tool_calls";
186
+ dataType: "date";
187
+ columnType: "PgTimestamp";
188
+ data: Date;
189
+ driverParam: string;
190
+ notNull: true;
191
+ hasDefault: true;
192
+ isPrimaryKey: false;
193
+ isAutoincrement: false;
194
+ hasRuntimeDefault: false;
195
+ enumValues: undefined;
196
+ baseColumn: never;
197
+ identity: undefined;
198
+ generated: undefined;
199
+ }, {}, {}>;
200
+ };
201
+ dialect: "pg";
202
+ }>;
203
+ //# sourceMappingURL=tool-calls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-calls.d.ts","sourceRoot":"","sources":["../../../../../src/lib/chat/infrastructure/schema/tool-calls.ts"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwC5B,CAAC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copilotToolCalls = void 0;
4
+ const pg_core_1 = require("drizzle-orm/pg-core");
5
+ const conversations_1 = require("./conversations");
6
+ /**
7
+ * What actually touched data — **the security-review surface**
8
+ * ([ADR-0005](../../../../../../docs/adr/0005-copilot-authority-model.md), consequences:
9
+ * "Security review has one surface: `copilot_tool_calls` joined to the activity
10
+ * log"). One row per attempted call, written whether it succeeded, failed, or
11
+ * was refused by the authorize step, because a refused call is exactly the
12
+ * event a reviewer is looking for.
13
+ */
14
+ exports.copilotToolCalls = (0, pg_core_1.pgTable)('copilot_tool_calls', {
15
+ /** Primary key. */
16
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
17
+ /** The thread the call was made in. */
18
+ conversationId: (0, pg_core_1.uuid)('conversation_id')
19
+ .notNull()
20
+ .references(() => conversations_1.copilotConversations.id, { onDelete: 'cascade' }),
21
+ /** The run the call belongs to. */
22
+ runId: (0, pg_core_1.uuid)('run_id').notNull(),
23
+ /** The provider-assigned call id, as the model issued it. */
24
+ callId: (0, pg_core_1.text)('call_id').notNull(),
25
+ /** The tool's name, e.g. `admin_content_search`. */
26
+ name: (0, pg_core_1.text)('name').notNull(),
27
+ /** The arguments the model supplied. */
28
+ input: (0, pg_core_1.jsonb)('input'),
29
+ /**
30
+ * The result, **redacted to a summary** rather than stored whole. A
31
+ * search can return a page of entry bodies, and copying those into an
32
+ * append-only audit table would duplicate content indefinitely and
33
+ * spread anything sensitive in it into a second place with a different
34
+ * deletion story. The transcript already holds what the model saw.
35
+ */
36
+ outputSummary: (0, pg_core_1.text)('output_summary'),
37
+ /** Whether the call succeeded. */
38
+ ok: (0, pg_core_1.boolean)('ok').notNull(),
39
+ /** The error message, when it did not. */
40
+ error: (0, pg_core_1.text)('error'),
41
+ /** How long it took, in milliseconds. */
42
+ durationMs: (0, pg_core_1.integer)('duration_ms').notNull(),
43
+ /** Row creation timestamp. */
44
+ createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true })
45
+ .notNull()
46
+ .defaultNow()
47
+ }, (table) => [
48
+ // "What did this run do?" — the review query, and the UI's step list.
49
+ (0, pg_core_1.index)('copilot_tool_calls_run_idx').on(table.runId, table.createdAt)
50
+ ]);
@@ -0,0 +1,30 @@
1
+ import { DynamicModule } from '@nestjs/common';
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
+ /** Options `CopilotModule.forRoot` binds into DI. */
6
+ export interface CopilotModuleOptions {
7
+ /** The model backends this deployment offers, in preference order. */
8
+ providers: readonly ProviderRegistration[];
9
+ /** Optional custom handler picking a provider per run. */
10
+ resolve?: ModelResolver;
11
+ /** Skills defined in code, available in every workspace. */
12
+ skills?: readonly SkillDefinition[];
13
+ /** Host config (kill switch + output ceiling + run limits). */
14
+ config: CopilotPluginConfig;
15
+ }
16
+ /**
17
+ * NestJS module for the copilot plugin. Registered globally, like every other
18
+ * plugin module here, so a tool-binding plugin can inject
19
+ * {@link CopilotToolRegistry} without an explicit import.
20
+ *
21
+ * Phase 1 adds the chat vertical slice on top of phase 0's model seam: the SSE
22
+ * run route, the bounded run engine, the capability profile, and conversation
23
+ * persistence. The tools themselves are bound by the plugins that own the logic
24
+ * they wrap, never by this module.
25
+ */
26
+ export declare class CopilotModule {
27
+ /** Creates the global dynamic module around a validated config. */
28
+ static forRoot(options: CopilotModuleOptions): DynamicModule;
29
+ }
30
+ //# sourceMappingURL=copilot.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.module.d.ts","sourceRoot":"","sources":["../../src/lib/copilot.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAIH,KAAK,aAAa,EAClB,KAAK,eAAe,EACvB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAEH,KAAK,oBAAoB,EAC5B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAqBlE,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACjC,sEAAsE;IACtE,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3C,0DAA0D;IAC1D,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,+DAA+D;IAC/D,MAAM,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,qBACa,aAAa;IACtB,mEAAmE;IACnE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa;CAwG/D"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var CopilotModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CopilotModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const copilot_domain_1 = require("@orthacms/copilot-domain");
8
+ const database_1 = require("@orthacms/database");
9
+ const tools_server_1 = require("@orthacms/tools-server");
10
+ const copilot_tokens_1 = require("./copilot.tokens");
11
+ const model_registry_1 = require("./infrastructure/model-registry");
12
+ const capability_profile_service_1 = require("./chat/application/capability-profile.service");
13
+ const decide_proposal_service_1 = require("./chat/application/decide-proposal.service");
14
+ const tool_permission_broker_1 = require("./chat/application/tool-permission.broker");
15
+ const proposal_applier_registry_1 = require("./chat/application/proposal-applier.registry");
16
+ const content_type_summary_service_1 = require("./chat/application/content-type-summary.service");
17
+ const run_engine_service_1 = require("./chat/application/run-engine.service");
18
+ const conversation_repository_1 = require("./chat/infrastructure/persistence/conversation.repository");
19
+ const proposal_repository_1 = require("./chat/infrastructure/persistence/proposal.repository");
20
+ const create_run_controller_1 = require("./chat/http/controllers/create-run.controller");
21
+ const get_conversation_controller_1 = require("./chat/http/controllers/get-conversation.controller");
22
+ const list_conversations_controller_1 = require("./chat/http/controllers/list-conversations.controller");
23
+ const list_models_controller_1 = require("./chat/http/controllers/list-models.controller");
24
+ const proposals_controller_1 = require("./chat/http/controllers/proposals.controller");
25
+ const tool_permission_controller_1 = require("./chat/http/controllers/tool-permission.controller");
26
+ const update_conversation_controller_1 = require("./chat/http/controllers/update-conversation.controller");
27
+ const skill_catalog_service_1 = require("./skills/application/skill-catalog.service");
28
+ const skill_repository_1 = require("./skills/infrastructure/persistence/skill.repository");
29
+ const list_skills_controller_1 = require("./skills/http/controllers/list-skills.controller");
30
+ const manage_skills_controller_1 = require("./skills/http/controllers/manage-skills.controller");
31
+ /**
32
+ * NestJS module for the copilot plugin. Registered globally, like every other
33
+ * plugin module here, so a tool-binding plugin can inject
34
+ * {@link CopilotToolRegistry} without an explicit import.
35
+ *
36
+ * Phase 1 adds the chat vertical slice on top of phase 0's model seam: the SSE
37
+ * run route, the bounded run engine, the capability profile, and conversation
38
+ * persistence. The tools themselves are bound by the plugins that own the logic
39
+ * they wrap, never by this module.
40
+ */
41
+ let CopilotModule = CopilotModule_1 = class CopilotModule {
42
+ /** Creates the global dynamic module around a validated config. */
43
+ static forRoot(options) {
44
+ // No `resolve` handler means the **first registered provider** serves
45
+ // every run that names none. There is no separate `defaultProvider`
46
+ // setting to keep in sync with the list — the list *is* the setting,
47
+ // and its order is the preference order (`catalogue()` renders in it,
48
+ // and the admin's picker opens on its first entry).
49
+ const [first] = options.providers;
50
+ if (!first) {
51
+ throw new Error('CopilotModule requires at least one model provider — the first one registered ' +
52
+ 'is what serves a run that names none.');
53
+ }
54
+ const resolver = options.resolve ?? (() => first.name);
55
+ return {
56
+ module: CopilotModule_1,
57
+ global: true,
58
+ // `DatabaseModule` is global, but importing it explicitly keeps
59
+ // this module standalone-testable.
60
+ // `ToolsModule` carries the shared tool registry — the same
61
+ // catalogue the MCP endpoint serves. Imported rather than provided
62
+ // so a deployment running the copilot *without* MCP still has one,
63
+ // and one running both has exactly one.
64
+ imports: [database_1.DatabaseModule, tools_server_1.ToolsModule],
65
+ controllers: [
66
+ create_run_controller_1.CreateRunController,
67
+ // Before `GetConversationController`: `conversations/:id` and
68
+ // `models` can't collide (different first segments), but keep
69
+ // the read routes grouped after the run route.
70
+ list_models_controller_1.ListModelsController,
71
+ list_conversations_controller_1.ListConversationsController,
72
+ // `PATCH conversations/:id`. No ordering hazard with the `GET`
73
+ // wildcard below — Express matches method and path together —
74
+ // but it reads with the other conversation routes.
75
+ update_conversation_controller_1.UpdateConversationController,
76
+ // Before `GetConversationController`, whose `conversations/:id`
77
+ // is the only wildcard here — Express matches in declaration
78
+ // order, so the literal-prefixed routes go first.
79
+ proposals_controller_1.ProposalsController,
80
+ // Before `GetConversationController` for the same reason as
81
+ // the others: its `conversations/:id` is the only wildcard, and
82
+ // Express matches in declaration order.
83
+ tool_permission_controller_1.ToolPermissionController,
84
+ // Both skill controllers before the conversation wildcard, for
85
+ // the same declaration-order reason as the rest. `skills` and
86
+ // `skills/:id` live in different controllers and cannot
87
+ // collide (different segment counts); `skills/manage` is
88
+ // declared above `skills/:id` inside the manage controller.
89
+ list_skills_controller_1.ListSkillsController,
90
+ manage_skills_controller_1.ManageSkillsController,
91
+ get_conversation_controller_1.GetConversationController
92
+ ],
93
+ providers: [
94
+ { provide: copilot_tokens_1.COPILOT_CONFIG, useValue: options.config },
95
+ {
96
+ provide: copilot_domain_1.MODEL_REGISTRY,
97
+ useValue: (0, model_registry_1.buildModelRegistry)(options.providers)
98
+ },
99
+ {
100
+ // Always bound, empty when the host declared none: "this
101
+ // deployment ships no skills" must not present as a missing
102
+ // dependency.
103
+ provide: copilot_tokens_1.COPILOT_SKILL_REGISTRY,
104
+ useValue: (0, copilot_domain_1.buildSkillRegistry)(options.skills ?? [])
105
+ },
106
+ { provide: copilot_domain_1.MODEL_RESOLVER, useValue: resolver },
107
+ capability_profile_service_1.CapabilityProfileService,
108
+ content_type_summary_service_1.ContentTypeSummaryService,
109
+ conversation_repository_1.ConversationRepository,
110
+ proposal_repository_1.ProposalRepository,
111
+ proposal_applier_registry_1.ProposalApplierRegistry,
112
+ decide_proposal_service_1.DecideProposalService,
113
+ {
114
+ // Constructed through a factory so the operator's
115
+ // `permissionDecisionBudgetMs` reaches it — the wait for a
116
+ // permission decision is an accessibility limit as much as a
117
+ // resource one, and five minutes is not generous for a
118
+ // screen-magnifier or switch-access user (`ORT-118`).
119
+ provide: tool_permission_broker_1.ToolPermissionBroker,
120
+ useFactory: () => {
121
+ const broker = new tool_permission_broker_1.ToolPermissionBroker();
122
+ broker.configure(options.config.permissionDecisionBudgetMs);
123
+ return broker;
124
+ }
125
+ },
126
+ skill_repository_1.SkillRepository,
127
+ skill_catalog_service_1.SkillCatalogService,
128
+ run_engine_service_1.RunEngine
129
+ ],
130
+ exports: [
131
+ copilot_tokens_1.COPILOT_CONFIG,
132
+ copilot_domain_1.MODEL_REGISTRY,
133
+ copilot_domain_1.MODEL_RESOLVER,
134
+ copilot_tokens_1.COPILOT_SKILL_REGISTRY,
135
+ // Exported so the plugins that own writes can register their
136
+ // proposal appliers. Tools go to the shared `ToolRegistry` in
137
+ // `@orthacms/tools-server`, which the MCP module provides.
138
+ proposal_applier_registry_1.ProposalApplierRegistry
139
+ ]
140
+ };
141
+ }
142
+ };
143
+ exports.CopilotModule = CopilotModule;
144
+ exports.CopilotModule = CopilotModule = CopilotModule_1 = tslib_1.__decorate([
145
+ (0, common_1.Module)({})
146
+ ], CopilotModule);
@@ -0,0 +1,34 @@
1
+ /**
2
+ * DI tokens and their inject decorators for the copilot plugin. Kept in a
3
+ * dependency-free module (imports only `@nestjs/common`) so providers and
4
+ * services can reference them without forming an import cycle with
5
+ * `copilot.module.ts`.
6
+ *
7
+ * The model-provider seam's tokens (`MODEL_REGISTRY`, `MODEL_RESOLVER`) live
8
+ * in `@orthacms/copilot-domain` alongside the port they bind, so an adapter
9
+ * package never has to import the server.
10
+ */
11
+ /** Injection token for the resolved copilot configuration. */
12
+ export declare const COPILOT_CONFIG: unique symbol;
13
+ /** Parameter decorator that injects the copilot configuration. */
14
+ export declare const InjectCopilotConfig: () => ParameterDecorator;
15
+ /**
16
+ * Optional override for the run engine's ceilings (`RunLimits`). Unbound, the
17
+ * engine uses `DEFAULT_RUN_LIMITS`.
18
+ *
19
+ * A token rather than a defaulted constructor parameter: Nest resolves every
20
+ * constructor argument positionally and does **not** honour a TypeScript
21
+ * default, so `limits: RunLimits = DEFAULT_RUN_LIMITS` fails boot with an
22
+ * unresolvable dependency at that index rather than quietly using the default.
23
+ */
24
+ export declare const COPILOT_RUN_LIMITS: unique symbol;
25
+ /**
26
+ * The host's code-defined skills, as a built `SkillRegistry`.
27
+ *
28
+ * Always bound (an empty registry when the host declared none) rather than
29
+ * optional: "this deployment ships no skills" and "the registry was not wired"
30
+ * would otherwise be the same missing dependency, and only one of them is a
31
+ * bug.
32
+ */
33
+ export declare const COPILOT_SKILL_REGISTRY: unique symbol;
34
+ //# sourceMappingURL=copilot.tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.tokens.d.ts","sourceRoot":"","sources":["../../src/lib/copilot.tokens.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,cAAc,eAA2B,CAAC;AAEvD,kEAAkE;AAClE,eAAO,MAAM,mBAAmB,QAAO,kBACb,CAAC;AAE3B;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,eAA+B,CAAC;AAE/D;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,eAAmC,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COPILOT_SKILL_REGISTRY = exports.COPILOT_RUN_LIMITS = exports.InjectCopilotConfig = exports.COPILOT_CONFIG = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ /**
6
+ * DI tokens and their inject decorators for the copilot plugin. Kept in a
7
+ * dependency-free module (imports only `@nestjs/common`) so providers and
8
+ * services can reference them without forming an import cycle with
9
+ * `copilot.module.ts`.
10
+ *
11
+ * The model-provider seam's tokens (`MODEL_REGISTRY`, `MODEL_RESOLVER`) live
12
+ * in `@orthacms/copilot-domain` alongside the port they bind, so an adapter
13
+ * package never has to import the server.
14
+ */
15
+ /** Injection token for the resolved copilot configuration. */
16
+ exports.COPILOT_CONFIG = Symbol('COPILOT_CONFIG');
17
+ /** Parameter decorator that injects the copilot configuration. */
18
+ const InjectCopilotConfig = () => (0, common_1.Inject)(exports.COPILOT_CONFIG);
19
+ exports.InjectCopilotConfig = InjectCopilotConfig;
20
+ /**
21
+ * Optional override for the run engine's ceilings (`RunLimits`). Unbound, the
22
+ * engine uses `DEFAULT_RUN_LIMITS`.
23
+ *
24
+ * A token rather than a defaulted constructor parameter: Nest resolves every
25
+ * constructor argument positionally and does **not** honour a TypeScript
26
+ * default, so `limits: RunLimits = DEFAULT_RUN_LIMITS` fails boot with an
27
+ * unresolvable dependency at that index rather than quietly using the default.
28
+ */
29
+ exports.COPILOT_RUN_LIMITS = Symbol('COPILOT_RUN_LIMITS');
30
+ /**
31
+ * The host's code-defined skills, as a built `SkillRegistry`.
32
+ *
33
+ * Always bound (an empty registry when the host declared none) rather than
34
+ * optional: "this deployment ships no skills" and "the registry was not wired"
35
+ * would otherwise be the same missing dependency, and only one of them is a
36
+ * bug.
37
+ */
38
+ exports.COPILOT_SKILL_REGISTRY = Symbol('COPILOT_SKILL_REGISTRY');
@@ -0,0 +1,22 @@
1
+ import { type ModelProvider, type ModelRegistry } from '@orthacms/copilot-domain';
2
+ /** One provider the host offers, under the name runs refer to it by. */
3
+ export interface ProviderRegistration {
4
+ /** Unique, operator-chosen name — `claude`, `ollama-big`, `fake`. */
5
+ name: string;
6
+ /** The adapter instance, already constructed with its own config. */
7
+ provider: ModelProvider;
8
+ }
9
+ /**
10
+ * Builds an immutable {@link ModelRegistry} over the host's provider list.
11
+ * Bound to `MODEL_REGISTRY` at the composition root; the resolver returns a
12
+ * name, the core looks the provider up here.
13
+ *
14
+ * Registration order is preserved, so {@link ModelRegistry.catalogue} renders
15
+ * in the order the operator wrote — the first entry reads as the house default.
16
+ *
17
+ * @throws When a name is blank or registered twice. A list can express both,
18
+ * unlike a map, so the guard has to be explicit — and silently dropping one
19
+ * of two same-named providers would route runs to a backend nobody chose.
20
+ */
21
+ export declare function buildModelRegistry(registrations: readonly ProviderRegistration[]): ModelRegistry;
22
+ //# sourceMappingURL=model-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../../src/lib/infrastructure/model-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,aAAa,EAClB,KAAK,aAAa,EACrB,MAAM,0BAA0B,CAAC;AAElC,wEAAwE;AACxE,MAAM,WAAW,oBAAoB;IACjC,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,QAAQ,EAAE,aAAa,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAC9B,aAAa,EAAE,SAAS,oBAAoB,EAAE,GAC/C,aAAa,CA+Cf"}