@rubytech/create-maxy-code 0.1.75 → 0.1.80

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 (127) hide show
  1. package/dist/__tests__/plugin-install.test.js +2 -2
  2. package/dist/lib/plugin-install.js +1 -1
  3. package/package.json +1 -1
  4. package/payload/platform/config/brand.json +1 -1
  5. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  6. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  7. package/payload/platform/package.json +1 -1
  8. package/payload/platform/plugins/.claude-plugin/marketplace.json +101 -1
  9. package/payload/platform/plugins/admin/mcp/dist/index.js +1 -1
  10. package/payload/platform/plugins/admin/skills/commitment-followthrough/SKILL.md +1 -1
  11. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +1 -1
  12. package/payload/platform/plugins/business-assistant/PLUGIN.md +1 -1
  13. package/payload/platform/plugins/business-assistant/references/task-management.md +13 -13
  14. package/payload/platform/plugins/docs/references/admin-session.md +7 -6
  15. package/payload/platform/plugins/docs/references/internals.md +2 -2
  16. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  17. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts +2 -0
  18. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts.map +1 -0
  19. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js +57 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js.map +1 -0
  21. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts.map +1 -1
  22. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +9 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -1
  24. package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
  25. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -2
  26. package/payload/platform/plugins/projects/PLUGIN.md +3 -3
  27. package/payload/platform/plugins/projects/references/sprint.md +2 -2
  28. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +2 -2
  29. package/payload/platform/plugins/tasks/.claude-plugin/plugin.json +1 -1
  30. package/payload/platform/plugins/work/.claude-plugin/plugin.json +17 -0
  31. package/payload/platform/plugins/{tasks → work}/.mcp.json +2 -2
  32. package/payload/platform/plugins/work/PLUGIN.md +120 -0
  33. package/payload/platform/plugins/work/mcp/dist/index.d.ts +2 -0
  34. package/payload/platform/plugins/work/mcp/dist/index.d.ts.map +1 -0
  35. package/payload/platform/plugins/work/mcp/dist/index.js +543 -0
  36. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -0
  37. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts +7 -0
  38. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts.map +1 -0
  39. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js +24 -0
  40. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js.map +1 -0
  41. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts +5 -0
  42. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts.map +1 -0
  43. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js +40 -0
  44. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js.map +1 -0
  45. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts +17 -0
  46. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts.map +1 -0
  47. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js +76 -0
  48. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js.map +1 -0
  49. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts +29 -0
  50. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts.map +1 -0
  51. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +235 -0
  52. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -0
  53. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts +40 -0
  54. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts.map +1 -0
  55. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js +125 -0
  56. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js.map +1 -0
  57. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts +26 -0
  58. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts.map +1 -0
  59. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js +81 -0
  60. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js.map +1 -0
  61. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts +19 -0
  62. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts.map +1 -0
  63. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js +102 -0
  64. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js.map +1 -0
  65. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +20 -0
  66. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -0
  67. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +37 -0
  68. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -0
  69. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts +12 -0
  70. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts.map +1 -0
  71. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js +28 -0
  72. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js.map +1 -0
  73. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts +16 -0
  74. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts.map +1 -0
  75. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js +33 -0
  76. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js.map +1 -0
  77. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts +63 -0
  78. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -0
  79. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +141 -0
  80. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -0
  81. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts +19 -0
  82. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts.map +1 -0
  83. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js +51 -0
  84. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js.map +1 -0
  85. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts +18 -0
  86. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts.map +1 -0
  87. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js +66 -0
  88. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js.map +1 -0
  89. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts +21 -0
  90. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts.map +1 -0
  91. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js +54 -0
  92. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js.map +1 -0
  93. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts +12 -0
  94. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts.map +1 -0
  95. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js +59 -0
  96. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js.map +1 -0
  97. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts +32 -0
  98. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts.map +1 -0
  99. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js +112 -0
  100. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js.map +1 -0
  101. package/payload/platform/plugins/{tasks → work}/mcp/package.json +1 -1
  102. package/payload/platform/scripts/conversation-id-allowlist.txt +4 -4
  103. package/payload/platform/scripts/seed-neo4j.sh +1 -1
  104. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  105. package/payload/platform/services/claude-session-manager/dist/http-server.js +34 -5
  106. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  107. package/payload/platform/services/claude-session-manager/dist/index.js +32 -0
  108. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  109. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +33 -1
  110. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  111. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +202 -39
  112. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  113. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -1
  114. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +10 -4
  115. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -1
  116. package/payload/platform/templates/agents/admin/IDENTITY.md +21 -37
  117. package/payload/platform/templates/specialists/agents/database-operator.md +2 -2
  118. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  119. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  120. package/payload/platform/templates/specialists/agents/project-manager.md +3 -3
  121. package/payload/premium-plugins/real-agent/plugins/leads/PLUGIN.md +1 -1
  122. package/payload/server/{chunk-ITQ55PCQ.js → chunk-TFEIFU7F.js} +1 -1
  123. package/payload/server/{chunk-HZ77KMTV.js → chunk-W33UUYYR.js} +1 -4
  124. package/payload/server/{cloudflare-task-tracker-PZBX7X3D.js → cloudflare-task-tracker-7P355PSD.js} +1 -1
  125. package/payload/server/maxy-edge.js +1 -1
  126. package/payload/server/server.js +50 -18
  127. package/payload/platform/plugins/tasks/PLUGIN.md +0 -120
