@wowok/agent-mcp 2.6.9 → 2.7.1

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 (139) hide show
  1. package/README.md +0 -2
  2. package/dist/customer/risk-assessment.d.ts +5 -1
  3. package/dist/customer/risk-assessment.js +4 -4
  4. package/dist/evaluation/arbitration-game.d.ts +16 -0
  5. package/dist/evaluation/arbitration-game.js +48 -0
  6. package/dist/evaluation/builtins/demand-match.d.ts +15 -0
  7. package/dist/evaluation/builtins/demand-match.js +153 -0
  8. package/dist/evaluation/builtins/index.d.ts +3 -0
  9. package/dist/evaluation/builtins/index.js +10 -0
  10. package/dist/evaluation/builtins/service-risk.d.ts +6 -0
  11. package/dist/evaluation/builtins/service-risk.js +55 -0
  12. package/dist/evaluation/capability.d.ts +50 -0
  13. package/dist/evaluation/capability.js +13 -0
  14. package/dist/evaluation/composer.d.ts +13 -0
  15. package/dist/evaluation/composer.js +40 -0
  16. package/dist/evaluation/engine.d.ts +18 -0
  17. package/dist/evaluation/engine.js +175 -0
  18. package/dist/evaluation/extract.d.ts +30 -0
  19. package/dist/evaluation/extract.js +115 -0
  20. package/dist/evaluation/gap.d.ts +2 -0
  21. package/dist/evaluation/gap.js +100 -0
  22. package/dist/evaluation/index.d.ts +11 -0
  23. package/dist/evaluation/index.js +11 -0
  24. package/dist/evaluation/node-game.d.ts +34 -0
  25. package/dist/evaluation/node-game.js +57 -0
  26. package/dist/evaluation/region.d.ts +10 -0
  27. package/dist/evaluation/region.js +36 -0
  28. package/dist/evaluation/types.d.ts +76 -0
  29. package/dist/evaluation/types.js +1 -0
  30. package/dist/evaluation/user-injection.d.ts +6 -0
  31. package/dist/evaluation/user-injection.js +27 -0
  32. package/dist/examples/education-contact-create.json +40 -0
  33. package/dist/examples/freelance-contact-create.json +40 -0
  34. package/dist/examples/insurance-machine-create.json +1 -1
  35. package/dist/examples/insurance-service-allocators.json +1 -1
  36. package/dist/examples/machine-publish.json +1 -1
  37. package/dist/examples/rental-ziroom-service-create.json +1 -1
  38. package/dist/examples/retail-adv-guard-messenger-proof-create.json +1 -1
  39. package/dist/examples/retail-myshop-service-create.json +1 -1
  40. package/dist/examples/retail-myshop-service-customer-required.json +1 -1
  41. package/dist/examples/subscription-contact-create.json +40 -0
  42. package/dist/examples/threebody-machine-create.json +1 -1
  43. package/dist/examples/travel-machine-create.json +1 -1
  44. package/dist/examples/travel-service-create.json +1 -1
  45. package/dist/harness/plan.js +42 -3
  46. package/dist/intent/enrich.d.ts +1 -0
  47. package/dist/intent/enrich.js +67 -0
  48. package/dist/intent/index.d.ts +23 -0
  49. package/dist/intent/index.js +60 -0
  50. package/dist/intent/matcher.d.ts +2 -0
  51. package/dist/intent/matcher.js +81 -0
  52. package/dist/intent/store.d.ts +19 -0
  53. package/dist/intent/store.js +55 -0
  54. package/dist/intent/types.d.ts +33 -0
  55. package/dist/intent/types.js +10 -0
  56. package/dist/knowledge/arbitration-risk.js +1 -11
  57. package/dist/knowledge/contact-templates.d.ts +27 -0
  58. package/dist/knowledge/contact-templates.js +60 -0
  59. package/dist/knowledge/examples-scanner.js +21 -3
  60. package/dist/knowledge/fund-layer.js +8 -4
  61. package/dist/knowledge/industry-generalizer.js +21 -21
  62. package/dist/knowledge/machine-risk.js +0 -1
  63. package/dist/knowledge/mcp-schema-audit.d.ts +1 -1
  64. package/dist/knowledge/mcp-schema-audit.js +8 -4
  65. package/dist/knowledge/service-risk.js +38 -2
  66. package/dist/knowledge/service-templates.js +1 -1
  67. package/dist/knowledge/service-translation.js +2 -2
  68. package/dist/knowledge/template-registry.d.ts +1 -1
  69. package/dist/knowledge/template-registry.js +13 -1
  70. package/dist/knowledge/tools-reference.js +23 -0
  71. package/dist/persona/analyzer.d.ts +16 -0
  72. package/dist/persona/analyzer.js +66 -0
  73. package/dist/persona/bridge.d.ts +5 -0
  74. package/dist/persona/bridge.js +86 -0
  75. package/dist/persona/defaults.d.ts +4 -0
  76. package/dist/persona/defaults.js +195 -0
  77. package/dist/persona/experience-bridge.d.ts +3 -0
  78. package/dist/persona/experience-bridge.js +23 -0
  79. package/dist/persona/index.d.ts +18 -0
  80. package/dist/persona/index.js +71 -0
  81. package/dist/persona/model.d.ts +7 -0
  82. package/dist/persona/model.js +111 -0
  83. package/dist/persona/store.d.ts +19 -0
  84. package/dist/persona/store.js +62 -0
  85. package/dist/persona/types.d.ts +43 -0
  86. package/dist/persona/types.js +5 -0
  87. package/dist/project/handlers.d.ts +5 -0
  88. package/dist/project/handlers.js +23 -1
  89. package/dist/project/semantic-graph.js +47 -0
  90. package/dist/rules.d.ts +2 -0
  91. package/dist/rules.js +43 -0
  92. package/dist/schema/call/semantic.js +23 -1
  93. package/dist/schema/call/service.js +7 -1
  94. package/dist/schema/evaluation/index.d.ts +4239 -0
  95. package/dist/schema/evaluation/index.js +356 -0
  96. package/dist/schema/index.d.ts +4 -0
  97. package/dist/schema/index.js +4 -0
  98. package/dist/schema/intent-radar/index.d.ts +284 -0
  99. package/dist/schema/intent-radar/index.js +89 -0
  100. package/dist/schema/messenger/index.d.ts +171 -0
  101. package/dist/schema/messenger/index.js +5 -0
  102. package/dist/schema/operations.js +1 -1
  103. package/dist/schema/persona/index.d.ts +1985 -0
  104. package/dist/schema/persona/index.js +148 -0
  105. package/dist/schema/project/index.d.ts +2 -2
  106. package/dist/schema/query/index.js +6 -0
  107. package/dist/schema/sync-layer4.d.ts +1 -1
  108. package/dist/schema/sync-layer4.js +9 -5
  109. package/dist/schema/task-status.d.ts +168 -0
  110. package/dist/schema/task-status.js +36 -0
  111. package/dist/schema/trust/index.js +1 -1
  112. package/dist/schemas/evaluation_operation.output.json +677 -0
  113. package/dist/schemas/evaluation_operation.schema.json +903 -0
  114. package/dist/schemas/index.json +25 -1
  115. package/dist/schemas/intent_radar.output.json +229 -0
  116. package/dist/schemas/intent_radar.schema.json +135 -0
  117. package/dist/schemas/messenger_operation.output.json +14 -0
  118. package/dist/schemas/messenger_operation.schema.json +18 -0
  119. package/dist/schemas/onchain_operations.schema.json +2 -2
  120. package/dist/schemas/onchain_operations_service.schema.json +2 -2
  121. package/dist/schemas/persona_operation.output.json +389 -0
  122. package/dist/schemas/persona_operation.schema.json +247 -0
  123. package/dist/schemas/query_task_status.output.json +115 -0
  124. package/dist/schemas/query_task_status.schema.json +24 -0
  125. package/dist/schemas/query_toolkit.output.json +1 -1
  126. package/dist/schemas/trust_score.schema.json +1 -1
  127. package/dist/tools/handlers/evaluation.d.ts +2 -0
  128. package/dist/tools/handlers/evaluation.js +123 -0
  129. package/dist/tools/handlers/intent-radar.d.ts +2 -0
  130. package/dist/tools/handlers/intent-radar.js +76 -0
  131. package/dist/tools/handlers/onchain.js +98 -0
  132. package/dist/tools/handlers/persona.d.ts +4 -0
  133. package/dist/tools/handlers/persona.js +89 -0
  134. package/dist/tools/handlers/task-status.d.ts +0 -168
  135. package/dist/tools/handlers/task-status.js +0 -29
  136. package/dist/tools/index.js +83 -7
  137. package/dist/tools/wip-deploy-assist.d.ts +1 -1
  138. package/dist/tools/wip-deploy-assist.js +33 -5
  139. package/package.json +2 -2
