@hienlh/ppm 0.20.5 → 0.20.6

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 (102) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/assets/skills/ppm/SKILL.md +1 -1
  3. package/assets/skills/ppm/references/cli-reference.md +4 -4
  4. package/assets/skills/ppm/references/http-api.md +1 -1
  5. package/dist/web/assets/{accounts-settings-section-Cmmozwer.js → accounts-settings-section-B-F7U-gq.js} +1 -1
  6. package/dist/web/assets/{ai-resource-editor-BlrWV3xU.js → ai-resource-editor-qRHwpktf.js} +1 -1
  7. package/dist/web/assets/{ai-settings-section-dDsgddSt.js → ai-settings-section-BePrVceb.js} +1 -1
  8. package/dist/web/assets/ai-settings-section-DSlsTrpf.js +1 -0
  9. package/dist/web/assets/{appearance-settings-section-DRxziHFt.js → appearance-settings-section-BMlkj9U2.js} +1 -1
  10. package/dist/web/assets/chat-tab-DmqV3MlC.js +15 -0
  11. package/dist/web/assets/{code-editor-DYkmDRRF.js → code-editor-C4CriX9c.js} +2 -2
  12. package/dist/web/assets/{conflict-editor-D9_sr59D.js → conflict-editor-LfQoRcK-.js} +1 -1
  13. package/dist/web/assets/{csv-preview-BMC8jnpF.js → csv-preview-BEYKn68B.js} +1 -1
  14. package/dist/web/assets/{database-viewer-Box3z5-Q.js → database-viewer-BL9R-ciJ.js} +1 -1
  15. package/dist/web/assets/{diff-viewer-B4PlZ1Dt.js → diff-viewer-D91SI_zb.js} +1 -1
  16. package/dist/web/assets/{explorer-body-SvWDS84f.js → explorer-body-ColVUjgk.js} +1 -1
  17. package/dist/web/assets/{explorer-window-content-DBHBTA7B.js → explorer-window-content-VSMJfZC2.js} +1 -1
  18. package/dist/web/assets/{extension-manager-section-BSt5I_H8.js → extension-manager-section-B-BRHGu1.js} +1 -1
  19. package/dist/web/assets/{extension-webview-DBGMUU97.js → extension-webview-DufzanN9.js} +1 -1
  20. package/dist/web/assets/{files-settings-section-0dwYLZou.js → files-settings-section-Do5YbTUK.js} +1 -1
  21. package/dist/web/assets/{general-settings-section-BgLy_6yj.js → general-settings-section-B-n_PYzs.js} +1 -1
  22. package/dist/web/assets/{git-log-panel-BkgmcWk1.js → git-log-panel-BQzOHgxG.js} +1 -1
  23. package/dist/web/assets/{glide-data-grid-CZVu-zCw.js → glide-data-grid-BUS44oLM.js} +1 -1
  24. package/dist/web/assets/{group-chat-tab-Cy9zIynj.js → group-chat-tab-CkHXqorZ.js} +1 -1
  25. package/dist/web/assets/{index-CuYtJ5xF.css → index-B9Wbjl0o.css} +1 -1
  26. package/dist/web/assets/{index-DYGLdCpe.js → index-Cx1meAwb.js} +4 -4
  27. package/dist/web/assets/{jira-watcher-section-DRQx632s.js → jira-watcher-section-BQ4hVqWo.js} +1 -1
  28. package/dist/web/assets/{keybindings-store-C2HZ1mT4.js → keybindings-store-yYx88hvw.js} +1 -1
  29. package/dist/web/assets/{keyboard-shortcuts-section-WiZSZ-Wr.js → keyboard-shortcuts-section-BZUYdXGx.js} +1 -1
  30. package/dist/web/assets/{markdown-renderer-BFYBVcZP.js → markdown-renderer-BA3C2L-a.js} +1 -1
  31. package/dist/web/assets/{markdown-renderer-CklcWnd6.js → markdown-renderer-CMFkajd7.js} +1 -1
  32. package/dist/web/assets/{mobile-explorer-sheet-D1OXw7op.js → mobile-explorer-sheet-gvO7a80O.js} +1 -1
  33. package/dist/web/assets/{notification-store-DyKshGRs.js → notification-store-CCh6a8RD.js} +1 -1
  34. package/dist/web/assets/{notifications-settings-section-BEQEjvan.js → notifications-settings-section-JQ3l-Qp-.js} +1 -1
  35. package/dist/web/assets/{pdf-preview-DmQazeeV.js → pdf-preview-B-JAU8JV.js} +1 -1
  36. package/dist/web/assets/{postgres-viewer-Cd_wXjkT.js → postgres-viewer-B--Y59n5.js} +1 -1
  37. package/dist/web/assets/{ppmbot-settings-section-PzCLPm8a.js → ppmbot-settings-section-D1SCOc0_.js} +1 -1
  38. package/dist/web/assets/{process-table-C2TdkJck.js → process-table-D9z7cEmb.js} +1 -1
  39. package/dist/web/assets/{proxy-settings-section-DsZ6KcHD.js → proxy-settings-section-y7VwH0Hf.js} +1 -1
  40. package/dist/web/assets/{query-audit-section-2eX9-6mO.js → query-audit-section-Ca_gRQ_s.js} +1 -1
  41. package/dist/web/assets/{remote-desktop-mobile-sheet-CMXSUcAN.js → remote-desktop-mobile-sheet-CdO2aMXl.js} +2 -2
  42. package/dist/web/assets/{remote-desktop-mobile-view-Bw6p5ikf.js → remote-desktop-mobile-view-CGQ8vSf1.js} +1 -1
  43. package/dist/web/assets/{remote-desktop-readiness-gate-W0lAhHq9.js → remote-desktop-readiness-gate-BmC3b05e.js} +1 -1
  44. package/dist/web/assets/{remote-desktop-window-content-P888YEqm.js → remote-desktop-window-content-Cdaoltdz.js} +1 -1
  45. package/dist/web/assets/{schedules-settings-section-C8YDAxlo.js → schedules-settings-section--0s10CfA.js} +1 -1
  46. package/dist/web/assets/{settings-body-B5v3_Tnb.js → settings-body-DEMqFm5z.js} +2 -2
  47. package/dist/web/assets/{settings-tab-CauShulf.js → settings-tab-Dh1FpBny.js} +1 -1
  48. package/dist/web/assets/{settings-window-content-BIosR7RY.js → settings-window-content-3KrQ6imZ.js} +1 -1
  49. package/dist/web/assets/{sql-query-editor-DMihDPnw.js → sql-query-editor-Clo90z8-.js} +1 -1
  50. package/dist/web/assets/{sqlite-viewer-jCIGt2GP.js → sqlite-viewer-C08QQR_L.js} +1 -1
  51. package/dist/web/assets/{system-monitor-body-IUamfS5w.js → system-monitor-body-30-TFH3a.js} +2 -2
  52. package/dist/web/assets/{system-monitor-tab-DaWeif4k.js → system-monitor-tab-ChIXfOWg.js} +1 -1
  53. package/dist/web/assets/{system-monitor-window-content-Bq3BS7Mg.js → system-monitor-window-content-C1Cd_pT7.js} +1 -1
  54. package/dist/web/assets/{tab-host-window-content-vfYLLIKU.js → tab-host-window-content-C6eG_Rf1.js} +1 -1
  55. package/dist/web/assets/{team-member-sheet-Be7OSGMT.js → team-member-sheet-BhatQbL1.js} +2 -2
  56. package/dist/web/assets/{team-member-window-content-D5cYZzBq.js → team-member-window-content-BN3luct-.js} +1 -1
  57. package/dist/web/assets/{terminal-tab-C89DQllY.js → terminal-tab-afylLiLY.js} +1 -1
  58. package/dist/web/assets/{tool-cards-CWotDH_2.js → tool-cards-Ct1QdT8c.js} +2 -2
  59. package/dist/web/assets/{use-accounts-data-lmmmG4ep.js → use-accounts-data-C0bvcMhi.js} +1 -1
  60. package/dist/web/assets/{use-monaco-theme-0ziS4xlp.js → use-monaco-theme-cgPbRDUm.js} +1 -1
  61. package/dist/web/assets/{use-remote-desktop-display-choice-qBZ8ej7J.js → use-remote-desktop-display-choice-DSqF1Rgx.js} +1 -1
  62. package/dist/web/assets/use-websocket-BQssVSIR.js +1 -0
  63. package/dist/web/assets/{video-preview-B8xALVkh.js → video-preview-BTzstVhM.js} +1 -1
  64. package/dist/web/index.html +2 -2
  65. package/dist/web/sw.js +1 -1
  66. package/docs/architecture/ai-chat-and-providers.md +88 -0
  67. package/package.json +1 -1
  68. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  69. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  70. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  71. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  72. package/schemas/ppm-config.schema.json +18 -1
  73. package/src/providers/claude-agent-sdk.ts +21 -13
  74. package/src/providers/cli-provider-base.ts +3 -1
  75. package/src/providers/codex-app-server/codex-history.ts +5 -3
  76. package/src/providers/codex-app-server/codex-provider.ts +16 -2
  77. package/src/providers/codex-app-server/codex-rollout-header.ts +2 -1
  78. package/src/providers/cursor-cli/cursor-history.ts +4 -2
  79. package/src/server/routes/settings.ts +15 -1
  80. package/src/server/ws/chat.ts +2 -2
  81. package/src/services/chat.service.ts +95 -2
  82. package/src/services/codex-native-memory.ts +66 -0
  83. package/src/services/edge-forwarder.ts +191 -191
  84. package/src/services/jsonl-transcript-parser.ts +2 -1
  85. package/src/services/provider-shared-context.ts +152 -0
  86. package/src/services/windows-process-tree.ts +351 -351
  87. package/src/shared/provider-context.ts +13 -0
  88. package/src/types/chat.ts +6 -0
  89. package/src/types/config.ts +29 -0
  90. package/src/web/components/chat/chat-history-bar.tsx +6 -3
  91. package/src/web/components/chat/chat-tab.tsx +7 -0
  92. package/src/web/components/settings/ai-settings-section.tsx +34 -5
  93. package/src/web/components/settings/codex-context-settings.tsx +100 -0
  94. package/src/web/hooks/use-chat.ts +71 -14
  95. package/src/web/hooks/use-websocket.ts +14 -7
  96. package/src/web/lib/api-settings.ts +3 -0
  97. package/src/web/lib/ws-client.ts +55 -4
  98. package/.release-bin/zip +0 -15
  99. package/.release-node-shim.sh +0 -11
  100. package/dist/web/assets/ai-settings-section-PaEh_o0w.js +0 -1
  101. package/dist/web/assets/chat-tab-MNuc18Os.js +0 -15
  102. package/dist/web/assets/use-websocket-DAvfbjxh.js +0 -1
