@avantf/dsh-mem 0.1.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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/lib/client.js +5901 -0
  4. package/lib/client.js.map +1 -0
  5. package/lib/dsh-build.json +7 -0
  6. package/lib/index.js +14329 -0
  7. package/lib/types/client/domains.d.ts +52 -0
  8. package/lib/types/client/domains.d.ts.map +1 -0
  9. package/lib/types/client/domains.js +25 -0
  10. package/lib/types/client/domains.js.map +1 -0
  11. package/lib/types/client/index.d.ts +35 -0
  12. package/lib/types/client/index.d.ts.map +1 -0
  13. package/lib/types/client/index.js +1351 -0
  14. package/lib/types/client/index.js.map +1 -0
  15. package/lib/types/client/ingest.d.ts +24 -0
  16. package/lib/types/client/ingest.d.ts.map +1 -0
  17. package/lib/types/client/ingest.js +30 -0
  18. package/lib/types/client/ingest.js.map +1 -0
  19. package/lib/types/client/paging.d.ts +30 -0
  20. package/lib/types/client/paging.d.ts.map +1 -0
  21. package/lib/types/client/paging.js +36 -0
  22. package/lib/types/client/paging.js.map +1 -0
  23. package/lib/types/client/summarize.d.ts +11 -0
  24. package/lib/types/client/summarize.d.ts.map +1 -0
  25. package/lib/types/client/summarize.js +79 -0
  26. package/lib/types/client/summarize.js.map +1 -0
  27. package/lib/types/envinit-bootstrap.d.ts +43 -0
  28. package/lib/types/envinit-bootstrap.js +323 -0
  29. package/lib/types/envinit.d.ts +145 -0
  30. package/lib/types/envinit.d.ts.map +1 -0
  31. package/lib/types/envinit.js +495 -0
  32. package/lib/types/envinit.js.map +1 -0
  33. package/lib/types/hints.d.ts +42 -0
  34. package/lib/types/hints.d.ts.map +1 -0
  35. package/lib/types/hints.js +54 -0
  36. package/lib/types/hints.js.map +1 -0
  37. package/lib/types/index.d.ts +74 -0
  38. package/lib/types/index.d.ts.map +1 -0
  39. package/lib/types/index.js +708 -0
  40. package/lib/types/index.js.map +1 -0
  41. package/lib/types/inject.d.ts +14 -0
  42. package/lib/types/inject.d.ts.map +1 -0
  43. package/lib/types/inject.js +14 -0
  44. package/lib/types/inject.js.map +1 -0
  45. package/lib/types/open.d.ts +27 -0
  46. package/lib/types/open.d.ts.map +1 -0
  47. package/lib/types/open.js +133 -0
  48. package/lib/types/open.js.map +1 -0
  49. package/lib/types/prompt.d.ts +49 -0
  50. package/lib/types/prompt.d.ts.map +1 -0
  51. package/lib/types/prompt.js +65 -0
  52. package/lib/types/prompt.js.map +1 -0
  53. package/lib/types/provision.d.ts +117 -0
  54. package/lib/types/provision.d.ts.map +1 -0
  55. package/lib/types/provision.js +233 -0
  56. package/lib/types/provision.js.map +1 -0
  57. package/lib/types/remote.d.ts +17 -0
  58. package/lib/types/remote.d.ts.map +1 -0
  59. package/lib/types/remote.js +233 -0
  60. package/lib/types/remote.js.map +1 -0
  61. package/lib/types/tool_schema.d.ts +40 -0
  62. package/lib/types/tool_schema.d.ts.map +1 -0
  63. package/lib/types/tool_schema.js +149 -0
  64. package/lib/types/tool_schema.js.map +1 -0
  65. package/package.json +109 -0