@@ -0,0 +1,86 @@
1
+ const REQUIREMENT_RULE_MAP = [
2
+ { keywords: ["arbitration", "arb"], rule_id: "r_trust" },
3
+ { keywords: ["compensation", "fund"], rule_id: "r_fund" },
4
+ { keywords: ["region", "location"], rule_id: "r_region" },
5
+ { keywords: ["price", "budget"], rule_id: "r_price" },
6
+ { keywords: ["industry"], rule_id: "r_industry" },
7
+ { keywords: ["capability"], rule_id: "r_capabilities" },
8
+ { keywords: ["trust", "score"], rule_id: "r_trust" },
9
+ ];
10
+ const FORBID_KEYWORDS = ["forbid", "never", "no "];
11
+ function mapRequirement(req) {
12
+ const lower = req.toLowerCase();
13
+ const forbid = FORBID_KEYWORDS.some((k) => lower.includes(k));
14
+ for (const m of REQUIREMENT_RULE_MAP) {
15
+ if (m.keywords.some((k) => lower.includes(k))) {
16
+ return { rule_id: m.rule_id, condition: forbid ? "forbid" : "require", note: req };
17
+ }
18
+ }
19
+ return { rule_id: "r_trust", condition: forbid ? "forbid" : "require", note: req };
20
+ }
21
+ export function personaToInjection(effective) {
22
+ const requirements = (effective.layer.requirements ?? []).map(mapRequirement);
23
+ const intent = [
24
+ `role=${effective.role}`,
25
+ effective.industries.length ? `industries=${effective.industries.join(",")}` : "",
26
+ effective.layer.identity?.self_description ?? "",
27
+ ].filter(Boolean).join("; ");
28
+ return {
29
+ intent,
30
+ preferences: effective.layer.preferences ?? {},
31
+ requirements: requirements.length ? requirements : undefined,
32
+ };
33
+ }
34
+ export function personaToContextText(effective) {
35
+ const lines = [];
36
+ lines.push(`# Effective Persona (role=${effective.role}, industries=${effective.industries.join(",") || "any"})`);
37
+ const id = effective.layer.identity;
38
+ if (id) {
39
+ if (id.self_description)
40
+ lines.push(`- self: ${id.self_description}`);
41
+ if (id.region)
42
+ lines.push(`- region: ${id.region}`);
43
+ if (id.languages?.length)
44
+ lines.push(`- languages: ${id.languages.join(", ")}`);
45
+ }
46
+ if (effective.layer.strategy?.length) {
47
+ lines.push("- strategy:");
48
+ for (const s of effective.layer.strategy)
49
+ lines.push(` - ${s}`);
50
+ }
51
+ if (effective.layer.rules?.length) {
52
+ lines.push("- rules:");
53
+ for (const r of effective.layer.rules)
54
+ lines.push(` - ${r}`);
55
+ }
56
+ if (effective.layer.requirements?.length) {
57
+ lines.push("- requirements:");
58
+ for (const r of effective.layer.requirements)
59
+ lines.push(` - ${r}`);
60
+ }
61
+ if (effective.layer.spec) {
62
+ lines.push("- spec:");
63
+ lines.push(effective.layer.spec);
64
+ }
65
+ return lines.join("\n");
66
+ }
67
+ export function mergeInjections(base, override) {
68
+ if (!base && !override)
69
+ return undefined;
70
+ if (!base)
71
+ return override ?? undefined;
72
+ if (!override)
73
+ return base;
74
+ return {
75
+ intent: override.intent ?? base.intent,
76
+ preferences: { ...(base.preferences ?? {}), ...(override.preferences ?? {}) },
77
+ requirements: [...(base.requirements ?? []), ...(override.requirements ?? [])],
78
+ overrides: {
79
+ rules: { ...(base.overrides?.rules ?? {}), ...(override.overrides?.rules ?? {}) },
80
+ data_sources: {
81
+ ...(base.overrides?.data_sources ?? {}),
82
+ ...(override.overrides?.data_sources ?? {}),
83
+ },
84
+ },
85
+ };
86
+ }
@@ -0,0 +1,4 @@
1
+ import { type Industry, type Persona, type PersonaRole } from "./types.js";
2
+ export declare const GENERIC_PERSONA: Persona;
3
+ export declare function getIndustryDefault(role: PersonaRole, industry: Industry): Persona;
4
+ export declare function listIndustryDefaults(): Persona[];
@@ -0,0 +1,195 @@
1
+ import { getDefaultPreferences } from "../customer/user-preferences.js";
2
+ import { PERSONA_VERSION, } from "./types.js";
3
+ function safePrefs(prefs) {
4
+ const { budget_range: _budget, ...rest } = prefs;
5
+ return rest;
6
+ }
7
+ function industryPrefs(industry) {
8
+ return safePrefs(getDefaultPreferences(industry));
9
+ }
10
+ const SPECS = [
11
+ {
12
+ role: "merchant", industry: "freelance",
13
+ strategy: [
14
+ "Deliver in milestones and release per milestone (avoid all-or-nothing non-acceptance).",
15
+ "Record WIP hash at each key node as evidence.",
16
+ "Use an accept_guard time gate so non-accepting clients auto-release after the deadline.",
17
+ ],
18
+ requirements: [
19
+ "must have arbitration",
20
+ "must have a compensation fund",
21
+ "forbid full upfront payment before any delivery",
22
+ ],
23
+ },
24
+ {
25
+ role: "user", industry: "freelance",
26
+ strategy: [
27
+ "Pay per milestone, verify each before releasing the next.",
28
+ "Verify WIP hash before accepting a delivery.",
29
+ "Open arbitration if the provider is unresponsive.",
30
+ ],
31
+ requirements: [
32
+ "must have arbitration",
33
+ "must have a compensation fund",
34
+ "forbid direct payment without escrow",
35
+ ],
36
+ },
37
+ {
38
+ role: "merchant", industry: "rental",
39
+ strategy: [
40
+ "Record pre/post rental WIP hashes as the damage-claim baseline.",
41
+ "Hold the deposit in a graded allocator (normal return auto-releases).",
42
+ "Keep an evidence chain for any damage claim.",
43
+ ],
44
+ requirements: [
45
+ "must have arbitration",
46
+ "damage claims require pre-rental baseline evidence",
47
+ ],
48
+ },
49
+ {
50
+ role: "user", industry: "rental",
51
+ strategy: [
52
+ "Record condition evidence (WIP hash) before renting.",
53
+ "Confirm the return only after verifying no damage.",
54
+ "Open arbitration against unfair damage claims.",
55
+ ],
56
+ requirements: [
57
+ "must have arbitration",
58
+ "deposit must be refundable (a return path must exist)",
59
+ ],
60
+ },
61
+ {
62
+ role: "merchant", industry: "education",
63
+ strategy: [
64
+ "Release tuition per lesson (1/N) to structurally prevent run-away disputes.",
65
+ "Keep attendance/completion evidence.",
66
+ "Declare the refund policy up front.",
67
+ ],
68
+ requirements: [
69
+ "must have arbitration",
70
+ "tuition must be escrowed (not directly received)",
71
+ ],
72
+ },
73
+ {
74
+ role: "user", industry: "education",
75
+ strategy: [
76
+ "Pay per lesson, never full upfront.",
77
+ "Confirm completed lessons before paying.",
78
+ "Request proportional refund if the course is cancelled.",
79
+ ],
80
+ requirements: [
81
+ "must have arbitration",
82
+ "forbid one-time full upfront payment",
83
+ ],
84
+ },
85
+ {
86
+ role: "merchant", industry: "travel",
87
+ strategy: [
88
+ "Model multi-leg trips as a multi-leg machine with a transparent fund waterfall.",
89
+ "Declare the cancellation policy up front.",
90
+ "Separate refundable vs non-refundable legs.",
91
+ ],
92
+ requirements: [
93
+ "must have arbitration",
94
+ "funds must be escrowed (conditionally released)",
95
+ ],
96
+ },
97
+ {
98
+ role: "user", industry: "travel",
99
+ strategy: [
100
+ "Confirm the cancellation/refund policy before booking.",
101
+ "Watch cross-leg responsibility in multi-leg trips.",
102
+ "Pursue the non-refundable downstream on flight cancellation.",
103
+ ],
104
+ requirements: [
105
+ "must have arbitration",
106
+ "cancellation must be refundable (a refund path must exist)",
107
+ ],
108
+ },
109
+ {
110
+ role: "merchant", industry: "subscription",
111
+ strategy: [
112
+ "Charge each period via charge_guard_signer (explicit user signature).",
113
+ "Keep 100% of revenue (no platform cut).",
114
+ "Declare pauses/cancellation explicitly.",
115
+ ],
116
+ requirements: [
117
+ "forbid auto-renewal traps (every period must be explicitly signed)",
118
+ ],
119
+ },
120
+ {
121
+ role: "user", industry: "subscription",
122
+ strategy: [
123
+ "Confirm authorization before each charge.",
124
+ "Cancel anytime without friction.",
125
+ "Stop charging when the creator pauses.",
126
+ ],
127
+ requirements: [
128
+ "forbid auto-renewal (every period must be explicitly signed)",
129
+ "cancellation must be frictionless",
130
+ ],
131
+ },
132
+ {
133
+ role: "merchant", industry: "retail",
134
+ strategy: [
135
+ "Release funds on confirmed receipt (escrow).",
136
+ "Keep an evidence chain for authenticity disputes.",
137
+ "Declare the return policy up front.",
138
+ ],
139
+ requirements: [
140
+ "must have arbitration",
141
+ "funds must be escrowed (released on confirmed receipt)",
142
+ ],
143
+ },
144
+ {
145
+ role: "user", industry: "retail",
146
+ strategy: [
147
+ "Verify authenticity before confirming receipt.",
148
+ "Never confirm receipt before the goods arrive.",
149
+ "Open arbitration for counterfeit / not-received.",
150
+ ],
151
+ requirements: [
152
+ "must have arbitration",
153
+ "not-received must be refundable",
154
+ ],
155
+ },
156
+ ];
157
+ function buildDefault(spec) {
158
+ const industries = spec.industry ? [spec.industry] : [];
159
+ const longTerm = {
160
+ identity: {
161
+ self_description: `${spec.role} in ${spec.industry ?? "any"} industry`,
162
+ },
163
+ preferences: spec.industry ? industryPrefs(spec.industry) : {},
164
+ };
165
+ const current = {
166
+ strategy: spec.strategy,
167
+ requirements: spec.requirements,
168
+ };
169
+ return {
170
+ version: PERSONA_VERSION,
171
+ scope: "system",
172
+ role: spec.role,
173
+ industries,
174
+ long_term: longTerm,
175
+ current,
176
+ updated_at: 0,
177
+ };
178
+ }
179
+ const DEFAULTS = SPECS.map(buildDefault);
180
+ export const GENERIC_PERSONA = {
181
+ version: PERSONA_VERSION,
182
+ scope: "system",
183
+ role: "user",
184
+ industries: [],
185
+ long_term: { identity: { self_description: "generic WoWok user" } },
186
+ current: {},
187
+ updated_at: 0,
188
+ };
189
+ export function getIndustryDefault(role, industry) {
190
+ const found = DEFAULTS.find((p) => p.role === role && p.industries[0] === industry);
191
+ return found ? { ...found } : { ...GENERIC_PERSONA, role };
192
+ }
193
+ export function listIndustryDefaults() {
194
+ return DEFAULTS.map((p) => ({ ...p }));
195
+ }
@@ -0,0 +1,3 @@
1
+ import type { UserProfile } from "../experience/types.js";
2
+ import type { PersonaLayer } from "./types.js";
3
+ export declare function profileToCurrentLayer(profile: UserProfile): PersonaLayer;
@@ -0,0 +1,23 @@
1
+ export function profileToCurrentLayer(profile) {
2
+ if (profile.total_operations <= 0) {
3
+ return {};
4
+ }
5
+ const layer = {};
6
+ const preferences = {};
7
+ if (profile.risk_appetite && profile.risk_appetite !== "balanced")
8
+ preferences.risk_appetite = profile.risk_appetite;
9
+ if (profile.expertise_tier && profile.expertise_tier !== "novice")
10
+ preferences.expertise_tier = profile.expertise_tier;
11
+ if (profile.preferred_confirmation && profile.preferred_confirmation !== "standard")
12
+ preferences.preferred_confirmation = profile.preferred_confirmation;
13
+ if (profile.preferred_industries?.length)
14
+ preferences.preferred_industries = profile.preferred_industries;
15
+ if (typeof profile.success_rate === "number")
16
+ preferences.success_rate = profile.success_rate;
17
+ if (Object.keys(preferences).length)
18
+ layer.preferences = preferences;
19
+ if (profile.frequent_pitfalls?.length) {
20
+ layer.rules = profile.frequent_pitfalls.map((p) => `avoid pitfall: ${p}`);
21
+ }
22
+ return layer;
23
+ }
@@ -0,0 +1,18 @@
1
+ import { type PersonaAnalysis } from "./analyzer.js";
2
+ import type { EffectivePersona, Industry, Persona, PersonaLayer, PersonaRole, PersonaScope } from "./types.js";
3
+ import type { UserProfile } from "../experience/types.js";
4
+ export { GENERIC_PERSONA, getIndustryDefault, listIndustryDefaults } from "./defaults.js";
5
+ export { SqlitePersonaStore, getPersonaStore, setPersonaStore } from "./store.js";
6
+ export { countPersonaLines, emptyPersona, mergeLayers, mutateLayer, resolveEffective, validatePersona } from "./model.js";
7
+ export { personaToContextText, personaToInjection, mergeInjections } from "./bridge.js";
8
+ export { analyzePersonaContext } from "./analyzer.js";
9
+ export { profileToCurrentLayer } from "./experience-bridge.js";
10
+ export type { EffectivePersona, Industry, Persona, PersonaIdentity, PersonaLayer, PersonaMutationMode, PersonaRole, PersonaScope, } from "./types.js";
11
+ export declare function getEffectivePersona(account?: string, industry?: Industry, role?: PersonaRole): Promise<EffectivePersona>;
12
+ export declare function analysisToLayerDelta(analysis: PersonaAnalysis): PersonaLayer;
13
+ export declare function applyAnalysisToCurrent(scope: PersonaScope, account: string | undefined, analysis: PersonaAnalysis, mode?: "merge" | "replace", role?: PersonaRole, industries?: Industry[]): Promise<Persona>;
14
+ export declare function syncExperienceToCurrent(account?: string, profile?: UserProfile): Promise<{
15
+ persona: Persona;
16
+ applied: PersonaLayer;
17
+ effective: EffectivePersona;
18
+ }>;
@@ -0,0 +1,71 @@
1
+ import { GENERIC_PERSONA, getIndustryDefault } from "./defaults.js";
2
+ import { getPersonaStore } from "./store.js";
3
+ import { emptyPersona, mutateLayer, resolveEffective, validatePersona, } from "./model.js";
4
+ import { profileToCurrentLayer } from "./experience-bridge.js";
5
+ import { getProfile } from "../experience/index.js";
6
+ export { GENERIC_PERSONA, getIndustryDefault, listIndustryDefaults } from "./defaults.js";
7
+ export { SqlitePersonaStore, getPersonaStore, setPersonaStore } from "./store.js";
8
+ export { countPersonaLines, emptyPersona, mergeLayers, mutateLayer, resolveEffective, validatePersona } from "./model.js";
9
+ export { personaToContextText, personaToInjection, mergeInjections } from "./bridge.js";
10
+ export { analyzePersonaContext } from "./analyzer.js";
11
+ export { profileToCurrentLayer } from "./experience-bridge.js";
12
+ export async function getEffectivePersona(account, industry, role) {
13
+ const store = getPersonaStore();
14
+ const system = await store.get("system");
15
+ const acct = account ? await store.get("account", account) : null;
16
+ const base = industry
17
+ ? getIndustryDefault(role ?? "user", industry)
18
+ : { ...GENERIC_PERSONA, role: role ?? "user" };
19
+ return resolveEffective(system, acct, base);
20
+ }
21
+ export function analysisToLayerDelta(analysis) {
22
+ const layer = {};
23
+ if (analysis.preferences && Object.keys(analysis.preferences).length) {
24
+ layer.preferences = analysis.preferences;
25
+ }
26
+ if (analysis.requirements.length)
27
+ layer.requirements = analysis.requirements;
28
+ if (analysis.rules.length)
29
+ layer.rules = analysis.rules;
30
+ return layer;
31
+ }
32
+ export async function applyAnalysisToCurrent(scope, account, analysis, mode = "merge", role, industries) {
33
+ const store = getPersonaStore();
34
+ const existing = scope === "account" && account
35
+ ? await store.get("account", account)
36
+ : await store.get("system");
37
+ const resolvedRole = role ?? analysis.role ?? existing?.role ?? "user";
38
+ const resolvedIndustries = industries ?? analysis.industries;
39
+ const base = existing ?? emptyPersona(scope, account, resolvedRole, resolvedIndustries);
40
+ const mergedIndustries = Array.from(new Set([...base.industries, ...(resolvedIndustries ?? [])]));
41
+ const delta = analysisToLayerDelta(analysis);
42
+ const current = mutateLayer(base.current, delta, mode);
43
+ const persona = {
44
+ ...base,
45
+ role: resolvedRole,
46
+ industries: mergedIndustries,
47
+ current,
48
+ updated_at: Date.now(),
49
+ };
50
+ const issues = validatePersona(persona);
51
+ if (issues.length > 0) {
52
+ throw new Error(`persona invalid after apply: ${issues.join("; ")}`);
53
+ }
54
+ await store.put(persona);
55
+ return persona;
56
+ }
57
+ export async function syncExperienceToCurrent(account, profile) {
58
+ const store = getPersonaStore();
59
+ const scope = account ? "account" : "system";
60
+ const existing = account ? await store.get("account", account) : await store.get("system");
61
+ const base = existing ?? emptyPersona(scope, account, "user", []);
62
+ const delta = profileToCurrentLayer(profile ?? getProfile());
63
+ const current = mutateLayer(base.current, delta, "merge");
64
+ const persona = { ...base, current, updated_at: Date.now() };
65
+ const issues = validatePersona(persona);
66
+ if (issues.length > 0) {
67
+ throw new Error(`persona invalid after sync: ${issues.join("; ")}`);
68
+ }
69
+ await store.put(persona);
70
+ return { persona, applied: delta, effective: await getEffectivePersona(account) };
71
+ }
@@ -0,0 +1,7 @@
1
+ import { type EffectivePersona, type Persona, type PersonaLayer, type PersonaMutationMode } from "./types.js";
2
+ export declare function mergeLayers(layers: PersonaLayer[]): PersonaLayer;
3
+ export declare function mutateLayer(layer: PersonaLayer, delta: PersonaLayer, mode: PersonaMutationMode): PersonaLayer;
4
+ export declare function resolveEffective(system?: Persona | null, account?: Persona | null, base?: Persona | null): EffectivePersona;
5
+ export declare function countPersonaLines(persona: Persona): number;
6
+ export declare function validatePersona(persona: Persona): string[];
7
+ export declare function emptyPersona(scope: "system" | "account", account: string | undefined, role: Persona["role"], industries: Persona["industries"]): Persona;
@@ -0,0 +1,111 @@
1
+ import { PERSONA_MAX_LINES, PERSONA_VERSION, } from "./types.js";
2
+ function dedupe(items) {
3
+ return Array.from(new Set(items.filter((s) => typeof s === "string" && s.length > 0)));
4
+ }
5
+ export function mergeLayers(layers) {
6
+ const merged = {};
7
+ for (const layer of layers) {
8
+ if (!layer)
9
+ continue;
10
+ if (layer.identity) {
11
+ merged.identity = { ...merged.identity, ...layer.identity };
12
+ if (layer.identity.languages) {
13
+ merged.identity.languages = dedupe([
14
+ ...(merged.identity.languages ?? []),
15
+ ...layer.identity.languages,
16
+ ]);
17
+ }
18
+ }
19
+ if (layer.preferences) {
20
+ merged.preferences = { ...merged.preferences, ...layer.preferences };
21
+ }
22
+ if (layer.strategy) {
23
+ merged.strategy = dedupe([...(merged.strategy ?? []), ...layer.strategy]);
24
+ }
25
+ if (layer.rules) {
26
+ merged.rules = dedupe([...(merged.rules ?? []), ...layer.rules]);
27
+ }
28
+ if (layer.requirements) {
29
+ merged.requirements = dedupe([...(merged.requirements ?? []), ...layer.requirements]);
30
+ }
31
+ if (layer.spec) {
32
+ merged.spec = [merged.spec, layer.spec].filter(Boolean).join("\n\n");
33
+ }
34
+ }
35
+ return merged;
36
+ }
37
+ export function mutateLayer(layer, delta, mode) {
38
+ if (mode === "replace") {
39
+ return { ...delta };
40
+ }
41
+ return mergeLayers([layer, delta]);
42
+ }
43
+ export function resolveEffective(system, account, base) {
44
+ const layers = [];
45
+ const sources = [];
46
+ if (base) {
47
+ layers.push(base.long_term);
48
+ sources.push({ scope: base.scope, part: "long_term" });
49
+ layers.push(base.current);
50
+ sources.push({ scope: base.scope, part: "current" });
51
+ }
52
+ if (system) {
53
+ layers.push(system.long_term);
54
+ sources.push({ scope: "system", part: "long_term" });
55
+ layers.push(system.current);
56
+ sources.push({ scope: "system", part: "current" });
57
+ }
58
+ if (account) {
59
+ layers.push(account.long_term);
60
+ sources.push({ scope: "account", account: account.account, part: "long_term" });
61
+ layers.push(account.current);
62
+ sources.push({ scope: "account", account: account.account, part: "current" });
63
+ }
64
+ const winner = account ?? system ?? base;
65
+ return {
66
+ scope: account ? "account" : system ? "system" : base ? "system" : "system",
67
+ account: account?.account ?? system?.account,
68
+ role: winner?.role ?? "user",
69
+ industries: winner?.industries ?? [],
70
+ layer: mergeLayers(layers),
71
+ sources,
72
+ };
73
+ }
74
+ export function countPersonaLines(persona) {
75
+ return JSON.stringify(persona, null, 2).split("\n").length;
76
+ }
77
+ export function validatePersona(persona) {
78
+ const issues = [];
79
+ if (persona.version !== PERSONA_VERSION) {
80
+ issues.push(`version must be ${PERSONA_VERSION}`);
81
+ }
82
+ if (persona.scope === "account" && !persona.account) {
83
+ issues.push("account is required when scope=account");
84
+ }
85
+ if (persona.scope !== "account" && persona.account) {
86
+ issues.push("account should only be set when scope=account");
87
+ }
88
+ if (!persona.role || !["merchant", "user", "arbitrator"].includes(persona.role)) {
89
+ issues.push("role must be merchant|user|arbitrator");
90
+ }
91
+ if (!Array.isArray(persona.industries)) {
92
+ issues.push("industries must be an array");
93
+ }
94
+ const lines = countPersonaLines(persona);
95
+ if (lines > PERSONA_MAX_LINES) {
96
+ issues.push(`persona is ${lines} lines (max ${PERSONA_MAX_LINES})`);
97
+ }
98
+ return issues;
99
+ }
100
+ export function emptyPersona(scope, account, role, industries) {
101
+ return {
102
+ version: PERSONA_VERSION,
103
+ scope,
104
+ account,
105
+ role,
106
+ industries,
107
+ long_term: {},
108
+ current: {},
109
+ updated_at: Date.now(),
110
+ };
111
+ }
@@ -0,0 +1,19 @@
1
+ import { SQLiteStorage } from "@wowok/wowok";
2
+ import type { Persona, PersonaScope } from "./types.js";
3
+ export interface PersonaStore {
4
+ get(scope: PersonaScope, account?: string): Promise<Persona | null>;
5
+ list(): Promise<Persona[]>;
6
+ put(persona: Persona): Promise<void>;
7
+ delete(scope: PersonaScope, account?: string): Promise<boolean>;
8
+ }
9
+ export declare class SqlitePersonaStore implements PersonaStore {
10
+ private readonly kv;
11
+ constructor(kv?: SQLiteStorage);
12
+ private key;
13
+ get(scope: PersonaScope, account?: string): Promise<Persona | null>;
14
+ list(): Promise<Persona[]>;
15
+ put(persona: Persona): Promise<void>;
16
+ delete(scope: PersonaScope, account?: string): Promise<boolean>;
17
+ }
18
+ export declare function getPersonaStore(): PersonaStore;
19
+ export declare function setPersonaStore(store: PersonaStore): void;
@@ -0,0 +1,62 @@
1
+ import { SQLiteStorage } from "@wowok/wowok";
2
+ function safeParse(raw) {
3
+ try {
4
+ return JSON.parse(raw);
5
+ }
6
+ catch {
7
+ return null;
8
+ }
9
+ }
10
+ const SQLITE_KEY_PREFIX = "persona:";
11
+ const SQLITE_SYSTEM_KEY = "persona:system";
12
+ const SQLITE_ACCOUNT_PREFIX = "persona:account:";
13
+ export class SqlitePersonaStore {
14
+ kv;
15
+ constructor(kv) {
16
+ this.kv = kv ?? new SQLiteStorage();
17
+ }
18
+ key(scope, account) {
19
+ return scope === "account" && account
20
+ ? `${SQLITE_ACCOUNT_PREFIX}${account}`
21
+ : SQLITE_SYSTEM_KEY;
22
+ }
23
+ async get(scope, account) {
24
+ const raw = await this.kv.get(this.key(scope, account));
25
+ return raw ? safeParse(raw) : null;
26
+ }
27
+ async list() {
28
+ const rows = await this.kv.list(SQLITE_KEY_PREFIX);
29
+ const personas = [];
30
+ for (const { value } of rows) {
31
+ const persona = safeParse(value);
32
+ if (persona)
33
+ personas.push(persona);
34
+ }
35
+ const systemRaw = await this.kv.get(SQLITE_SYSTEM_KEY);
36
+ if (systemRaw) {
37
+ const persona = safeParse(systemRaw);
38
+ if (persona)
39
+ personas.push(persona);
40
+ }
41
+ return personas;
42
+ }
43
+ async put(persona) {
44
+ await this.kv.put(this.key(persona.scope, persona.account), JSON.stringify(persona));
45
+ }
46
+ async delete(scope, account) {
47
+ const key = this.key(scope, account);
48
+ const exists = (await this.kv.get(key)) !== undefined;
49
+ if (exists)
50
+ await this.kv.del(key);
51
+ return exists;
52
+ }
53
+ }
54
+ let _store = null;
55
+ export function getPersonaStore() {
56
+ if (!_store)
57
+ _store = new SqlitePersonaStore();
58
+ return _store;
59
+ }
60
+ export function setPersonaStore(store) {
61
+ _store = store;
62
+ }
@@ -0,0 +1,43 @@
1
+ export type PersonaScope = "system" | "account";
2
+ export type PersonaRole = "merchant" | "user" | "arbitrator";
3
+ export type Industry = "freelance" | "rental" | "education" | "travel" | "subscription" | "retail";
4
+ export declare const SUPPORTED_INDUSTRIES: Industry[];
5
+ export interface PersonaIdentity {
6
+ region?: string;
7
+ languages?: string[];
8
+ self_description?: string;
9
+ }
10
+ export interface PersonaLayer {
11
+ identity?: PersonaIdentity;
12
+ preferences?: Record<string, unknown>;
13
+ strategy?: string[];
14
+ rules?: string[];
15
+ requirements?: string[];
16
+ spec?: string;
17
+ }
18
+ export type PersonaMutationMode = "merge" | "replace";
19
+ export interface Persona {
20
+ version: number;
21
+ scope: PersonaScope;
22
+ account?: string;
23
+ role: PersonaRole;
24
+ industries: Industry[];
25
+ long_term: PersonaLayer;
26
+ current: PersonaLayer;
27
+ updated_at: number;
28
+ }
29
+ export interface PersonaSource {
30
+ scope: PersonaScope;
31
+ account?: string;
32
+ part: "long_term" | "current";
33
+ }
34
+ export interface EffectivePersona {
35
+ scope: PersonaScope;
36
+ account?: string;
37
+ role: PersonaRole;
38
+ industries: Industry[];
39
+ layer: PersonaLayer;
40
+ sources: PersonaSource[];
41
+ }
42
+ export declare const PERSONA_VERSION = 1;
43
+ export declare const PERSONA_MAX_LINES = 300;
@@ -0,0 +1,5 @@
1
+ export const SUPPORTED_INDUSTRIES = [
2
+ "freelance", "rental", "education", "travel", "subscription", "retail",
3
+ ];
4
+ export const PERSONA_VERSION = 1;
5
+ export const PERSONA_MAX_LINES = 300;
@@ -269,6 +269,11 @@ export declare function handleEvaluateProject(v: ProjectInput): Promise<{
269
269
  evaluationId: string;
270
270
  refreshWarning: string | undefined;
271
271
  graphFallbackWarning: string | undefined;
272
+ } | {
273
+ action: "evaluate_project";
274
+ async_mode: true;
275
+ task_id: string;
276
+ hint: string;
272
277
  }>;
273
278
  export declare function handleSaveEvaluation(v: ProjectInput): Promise<{
274
279
  action: "save_evaluation";