@pellux/goodvibes-tui 0.25.0 → 0.26.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 (84) hide show
  1. package/CHANGELOG.md +5 -3
  2. package/README.md +1 -1
  3. package/docs/foundation-artifacts/operator-contract.json +2419 -1040
  4. package/package.json +2 -2
  5. package/src/daemon/{calendar → handlers/calendar}/caldav-client.ts +28 -24
  6. package/src/daemon/handlers/calendar/index.ts +316 -0
  7. package/src/daemon/handlers/context.ts +29 -0
  8. package/src/daemon/handlers/contracts.ts +77 -0
  9. package/src/daemon/{channels → handlers}/drafts/draft-store.ts +114 -50
  10. package/src/daemon/handlers/drafts/index.ts +17 -0
  11. package/src/daemon/handlers/drafts/register.ts +331 -0
  12. package/src/daemon/handlers/email/config.ts +164 -0
  13. package/src/daemon/handlers/email/index.ts +43 -0
  14. package/src/daemon/handlers/email/read-handlers.ts +80 -0
  15. package/src/daemon/handlers/email/runtime.ts +140 -0
  16. package/src/daemon/handlers/email/validation.ts +147 -0
  17. package/src/daemon/handlers/email/write-handlers.ts +133 -0
  18. package/src/daemon/handlers/errors.ts +18 -0
  19. package/src/daemon/{channels → handlers}/inbox/cursor-store.ts +58 -66
  20. package/src/daemon/handlers/inbox/index.ts +210 -0
  21. package/src/daemon/{channels → handlers}/inbox/mapping.ts +8 -6
  22. package/src/daemon/{channels → handlers}/inbox/poller.ts +4 -4
  23. package/src/daemon/{channels → handlers}/inbox/provider-adapter.ts +14 -10
  24. package/src/daemon/{channels → handlers}/inbox/providers/discord.ts +8 -10
  25. package/src/daemon/{channels → handlers}/inbox/providers/imap-client.ts +1 -1
  26. package/src/daemon/{channels → handlers}/inbox/providers/route-util.ts +2 -2
  27. package/src/daemon/{channels → handlers}/inbox/providers/slack.ts +9 -11
  28. package/src/daemon/handlers/index.ts +107 -0
  29. package/src/daemon/handlers/register.ts +161 -0
  30. package/src/daemon/{remote → handlers/remote}/backends/cloud-terminal.ts +8 -3
  31. package/src/daemon/{remote → handlers/remote}/backends/docker.ts +2 -3
  32. package/src/daemon/handlers/remote/backends/index.ts +40 -0
  33. package/src/daemon/{remote → handlers/remote}/backends/process-runner.ts +16 -40
  34. package/src/daemon/{remote → handlers/remote}/backends/ssh.ts +8 -3
  35. package/src/daemon/{remote → handlers/remote}/backends/types.ts +29 -3
  36. package/src/daemon/{remote → handlers/remote}/dispatcher.ts +27 -6
  37. package/src/daemon/handlers/remote/index.ts +119 -0
  38. package/src/daemon/{remote → handlers/remote}/peer-registry.ts +47 -11
  39. package/src/daemon/handlers/remote/service.ts +191 -0
  40. package/src/daemon/{channels → handlers}/routing/inbox-bridge.ts +33 -20
  41. package/src/daemon/handlers/routing/index.ts +261 -0
  42. package/src/daemon/{channels → handlers}/routing/route-store.ts +57 -16
  43. package/src/daemon/{channels → handlers}/routing/routing-resolver.ts +1 -1
  44. package/src/daemon/{operator → handlers}/sqlite-store.ts +5 -5
  45. package/src/daemon/handlers/triage/index.ts +57 -0
  46. package/src/daemon/handlers/triage/integration.ts +212 -0
  47. package/src/daemon/{triage → handlers/triage}/pipeline.ts +58 -70
  48. package/src/daemon/{triage → handlers/triage}/scorer.ts +21 -21
  49. package/src/daemon/handlers/triage/tagger/discord.ts +186 -0
  50. package/src/daemon/handlers/triage/tagger/imap.ts +383 -0
  51. package/src/daemon/handlers/triage/tagger/index.ts +184 -0
  52. package/src/daemon/handlers/triage/tagger/shared.ts +70 -0
  53. package/src/daemon/handlers/triage/tagger/slack.ts +69 -0
  54. package/src/daemon/handlers/triage/types.ts +50 -0
  55. package/src/runtime/services.ts +48 -35
  56. package/src/version.ts +1 -1
  57. package/src/daemon/calendar/index.ts +0 -52
  58. package/src/daemon/calendar/register.ts +0 -527
  59. package/src/daemon/channels/drafts/index.ts +0 -22
  60. package/src/daemon/channels/drafts/register.ts +0 -449
  61. package/src/daemon/channels/inbox/index.ts +0 -58
  62. package/src/daemon/channels/inbox/register.ts +0 -247
  63. package/src/daemon/channels/routing/index.ts +0 -39
  64. package/src/daemon/channels/routing/register.ts +0 -296
  65. package/src/daemon/email/index.ts +0 -68
  66. package/src/daemon/email/register.ts +0 -715
  67. package/src/daemon/operator/index.ts +0 -43
  68. package/src/daemon/operator/register-helper.ts +0 -150
  69. package/src/daemon/operator/surfaces.ts +0 -137
  70. package/src/daemon/operator/types.ts +0 -207
  71. package/src/daemon/remote/backends/index.ts +0 -34
  72. package/src/daemon/remote/index.ts +0 -74
  73. package/src/daemon/remote/register.ts +0 -411
  74. package/src/daemon/triage/index.ts +0 -59
  75. package/src/daemon/triage/integration.ts +0 -179
  76. package/src/daemon/triage/register.ts +0 -231
  77. package/src/daemon/triage/tagger.ts +0 -777
  78. /package/src/daemon/{calendar → handlers/calendar}/ics.ts +0 -0
  79. /package/src/daemon/{operator/credential-store.ts → handlers/credentials.ts} +0 -0
  80. /package/src/daemon/{email → handlers/email}/imap-connector.ts +0 -0
  81. /package/src/daemon/{email → handlers/email}/imap-parsing.ts +0 -0
  82. /package/src/daemon/{email → handlers/email}/smtp-connector.ts +0 -0
  83. /package/src/daemon/{channels → handlers}/inbox/providers/email.ts +0 -0
  84. /package/src/daemon/{remote → handlers/remote}/backends/local-process.ts +0 -0