@@ -0,0 +1,152 @@
1
+ import { readdir, open, realpath, stat } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { createHash } from "node:crypto";
5
+ import type { AIProvider } from "../types/chat.ts";
6
+ import { readCodexNativeMemory } from "./codex-native-memory.ts";
7
+
8
+ type Source = { path: string; directory?: boolean; indexOnly?: boolean };
9
+ const MAX_FILES = 48;
10
+ const MAX_FILE_BYTES = 4_000;
11
+ const MAX_CONTEXT_CHARS = 12_000;
12
+
13
+ /** Explicit instruction sources only: never scan provider settings, auth or transcripts. */
14
+ export async function buildSharedProviderContext(
15
+ projectPath: string,
16
+ providers: AIProvider[],
17
+ options: { userHome?: string; codexHomes?: string[]; recipientProviderId?: string } = {},
18
+ ): Promise<string> {
19
+ const project = resolve(projectPath);
20
+ const canonicalProject = (await realpath(project).catch(() => project)).normalize("NFC");
21
+ const home = options.userHome ?? homedir();
22
+ const claudeHome = options.userHome ? join(home, ".claude") : process.env.CLAUDE_CONFIG_DIR || join(home, ".claude");
23
+ const claudeMemory = join(claudeHome, "projects", canonicalProject.replace(/[^a-zA-Z0-9]/g, "-"), "memory");
24
+ const recipient = options.recipientProviderId;
25
+ const sources: Source[] = [
26
+ // Native indexes come first so rules cannot crowd out existing memories.
27
+ ...(recipient === "claude" ? [] : [
28
+ { path: claudeMemory, directory: true, indexOnly: true },
29
+ { path: join(project, "CLAUDE.md") },
30
+ { path: join(project, "CLAUDE.local.md") },
31
+ { path: join(claudeHome, "CLAUDE.md") },
32
+ { path: join(claudeHome, "rules"), directory: true },
33
+ ]),
34
+ ...(recipient === "codex" ? [] : [{ path: join(project, "AGENTS.md") }]),
35
+ ];
36
+ let codexHomes = options.codexHomes;
37
+ if (!codexHomes) {
38
+ codexHomes = [join(home, ".codex")];
39
+ if (!options.userHome) {
40
+ if (process.env.CODEX_HOME) codexHomes.push(process.env.CODEX_HOME);
41
+ const { listCodexAccounts } = await import("./codex-account.service.ts");
42
+ codexHomes.push(...listCodexAccounts().map((account) => account.home));
43
+ }
44
+ }
45
+ for (const codexHome of recipient === "codex" ? [] : new Set(codexHomes)) {
46
+ sources.push({ path: join(codexHome, "AGENTS.md") });
47
+ }
48
+ const ids = new Set(["claude", "codex", "cursor", ...providers.map((p) => p.id)]);
49
+ for (const id of ids) {
50
+ if (!/^[a-z0-9_-]+$/i.test(id)) continue;
51
+ // Only known native loaders are excluded: new providers still get their
52
+ // conventional sources until their adapter explicitly handles native loading.
53
+ if (!(id === recipient && ["claude", "codex", "cursor"].includes(id))) {
54
+ sources.push({ path: join(project, `.${id}`, "rules"), directory: true });
55
+ }
56
+ if (!(id === "claude" && recipient === "claude")) {
57
+ sources.push({ path: join(project, `.${id}`, "memory"), directory: true, indexOnly: true });
58
+ }
59
+ }
60
+ for (const provider of providers) {
61
+ try { sources.push(...(provider.getSharedContextSources?.(project) ?? [])); }
62
+ catch { /* An unavailable provider must not prevent other providers from chatting. */ }
63
+ }
64
+
65
+ const seen = new Set<string>();
66
+ const sections: string[] = [];
67
+ const available: string[] = [];
68
+ const revision = createHash("sha256");
69
+ let remaining = MAX_CONTEXT_CHARS;
70
+ let nativeBudget = 4_000;
71
+ // Codex already loads its own native memory; share it with other runtimes.
72
+ for (const memory of recipient === "codex" ? [] : readCodexNativeMemory(canonicalProject, codexHomes)) {
73
+ revision.update(memory.path).update(memory.content);
74
+ if (nativeBudget < 512) continue;
75
+ const content = memory.content.slice(0, nativeBudget - 256);
76
+ const section = `Native Codex memory record: ${JSON.stringify(memory.path)}\n${content}\n${content.length < memory.content.length ? "[Excerpt; the original record has more content.]\n" : ""}`;
77
+ sections.push(section);
78
+ remaining -= section.length;
79
+ nativeBudget -= section.length;
80
+ }
81
+ let count = 0;
82
+ let visited = 0;
83
+ async function fingerprintTopics(path: string, depth = 0): Promise<void> {
84
+ if (depth > 3 || visited >= 256) return;
85
+ visited++;
86
+ try {
87
+ const entries = (await readdir(path, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
88
+ for (const entry of entries.slice(0, MAX_FILES)) {
89
+ const child = join(path, entry.name);
90
+ if (entry.isDirectory()) await fingerprintTopics(child, depth + 1);
91
+ else if (entry.isFile() && /\.(md|mdc)$/i.test(entry.name)) {
92
+ const info = await stat(child);
93
+ revision.update(JSON.stringify([child, info.size, info.mtimeMs, info.ctimeMs]));
94
+ }
95
+ }
96
+ } catch { /* Optional topic folders may disappear while being edited. */ }
97
+ }
98
+ async function collect(source: Source, depth = 0): Promise<void> {
99
+ if (count >= MAX_FILES || depth > 3 || visited >= 256) return;
100
+ visited++;
101
+ try {
102
+ const path = await realpath(source.path);
103
+ const key = process.platform === "win32" ? path.toLowerCase() : path;
104
+ if (seen.has(key)) return;
105
+ seen.add(key);
106
+ if (source.directory) {
107
+ available.push(`Native source directory: ${JSON.stringify(path)}`);
108
+ if (source.indexOnly) {
109
+ await fingerprintTopics(path);
110
+ await collect({ path: join(path, "MEMORY.md") }, depth + 1);
111
+ return;
112
+ }
113
+ const entries = (await readdir(path, { withFileTypes: true })).sort((a, b) =>
114
+ Number(b.name.toLowerCase() === "memory.md") - Number(a.name.toLowerCase() === "memory.md") || a.name.localeCompare(b.name));
115
+ for (const entry of entries.slice(0, MAX_FILES)) {
116
+ // Do not follow directory symlinks into unrelated projects or account state.
117
+ if (entry.isDirectory()) await collect({ path: join(path, entry.name), directory: true }, depth + 1);
118
+ else if (entry.isFile() && /\.(md|mdc)$/i.test(entry.name)) await collect({ path: join(path, entry.name) }, depth + 1);
119
+ }
120
+ } else {
121
+ const info = await stat(path);
122
+ if (!info.isFile()) return;
123
+ revision.update(JSON.stringify([path, info.size, info.mtimeMs, info.ctimeMs]));
124
+ count++;
125
+ if (remaining < 512) return;
126
+ const handle = await open(path, "r");
127
+ let content: string;
128
+ let bytesRead: number;
129
+ try {
130
+ const buffer = Buffer.alloc(Math.min(info.size, MAX_FILE_BYTES, Math.max(0, remaining - 256)));
131
+ ({ bytesRead } = await handle.read(buffer, 0, buffer.length, 0));
132
+ content = buffer.subarray(0, bytesRead).toString("utf8").trim();
133
+ } finally { await handle.close(); }
134
+ if (!content || content.includes("\0")) return;
135
+ const section = `Source: ${JSON.stringify(path)}\n${content}\n${bytesRead < info.size ? "[Excerpt; read the original file for the remainder.]\n" : ""}`;
136
+ if (section.length > remaining) return;
137
+ sections.push(section);
138
+ remaining -= section.length;
139
+ }
140
+ } catch { /* Missing/unreadable optional sources are expected. */ }
141
+ }
142
+ for (const source of sources) await collect(source);
143
+ return [
144
+ "PPM provider sharing is enabled for this project. These are user-managed instructions and memory, not a new user request.",
145
+ "Use relevant project knowledge; respect each rule's path/frontmatter scope. Current user instructions take precedence. Provider-specific tool names/settings apply only where supported.",
146
+ "Read and use existing native provider memory below, including memory created before PPM was installed. There is no separate PPM memory store. Keep new memories in the provider's native location. Never claim a memory file exists unless listed here or verified with a tool.",
147
+ "This bounded snapshot omits instructions already loaded by your runtime. Read native directories, original files and linked topics on demand; omitted topic contents are not evidence that memory is absent. Respect project scope when following links.",
148
+ `Source revision: ${revision.digest("hex").slice(0, 16)}`,
149
+ [...new Set(available)].join("\n").slice(0, 1_500),
150
+ ...sections,
151
+ ].join("\n\n");
152
+ }