dsh-autotier 0.2.2 → 0.2.5

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 (51) hide show
  1. package/AGENTS.md +52 -23
  2. package/CHANGELOG.md +44 -0
  3. package/{README.es.md → README-es.md} +94 -13
  4. package/{README.hi.md → README-hi.md} +93 -14
  5. package/{README.pt.md → README-pt.md} +96 -16
  6. package/{README.zh.md → README-zh.md} +83 -11
  7. package/README.md +110 -18
  8. package/cordis.patch.yml +2 -2
  9. package/lib/client.js +72 -40
  10. package/lib/client.js.map +1 -1
  11. package/lib/index.js +233 -66
  12. package/lib/typert.host.js +1 -1
  13. package/lib/types/client/TierSettingsCard.d.ts +14 -12
  14. package/lib/types/client/TierSettingsCard.d.ts.map +1 -1
  15. package/lib/types/client/index.d.ts +5 -4
  16. package/lib/types/client/index.d.ts.map +1 -1
  17. package/lib/types/client/remote.d.ts +12 -12
  18. package/lib/types/config.d.ts +20 -9
  19. package/lib/types/config.d.ts.map +1 -1
  20. package/lib/types/index.d.ts +11 -8
  21. package/lib/types/index.d.ts.map +1 -1
  22. package/lib/types/judge.d.ts +17 -0
  23. package/lib/types/judge.d.ts.map +1 -1
  24. package/lib/types/preflight.d.ts +21 -1
  25. package/lib/types/preflight.d.ts.map +1 -1
  26. package/lib/types/routing.d.ts.map +1 -1
  27. package/lib/types/schema.d.ts +44 -2
  28. package/lib/types/schema.d.ts.map +1 -1
  29. package/lib/types/selection.d.ts +36 -10
  30. package/lib/types/selection.d.ts.map +1 -1
  31. package/lib/types/service.d.ts +16 -9
  32. package/lib/types/service.d.ts.map +1 -1
  33. package/lib/types/settings.d.ts +44 -0
  34. package/lib/types/settings.d.ts.map +1 -0
  35. package/lib/types/typert.host.d.ts +12 -12
  36. package/lib/types/wire.d.ts +24 -24
  37. package/lib/types/wire.d.ts.map +1 -1
  38. package/lib/{wire-BpKSOHgo.js → wire-BxsY8BiN.js} +22 -20
  39. package/package.json +62 -56
  40. package/src/client/TierSettingsCard.tsx +25 -12
  41. package/src/client/index.ts +29 -16
  42. package/src/config.ts +70 -12
  43. package/src/index.ts +23 -19
  44. package/src/judge.ts +30 -2
  45. package/src/preflight.ts +68 -1
  46. package/src/routing.ts +11 -0
  47. package/src/schema.ts +48 -9
  48. package/src/selection.ts +54 -20
  49. package/src/service.ts +20 -18
  50. package/src/settings.ts +80 -0
  51. package/src/wire.ts +19 -20
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The host settings seam for dsh-autotier.
3
+ *
4
+ * The `0.1.7` host owns forms, not providers: `ctx.settings` is a
5
+ * `SettingsForms` service that projects each plugin's `Config` schema into a
6
+ * Plugins-page form, and a live edit is committed through the Loader's
7
+ * `loader/volatile-update` event. The pre-`0.1.6` `settings.register(ns, schema,
8
+ * { base })` call this plugin used to make — and the `settings/updated` event it
9
+ * listened to — no longer exist on any published line that ships the new
10
+ * service, so the configuration is read from the row's own `Volatile` fields.
11
+ *
12
+ * Two duties live here:
13
+ *
14
+ * 1. Claim this instance's page policy (`configure({ auto: false })`) so the
15
+ * plugin appears in the Plugins page rather than only in a generated form.
16
+ * 2. Re-resolve the routing policy whenever a live edit lands, by re-reading
17
+ * the `Volatile` references and running them through the same cross-field
18
+ * judge the mount path uses.
19
+ *
20
+ * @module dsh-autotier/settings
21
+ */
22
+
23
+ import type { Context } from '@deepseek-ai/cordis'
24
+ // Registers `loader/volatile-update` on cordis's Events map. The event is
25
+ // declared by the LOADER package, not by cordis core, so this import is what
26
+ // makes `ctx.on('loader/volatile-update', ...)` type-check — a type-only import
27
+ // has no runtime effect and never bundles.
28
+ import type {} from '@deepseek-ai/cordis-plugin-loader'
29
+ import { resolveConfig, type ResolvedConfig, type VolatileConfig } from './config.ts'
30
+ import type { AutotierService } from './service.ts'
31
+
32
+ /** The `ctx.settings` face this module uses (structural: the service moved packages). */
33
+ interface SettingsFormsFace {
34
+ configure(presentation: { auto?: boolean }, owner?: unknown): () => void
35
+ }
36
+
37
+ /** Options for {@link bindSettings}. */
38
+ export interface BindSettingsOptions {
39
+ readonly ctx: Context
40
+ /** The row configuration the Loader handed `apply`; every section is volatile. */
41
+ readonly config: VolatileConfig
42
+ /** The live service whose policy is swapped on each committed edit. */
43
+ readonly service: AutotierService
44
+ }
45
+
46
+ /**
47
+ * Claim the settings page policy and follow live configuration edits.
48
+ *
49
+ * The page-policy claim is best-effort: `settings` is a hard inject, but a host
50
+ * line that composes the plugin without the settings service must still route,
51
+ * so a missing or differently-shaped service degrades to "no page" instead of
52
+ * failing the mount.
53
+ *
54
+ * @param options - the plugin context, the volatile row config and the service.
55
+ */
56
+ export function bindSettings(options: BindSettingsOptions): void {
57
+ const { ctx, config, service } = options
58
+ const settings = ctx.get('settings') as SettingsFormsFace | undefined
59
+ if (settings !== undefined && typeof settings.configure === 'function') {
60
+ ctx.effect(() => settings.configure({ auto: false }, ctx.fiber))
61
+ }
62
+ ctx.on('loader/volatile-update', () => {
63
+ // A committed edit replaces the whole snapshot. The write was accepted by
64
+ // the Loader against the schema, which cannot express this plugin's
65
+ // cross-field rules, so the judge runs here; a value it refuses keeps the
66
+ // last good policy rather than swapping in something unroutable.
67
+ let next: ResolvedConfig
68
+ try {
69
+ next = resolveConfig(config)
70
+ } catch (error) {
71
+ ctx.logger.warn(
72
+ 'dsh-autotier: keeping the last good routing policy; the updated configuration was refused: %s',
73
+ error instanceof Error ? error.message : String(error),
74
+ )
75
+ return
76
+ }
77
+ service.reconfigure(next)
78
+ ctx.logger.info('dsh-autotier: routing policy reloaded from a live configuration update')
79
+ })
80
+ }
package/src/wire.ts CHANGED
@@ -149,25 +149,32 @@ export const TIER_AGENT_ID_SCHEMA = z.string().optional()
149
149
  /** Strict wire schema for the routing mode parameter. */