@@ -1,231 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Daemon-internal triage surface REGISTRATION.
3
- //
4
- // Registers the internal methods inbox.triage.list and inbox.triage.tag with
5
- // transport ['internal'] ONLY — deliberately NOT 'ws'. This keeps them OFF the
6
- // agent-facing WS method list while remaining invocable by the inbox poller
7
- // internally. Access is 'operator'.
8
- //
9
- // If these are ever promoted to agent-facing methods, their IDs must move to a
10
- // separate handoff (per the contract); they must not be added to 'ws' here.
11
- // ---------------------------------------------------------------------------
12
-
13
- import {
14
- OperatorError,
15
- declareOperatorMethods,
16
- type InboundChannelItem,
17
- type OperatorContext,
18
- type SurfaceRegister,
19
- type Unregister,
20
- } from '../operator/index.ts';
21
- import { runInboxTriage, type RunInboxTriageOptions } from './pipeline.ts';
22
- import { createTriageTagger, type TriageTaggerOptions } from './tagger.ts';
23
- import type { TriageLabel } from './scorer.ts';
24
-
25
- export const TRIAGE_METHOD_IDS = {
26
- // Internal step name per the handoff contract (line 612): the scoring step is
27
- // 'inbox.triage.list' (it lists scored items), the mutation step is
28
- // 'inbox.triage.tag'. These are non-published, transport ['internal'] only.
29
- list: 'inbox.triage.list',
30
- tag: 'inbox.triage.tag',
31
- } as const;
32
-
33
- const SCORE_INPUT_SCHEMA: Record<string, unknown> = {
34
- type: 'object',
35
- required: ['items'],
36
- additionalProperties: false,
37
- properties: {
38
- items: {
39
- type: 'array',
40
- items: { type: 'object' },
41
- description: 'InboundChannelItem[] to score.',
42
- },
43
- persist: {
44
- type: 'boolean',
45
- description:
46
- 'Omit or set true to persist triageScore/triageTags to the inbox triage store; set false to dry-run (compute scores only, no write).',
47
- },
48
- },
49
- };
50
-
51
- const SCORE_OUTPUT_SCHEMA: Record<string, unknown> = {
52
- type: 'object',
53
- required: ['items', 'scored', 'persisted'],
54
- properties: {
55
- scored: { type: 'number' },
56
- persisted: { type: 'number' },
57
- items: {
58
- type: 'array',
59
- items: {
60
- type: 'object',
61
- properties: {
62
- id: { type: 'string' },
63
- triage: {
64
- type: 'object',
65
- properties: {
66
- triageScore: { type: 'number' },
67
- triageLabel: { type: 'string', enum: ['spam', 'priority', 'normal'] },
68
- triageTags: { type: 'array', items: { type: 'string' } },
69
- },
70
- },
71
- },
72
- },
73
- },
74
- },
75
- };
76
-
77
- // NOTE: `confirm` is deliberately ABSENT from this advertised schema. Per the
78
- // operator-confirm-contract-fidelity pattern, confirmed methods must NOT
79
- // advertise `confirm` in their inputSchema; enforcement is body-level via
80
- // assertConfirmed (register-helper.ts), which reads body.confirm from the raw
81
- // untyped invocation body. Keeping it out of the schema makes this an exact
82
- // match to the handoff Input contract instead of a strict superset.
83
- const TAG_INPUT_SCHEMA: Record<string, unknown> = {
84
- type: 'object',
85
- required: ['item'],
86
- additionalProperties: false,
87
- properties: {
88
- item: { type: 'object', description: 'InboundChannelItem to tag provider-side.' },
89
- tags: { type: 'array', items: { type: 'string' } },
90
- label: { type: 'string', enum: ['spam', 'priority', 'normal'] },
91
- },
92
- };
93
-
94
- const TAG_OUTPUT_SCHEMA: Record<string, unknown> = {
95
- type: 'object',
96
- required: ['surface', 'itemId', 'appliedTags', 'skipped'],
97
- properties: {
98
- surface: { type: 'string' },
99
- itemId: { type: 'string' },
100
- appliedTags: { type: 'array', items: { type: 'string' } },
101
- skipped: { type: 'boolean' },
102
- reason: { type: 'string' },
103
- },
104
- };
105
-
106
- interface ScoreBody {
107
- items?: unknown;
108
- persist?: unknown;
109
- }
110
-
111
- interface TagBody {
112
- item?: unknown;
113
- tags?: unknown;
114
- label?: unknown;
115
- confirm?: unknown;
116
- }
117
-
118
- function asInboundItems(value: unknown): InboundChannelItem[] {
119
- if (!Array.isArray(value)) {
120
- throw new OperatorError('`items` must be an array of inbound items.', 'TRIAGE_INVALID_INPUT', 400);
121
- }
122
- return value.map((entry, index) => {
123
- if (typeof entry !== 'object' || entry === null) {
124
- throw new OperatorError(`items[${index}] is not an object.`, 'TRIAGE_INVALID_INPUT', 400);
125
- }
126
- const item = entry as Partial<InboundChannelItem>;
127
- if (typeof item.id !== 'string' || typeof item.surface !== 'string') {
128
- throw new OperatorError(
129
- `items[${index}] requires string id and surface.`,
130
- 'TRIAGE_INVALID_INPUT',
131
- 400,
132
- );
133
- }
134
- return item as InboundChannelItem;
135
- });
136
- }
137
-
138
- function asInboundItem(value: unknown): InboundChannelItem {
139
- const [item] = asInboundItems([value]);
140
- return item!;
141
- }
142
-
143
- export interface RegisterTriageOptions {
144
- pipeline?: RunInboxTriageOptions;
145
- tagger?: TriageTaggerOptions;
146
- }
147
-
148
- /**
149
- * SurfaceRegister for the daemon-internal triage surface.
150
- *
151
- * Wiring contract: the daemon integration layer (services.ts, the single
152
- * allowed edit site there) calls `registerTriageMethods(ctx)` once with the
153
- * OperatorContext and retains the returned Unregister for teardown. For the
154
- * full poll -> score -> persist -> list enrichment loop the contract relies on,
155
- * compose it via `registerTriagedInbox` (see ./integration.ts), which is
156
- * directly exercised by the integration test.
157
- */
158
- export function createTriageRegister(options: RegisterTriageOptions = {}): SurfaceRegister {
159
- return (ctx: OperatorContext): Unregister => {
160
- const tagger = createTriageTagger(ctx, options.tagger);
161
-
162
- return declareOperatorMethods(ctx, [
163
- {
164
- descriptor: {
165
- id: TRIAGE_METHOD_IDS.list,
166
- title: 'Inbox Triage — List (score)',
167
- description:
168
- 'Daemon-internal: score inbound items for spam/priority and optionally persist triageScore/triageTags.',
169
- category: 'inbox',
170
- source: 'daemon',
171
- access: 'operator',
172
- transport: ['internal'],
173
- scopes: ['inbox:triage'],
174
- effect: 'local-state-mutation',
175
- inputSchema: SCORE_INPUT_SCHEMA,
176
- outputSchema: SCORE_OUTPUT_SCHEMA,
177
- },
178
- handler: async (input) => {
179
- const body = (input.body ?? {}) as ScoreBody;
180
- const items = asInboundItems(body.items);
181
- const dryRun = body.persist === false;
182
- return runInboxTriage(items, ctx, { ...options.pipeline, dryRun });
183
- },
184
- },
185
- {
186
- descriptor: {
187
- id: TRIAGE_METHOD_IDS.tag,
188
- title: 'Inbox Triage — Tag',
189
- description:
190
- 'Daemon-internal: apply a triage label back on the provider side (IMAP flag / Slack or Discord reaction).',
191
- category: 'inbox',
192
- source: 'daemon',
193
- access: 'operator',
194
- transport: ['internal'],
195
- scopes: ['inbox:triage', 'inbox:triage:write'],
196
- effect: 'confirmed-connected-host-state',
197
- confirm: true,
198
- inputSchema: TAG_INPUT_SCHEMA,
199
- outputSchema: TAG_OUTPUT_SCHEMA,
200
- },
201
- handler: async (input) => {
202
- const body = (input.body ?? {}) as TagBody;
203
- const item = asInboundItem(body.item);
204
- const tags = Array.isArray(body.tags)
205
- ? body.tags.filter((t): t is string => typeof t === 'string')
206
- : undefined;
207
- const label =
208
- typeof body.label === 'string' ? (body.label as TriageLabel) : undefined;
209
- return tagger.applyTags({
210
- item,
211
- tags,
212
- label,
213
- // confirm:true is enforced by the declareOperatorMethod guard before
214
- // we reach here; mirror both flags into the tagger for defense-in-depth.
215
- confirm: body.confirm === true,
216
- explicitUserRequest: input.context.explicitUserRequest === true,
217
- });
218
- },
219
- },
220
- ]);
221
- };
222
- }
223
-
224
- /**
225
- * Default SurfaceRegister export. Integration may import either this `register`
226
- * or `registerTriageMethods` (alias) and call it with the OperatorContext.
227
- */
228
- export const register: SurfaceRegister = createTriageRegister();
229
-
230
- /** Named alias matching the integration contract (registerTriageMethods). */
231
- export const registerTriageMethods: SurfaceRegister = register;