(source: string)
| 60 | } |
| 61 | |
| 62 | async install(source: string): Promise<PluginRecord> { |
| 63 | const resolved = resolveInstallSource(source); |
| 64 | |
| 65 | let normalizedRoot: string; |
| 66 | let originalSource: string; |
| 67 | let sourceType: PluginSource; |
| 68 | let parsed: ParsedManifestResult; |
| 69 | let id: string; |
| 70 | let github: PluginGithubMetadata | undefined; |
| 71 | |
| 72 | if (resolved.kind === 'local-path') { |
| 73 | const sourceRoot = await normalizeInstallRoot(resolved.path); |
| 74 | originalSource = resolved.path; |
| 75 | sourceType = 'local-path'; |
| 76 | parsed = await parseManifest(sourceRoot); |
| 77 | if (parsed.manifest === undefined) { |
| 78 | const msg = parsed.diagnostics.find((d) => d.severity === 'error')?.message ?? 'no manifest'; |
| 79 | throw new Error(`Cannot install plugin at ${sourceRoot}: ${msg}`); |
| 80 | } |
| 81 | id = normalizePluginId(parsed.manifest.name); |
| 82 | normalizedRoot = await copyPluginToManagedRoot(this.kimiHomeDir, id, sourceRoot); |
| 83 | parsed = await parseManifest(normalizedRoot); |
| 84 | } else { |
| 85 | let zipUrl: string; |
| 86 | if (resolved.kind === 'github') { |
| 87 | const githubResolution = await resolveGithubSource(resolved); |
| 88 | zipUrl = githubResolution.tarballUrl; |
| 89 | originalSource = source.trim(); |
| 90 | sourceType = 'github'; |
| 91 | github = { |
| 92 | owner: resolved.owner, |
| 93 | repo: resolved.repo, |
| 94 | ref: githubResolution.ref, |
| 95 | }; |
| 96 | } else { |
| 97 | zipUrl = resolved.path; |
| 98 | originalSource = resolved.path; |
| 99 | sourceType = 'zip-url'; |
| 100 | } |
| 101 | const buffer = await downloadZip(zipUrl); |
| 102 | const tmpDir = await mkdtemp(path.join(tmpdir(), 'kimi-plugin-zip-')); |
| 103 | try { |
| 104 | const detectedRoot = await extractZip(buffer, tmpDir); |
| 105 | parsed = await parseManifest(detectedRoot); |
| 106 | if (parsed.manifest === undefined) { |
| 107 | const msg = parsed.diagnostics.find((d) => d.severity === 'error')?.message ?? 'no manifest'; |
| 108 | throw new Error(`Cannot install plugin from ${originalSource}: ${msg}`); |
| 109 | } |
| 110 | id = normalizePluginId(parsed.manifest.name); |
| 111 | normalizedRoot = await copyPluginToManagedRoot(this.kimiHomeDir, id, detectedRoot); |
| 112 | parsed = await parseManifest(normalizedRoot); |
| 113 | } finally { |
| 114 | await rm(tmpDir, { recursive: true, force: true }); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | if (parsed.manifest === undefined) { |
| 119 | const msg = parsed.diagnostics.find((d) => d.severity === 'error')?.message ?? 'no manifest'; |
nothing calls this directly
no test coverage detected