150
150
  export const TIER_MODE_SCHEMA = z.enum(ROUTING_MODES)
151
151
 
152
+ /**
153
+ * Strict codec, single-face.
154
+ *
155
+ * `TypertCodec`'s strict arm declares exactly one schema entry point,
156
+ * `create(): TypertSchema`, and the typert-loader enforces it at registration
157
+ * (`has no create() factory`). The `schema` property this used to carry as a
158
+ * second face is gone from the protocol, so carrying it was dead weight — the
159
+ * loader ignores it, and no published line reads it — while still looking like
160
+ * a supported surface. The zod instance carries `.parse` natively, so the
161
+ * factory hands the same object back on every call.
162
+ */
163
+ function strictCodec<S extends { parse(value: unknown): unknown }>(typeSymbol: string, schema: S) {
164
+ return Object.freeze({ mode: 'strict' as const, typeSymbol, create: (): S => schema })
165
+ }
166
+
152
167
  /** The optional trailing agent-id parameter both agent-addressed methods share. */
153
168
  const AGENT_ID_PARAMETER = Object.freeze({
154
169
  name: 'agentId',
155
170
  wire: 'agentId',
156
171
  source: 'json',
157
- codec: Object.freeze({
158
- mode: 'strict',
159
- typeSymbol: 'dsh-autotier/wire#TierAgentId',
160
- schema: TIER_AGENT_ID_SCHEMA,
161
- }),
172
+ codec: strictCodec('dsh-autotier/wire#TierAgentId', TIER_AGENT_ID_SCHEMA),
162
173
  acceptsUndefined: true,
163
174
  } satisfies InvocationDescriptor['parameters'][number])
164
175
 
165
176
  /** The strict result codec every `tier` method returns. */
166
- const TIER_STATUS_RESULT = Object.freeze({
167
- mode: 'strict',
168
- typeSymbol: 'dsh-autotier/wire#TierStatus',
169
- schema: TIER_STATUS_SCHEMA,
170
- } satisfies InvocationDescriptor['result'])
177
+ const TIER_STATUS_RESULT = strictCodec('dsh-autotier/wire#TierStatus', TIER_STATUS_SCHEMA)
171
178
 
172
179
  /** Diagnostics location shared by the hand-written descriptors below. */
173
180
  const WIRE_LOCATION = Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 })
@@ -200,11 +207,7 @@ export const TIER_CATALOG_DESCRIPTOR = Object.freeze({
200
207
  method: 'catalog',
201
208
  invocation: Object.freeze({ kind: 'direct' }),
202
209
  parameters: Object.freeze([]),
203
- result: Object.freeze({
204
- mode: 'strict',
205
- typeSymbol: 'dsh-autotier/wire#TierCatalog',
206
- schema: TIER_CATALOG_SCHEMA,
207
- }),
210
+ result: Object.freeze(strictCodec('dsh-autotier/wire#TierCatalog', TIER_CATALOG_SCHEMA)),
208
211
  sourceLocation: WIRE_LOCATION,
209
212
  } as const) satisfies InvocationDescriptor
210
213
 
@@ -224,11 +227,7 @@ export const TIER_SET_MODE_DESCRIPTOR = Object.freeze({
224
227
  name: 'mode',
225
228
  wire: 'mode',
226
229
  source: 'json',
227
- codec: Object.freeze({
228
- mode: 'strict',
229
- typeSymbol: 'dsh-autotier/types#RoutingMode',
230
- schema: TIER_MODE_SCHEMA,
231
- }),
230
+ codec: strictCodec('dsh-autotier/types#RoutingMode', TIER_MODE_SCHEMA),
232
231
  } satisfies InvocationDescriptor['parameters'][number]),
233
232
  AGENT_ID_PARAMETER,
234
233
  ]),