@@ -0,0 +1,233 @@
1
+ /**
2
+ * This plugin's compatibility spec, and the wiring that runs it.
3
+ *
4
+ * The rules, the probes, the report and the post-registration check all live in
5
+ * `@avantf/dsh-compat` (shared with the rest of the family). What stays here is only what is true of
6
+ * THIS plugin: the services and methods it calls, the dsh packages that identify the host, the wire
7
+ * schema names and tool names that must be visible afterwards, the events it listens to, and the
8
+ * Chinese report a user reads. See `DESIGN.md` §12.1.
9
+ *
10
+ * **Who obtains the base.** Not this module. The family framework `@avantf/dsh-envinit` provisions
11
+ * `@avantf/dsh-compat` as the `mem:compat` manifest item and hands back the directory it landed in
12
+ * (`src/envinit.ts`); this module is given the loaded module and derives everything from it. That is
13
+ * the whole point of the framework: acquisition (resolve → managed copy → verified download →
14
+ * atomic publish) is one shared mechanism, and the plugin only declares what it needs.
15
+ *
16
+ * The base therefore has NO import path of its own here — not even a dynamic one. A static `import`
17
+ * would throw `ERR_MODULE_NOT_FOUND` while the artifact was being evaluated (the base is not a
18
+ * runtime dependency of the published plugin any more), and a bare dynamic `import()` would bypass
19
+ * the framework's managed copy. The plugin loads the module the framework resolved, by file URL.
20
+ *
21
+ * The plugin computes the gate's verdict here and hands it to the engine as plain data
22
+ * (`{ load, status, reason }`), so the inlined engine bundle never imports the base either.
23
+ *
24
+ * @module @avantf/dsh-mem/provision
25
+ */
26
+ import { readFile } from 'node:fs/promises';
27
+ import { defineTool } from '@deepseek-ai/dsh-tools';
28
+ import { hostContribution } from './remote.js';
29
+ /** The base package id, named here too so the item declaration and the spec need no import. */
30
+ export const COMPAT_PACKAGE = '@avantf/dsh-compat';
31
+ /**
32
+ * Fallback range for `@avantf/dsh-compat`, used only when `package.json` has lost the dependency
33
+ * entry. The manifest is the single source of truth (`compatRange()`); `scripts/pack-plugin.mjs`
34
+ * pins this constant to it so the two cannot drift.
35
+ */
36
+ export const COMPAT_RANGE = '^0.1.0';
37
+ /**
38
+ * The services this plugin calls, with the methods it calls on them.
39
+ *
40
+ * `required` is this plugin's REFUSAL policy, not cordis's `inject`: `typert` is injected (the real
41
+ * wire face is registered at mount) yet a composition without the registry must still mount the
42
+ * memory tools, so its absence is a note rather than a refusal. Optional services are read with
43
+ * `ctx.get()`.
44
+ *
45
+ * `tools` lists only `register` because that is the one method this plugin calls; the post-load
46
+ * check reads `get`, but guards it and degrades to "not verified", so demanding it here would refuse
47
+ * a host this plugin can still drive.
48
+ */
49
+ export const SERVICE_CONTRACTS = [
50
+ { name: 'tools', required: true, methods: ['register'] },
51
+ { name: 'systemPrompt', required: true, methods: ['section', 'context'] },
52
+ { name: 'typert', required: false, methods: ['register', 'get', 'list', 'listPackages', 'toJSONSchema'] },
53
+ // Read with `ctx.get()` only by the refusal megaphone; a host without it must not become a refusal.
54
+ { name: 'commands', required: false, methods: ['register'] },
55
+ ];
56
+ /**
57
+ * The events this plugin listens to — reported, never verified.
58
+ *
59
+ * A listener for a name the host no longer emits registers happily and then never runs: the house
60
+ * hints would simply stop appearing. Nothing inside a plugin can prove the host still emits a name,
61
+ * so the list is a known limit the gate records and the running dsh version is the operator's signal.
62
+ */
63
+ export const REQUIRED_EVENTS = ['agent/inbox/inserted', 'tools/result'];
64
+ /** Packages released in lockstep with dsh; their version says which dsh is running. */
65
+ export const VERSION_PACKAGES = ['@deepseek-ai/dsh-tools', '@deepseek-ai/dsh-typert-protocol'];
66
+ /** This plugin's npm package id, which names the probe and verification keys. */
67
+ const PACKAGE_ID = String(hostContribution.package ?? '@avantf/dsh-mem');
68
+ /** Best-effort one-line reason for a caught value. */
69
+ export function reasonOf(error) {
70
+ return error instanceof Error ? error.message : String(error);
71
+ }
72
+ /** Emit a warning without ever letting the logger turn it into a crash. */
73
+ export function warn(log, message) {
74
+ try {
75
+ log?.warn(message);
76
+ }
77
+ catch {
78
+ // A logger that throws is not evidence of anything.
79
+ }
80
+ }
81
+ /**
82
+ * The range of `@avantf/dsh-compat` this build is written against.
83
+ *
84
+ * Read from THIS plugin's manifest, which is the single source of truth — the framework does not
85
+ * pick it, and a hardcoded constant would silently keep provisioning an old range after the family
86
+ * publishes a new one. The constant is only a fallback for a manifest that lost the entry.
87
+ *
88
+ * It lives in `devDependencies`, deliberately. Nothing imports the base: the framework fetches it
89
+ * into its own managed home and this plugin loads it from there, so a RUNTIME dependency would
90
+ * install a second copy on every consumer that no code path ever loads. `devDependencies` still
91
+ * ships in the packed manifest (pnpm keeps it, rewriting `catalog:` like any other field), so the
92
+ * range travels with the artifact; it just is not installed.
93
+ */
94
+ export async function compatRange(manifestUrl = new URL('../package.json', import.meta.url)) {
95
+ try {
96
+ const raw = JSON.parse(await readFile(manifestUrl, 'utf8'));
97
+ const declared = raw.devDependencies?.[COMPAT_PACKAGE] ?? raw.dependencies?.[COMPAT_PACKAGE];
98
+ if (typeof declared === 'string' && declared.trim() !== '')
99
+ return declared;
100
+ }
101
+ catch {
102
+ // Fall through to the pinned fallback.
103
+ }
104
+ return COMPAT_RANGE;
105
+ }
106
+ /**
107
+ * Build the plugin-specific half of the gate from a loaded base.
108
+ *
109
+ * Called ONCE per process (the loaded runtime is cached by `src/envinit.ts`), which is what makes the
110
+ * lazy construction equivalent to the module-level constants it replaces — `readBuildVersions` still
111
+ * reads the baked `lib/dsh-build.json` beside the built entry, falling back per package to the peer
112
+ * range floor when it is absent (a dev tree, a test run).
113
+ */
114
+ export function runtimeFromCompat(module) {
115
+ const peerFloors = module.readDeclaredVersions(new URL('../package.json', import.meta.url), VERSION_PACKAGES);
116
+ const buildVersionsUrl = new URL(`./${module.BUILD_VERSIONS_FILE}`, import.meta.url);
117
+ const schemaNames = module.schemaNamesFrom(hostContribution);
118
+ const spec = {
119
+ packageId: PACKAGE_ID,
120
+ services: SERVICE_CONTRACTS,
121
+ // The version THIS BUILD was compiled against: the exact one baked at build time, falling back
122
+ // per package to the peer range floor. A range floor alone cannot say what the build linked.
123
+ declared: module.readBuildVersions(buildVersionsUrl, VERSION_PACKAGES, peerFloors),
124
+ // Resolved from THIS package's links: the packages that identify the host are its peers. Note
125
+ // this is NOT the host's identity — see the base package's README «已知边界».
126
+ runtime: module.readRuntimeVersions(VERSION_PACKAGES, import.meta.url),
127
+ // The base package knows no dsh type, so the probe's declaration comes from here — the probe must
128
+ // mirror the declaration path the REAL tools use.
129
+ probeTool: module.toolProbeDeclaration(defineTool),
130
+ // The wire probe IS the real host face, codecs and all. A probe that merely RESEMBLED it once
131
+ // reported `ok` on a 0.1.6 host whose codec contract had moved, and the real registration then
132
+ // threw halfway through `apply` — the half-mounted outcome this gate exists to prevent. Same
133
+ // object, same host, so "the probe passed" now means "this registration passes".
134
+ probeTypert: () => hostContribution,
135
+ schemaNames,
136
+ events: REQUIRED_EVENTS,
137
+ };
138
+ return { module, prefix: module.COMPAT_PREFIX, spec, schemaNames };
139
+ }
140
+ /** The "the check itself failed" outcome: keep loading, say why. */
141
+ function cannotDetermine(error, log, prefix) {
142
+ const message = `${prefix} WARNING — the compatibility check itself failed (${reasonOf(error)}); loading anyway`;
143
+ warn(log, message);
144
+ return {
145
+ verdict: {
146
+ load: true,
147
+ skipped: true,
148
+ status: 'probe-skipped',
149
+ problems: [],
150
+ warnings: [message],
151
+ notes: ['the check itself failed'],
152
+ lines: [{ level: 'warn', message }],
153
+ reason: '',
154
+ },
155
+ };
156
+ }
157
+ /**
158
+ * Run the gate. Call this FIRST in `apply()`: on a refusal nothing has been registered yet, so
159
+ * "do not load" costs nothing to unwind. Never throws — not even with a throwing logger, because
160
+ * "cannot tell" is not "incompatible".
161
+ * @param ctx - the plugin's context.
162
+ * @param log - the plugin's logger.
163
+ * @param compat - the loaded gate runtime (see `src/envinit.ts`).
164
+ * @param spec - what to judge (defaults to the runtime's spec; injectable so the version path is
165
+ * testable without a second host).
166
+ * @returns the verdict `apply` branches on.
167
+ */
168
+ export function provision(ctx, log, compat, spec = compat.spec) {
169
+ let evidence;
170
+ try {
171
+ evidence = compat.module.gatherEvidence(ctx, spec);
172
+ }
173
+ catch (error) {
174
+ return cannotDetermine(error, log, compat.prefix);
175
+ }
176
+ let verdict;
177
+ try {
178
+ verdict = compat.module.verdictOf(evidence);
179
+ }
180
+ catch (error) {
181
+ return cannotDetermine(error, log, compat.prefix);
182
+ }
183
+ for (const line of verdict.lines) {
184
+ try {
185
+ log[line.level](line.message);
186
+ }
187
+ catch {
188
+ // A logger that throws must not turn a verdict into a crash.
189
+ }
190
+ }
191
+ return { verdict };
192
+ }
193
+ /**
194
+ * Keep one `/mem` command that reports a refusal.
195
+ *
196
+ * The plugin provides nothing else when it refuses, and the alternative is a user watching a tab
197
+ * that never loads with no way to ask why.
198
+ * @param ctx - the plugin's context.
199
+ * @param verdict - the refusal to report.
200
+ * @param log - the plugin's logger.
201
+ * @param compat - the loaded gate runtime.
202
+ */
203
+ export function registerCompatMegaphone(ctx, verdict, log, compat) {
204
+ compat.module.registerMegaphone({
205
+ ctx,
206
+ log,
207
+ command: { name: 'mem', description: '报告记忆插件为何未加载(兼容性检查未通过)' },
208
+ text: compat.module.compatReport(verdict, {
209
+ heading: '记忆插件未加载:与当前 dsh 的兼容性检查未通过,插件已拒绝加载(不注册服务、工具、prompt 段与真实 typert face)。',
210
+ warningsLabel: '风险提示:',
211
+ warnings: verdict.warnings,
212
+ fix: '修复:在本仓库重建(`pnpm build:dsh`),或把 `@deepseek-ai/dsh` 换回本构建声明的版本。',
213
+ }),
214
+ });
215
+ }
216
+ /**
217
+ * The second phase: every real registration must be visible afterwards.
218
+ *
219
+ * Warn-only by design — the plugin is mounted by now, so there is no clean "do not load" left to
220
+ * take, and a silently dropped schema or tool is exactly what nothing else would report.
221
+ * @param input - the live context, the real tool names, the logger, and the loaded gate runtime.
222
+ * @returns the registrations that did not show up (empty on success).
223
+ */
224
+ export function verifyRegisteredFaces(input) {
225
+ return input.compat.module.verifyRegisteredFaces({
226
+ ctx: input.ctx,
227
+ log: input.log,
228
+ packageId: input.compat.spec.packageId,
229
+ schemaNames: input.compat.schemaNames,
230
+ toolNames: input.toolNames,
231
+ });
232
+ }
233
+ //# sourceMappingURL=provision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/provision.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { InvocationDescriptor, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
2
+ import type { TypertContribution } from '@deepseek-ai/dsh-typert-registry/types';
3
+ export declare const descriptors: readonly InvocationDescriptor[];
4
+ /** Client face: mounted by the client half through `ctx.remote.$mount()`. */
5
+ export declare const clientContribution: TypertRemoteContribution;
6
+ /**
7
+ * Host face: registered by the host half through `ctx.typert.register()`.
8
+ *
9
+ * The schema assertions name `TypertSchema['schema']` — the FIELD they are assigned to — rather
10
+ * than this package's own `z.ZodType`. The two are different zod copies: the plugin pins
11
+ * zod 4.4.3, the harness bundles 4.6.2, and `ZodType` gained members between them, so a cast to
12
+ * the local `z.ZodType` could never be assignable and the annotation said nothing. Through
13
+ * `TypertSchema['schema']` the assertion is at least against the type the field actually
14
+ * requires, and a future zod alignment (which would make the cast unnecessary) shows up here.
15
+ */
16
+ export declare const hostContribution: TypertContribution;
17
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/remote.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACV,oBAAoB,EAGpB,wBAAwB,EACzB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,wCAAwC,CAAA;AAuE9F,eAAO,MAAM,WAAW,EAAE,SAAS,oBAAoB,EAqGtD,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,EAAE,wBAGhC,CAAA;AAqBD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,kBA0C9B,CAAA"}
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Hand-written Typert wire faces for the `avantfMem` Remote namespace.
3
+ *
4
+ * DSH packages normally ship generator-produced faces (`typert.host.js` /
5
+ * `typert.remote-client.js`), but the Typert generator runs only inside the
6
+ * harness workspace. Both faces are therefore hand-written here, following the
7
+ * generator's exact conventions: zod v4 strict codecs, one `args` object
8
+ * parameter per method, `<pkg>#<namespace>/<method>` invocation ids, and a host
9
+ * contribution registered through `ctx.typert.register()` (the documented
10
+ * path for hand-written wire schemas, see `@deepseek-ai/dsh-typert-loader`).
11
+ *
12
+ * The five methods mirror the five agent tools (remember/recall/admin/kb/query)
13
+ * so the 记忆/知识 tabs can do full CRUD + KB management. Args carry the merged
14
+ * optional field set of the contract's action unions; the HOST re-validates
15
+ * every payload with the contract zod schema before dispatch, so the wire face
16
+ * only needs to guarantee JSON shape sanity. Five methods have no tool behind
17
+ * them — `openDoc` (the 知识 tab's 「编辑」/「打开目录」 buttons), `classifySource`
18
+ * and `browseDir` (its source input and 选择 picker), `kbDomains` (its domain
19
+ * dropdown) and `kbAddDomain` (its 「+」 next to that dropdown).
20
+ *
21
+ * The host half consumes `hostContribution`; the client half mounts
22
+ * `clientContribution` via `ctx.remote.$mount()`.
23
+ */
24
+ import { z } from 'zod';
25
+ const PACKAGE = '@avantf/dsh-mem';
26
+ const NAMESPACE = 'avantfMem';
27
+ const endpointId = (method) => `${PACKAGE}#${NAMESPACE}/${method}`;
28
+ const fieldSymbol = (method, field) => `${PACKAGE}#${NAMESPACE}/${method}:${field}`;
29
+ const resultSymbol = (method) => fieldSymbol(method, 'result');
30
+ /**
31
+ * zod v4 strict codec envelope the Typert boundary validates with.
32
+ *
33
+ * Carries BOTH members on purpose: the host's validator moved from `codec.schema.parse` (0.1.5) to
34
+ * `codec.create()` (0.1.6), and each generation checks only its own. One shape therefore serves
35
+ * either host — the same "one shape satisfies two revisions" trick the job plugin's `strict()` uses.
36
+ */
37
+ function strict(schema, typeSymbol) {
38
+ return { mode: 'strict', typeSymbol, schema, create: () => schema };
39
+ }
40
+ /** One JSON wire parameter; optional parameters accept a missing wire field. */
41
+ function parameter(method, name, schema, acceptsUndefined) {
42
+ return {
43
+ name,
44
+ wire: name,
45
+ source: 'json',
46
+ codec: strict(schema, fieldSymbol(method, name)),
47
+ ...(acceptsUndefined === undefined ? {} : { acceptsUndefined }),
48
+ };
49
+ }
50
+ const text = z.string();
51
+ // Optional wire fields are written as `X.optional()`, NOT `z.union([z.undefined(), X])`. The two
52
+ // accept the same payloads, but the union is invisible to the HOST's JSON-Schema projector:
53
+ // `z.toJSONSchema()` throws "Undefined cannot be represented in JSON Schema" over it, and the
54
+ // startup compatibility gate projects the REAL wire face through that host method — so the union
55
+ // form made a healthy host read as an incompatible one. `.optional()` projects to a non-required
56
+ // property, which is exactly what these fields are.
57
+ const count = z.number().int().optional();
58
+ const optionalText = z.string().optional();
59
+ const bool = z.boolean().optional();
60
+ const textArray = z.array(z.string()).optional();
61
+ /** One direct Remote method carrying a single `args` object parameter. */
62
+ function direct(method, args) {
63
+ return {
64
+ id: endpointId(method),
65
+ service: NAMESPACE,
66
+ namespace: NAMESPACE,
67
+ method,
68
+ invocation: { kind: 'direct' },
69
+ parameters: [parameter(method, 'args', args)],
70
+ // The runtime's result shapes vary by store backend and evolve fast;
71
+ // keep the boundary tolerant (`z.any()` never rejects a host reply).
72
+ result: strict(z.any(), resultSymbol(method)),
73
+ };
74
+ }
75
+ export const descriptors = [
76
+ // remember: add/update/remove/helpful/unhelpful (action defaults to 'add' host-side)
77
+ direct('remember', z.object({
78
+ action: optionalText.optional(),
79
+ content: optionalText.optional(),
80
+ fact_id: count.optional(),
81
+ category: optionalText.optional(),
82
+ ttl_days: count.optional(),
83
+ reason: optionalText.optional(),
84
+ })),
85
+ // recall: search/ask/chain/probe/reason/related/contradict (defaults to 'search')
86
+ direct('recall', z.object({
87
+ action: optionalText.optional(),
88
+ query: optionalText.optional(),
89
+ entity: optionalText.optional(),
90
+ entities: textArray.optional(),
91
+ subj: optionalText.optional(),
92
+ pred: optionalText.optional(),
93
+ obj: optionalText.optional(),
94
+ second_pred: optionalText.optional(),
95
+ category: optionalText.optional(),
96
+ limit: count.optional(),
97
+ max_tokens: count.optional(),
98
+ })),
99
+ // admin: stats/list/detail/archive/restore/vectors_*/contradict_*/maintenance (defaults to 'list')
100
+ //
101
+ // Every field the client sends must be declared here: a strict codec PARSES the args before they
102
+ // go out (harness `api/gateway` `parseInput`), and a zod object drops unknown keys — a missing
103
+ // field is not an error, it is a silently emptied request that then fails contract validation
104
+ // host-side. That is exactly how the three 矛盾裁决 buttons shipped broken: `contradiction_id`,
105
+ // `resolution` and `loser_fact_id` were never declared, so only `{action}` reached the host.
106
+ // `test/remote_wire.spec.ts` pins the invariant that actually generalises — declared ⊇ the
107
+ // contract union's fields — because "declared ⊇ what the client source sends" has blind spots a
108
+ // wrapper function (`kbCall(label, args)`) or a conditional spread hides.
109
+ direct('admin', z.object({
110
+ action: optionalText.optional(),
111
+ fact_id: count.optional(),
112
+ category: optionalText.optional(),
113
+ status: optionalText.optional(),
114
+ limit: count.optional(),
115
+ offset: count.optional(),
116
+ reason: optionalText.optional(),
117
+ dry_run: bool.optional(),
118
+ contradiction_id: count.optional(),
119
+ resolution: optionalText.optional(),
120
+ loser_fact_id: count.optional(),
121
+ })),
122
+ // kb: ingest/import/list/detail/remove/reindex/sync (action REQUIRED — no safe default)
123
+ //
124
+ // `overwrite` is a field of THIS face only: the UI's 入库 form sends it after the user confirms
125
+ // the collision dialog, and the CLI after `--overwrite`. It is deliberately NOT a field of
126
+ // `KB_ADD_TOOL.input`, so the add-only mode cannot leak into the model's view.
127
+ //
128
+ // `adopt` is the 知识 tab's 「认领文件」 button: sync one document whose frontmatter was destroyed
129
+ // by a whole-file overwrite, accepting the store's guess about which row it belongs to. It was
130
+ // missing from this face, so the button sent `{action:'sync', doc_id}` and reported
131
+ // 「认领完成:0 篇」 — the fourth field to ship silently undeclared.
132
+ direct('kb', z.object({
133
+ action: optionalText.optional(),
134
+ text: optionalText.optional(),
135
+ source_uri: optionalText.optional(),
136
+ domain: optionalText.optional(),
137
+ source: optionalText.optional(),
138
+ title: optionalText.optional(),
139
+ paths: textArray.optional(),
140
+ doc_id: count.optional(),
141
+ limit: count.optional(),
142
+ offset: count.optional(),
143
+ dry_run: bool.optional(),
144
+ overwrite: bool.optional(),
145
+ adopt: bool.optional(),
146
+ })),
147
+ // query: cross-store retrieval
148
+ direct('query', z.object({
149
+ query: text,
150
+ kind: optionalText.optional(),
151
+ domain: optionalText.optional(),
152
+ source: optionalText.optional(),
153
+ limit: count.optional(),
154
+ max_tokens: count.optional(),
155
+ })),
156
+ // classifySource / browseDir: UI-only. The 知识 tab has ONE source input, so the host has to say
157
+ // what a string IS (URL / file / directory / missing / pasted text) and let the user browse for a
158
+ // path — a browser can check `^https?://` and nothing else, and only the host may stat a path.
159
+ direct('classifySource', z.object({ text: optionalText.optional() })),
160
+ direct('browseDir', z.object({ path: optionalText.optional() })),
161
+ // kbDomains: UI-only. The 知识 tab's domain control is a picker, and the two halves of its option
162
+ // list — the configured `knowledge.domains` allowlist and the domains already in the library —
163
+ // live host-side, so the client asks for the union instead of guessing it.
164
+ direct('kbDomains', z.object({})),
165
+ // kbAddDomain: UI-only (no agent tool mirrors it, deliberately — an autonomous writer is where
166
+ // domain sprawl would come from). Appends the name to the store config's `domains` allowlist and
167
+ // to the live set, and answers with the new catalog so the picker can select it.
168
+ direct('kbAddDomain', z.object({ domain: text })),
169
+ // openDoc: UI-only (no agent tool mirrors it) — hand one managed document file, or the
170
+ // directory holding it, to the user's editor. The host resolves the path from `doc_id`, so the
171
+ // client never supplies a path the host would have to trust.
172
+ direct('openDoc', z.object({
173
+ doc_id: count,
174
+ target: optionalText.optional(),
175
+ })),
176
+ ];
177
+ /** Client face: mounted by the client half through `ctx.remote.$mount()`. */
178
+ export const clientContribution = {
179
+ package: PACKAGE,
180
+ descriptors,
181
+ };
182
+ /** Declare one registered wire schema: the factory 0.1.6 calls, plus the schema 0.1.5 reads. */
183
+ function declared(name, schema) {
184
+ return { name, schema, create: () => schema };
185
+ }
186
+ /**
187
+ * Host face: registered by the host half through `ctx.typert.register()`.
188
+ *
189
+ * The schema assertions name `TypertSchema['schema']` — the FIELD they are assigned to — rather
190
+ * than this package's own `z.ZodType`. The two are different zod copies: the plugin pins
191
+ * zod 4.4.3, the harness bundles 4.6.2, and `ZodType` gained members between them, so a cast to
192
+ * the local `z.ZodType` could never be assignable and the annotation said nothing. Through
193
+ * `TypertSchema['schema']` the assertion is at least against the type the field actually
194
+ * requires, and a future zod alignment (which would make the cast unnecessary) shows up here.
195
+ */
196
+ export const hostContribution = {
197
+ package: PACKAGE,
198
+ face: 'host',
199
+ schemas: descriptors.flatMap((descriptor) => [
200
+ ...descriptor.parameters.map(parameter => declared(`${descriptor.method}${parameter.name}`, parameter.codec.schema)),
201
+ declared(`${descriptor.method}Result`, descriptor.result.schema),
202
+ ]),
203
+ model: {
204
+ services: [
205
+ {
206
+ key: 'avantfMemory',
207
+ exportName: 'avantfMemory',
208
+ description: 'avantf-mem runtime facade: memory store, knowledge store, ingestion, lifecycle, cross-retrieval router',
209
+ summary: 'avantf-mem engine runtime',
210
+ tags: [],
211
+ members: [],
212
+ types: [],
213
+ },
214
+ {
215
+ key: NAMESPACE,
216
+ exportName: NAMESPACE,
217
+ description: 'Client Remote namespace: remember / recall / admin / kb / query over the avantf-mem stores',
218
+ summary: 'avantf-mem client remote',
219
+ tags: [],
220
+ members: descriptors.map(descriptor => ({
221
+ kind: 'method',
222
+ name: descriptor.method,
223
+ signature: '(args: object) => Promise<unknown>',
224
+ })),
225
+ types: [],
226
+ },
227
+ ],
228
+ events: [],
229
+ objects: [],
230
+ },
231
+ invocations: descriptors,
232
+ };
233
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../src/remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type ToolSpec } from '@avantf/mem-contract';
2
+ export type ParamSpec = {
3
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object';
4
+ description?: string;
5
+ required?: true;
6
+ enum?: readonly string[];
7
+ items?: ParamSpec;
8
+ };
9
+ /** The slice of zod v4's `def` this derivation reads (structure only, never type tags). */
10
+ export interface ZodDef {
11
+ type?: string;
12
+ shape?: Record<string, unknown>;
13
+ options?: unknown[];
14
+ /** A literal's / enum's values; v4 keeps them in an array. */
15
+ values?: unknown;
16
+ }
17
+ export declare function zodDef(schema: unknown): ZodDef;
18
+ /** Nearest `description` on a schema (wrappers included — the converter already unwrapped them). */
19
+ export declare function schemaDescription(schema: unknown): string | undefined;
20
+ export declare function zodToSpec(schema: unknown): ParamSpec;
21
+ /** Materialize one zod object branch's fields, or undefined for a non-object. */
22
+ export declare function branchShape(schema: unknown): Record<string, unknown> | undefined;
23
+ /**
24
+ * Flatten a tool input schema into DSH's implicit parameter map. A discriminated
25
+ * union contributes one required `action` enum plus the merged field set (fields
26
+ * stay optional at the schema level because requiredness differs per action; the
27
+ * per-action requirement is stated in each field's description and enforced by
28
+ * `spec.input` validation before dispatch). A plain object marks its own required
29
+ * fields directly.
30
+ *
31
+ * The merged descriptions come from the contract's {@link mergedFieldDescription}, the SAME
32
+ * function `toolInputJsonSchema` uses for the MCP surface. Taking each field's first branch
33
+ * verbatim is what made the two model-facing surfaces disagree: `mem_admin`'s `fact_id` said
34
+ * "action=detail 时必填" on this surface while the MCP schema said
35
+ * "【detail/archive/restore/pin/unpin 必填】" — so a model calling `archive` without it had to
36
+ * learn the requirement from a `violations` retry. Both surfaces now read the same merged
37
+ * descriptions, which is what keeps them in agreement field for field.
38
+ */
39
+ export declare function flattenToolSpec(spec: ToolSpec): Record<string, ParamSpec>;
40
+ //# sourceMappingURL=tool_schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool_schema.d.ts","sourceRoot":"","sources":["../../src/tool_schema.ts"],"names":[],"mappings":"AAgBA,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE5E,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;IACtE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAED,2FAA2F;AAC3F,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,EAAE,CAAA;IACnB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAE9C;AAkBD,oGAAoG;AACpG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGrE;AAqBD,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAEpD;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAEhF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAiDzE"}