@clubnet/seedclub 0.2.39 → 0.2.41

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 (43) hide show
  1. package/assets/extensions/seedclub/commands/clip-status.ts +1 -1
  2. package/assets/extensions/seedclub/commands/seedclub.ts +1 -1
  3. package/assets/extensions/seedclub/commands/transcript-export.ts +1 -1
  4. package/assets/extensions/seedclub/commands/transcript-intent.ts +1 -1
  5. package/assets/extensions/seedclub/commands/transcripts.ts +1 -1
  6. package/assets/extensions/seedclub/index.ts +3 -3
  7. package/assets/extensions/seedclub/memory.ts +13 -2
  8. package/assets/extensions/seedclub/tool-utils.ts +1 -1
  9. package/assets/extensions/seedclub/tools/crm.ts +2 -2
  10. package/assets/extensions/seedclub/tools/media.ts +2 -2
  11. package/assets/extensions/seedclub/tools/meetings.ts +2 -2
  12. package/assets/extensions/seedclub/tools/{deal-sourcing.ts → opportunity-research.ts} +31 -29
  13. package/assets/extensions/seedclub/tools/utility.ts +1 -1
  14. package/assets/extensions/seedclub/tools/web.ts +1 -1
  15. package/assets/extensions/seedclub/ui-copy.ts +2 -0
  16. package/assets/theme/dark.json +1 -1
  17. package/assets/theme/light.json +1 -1
  18. package/package.json +2 -2
  19. package/packages/seedclub-runtime/README.md +1 -1
  20. package/packages/seedclub-runtime/pi-contract-baseline.json +1 -1
  21. package/packages/seedclub-runtime/src/contract.test.mjs +1 -1
  22. package/packages/seedclub-runtime/src/index.mjs +3 -3
  23. package/packages/seedclub-runtime/src/workspace-deps.mjs +4 -4
  24. package/packages/seedclub-tui/src/app/interactive-mode.mjs +43 -5
  25. package/packages/seedclub-tui/src/index.mjs +1 -1
  26. package/packages/seedclub-tui/src/vendor/coding-agent/README.md +2 -2
  27. package/packages/seedclub-tui/src/vendor/coding-agent/core/keybindings.js +1 -1
  28. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/assistant-message.js +1 -1
  29. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/bordered-loader.js +1 -1
  30. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/custom-editor.js +1 -1
  31. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-editor.js +1 -1
  32. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-input.js +1 -1
  33. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-selector.js +1 -1
  34. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/footer.js +1 -1
  35. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/login-dialog.js +1 -1
  36. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/oauth-selector.js +1 -1
  37. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/tool-execution.js +1 -1
  38. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/user-message.js +1 -1
  39. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/visual-truncate.js +1 -1
  40. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/dark.json +1 -1
  41. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/light.json +1 -1
  42. package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/theme.js +1 -1
  43. package/postinstall.js +1 -1
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { api } from "../api-client.js";
3
3
  import { getSessionContext } from "../tools/utility.js";
4
4
 
@@ -2,7 +2,7 @@
2
2
  * /seedclub — the main menu.
3
3
  */
4
4
 