@@ -0,0 +1,40 @@
1
+ import neo4j from "neo4j-driver";
2
+ import { readFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ let driver = null;
5
+ function readPassword() {
6
+ if (process.env.NEO4J_PASSWORD)
7
+ return process.env.NEO4J_PASSWORD;
8
+ const passwordFile = resolve(process.env.PLATFORM_ROOT ?? resolve(import.meta.dirname, "../../../.."), "config/.neo4j-password");
9
+ try {
10
+ return readFileSync(passwordFile, "utf-8").trim();
11
+ }
12
+ catch {
13
+ throw new Error(`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`);
14
+ }
15
+ }
16
+ export function getDriver() {
17
+ if (!driver) {
18
+ // NEO4J_URI must be explicit. Silent default to:7687 was the
19
+ // vector for the orphan data in Maxy's DB from a realagent install.
20
+ const uri = process.env.NEO4J_URI;
21
+ if (!uri) {
22
+ throw new Error("[tasks] NEO4J_URI unset — refusing to default to bolt://localhost:7687");
23
+ }
24
+ const user = process.env.NEO4J_USER ?? "neo4j";
25
+ const password = readPassword();
26
+ console.error(`[tasks] resolved neo4j_uri=${uri}`);
27
+ driver = neo4j.driver(uri, neo4j.auth.basic(user, password));
28
+ }
29
+ return driver;
30
+ }
31
+ export function getSession() {
32
+ return getDriver().session();
33
+ }
34
+ export async function closeDriver() {
35
+ if (driver) {
36
+ await driver.close();
37
+ driver = null;
38
+ }
39
+ }
40
+ //# sourceMappingURL=neo4j.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neo4j.js","sourceRoot":"","sources":["../../src/lib/neo4j.ts"],"names":[],"mappings":"AAAA,OAAO,KAA0B,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAElE,MAAM,YAAY,GAAG,OAAO,CAC1B,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EACxE,wBAAwB,CACzB,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yCAAyC,YAAY,gCAAgC,CACtF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,6DAA6D;QAC7D,oEAAoE;QACpE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC;QAC/C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;QACnD,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface ProjectCompleteParams {
2
+ projectId: string;
3
+ accountId: string;
4
+ note?: string;
5
+ }
6
+ export interface ProjectCompleteResult {
7
+ projectId: string;
8
+ completedTasks: number;
9
+ totalTasks: number;
10
+ incompleteChildren: Array<{
11
+ taskId: string;
12
+ name: string;
13
+ status: string;
14
+ }>;
15
+ }
16
+ export declare function projectComplete(params: ProjectCompleteParams): Promise<ProjectCompleteResult>;
17
+ //# sourceMappingURL=project-complete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-complete.d.ts","sourceRoot":"","sources":["../../src/tools/project-complete.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwFnG"}
@@ -0,0 +1,76 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { computeEmbedding } from "../lib/embeddings.js";
3
+ export async function projectComplete(params) {
4
+ const { projectId, accountId, note } = params;
5
+ const session = getSession();
6
+ try {
7
+ // Fetch the project and its children
8
+ const projectResult = await session.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
9
+ OPTIONAL MATCH (p)-[:HAS_TASK]->(child:Task)
10
+ RETURN p,
11
+ collect({taskId: child.taskId, name: child.name, status: child.status}) AS children`, { projectId, accountId });
12
+ if (projectResult.records.length === 0) {
13
+ throw new Error(`ProjectNotFound: ${projectId}`);
14
+ }
15
+ const rec = projectResult.records[0];
16
+ const p = rec.get("p").properties;
17
+ const children = rec.get("children")
18
+ .filter((c) => c.taskId !== null);
19
+ const totalTasks = children.length;
20
+ const completedTasks = children.filter((c) => c.status === "completed" || c.status === "cancelled").length;
21
+ const incompleteChildren = children
22
+ .filter((c) => c.status !== "completed" && c.status !== "cancelled")
23
+ .map((c) => ({ taskId: c.taskId, name: c.name, status: c.status }));
24
+ // Build completion note
25
+ const now = new Date().toISOString();
26
+ const timestamp = now.slice(0, 16).replace("T", " ");
27
+ const deferred = incompleteChildren.length;
28
+ const completionNote = `[${timestamp}] [PROJECT:COMPLETE] ${p.name} — ${completedTasks}/${totalTasks} tasks, ${deferred} deferred`;
29
+ const userNote = note ? `\n[${timestamp}] ${note}` : "";
30
+ const currentNotes = p.notes ?? "";
31
+ const newNotes = currentNotes
32
+ ? `${currentNotes}\n${completionNote}${userNote}`
33
+ : `${completionNote}${userNote}`;
34
+ // Re-embed
35
+ const embeddingText = `Project: ${p.name} — ${p.description} tier: ${p.tier} status: completed ${newNotes}`;
36
+ const embedding = await computeEmbedding(embeddingText);
37
+ const setClauses = [
38
+ "p.status = 'completed'",
39
+ "p.phase = 'complete'",
40
+ "p.notes = $notes",
41
+ "p.updatedAt = $updatedAt",
42
+ ];
43
+ const queryParams = {
44
+ projectId,
45
+ accountId,
46
+ notes: newNotes,
47
+ updatedAt: now,
48
+ };
49
+ if (embedding.length > 0) {
50
+ setClauses.push("p.embedding = $embedding");
51
+ queryParams.embedding = embedding;
52
+ }
53
+ await session.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
54
+ SET ${setClauses.join(", ")}`, queryParams);
55
+ console.error(`project-complete: ${projectId} completed, ${completedTasks}/${totalTasks} done, ${deferred} incomplete`);
56
+ return {
57
+ projectId,
58
+ completedTasks,
59
+ totalTasks,
60
+ incompleteChildren,
61
+ };
62
+ }
63
+ catch (err) {
64
+ if (err instanceof Error && err.message.startsWith("ProjectNotFound:")) {
65
+ console.error(`project-complete: failed — ${err.message}`);
66
+ }
67
+ else {
68
+ console.error(`project-complete: failed — ${err instanceof Error ? err.message : String(err)}`);
69
+ }
70
+ throw err;
71
+ }
72
+ finally {
73
+ await session.close();
74
+ }
75
+ }
76
+ //# sourceMappingURL=project-complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-complete.js","sourceRoot":"","sources":["../../src/tools/project-complete.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type CreatedBy } from "../../../../../lib/graph-write/dist/index.js";
2
+ export interface WorkItem {
3
+ name: string;
4
+ description: string;
5
+ priority?: "low" | "normal" | "high" | "urgent";
6
+ dueDate?: string;
7
+ /** Indices of other workItems this item blocks */
8
+ blocks?: number[];
9
+ }
10
+ export interface ProjectCreateParams {
11
+ accountId: string;
12
+ name: string;
13
+ description: string;
14
+ tier: "quick" | "standard" | "full";
15
+ clientRef?: string;
16
+ targetDate?: string;
17
+ dueDate?: string;
18
+ raisedBy?: string;
19
+ affects?: string[];
20
+ workItems?: WorkItem[];
21
+ sessionKey?: string;
22
+ createdBy: CreatedBy;
23
+ }
24
+ export interface ProjectCreateResult {
25
+ projectId: string;
26
+ childTaskIds: string[];
27
+ }
28
+ export declare function projectCreate(params: ProjectCreateParams): Promise<ProjectCreateResult>;
29
+ //# sourceMappingURL=project-create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-create.d.ts","sourceRoot":"","sources":["../../src/tools/project-create.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,8CAA8C,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAkDD,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6O7F"}
@@ -0,0 +1,235 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { getDriver } from "../lib/neo4j.js";
3
+ import { computeEmbedding } from "../lib/embeddings.js";
4
+ import { stampCreatedBy, } from "../../../../../lib/graph-write/dist/index.js";
5
+ /**
6
+ * Validates that blocks references form a DAG (no cycles).
7
+ * Uses Kahn's algorithm (topological sort) on the workItems array.
8
+ * Throws ValidationError if cycles detected or indices out of range.
9
+ */
10
+ function validateBlocks(workItems) {
11
+ const n = workItems.length;
12
+ // Build adjacency list and in-degree array
13
+ const adj = Array.from({ length: n }, () => []);
14
+ const inDegree = new Array(n).fill(0);
15
+ for (let i = 0; i < n; i++) {
16
+ const blocks = workItems[i].blocks;
17
+ if (!blocks)
18
+ continue;
19
+ for (const target of blocks) {
20
+ if (target < 0 || target >= n || !Number.isInteger(target)) {
21
+ throw new Error(`ValidationError: blocks index ${target} out of range (0-${n - 1})`);
22
+ }
23
+ if (target === i) {
24
+ throw new Error(`ValidationError: work item ${i} cannot block itself`);
25
+ }
26
+ // i blocks target → edge from i to target
27
+ adj[i].push(target);
28
+ inDegree[target]++;
29
+ }
30
+ }
31
+ // Kahn's algorithm — process nodes with in-degree 0
32
+ const queue = [];
33
+ for (let i = 0; i < n; i++) {
34
+ if (inDegree[i] === 0)
35
+ queue.push(i);
36
+ }
37
+ let processed = 0;
38
+ while (queue.length > 0) {
39
+ const node = queue.shift();
40
+ processed++;
41
+ for (const neighbor of adj[node]) {
42
+ inDegree[neighbor]--;
43
+ if (inDegree[neighbor] === 0)
44
+ queue.push(neighbor);
45
+ }
46
+ }
47
+ if (processed < n) {
48
+ throw new Error("ValidationError: circular dependency detected in work item blocks");
49
+ }
50
+ }
51
+ export async function projectCreate(params) {
52
+ const { accountId, name, description, tier, clientRef, targetDate, dueDate, raisedBy, affects, workItems = [], sessionKey, createdBy, } = params;
53
+ // --- Validation ---
54
+ if (workItems.length > 50) {
55
+ throw new Error("ValidationError: workItems exceeds maximum of 50");
56
+ }
57
+ if (workItems.length > 0) {
58
+ validateBlocks(workItems);
59
+ }
60
+ // --- Pre-compute embeddings (outside transaction) ---
61
+ const parentText = `Project: ${name} — ${description} tier: ${tier}`;
62
+ const parentEmbedding = await computeEmbedding(parentText);
63
+ const childEmbeddings = [];
64
+ for (const item of workItems) {
65
+ const text = `Task: ${item.name} — ${item.description} status: pending priority: ${item.priority ?? "normal"}`;
66
+ childEmbeddings.push(await computeEmbedding(text));
67
+ }
68
+ // --- Build node properties ---
69
+ const projectId = randomUUID();
70
+ const now = new Date().toISOString();
71
+ const timestamp = now.slice(0, 16).replace("T", " ");
72
+ const startNote = `[${timestamp}] [PROJECT:START] ${name} — ${tier} tier, ${workItems.length} tasks planned`;
73
+ const rawProjectProps = {
74
+ taskId: projectId,
75
+ accountId,
76
+ name,
77
+ description,
78
+ status: "pending",
79
+ priority: "normal",
80
+ tier,
81
+ phase: "planning",
82
+ notes: startNote,
83
+ createdAt: now,
84
+ updatedAt: now,
85
+ };
86
+ if (clientRef)
87
+ rawProjectProps.clientRef = clientRef;
88
+ if (targetDate)
89
+ rawProjectProps.targetDate = targetDate;
90
+ if (dueDate)
91
+ rawProjectProps.dueDate = dueDate;
92
+ if (parentEmbedding.length > 0)
93
+ rawProjectProps.embedding = parentEmbedding;
94
+ // Write doctrine: flatten provenance onto the node
95
+ // so forensic queries (WHERE n.createdByTool = 'project-create') work.
96
+ // project-create inlines the doctrine instead of routing through
97
+ // writeNodeWithEdges because the outer transaction must encompass
98
+ // child-Task and BLOCKS/RAISED_BY/AFFECTS creation — nested
99
+ // executeWrite is not permitted on a session that already has a
100
+ // managed tx open.
101
+ const projectProps = stampCreatedBy(rawProjectProps, createdBy);
102
+ const childIds = [];
103
+ const childPropsList = [];
104
+ for (let i = 0; i < workItems.length; i++) {
105
+ const item = workItems[i];
106
+ const childId = randomUUID();
107
+ childIds.push(childId);
108
+ const rawChildProps = {
109
+ taskId: childId,
110
+ accountId,
111
+ name: item.name,
112
+ description: item.description,
113
+ status: "pending",
114
+ priority: item.priority ?? "normal",
115
+ createdAt: now,
116
+ updatedAt: now,
117
+ };
118
+ if (item.dueDate)
119
+ rawChildProps.dueDate = item.dueDate;
120
+ if (childEmbeddings[i].length > 0)
121
+ rawChildProps.embedding = childEmbeddings[i];
122
+ // Stamp the same provenance on children. Each child has its own
123
+ // adjacency (HAS_TASK back to the Project) so no per-child
124
+ // pre-resolve is needed — the edge is co-created below.
125
+ childPropsList.push(stampCreatedBy(rawChildProps, createdBy));
126
+ }
127
+ // --- Single transaction: create all nodes and relationships ---
128
+ const driver = getDriver();
129
+ const session = driver.session();
130
+ const tx = session.beginTransaction();
131
+ try {
132
+ // Write doctrine pre-validation: resolve every
133
+ // adjacency source in one UNWIND round-trip BEFORE the Project is
134
+ // created. A Project that has no workItems, no raisedBy, no affects,
135
+ // and no admin-session Conversation is noise — reject loudly per
136
+ // doctrine. This mirrors writeNodeWithEdges' pre-check idiom but
137
+ // stays inside the outer tx so child-Task failures still roll the
138
+ // Project back atomically.
139
+ const candidateIds = [];
140
+ if (raisedBy)
141
+ candidateIds.push(raisedBy);
142
+ if (affects && affects.length > 0)
143
+ candidateIds.push(...affects);
144
+ let resolvedConversationId = null;
145
+ if (sessionKey) {
146
+ const convRes = await tx.run(`MATCH (c:Conversation {sessionKey: $sessionKey, accountId: $accountId})
147
+ RETURN elementId(c) AS id LIMIT 1`, { sessionKey, accountId });
148
+ if (convRes.records.length > 0) {
149
+ resolvedConversationId = convRes.records[0].get("id");
150
+ }
151
+ }
152
+ if (candidateIds.length > 0) {
153
+ const check = await tx.run(`UNWIND $ids AS id MATCH (t) WHERE elementId(t) = id RETURN collect(id) AS found`, { ids: candidateIds });
154
+ const found = check.records[0].get("found");
155
+ const missing = candidateIds.filter((id) => !found.includes(id));
156
+ if (missing.length > 0) {
157
+ throw new Error(`TargetNotFound: ${missing.length} of ${candidateIds.length} relationship target(s) did not resolve (elementId mismatch): ${missing.join(", ")}`);
158
+ }
159
+ }
160
+ const hasAdjacency = workItems.length > 0 ||
161
+ !!raisedBy ||
162
+ (affects && affects.length > 0) ||
163
+ !!resolvedConversationId;
164
+ if (!hasAdjacency) {
165
+ throw new Error("Write doctrine violated: project-create requires at least one adjacency — pass workItems (≥1), raisedBy, affects, or invoke inside an admin session with an existing Conversation.");
166
+ }
167
+ // Doctrine-satisfying CREATE: adjacency is guaranteed by the
168
+ // pre-validation above. The Project is linked either via HAS_TASK
169
+ // (children below), RAISED_BY/AFFECTS (explicit params), or PART_OF
170
+ // Conversation (session). Within this single tx, intermediate
171
+ // state is not externally observable, so creating the Project
172
+ // first and edges in subsequent statements is safe — the
173
+ // [graph-health] sweep only sees committed state.
174
+ // See .docs/neo4j.md § Write doctrine.
175
+ await tx.run(`CREATE (p:Project:Task $props)`, { props: projectProps });
176
+ // Link to session if the Conversation was resolved above. MATCH not
177
+ // MERGE — a missing Conversation must not spawn an orphan
178
+ // Conversation just to satisfy PART_OF.
179
+ if (resolvedConversationId) {
180
+ await tx.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
181
+ MATCH (c) WHERE elementId(c) = $conversationId
182
+ CREATE (p)-[:PART_OF]->(c)`, { projectId, accountId, conversationId: resolvedConversationId });
183
+ }
184
+ // Create child :Task nodes and HAS_TASK relationships
185
+ for (const childProps of childPropsList) {
186
+ await tx.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
187
+ CREATE (t:Task $childProps)
188
+ CREATE (p)-[:HAS_TASK]->(t)`, { projectId, accountId, childProps });
189
+ }
190
+ // Create BLOCKS relationships between children
191
+ for (let i = 0; i < workItems.length; i++) {
192
+ const blocks = workItems[i].blocks;
193
+ if (!blocks)
194
+ continue;
195
+ for (const target of blocks) {
196
+ await tx.run(`MATCH (blocker:Task {taskId: $blockerId, accountId: $accountId})
197
+ MATCH (blocked:Task {taskId: $blockedId, accountId: $accountId})
198
+ CREATE (blocker)-[:BLOCKS]->(blocked)`, { blockerId: childIds[i], blockedId: childIds[target], accountId });
199
+ }
200
+ }
201
+ // Create RAISED_BY relationship
202
+ if (raisedBy) {
203
+ const result = await tx.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
204
+ MATCH (person) WHERE elementId(person) = $raisedBy
205
+ CREATE (p)-[:RAISED_BY]->(person)
206
+ RETURN person`, { projectId, accountId, raisedBy });
207
+ if (result.records.length === 0) {
208
+ throw new Error(`TargetNotFound: raisedBy person not found (${raisedBy})`);
209
+ }
210
+ }
211
+ // Create AFFECTS relationships
212
+ if (affects && affects.length > 0) {
213
+ for (const entityId of affects) {
214
+ const result = await tx.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
215
+ MATCH (e) WHERE elementId(e) = $entityId
216
+ CREATE (p)-[:AFFECTS]->(e)
217
+ RETURN e`, { projectId, accountId, entityId });
218
+ if (result.records.length === 0) {
219
+ throw new Error(`TargetNotFound: affects entity not found (${entityId})`);
220
+ }
221
+ }
222
+ }
223
+ await tx.commit();
224
+ }
225
+ catch (err) {
226
+ await tx.rollback();
227
+ throw err;
228
+ }
229
+ finally {
230
+ await session.close();
231
+ }
232
+ console.error(`project-create: created ${projectId} with ${childIds.length} children, tier=${tier}`);
233
+ return { projectId, childTaskIds: childIds };
234
+ }
235
+ //# sourceMappingURL=project-create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-create.js","sourceRoot":"","sources":["../../src/tools/project-create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export interface ChildTaskSummary {
2
+ taskId: string;
3
+ name: string;
4
+ status: string;
5
+ priority: string;
6
+ dueDate?: string;
7
+ blockedBy: string[];
8
+ }
9
+ export interface ProjectHealth {
10
+ signal: "green" | "amber" | "red" | "grey";
11
+ totalTasks: number;
12
+ completedTasks: number;
13
+ overdueTasks: number;
14
+ blockedTasks: number;
15
+ daysSinceLastProgress: number | null;
16
+ }
17
+ export interface ProjectDetail {
18
+ projectId: string;
19
+ name: string;
20
+ description: string;
21
+ tier: string;
22
+ phase: string;
23
+ status: string;
24
+ clientRef?: string;
25
+ targetDate?: string;
26
+ dueDate?: string;
27
+ notes?: string;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ health: ProjectHealth;
31
+ children: ChildTaskSummary[];
32
+ relationships: Array<{
33
+ type: string;
34
+ targetLabel: string;
35
+ targetId: string;
36
+ targetName?: string;
37
+ }>;
38
+ }
39
+ export declare function projectGet(projectId: string, accountId: string): Promise<ProjectDetail>;
40
+ //# sourceMappingURL=project-get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-get.d.ts","sourceRoot":"","sources":["../../src/tools/project-get.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0I7F"}
@@ -0,0 +1,125 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ export async function projectGet(projectId, accountId) {
3
+ const session = getSession();
4
+ try {
5
+ // Fetch the project node (must have :Project label)
6
+ const projectResult = await session.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId}) RETURN p`, { projectId, accountId });
7
+ if (projectResult.records.length === 0) {
8
+ throw new Error(`ProjectNotFound: ${projectId}`);
9
+ }
10
+ const p = projectResult.records[0].get("p").properties;
11
+ // Fetch children with their blockers
12
+ const childrenResult = await session.run(`MATCH (proj:Project {taskId: $projectId, accountId: $accountId})-[:HAS_TASK]->(child:Task)
13
+ OPTIONAL MATCH (blocker:Task)-[:BLOCKS]->(child)
14
+ WHERE blocker.status IN ['pending', 'active']
15
+ RETURN child,
16
+ collect(DISTINCT blocker.taskId) AS blockedByIds
17
+ ORDER BY
18
+ CASE child.priority
19
+ WHEN 'urgent' THEN 0
20
+ WHEN 'high' THEN 1
21
+ WHEN 'normal' THEN 2
22
+ WHEN 'low' THEN 3
23
+ ELSE 4
24
+ END,
25
+ child.createdAt`, { projectId, accountId });
26
+ const children = childrenResult.records.map((rec) => {
27
+ const c = rec.get("child").properties;
28
+ const blockedByIds = rec.get("blockedByIds").filter((id) => id !== null);
29
+ const child = {
30
+ taskId: c.taskId,
31
+ name: c.name,
32
+ status: c.status,
33
+ priority: c.priority,
34
+ blockedBy: blockedByIds,
35
+ };
36
+ if (c.dueDate)
37
+ child.dueDate = c.dueDate;
38
+ return child;
39
+ });
40
+ // Compute health
41
+ const totalTasks = children.length;
42
+ const completedTasks = children.filter((c) => c.status === "completed").length;
43
+ const overdueTasks = children.filter((c) => {
44
+ if (!c.dueDate || c.status === "completed")
45
+ return false;
46
+ return new Date(c.dueDate) < new Date();
47
+ }).length;
48
+ const blockedTasks = children.filter((c) => c.blockedBy.length > 0).length;
49
+ let daysSinceLastProgress = null;
50
+ const completedChildren = children.filter((c) => c.status === "completed");
51
+ if (completedChildren.length > 0) {
52
+ // Approximate: use project's updatedAt as proxy for last progress
53
+ // (full computation would need child updatedAt, not returned in this query)
54
+ daysSinceLastProgress = null;
55
+ }
56
+ let signal = "green";
57
+ if (totalTasks === 0) {
58
+ signal = "grey";
59
+ }
60
+ else if (overdueTasks > 1 || (daysSinceLastProgress !== null && daysSinceLastProgress >= 7)) {
61
+ signal = "red";
62
+ }
63
+ else if (overdueTasks > 0 || blockedTasks > 0) {
64
+ signal = "amber";
65
+ }
66
+ const health = {
67
+ signal,
68
+ totalTasks,
69
+ completedTasks,
70
+ overdueTasks,
71
+ blockedTasks,
72
+ daysSinceLastProgress,
73
+ };
74
+ // Fetch non-HAS_TASK relationships (RAISED_BY, AFFECTS, PART_OF)
75
+ const relResult = await session.run(`MATCH (proj:Project {taskId: $projectId, accountId: $accountId})-[r]->(target)
76
+ WHERE type(r) <> 'HAS_TASK'
77
+ RETURN type(r) AS relType, labels(target) AS targetLabels, elementId(target) AS targetId,
78
+ target.name AS targetName, target.givenName AS targetGivenName`, { projectId, accountId });
79
+ const relationships = relResult.records.map((rec) => {
80
+ const targetLabels = rec.get("targetLabels");
81
+ const targetLabel = targetLabels[0] ?? "Unknown";
82
+ const targetId = rec.get("targetId");
83
+ const targetName = rec.get("targetName") ??
84
+ rec.get("targetGivenName") ??
85
+ targetId;
86
+ return { type: rec.get("relType"), targetLabel, targetId, targetName };
87
+ });
88
+ const detail = {
89
+ projectId: p.taskId,
90
+ name: p.name,
91
+ description: p.description,
92
+ tier: p.tier,
93
+ phase: p.phase,
94
+ status: p.status,
95
+ createdAt: p.createdAt,
96
+ updatedAt: p.updatedAt,
97
+ health,
98
+ children,
99
+ relationships,
100
+ };
101
+ if (p.clientRef)
102
+ detail.clientRef = p.clientRef;
103
+ if (p.targetDate)
104
+ detail.targetDate = p.targetDate;
105
+ if (p.dueDate)
106
+ detail.dueDate = p.dueDate;
107
+ if (p.notes)
108
+ detail.notes = p.notes;
109
+ console.error(`project-get: returned ${projectId} with ${children.length} children`);
110
+ return detail;
111
+ }
112
+ catch (err) {
113
+ if (err instanceof Error && err.message.startsWith("ProjectNotFound:")) {
114
+ console.error(`project-get: failed — ${err.message}`);
115
+ }
116
+ else {
117
+ console.error(`project-get: failed — ${err instanceof Error ? err.message : String(err)}`);
118
+ }
119
+ throw err;
120
+ }
121
+ finally {
122
+ await session.close();
123
+ }
124
+ }
125
+ //# sourceMappingURL=project-get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-get.js","sourceRoot":"","sources":["../../src/tools/project-get.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface ProjectHealth {
2
+ signal: "green" | "amber" | "red" | "grey";
3
+ totalTasks: number;
4
+ completedTasks: number;
5
+ overdueTasks: number;
6
+ blockedTasks: number;
7
+ daysSinceLastProgress: number | null;
8
+ }
9
+ export interface ProjectSummary {
10
+ projectId: string;
11
+ name: string;
12
+ tier: string;
13
+ phase: string;
14
+ status: string;
15
+ clientRef?: string;
16
+ targetDate?: string;
17
+ health: ProjectHealth;
18
+ nextAction?: string;
19
+ updatedAt: string;
20
+ }
21
+ export declare function projectList(params: {
22
+ accountId: string;
23
+ status?: string;
24
+ limit?: number;
25
+ }): Promise<ProjectSummary[]>;
26
+ //# sourceMappingURL=project-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-list.d.ts","sourceRoot":"","sources":["../../src/tools/project-list.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD,wBAAsB,WAAW,CAAC,MAAM,EAAE;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAsE5B"}