5
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
6
  import {
7
7
  clearStoredBases,
8
8
  getApiBase,
@@ -1,7 +1,7 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { join, resolve } from "node:path";
4
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
4
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
5
  import { api } from "../api-client.js";
6
6
  import { getSessionContext } from "../tools/utility.js";
7
7
  import { setWorkingMessage } from "../tool-utils.js";
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
4
4
  import { makeProgressCallRenderer, makeProgressResultRenderer } from "../tool-utils.js";
5
5
  import { exportTranscripts } from "./transcript-export.js";
@@ -2,7 +2,7 @@
2
2
  * /transcripts command — explicit slash-command wrapper around the shared transcript export flow.
3
3
  */
4
4
 
5
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
6
  import { exportTranscripts } from "./transcript-export.js";
7
7
 
8
8
  const DEFAULT_LIMIT = 10;
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { randomBytes } from "node:crypto";
9
9
  import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
10
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
11
  import { api, clearCredentials, setCachedToken } from "./api-client.js";
12
12
  import { getApiBase, getAuthBase, getStoredToken, storeToken } from "./auth.js";
13
13
  import { renderCallbackPage } from "./browser-pages.js";
@@ -32,7 +32,7 @@ import {
32
32
  } from "./recent-entities.js";
33
33
  import { getCurrentUser, getSessionContext, registerUtilityTools } from "./tools/utility.js";
34
34
  import { registerCrmTools } from "./tools/crm.js";
35
- import { registerDealSourcingTools } from "./tools/deal-sourcing.js";
35
+ import { registerOpportunityResearchTools } from "./tools/opportunity-research.js";
36
36
  import { registerMeetingTools } from "./tools/meetings.js";
37
37
  import { registerMediaTools } from "./tools/media.js";
38
38
  import { registerWebTools } from "./tools/web.js";
@@ -209,7 +209,7 @@ export default function (pi: ExtensionAPI) {
209
209
  // Tools
210
210
  registerUtilityTools(pi);
211
211
  registerCrmTools(pi);
212
- registerDealSourcingTools(pi);
212
+ registerOpportunityResearchTools(pi);
213
213
  registerMeetingTools(pi);
214
214
  registerMediaTools(pi);
215
215
  registerWebTools(pi);
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { execFileSync } from "node:child_process";
3
3
  import { createHash } from "node:crypto";
4
4
  import { readFile, writeFile } from "node:fs/promises";
@@ -27,6 +27,12 @@ const MEMORY_WRITE_TIMEOUT_MS = 20000;
27
27
  const MEMORY_SESSION_STRATEGY = String(process.env.SEEDCLUB_MEMORY_SESSION_STRATEGY ?? "repo").toLowerCase();
28
28
  const MEMORY_DEFAULT_ENABLED_KEY = "seedclubMemoryDefaultEnabled";
29
29
  const MEMORY_DEFAULT_APPLIED_KEY = "seedclubMemoryDefaultApplied";
30
+ const MEMORY_COMMAND_COMPLETIONS = [
31
+ { value: "status", label: "status", description: "Show memory status" },
32
+ { value: "recent", label: "recent", description: "Show recent memory" },
33
+ { value: "on", label: "on", description: "Turn memory on" },
34
+ { value: "off", label: "off", description: "Turn memory off" },
35
+ ];
30
36
 
31
37
  type MemoryStatus = {
32
38
  available: boolean;
@@ -318,9 +324,14 @@ export function registerMemory(pi: ExtensionAPI): MemoryController {
318
324
 
319
325
  pi.registerCommand("memory", {
320
326
  description: "Show Seed Club memory status, recent memory, or turn memory on/off (`status`, `recent`, `on`, `off`)",
327
+ getArgumentCompletions: (argumentPrefix) => {
328
+ const prefix = argumentPrefix.trim().toLowerCase();
329
+ const completions = MEMORY_COMMAND_COMPLETIONS.filter((item) => item.value.startsWith(prefix));
330
+ return completions.length ? completions : null;
331
+ },
321
332
  handler: async (args, ctx) => {
322
333
  const trimmedArgs = args.trim();
323
- const [rawAction = "menu", ...rest] = trimmedArgs.split(/\s+/);
334
+ const [rawAction = "menu", ...rest] = trimmedArgs ? trimmedArgs.split(/\s+/) : ["menu"];
324
335
  const action = rawAction.toLowerCase();
325
336
  const actionArgs = rest.join(" ");
326
337
  if (action === "status") {
@@ -3,7 +3,7 @@
3
3
  * Returns JSON results on success, clear error messages on failure.
4
4
  */
5
5
 
6
- import { Text } from "@mariozechner/pi-tui";
6
+ import { Text } from "@earendil-works/pi-tui";
7
7
  import { NotConnectedError } from "./api-client.js";
8
8
 
9
9
  const MAX_TOOL_RESULT_DEPTH = 6;
@@ -1,6 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import { Text } from "@mariozechner/pi-tui";
3
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import { Text } from "@earendil-works/pi-tui";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
4
  import { ApiError, api } from "../api-client.js";
5
5
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
6
6
  import { makeProgressCallRenderer, makeProgressResultRenderer, wrapExecute } from "../tool-utils.js";
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { execFile as execFileCallback } from "node:child_process";
4
4
  import { readFile, stat } from "node:fs/promises";
5
5
  import { basename } from "node:path";
@@ -7,7 +7,7 @@ import { promisify } from "node:util";
7
7
  import { ApiError, api } from "../api-client.js";
8
8
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
9
9
  import { makeProgressCallRenderer, makeProgressResultRenderer, type ToolRuntime, wrapExecute } from "../tool-utils.js";
10
- import { Text } from "@mariozechner/pi-tui";
10
+ import { Text } from "@earendil-works/pi-tui";
11
11
 
12
12
  const TRANSCRIPT_TEXT_PREVIEW_CHARS = 1200;
13
13
  const TRANSCRIPT_VTT_PREVIEW_CHARS = 800;
@@ -1,6 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import { Text } from "@mariozechner/pi-tui";
3
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import { Text } from "@earendil-works/pi-tui";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
4
  import { ApiError, api } from "../api-client.js";
5
5
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
6
6
  import { makeProgressCallRenderer, makeProgressResultRenderer, type ToolRuntime, wrapExecute } from "../tool-utils.js";
@@ -1,14 +1,14 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { readFile, stat } from "node:fs/promises";
4
4
  import { basename } from "node:path";
5
5
  import { ApiError, api, NotConnectedError } from "../api-client.js";
6
6
  import { makeProgressCallRenderer, makeProgressResultRenderer } from "../tool-utils.js";
7
7
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
8
8
 
9
- type DealSourcingDecision = "pushing" | "passing" | "holding";
9
+ type OpportunityResearchDecision = "pushing" | "passing" | "holding";
10
10
 
11
- const DEFAULT_DEAL_SOURCING_PROGRAM_SLUG = "seed-network";
11
+ const DEFAULT_OPPORTUNITY_RESEARCH_PROGRAM_SLUG = "seed-network";
12
12
  const MAX_DOCUMENT_PREVIEW_CHARS = 12000;
13
13
  const MAX_IMAGE_PREVIEW_BYTES = 8 * 1024 * 1024;
14
14
 
@@ -150,7 +150,7 @@ function suggestedReviewFields() {
150
150
  return [
151
151
  "Founder info",
152
152
  "Company info",
153
- "Deal info, including ask or explicit ask unknown",
153
+ "Opportunity info, including ask or explicit ask unknown",
154
154
  "Opportunity Summary",
155
155
  "Founder/contact path or explicit unknown",
156
156
  "Member relationship and excitement/vouch before push",
@@ -181,14 +181,16 @@ function inferDocumentContentType(fileName: string) {
181
181
  return "application/octet-stream";
182
182
  }
183
183
 
184
- function normalizeDecision(value: unknown): DealSourcingDecision | null {
184
+ function normalizeDecision(value: unknown): OpportunityResearchDecision | null {
185
185
  if (value === "pushing" || value === "passing" || value === "holding") return value;
186
186
  return null;
187
187
  }
188
188
 
189
- async function submitDraftPosition(programSlug: string, draftId: string, args: any, decision: DealSourcingDecision) {
190
- return api.post<any>(`/programs/${programSlug}/deal-sourcing/drafts/${draftId}/member-position`, {
189
+ async function submitDraftPosition(programSlug: string, draftId: string, args: any, decision: OpportunityResearchDecision) {
190
+ return api.post<any>(`/programs/${programSlug}/opportunity-research/drafts/${draftId}/member-position`, {
191
191
  ask_unknown: args.askUnknown === true,
192
+ company_name: normalizeOptionalString(args.companyName),
193
+ company_website_url: normalizeOptionalString(args.companyWebsiteUrl),
192
194
  contact_info: normalizeOptionalString(args.contactInfo),
193
195
  contact_unknown: args.contactUnknown === true,
194
196
  decision,
@@ -202,7 +204,7 @@ async function submitDraftPosition(programSlug: string, draftId: string, args: a
202
204
  });
203
205
  }
204
206
 
205
- async function submitDealSourcingDeck(args: {
207
+ async function submitOpportunityResearchDocument(args: {
206
208
  askUnknown?: boolean | null;
207
209
  programSlug?: string | null;
208
210
  filePath?: string | null;
@@ -212,7 +214,7 @@ async function submitDealSourcingDeck(args: {
212
214
  contentType?: string | null;
213
215
  contactInfo?: string | null;
214
216
  contactUnknown?: boolean | null;
215
- decision?: DealSourcingDecision | null;
217
+ decision?: OpportunityResearchDecision | null;
216
218
  draftId?: string | null;
217
219
  excitementReason?: string | null;
218
220
  fileName?: string | null;
@@ -227,15 +229,15 @@ async function submitDealSourcingDeck(args: {
227
229
  vouchText?: string | null;
228
230
  }, runtime?: any) {
229
231
  try {
230
- const programSlug = normalizeOptionalString(args.programSlug) ?? DEFAULT_DEAL_SOURCING_PROGRAM_SLUG;
232
+ const programSlug = normalizeOptionalString(args.programSlug) ?? DEFAULT_OPPORTUNITY_RESEARCH_PROGRAM_SLUG;
231
233
  const existingDraftId = normalizeOptionalString(args.draftId);
232
234
  const existingDecision = normalizeDecision(args.decision);
233
235
  if (existingDraftId) {
234
236
  if (!existingDecision) {
235
- return { draft: { id: existingDraftId }, next_action: "Ask the member whether they want to push/source this draft, pass/reject it, or hold it for later." };
237
+ return { draft: { id: existingDraftId }, next_action: "Ask the member whether they want to push this opportunity for review, pass, or hold it for later." };
236
238
  }
237
239
 
238
- runtime?.setWorkingMessage?.("Saving deal sourcing draft position...");
240
+ runtime?.setWorkingMessage?.("Saving opportunity draft position...");
239
241
  const positionResponse = await submitDraftPosition(programSlug, existingDraftId, args, existingDecision);
240
242
  return { draft: { id: existingDraftId }, draft_position_result: positionResponse };
241
243
  }
@@ -253,8 +255,8 @@ async function submitDealSourcingDeck(args: {
253
255
  const fileName = normalizeOptionalString(args.fileName) ?? basename(filePath);
254
256
  const contentType = normalizeOptionalString(args.contentType) ?? inferDocumentContentType(fileName);
255
257
  const assetKind = normalizeOptionalString(args.assetKind) ?? "deck";
256
- runtime?.setWorkingMessage?.("Requesting deal document upload target...");
257
- const ingestResponse = await api.post<any>(`/programs/${programSlug}/deal-sourcing/document-ingests`, {
258
+ runtime?.setWorkingMessage?.("Requesting research document upload target...");
259
+ const ingestResponse = await api.post<any>(`/programs/${programSlug}/opportunity-research/document-ingests`, {
258
260
  asset_kind: assetKind,
259
261
  content_type: contentType,
260
262
  file_name: fileName,
@@ -267,10 +269,10 @@ async function submitDealSourcingDeck(args: {
267
269
  const uploadId = typeof ingestResponse?.upload?.id === "string" ? ingestResponse.upload.id : null;
268
270
 
269
271
  if (!uploadUrl || !objectKey || !uploadId) {
270
- return { error: "The API did not return a valid deal document upload target.", response: ingestResponse };
272
+ return { error: "The API did not return a valid research document upload target.", response: ingestResponse };
271
273
  }
272
274
 
273
- runtime?.setWorkingMessage?.("Uploading deal document bytes...");
275
+ runtime?.setWorkingMessage?.("Uploading research document...");
274
276
  const bytes = await readFile(filePath);
275
277
  const documentPreview = await buildDocumentPreview(fileName, contentType, bytes);
276
278
  const uploadHeaders: Record<string, string> = {};
@@ -296,7 +298,7 @@ async function submitDealSourcingDeck(args: {
296
298
  }
297
299
 
298
300
  runtime?.setWorkingMessage?.("Creating private research draft...");
299
- const completeResponse = await api.post<any>(`/programs/${programSlug}/deal-sourcing/document-ingests/${uploadId}/complete`, {
301
+ const completeResponse = await api.post<any>(`/programs/${programSlug}/opportunity-research/document-ingests/${uploadId}/complete`, {
300
302
  asset_kind: assetKind,
301
303
  company_name: normalizeOptionalString(args.companyName),
302
304
  company_website_url: normalizeOptionalString(args.companyWebsiteUrl),
@@ -317,8 +319,8 @@ async function submitDealSourcingDeck(args: {
317
319
  decision_ignored_until_review: Boolean(decision),
318
320
  document_preview: documentPreview,
319
321
  next_action: decision
320
- ? "The document is saved as a private draft. Review the material, summarize Founder info, Company info, Deal info, and Opportunity Summary, then ask missing questions before submitting the member decision."
321
- : "Review the material, summarize Founder info, Company info, Deal info, and Opportunity Summary, then ask whether the member wants to push, pass, or hold after missing context is resolved.",
322
+ ? "The document is saved as a private draft. Review the material, summarize Founder info, Company info, Opportunity info, and Opportunity Summary, then ask missing questions before submitting the member decision."
323
+ : "Review the material, summarize Founder info, Company info, Opportunity info, and Opportunity Summary, then ask whether the member wants to push, pass, or hold after missing context is resolved.",
322
324
  suggested_review_fields: suggestedReviewFields(),
323
325
  upload: {
324
326
  ...completeResponse?.upload,
@@ -331,7 +333,7 @@ async function submitDealSourcingDeck(args: {
331
333
  }
332
334
  }
333
335
 
334
- function makeDealSourcingExecute(fn: typeof submitDealSourcingDeck) {
336
+ function makeOpportunityResearchExecute(fn: typeof submitOpportunityResearchDocument) {
335
337
  return async (_toolCallId: string, params: any, _signal: any, _onUpdate: any, ctx: any) => {
336
338
  const runtime = {
337
339
  ctx,
@@ -385,15 +387,15 @@ function makeDealSourcingExecute(fn: typeof submitDealSourcingDeck) {
385
387
  };
386
388
  }
387
389
 
388
- export function registerDealSourcingTools(pi: ExtensionAPI) {
390
+ export function registerOpportunityResearchTools(pi: ExtensionAPI) {
389
391
  pi.registerTool({
390
- name: "seedclub_submit_deal_sourcing_deck",
391
- label: "Submit Deal Sourcing Document",
392
+ name: "seedclub_upload_opportunity_document",
393
+ label: "Upload Opportunity Document",
392
394
  description:
393
- "Upload a local deck, memo, document, or image to seedclub-api as a private/team-private deal research draft, or submit pushing/passing/holding for an existing draftId. programSlug defaults to seed-network. Initial uploads always create a private draft first and return document preview context; do not push immediately from an upload. After reviewing and confirming with the member, use draftId plus a decision. If decision is pushing, provide founderNames or founderUnknown, founderRelationship, excitementReason or vouchText, contactInfo or contactUnknown, and targetAmount or askUnknown.",
395
+ "Upload a local deck, memo, document, or image to seedclub-api as a private/team-private opportunity research draft, or record pushing/passing/holding for an existing draftId. programSlug defaults to seed-network. For a plain deck upload or a prompt like 'let's chat about this opportunity', create the private draft, read the preview, and discuss the opportunity without implying it has been submitted for review. Initial uploads must not push immediately. After reviewing and confirming with the member, use draftId plus a decision. If decision is pushing, provide founderNames or founderUnknown, founderRelationship, excitementReason or vouchText, contactInfo or contactUnknown, and targetAmount or askUnknown.",
394
396
  parameters: Type.Object({
395
397
  askUnknown: Type.Optional(Type.Union([Type.Boolean(), Type.Null()], { description: "Set true when the member explicitly says the round ask is unknown." })),
396
- programSlug: Type.Optional(Type.Union([Type.String({ description: "Program slug for the investing/deal pipeline program. Defaults to seed-network." }), Type.Null()])),
398
+ programSlug: Type.Optional(Type.Union([Type.String({ description: "Program slug for the opportunity research program. Defaults to seed-network." }), Type.Null()])),
397
399
  filePath: Type.Optional(Type.Union([Type.String({ description: "Local deck, memo, document, or image path. Required unless draftId is provided." }), Type.Null()])),
398
400
  assetKind: Type.Optional(Type.Union([Type.Literal("deck"), Type.Literal("memo"), Type.Literal("supporting_material"), Type.Null()])),
399
401
  companyName: Type.Optional(Type.Union([Type.String(), Type.Null()])),
@@ -402,7 +404,7 @@ export function registerDealSourcingTools(pi: ExtensionAPI) {
402
404
  contactInfo: Type.Optional(Type.Union([Type.String(), Type.Null()], { description: "Founder/company contact info supplied by the member if not present in the uploaded material." })),
403
405
  contactUnknown: Type.Optional(Type.Union([Type.Boolean(), Type.Null()], { description: "Set true when the member explicitly says contact info is unknown." })),
404
406
  decision: Type.Optional(Type.Union([Type.Literal("pushing"), Type.Literal("passing"), Type.Literal("holding"), Type.Null()])),
405
- draftId: Type.Optional(Type.Union([Type.String({ description: "Existing private deal draft id to update without re-uploading the file." }), Type.Null()])),
407
+ draftId: Type.Optional(Type.Union([Type.String({ description: "Existing private opportunity draft id to update without re-uploading the file." }), Type.Null()])),
406
408
  excitementReason: Type.Optional(Type.Union([Type.String(), Type.Null()], { description: "Why the member is excited about the company/founder." })),
407
409
  fileName: Type.Optional(Type.Union([Type.String(), Type.Null()])),
408
410
  flaggedTopics: Type.Optional(Type.Union([Type.Array(Type.String()), Type.Null()])),
@@ -415,9 +417,9 @@ export function registerDealSourcingTools(pi: ExtensionAPI) {
415
417
  valuation: Type.Optional(Type.Union([Type.Number(), Type.Null()])),
416
418
  vouchText: Type.Optional(Type.Union([Type.String(), Type.Null()])),
417
419
  }),
418
- execute: makeDealSourcingExecute(submitDealSourcingDeck),
419
- renderCall: makeProgressCallRenderer(getToolCallLabel("seedclub_submit_deal_sourcing_deck"), (args) => args?.companyName || args?.draftId || args?.filePath || undefined),
420
- renderResult: makeProgressResultRenderer(getToolSuccessLabel("seedclub_submit_deal_sourcing_deck"), (details) => {
420
+ execute: makeOpportunityResearchExecute(submitOpportunityResearchDocument),
421
+ renderCall: makeProgressCallRenderer(getToolCallLabel("seedclub_upload_opportunity_document"), (args) => args?.companyName || args?.draftId || args?.filePath || undefined),
422
+ renderResult: makeProgressResultRenderer(getToolSuccessLabel("seedclub_upload_opportunity_document"), (details) => {
421
423
  const company = details?.company?.name ?? details?.draft_position_result?.funding_round?.organization_id ?? null;
422
424
  const state = details?.draft_position_result?.funding_round?.lifecycle_state ?? details?.draft?.status ?? details?.draft_position_result?.draft?.status ?? null;
423
425
  const id = details?.draft_position_result?.funding_round?.id ?? details?.draft?.id ?? details?.draft_position_result?.draft?.id ?? null;
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { ApiError, api } from "../api-client.js";
4
4
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
5
5
  import { makeProgressCallRenderer, makeProgressResultRenderer, wrapExecute } from "../tool-utils.js";
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { getToolCallLabel, getToolSuccessLabel } from "../ui-copy.js";
4
4
  import { makeProgressCallRenderer, makeProgressResultRenderer } from "../tool-utils.js";
5
5
 
@@ -11,6 +11,7 @@ export const TOOL_CALL_LABELS: Record<string, string> = {
11
11
  seedclub_create_crm_task: "Creating CRM task",
12
12
  seedclub_save_research: "Saving research",
13
13
  seedclub_research_opportunity: "Researching opportunity",
14
+ seedclub_upload_opportunity_document: "Uploading opportunity document",
14
15
  seedclub_get_research: "Loading research",
15
16
  seedclub_list_program_contacts: "Loading program contacts",
16
17
  seedclub_list_program_funnels: "Loading program funnels",
@@ -62,6 +63,7 @@ export const TOOL_SUCCESS_LABELS: Record<string, string> = {
62
63
  seedclub_create_crm_task: "CRM task created",
63
64
  seedclub_save_research: "Research saved",
64
65
  seedclub_research_opportunity: "Research queued",
66
+ seedclub_upload_opportunity_document: "Opportunity draft ready",
65
67
  seedclub_get_research: "Research loaded",
66
68
  seedclub_list_program_contacts: "Program contacts loaded",
67
69
  seedclub_list_program_funnels: "Program funnels loaded",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "dark",
4
4
  "vars": {
5
5
  "brand": 2,
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "light",
4
4
  "vars": {
5
5
  "brand": 2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubnet/seedclub",
3
- "version": "0.2.39",
3
+ "version": "0.2.41",
4
4
  "description": "A branded command-line agent wrapper around pi, with integrated Seed Club commands, tools, and app actions",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -23,7 +23,7 @@
23
23
  "upgrade:pi": "node scripts/upgrade-pi.mjs"
24
24
  },
25
25
  "dependencies": {
26
- "@mariozechner/pi-coding-agent": "0.65.2",
26
+ "@earendil-works/pi-coding-agent": "0.74.0",
27
27
  "@sinclair/typebox": "^0.34.49",
28
28
  "pdf-parse": "^2.4.5"
29
29
  },
@@ -2,7 +2,7 @@
2
2
 
3
3
  Seed Club-owned runtime adapter around pi's public SDK.
4
4
 
5
- This is the only package in the TUI architecture that should talk directly to `@mariozechner/pi-coding-agent`.
5
+ This is the only package in the TUI architecture that should talk directly to `@earendil-works/pi-coding-agent`.
6
6
 
7
7
  It also owns the Seed Club full system prompt, sourced from `assets/SYSTEM.md`.
8
8
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "piVersion": "0.65.2",
2
+ "piVersion": "0.74.0",
3
3
  "requiredRuntimeApis": [
4
4
  "AuthStorage",
5
5
  "DefaultResourceLoader",
@@ -38,7 +38,7 @@ test("seedclub runtime declares the public pi APIs used by the shell", () => {
38
38
 
39
39
  const boundary = describeSeedclubRuntimeBoundary();
40
40
  assert.equal(boundary.owner, "seedclub");
41
- assert.equal(boundary.upstreamRuntime, "@mariozechner/pi-coding-agent");
41
+ assert.equal(boundary.upstreamRuntime, "@earendil-works/pi-coding-agent");
42
42
  assert.deepEqual(boundary.publicApis, REQUIRED_RUNTIME_APIS);
43
43
  });
44
44
 
@@ -11,7 +11,7 @@ import {
11
11
  createAgentSession,
12
12
  createExtensionRuntime,
13
13
  discoverAndLoadExtensions,
14
- } from "@mariozechner/pi-coding-agent";
14
+ } from "@earendil-works/pi-coding-agent";
15
15
 
16
16
  export const PUBLIC_PI_RUNTIME_APIS = Object.freeze([
17
17
  "AuthStorage",
@@ -233,7 +233,7 @@ export function createSeedclubPiSession(options) {
233
233
  export function describeSeedclubRuntimeBoundary() {
234
234
  return Object.freeze({
235
235
  owner: "seedclub",
236
- upstreamRuntime: "@mariozechner/pi-coding-agent",
236
+ upstreamRuntime: "@earendil-works/pi-coding-agent",
237
237
  publicApis: [...PUBLIC_PI_RUNTIME_APIS],
238
238
  rules: [
239
239
  "use published pi packages only",
@@ -241,7 +241,7 @@ export function describeSeedclubRuntimeBoundary() {
241
241
  "no pi dist imports",
242
242
  "no tui app code in runtime adapter",
243
243
  "runtime owns the seedclub full system prompt",
244
- "embed agent sessions through createAgentSession() on pi 0.65.2",
244
+ "embed agent sessions through createAgentSession() on pi 0.74.0",
245
245
  ],
246
246
  seedclubAgentDir: getSeedclubAgentDir(),
247
247
  seedclubVersion: getSeedclubVersion(),
@@ -17,7 +17,7 @@ function readJson(filePath) {
17
17
 
18
18
  function getExpectedPiVersion() {
19
19
  const rootPackageJson = readJson(path.join(REPO_ROOT, "package.json"));
20
- return rootPackageJson?.dependencies?.["@mariozechner/pi-coding-agent"];
20
+ return rootPackageJson?.dependencies?.["@earendil-works/pi-coding-agent"];
21
21
  }
22
22
 
23
23
  function getInstalledPiVersion() {
@@ -25,7 +25,7 @@ function getInstalledPiVersion() {
25
25
  path.join(
26
26
  REPO_ROOT,
27
27
  "node_modules",
28
- "@mariozechner",
28
+ "@earendil-works",
29
29
  "pi-coding-agent",
30
30
  "package.json",
31
31
  ),
@@ -43,7 +43,7 @@ export function ensureSeedclubWorkspaceDependencies() {
43
43
  const foundVersion = installedPiVersion ?? "missing";
44
44
  console.error(
45
45
  `seedclub: workspace dependencies are out of sync ` +
46
- `(expected @mariozechner/pi-coding-agent ${expectedPiVersion}, found ${foundVersion}).`,
46
+ `(expected @earendil-works/pi-coding-agent ${expectedPiVersion}, found ${foundVersion}).`,
47
47
  );
48
48
  console.error("seedclub: running `npm install` to sync this branch...");
49
49
 
@@ -59,7 +59,7 @@ export function ensureSeedclubWorkspaceDependencies() {
59
59
 
60
60
  if (getInstalledPiVersion() !== expectedPiVersion) {
61
61
  console.error(
62
- `seedclub: dependency sync completed, but @mariozechner/pi-coding-agent is still not ${expectedPiVersion}.`,
62
+ `seedclub: dependency sync completed, but @earendil-works/pi-coding-agent is still not ${expectedPiVersion}.`,
63
63
  );
64
64
  process.exit(1);
65
65
  }
@@ -12,7 +12,7 @@ import {
12
12
  TUI,
13
13
  truncateToWidth,
14
14
  visibleWidth,
15
- } from "@mariozechner/pi-tui";
15
+ } from "@earendil-works/pi-tui";
16
16
  import {
17
17
  createSeedclubInteractiveModeSession,
18
18
  getSeedclubAgentDir,
@@ -959,6 +959,13 @@ function shouldShowCommandInList(name) {
959
959
  return !name.startsWith("skill:");
960
960
  }
961
961
 
962
+ const MEMORY_COMMAND_COMPLETIONS = [
963
+ { value: "status", label: "status", description: "Show memory status" },
964
+ { value: "recent", label: "recent", description: "Show recent memory" },
965
+ { value: "on", label: "on", description: "Turn memory on" },
966
+ { value: "off", label: "off", description: "Turn memory off" },
967
+ ];
968
+
962
969
  function getBuiltInSlashCommands() {
963
970
  return [
964
971
  { name: "new", description: "Start a new session" },
@@ -967,13 +974,22 @@ function getBuiltInSlashCommands() {
967
974
  { name: "calendar", description: "Open calendar connect and availability actions" },
968
975
  { name: "research", description: "Open a Seed Club research prompt" },
969
976
  { name: "source", description: "Open a source-backed research prompt" },
970
- { name: "memory", description: "Show Seed Club memory status, recent memory, or turn memory on/off" },
977
+ {
978
+ name: "memory",
979
+ description: "Show Seed Club memory status, recent memory, or turn memory on/off",
980
+ getArgumentCompletions: (argumentPrefix) => {
981
+ const prefix = argumentPrefix.trim().toLowerCase();
982
+ const completions = MEMORY_COMMAND_COMPLETIONS.filter((item) => item.value.startsWith(prefix));
983
+ return completions.length ? completions : null;
984
+ },
985
+ },
971
986
  { name: "worldview", description: "Open an investing worldview prompt" },
972
987
  { name: "theses", description: "Open an investment theses prompt" },
973
988
  { name: "concerns", description: "Open an investment concerns prompt" },
974
989
  { name: "model", description: "Select the current model" },
975
990
  { name: "login", description: "Log into a model provider" },
976
991
  { name: "logout", description: "Log out of a model provider" },
992
+ { name: "update", description: "Show the seedclub package update menu" },
977
993
  { name: "more", description: "Show everything else" },
978
994
  { name: "quit", description: "Exit seedclub" },
979
995
  ];
@@ -984,10 +1000,23 @@ function getAuxiliaryBuiltInSlashCommands() {
984
1000
  { name: "commands", description: "List the primary command menu" },
985
1001
  { name: "extensions", description: "List loaded extensions" },
986
1002
  { name: "reload", description: "Reload keybindings, extensions, prompts, and tools" },
987
- { name: "update", description: "Show the seedclub package update menu" },
988
1003
  ];
989
1004
  }
990
1005
 
1006
+ function getPrimaryExtensionCommandNames() {
1007
+ return new Set([
1008
+ "calendar",
1009
+ "concerns",
1010
+ "memory",
1011
+ "research",
1012
+ "seedclub",
1013
+ "seedenv",
1014
+ "source",
1015
+ "theses",
1016
+ "worldview",
1017
+ ]);
1018
+ }
1019
+
991
1020
  class SeedclubSurfaceEditor extends CustomEditor {
992
1021
  constructor(tui, editorTheme, keybindings, options) {
993
1022
  super(tui, editorTheme, keybindings, {
@@ -1312,7 +1341,7 @@ export class SeedclubInteractiveModeApp {
1312
1341
  configureAutocomplete() {
1313
1342
  const builtInCommands = getBuiltInSlashCommands();
1314
1343
  const builtInCommandNames = new Set(builtInCommands.map((command) => command.name));
1315
- const extraAutocompleteCommands = new Set(["seedclub"]);
1344
+ const extraAutocompleteCommands = getPrimaryExtensionCommandNames();
1316
1345
  const extensionCommands = this.session.extensionRunner?.getRegisteredCommands?.()
1317
1346
  .filter((command) => !builtInCommandNames.has(command.invocationName))
1318
1347
  .filter((command) => extraAutocompleteCommands.has(command.invocationName))
@@ -1340,7 +1369,16 @@ export class SeedclubInteractiveModeApp {
1340
1369
 
1341
1370
  showCommandsList() {
1342
1371
  const builtInCommands = getBuiltInSlashCommands();
1343
- const lines = builtInCommands
1372
+ const builtInCommandNames = new Set(builtInCommands.map((command) => command.name));
1373
+ const primaryExtensionCommandNames = getPrimaryExtensionCommandNames();
1374
+ const extensionCommands = this.session.extensionRunner?.getRegisteredCommands?.()
1375
+ .filter((command) => !builtInCommandNames.has(command.invocationName))
1376
+ .filter((command) => primaryExtensionCommandNames.has(command.invocationName))
1377
+ .map((command) => ({
1378
+ name: command.invocationName,
1379
+ description: command.description || "",
1380
+ })) ?? [];
1381
+ const lines = [...builtInCommands, ...extensionCommands]
1344
1382
  .filter((command) => shouldShowCommandInList(command.name))
1345
1383
  .map((command) => `- \`/${command.name}\`${command.description ? ` ${command.description}` : ""}`)
1346
1384
  .join("\n");
@@ -24,7 +24,7 @@ export function createSeedclubTuiContract() {
24
24
  "InteractiveMode.prototype",
25
25
  "AuthStorage.prototype",
26
26
  "ModelRegistry.prototype",
27
- "@mariozechner/pi-coding-agent/dist/*",
27
+ "@earendil-works/pi-coding-agent/dist/*",
28
28
  "packages/coding-agent/src/*",
29
29
  ],
30
30
  });
@@ -1,6 +1,6 @@
1
1
  This subtree is vendored downstream from:
2
2
 
3
- - `pi-mono/packages/coding-agent/src`
3
+ - `pi/packages/coding-agent/src`
4
4
 
5
5
  In this repo, it supplies copied interactive TUI support code used by `seedclub-tui`.
6
6
 
@@ -8,4 +8,4 @@ Key rule:
8
8
 
9
9
  - Treat files here as vendored upstream code.
10
10
  - Put Seed Club-owned product logic in `packages/seedclub-tui/src/app/`.
11
- - When updating from upstream, diff against `pi-mono/packages/coding-agent/src/*` and port only the needed changes.
11
+ - When updating from upstream, diff against `pi/packages/coding-agent/src/*` and port only the needed changes.
@@ -4,7 +4,7 @@ import {
4
4
  getKeybindings as getGlobalKeybindings,
5
5
  matchesKey,
6
6
  setKeybindings,
7
- } from "@mariozechner/pi-tui";
7
+ } from "@earendil-works/pi-tui";
8
8
  import { existsSync, readFileSync } from "fs";
9
9
  import { join } from "path";
10
10
  import { getAgentDir } from "../config.js";
@@ -1,4 +1,4 @@
1
- import { Container, Markdown, Spacer, Text } from "@mariozechner/pi-tui";
1
+ import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
2
2
  import { getMarkdownTheme, theme } from "../theme/theme.js";
3
3
  /**
4
4
  * Component that renders a complete assistant message
@@ -1,4 +1,4 @@
1
- import { CancellableLoader, Container, Loader, Spacer, Text } from "@mariozechner/pi-tui";
1
+ import { CancellableLoader, Container, Loader, Spacer, Text } from "@earendil-works/pi-tui";
2
2
  import { DynamicBorder } from "./dynamic-border.js";
3
3
  import { keyHint } from "./keybinding-hints.js";
4
4
  /** Loader wrapped with borders for extension UI */
@@ -1,4 +1,4 @@
1
- import { Editor } from "@mariozechner/pi-tui";
1
+ import { Editor } from "@earendil-works/pi-tui";
2
2
  /**
3
3
  * Custom editor that handles app-level keybindings for coding-agent.
4
4
  */
@@ -6,7 +6,7 @@ import { spawnSync } from "node:child_process";
6
6
  import * as fs from "node:fs";
7
7
  import * as os from "node:os";
8
8
  import * as path from "node:path";
9
- import { Container, Editor, Spacer, Text } from "@mariozechner/pi-tui";
9
+ import { Container, Editor, Spacer, Text } from "@earendil-works/pi-tui";
10
10
  import { getEditorKeybindings } from "../../../core/keybindings.js";
11
11
  import { getEditorTheme, theme } from "../theme/theme.js";
12
12
  import { DynamicBorder } from "./dynamic-border.js";
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Simple text input component for extensions.
3
3
  */
4
- import { Container, Input, Spacer, Text } from "@mariozechner/pi-tui";
4
+ import { Container, Input, Spacer, Text } from "@earendil-works/pi-tui";
5
5
  import { getEditorKeybindings } from "../../../core/keybindings.js";
6
6
  import { theme } from "../theme/theme.js";
7
7
  import { CountdownTimer } from "./countdown-timer.js";
@@ -2,7 +2,7 @@
2
2
  * Generic selector component for extensions.
3
3
  * Displays a list of string options with keyboard navigation.
4
4
  */
5
- import { Container, Spacer, Text } from "@mariozechner/pi-tui";
5
+ import { Container, Spacer, Text } from "@earendil-works/pi-tui";
6
6
  import { getEditorKeybindings } from "../../../core/keybindings.js";
7
7
  import { theme } from "../theme/theme.js";
8
8
  import { CountdownTimer } from "./countdown-timer.js";
@@ -1,4 +1,4 @@
1
- import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
1
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
2
2
  import { theme } from "../theme/theme.js";
3
3
  /**
4
4
  * Sanitize text for display in a single-line status.
@@ -1,4 +1,4 @@
1
- import { Container, Input, Spacer, Text } from "@mariozechner/pi-tui";
1
+ import { Container, Input, Spacer, Text } from "@earendil-works/pi-tui";
2
2
  import { exec } from "child_process";
3
3
  import { getEditorKeybindings } from "../../../core/keybindings.js";
4
4
  import { theme } from "../theme/theme.js";
@@ -1,4 +1,4 @@
1
- import { Container, Spacer, TruncatedText } from "@mariozechner/pi-tui";
1
+ import { Container, Spacer, TruncatedText } from "@earendil-works/pi-tui";
2
2
  import { getEditorKeybindings } from "../../../core/keybindings.js";
3
3
  import { theme } from "../theme/theme.js";
4
4
  import { DynamicBorder } from "./dynamic-border.js";
@@ -1,5 +1,5 @@
1
1
  import * as os from "node:os";
2
- import { Box, Container, getCapabilities, getImageDimensions, Image, imageFallback, Spacer, Text, truncateToWidth, } from "@mariozechner/pi-tui";
2
+ import { Box, Container, getCapabilities, getImageDimensions, Image, imageFallback, Spacer, Text, truncateToWidth, } from "@earendil-works/pi-tui";
3
3
  import stripAnsi from "strip-ansi";
4
4
  import { computeEditDiff } from "../../../core/tools/edit-diff.js";
5
5
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "../../../core/tools/truncate.js";
@@ -1,4 +1,4 @@
1
- import { Container, Markdown, Spacer } from "@mariozechner/pi-tui";
1
+ import { Container, Markdown, Spacer } from "@earendil-works/pi-tui";
2
2
  import { getMarkdownTheme, theme } from "../theme/theme.js";
3
3
 
4
4
  function getSurfaceState() {
@@ -2,7 +2,7 @@
2
2
  * Shared utility for truncating text to visual lines (accounting for line wrapping).
3
3
  * Used by both tool-execution.ts and bash-execution.ts for consistent behavior.
4
4
  */
5
- import { Text } from "@mariozechner/pi-tui";
5
+ import { Text } from "@earendil-works/pi-tui";
6
6
  /**
7
7
  * Truncate text to a maximum number of visual lines (from the end).
8
8
  * This accounts for line wrapping based on terminal width.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "dark",
4
4
  "vars": {
5
5
  "cyan": "#00d7ff",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "light",
4
4
  "vars": {
5
5
  "teal": "#5a8080",
@@ -514,7 +514,7 @@ function getDefaultTheme() {
514
514
  // Global Theme Instance
515
515
  // ============================================================================
516
516
  // Use globalThis to share theme across module loaders (tsx + jiti in dev mode)
517
- const THEME_KEY = Symbol.for("@mariozechner/pi-coding-agent:theme");
517
+ const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme");
518
518
  // Export theme as a getter that reads from globalThis
519
519
  // This ensures all module instances (tsx, jiti) see the same theme
520
520
  export const theme = new Proxy({}, {
package/postinstall.js CHANGED
@@ -110,7 +110,7 @@ writeFileSync(
110
110
  join(SC_DIR, ".seedclub-version"),
111
111
  JSON.stringify({
112
112
  seedclubVersion: pkg.version,
113
- piVersion: pkg.dependencies?.["@mariozechner/pi-coding-agent"] ?? "unknown",
113
+ piVersion: pkg.dependencies?.["@earendil-works/pi-coding-agent"] ?? "unknown",
114
114
  installedAt: new Date().toISOString().replace(/\.\d+Z$/, "Z"),
115
115
  }) + "\n",
116
116
  );