@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.
- package/assets/extensions/seedclub/commands/clip-status.ts +1 -1
- package/assets/extensions/seedclub/commands/seedclub.ts +1 -1
- package/assets/extensions/seedclub/commands/transcript-export.ts +1 -1
- package/assets/extensions/seedclub/commands/transcript-intent.ts +1 -1
- package/assets/extensions/seedclub/commands/transcripts.ts +1 -1
- package/assets/extensions/seedclub/index.ts +3 -3
- package/assets/extensions/seedclub/memory.ts +13 -2
- package/assets/extensions/seedclub/tool-utils.ts +1 -1
- package/assets/extensions/seedclub/tools/crm.ts +2 -2
- package/assets/extensions/seedclub/tools/media.ts +2 -2
- package/assets/extensions/seedclub/tools/meetings.ts +2 -2
- package/assets/extensions/seedclub/tools/{deal-sourcing.ts → opportunity-research.ts} +31 -29
- package/assets/extensions/seedclub/tools/utility.ts +1 -1
- package/assets/extensions/seedclub/tools/web.ts +1 -1
- package/assets/extensions/seedclub/ui-copy.ts +2 -0
- package/assets/theme/dark.json +1 -1
- package/assets/theme/light.json +1 -1
- package/package.json +2 -2
- package/packages/seedclub-runtime/README.md +1 -1
- package/packages/seedclub-runtime/pi-contract-baseline.json +1 -1
- package/packages/seedclub-runtime/src/contract.test.mjs +1 -1
- package/packages/seedclub-runtime/src/index.mjs +3 -3
- package/packages/seedclub-runtime/src/workspace-deps.mjs +4 -4
- package/packages/seedclub-tui/src/app/interactive-mode.mjs +43 -5
- package/packages/seedclub-tui/src/index.mjs +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/README.md +2 -2
- package/packages/seedclub-tui/src/vendor/coding-agent/core/keybindings.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/assistant-message.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/bordered-loader.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/custom-editor.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-editor.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-input.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/extension-selector.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/footer.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/login-dialog.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/oauth-selector.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/tool-execution.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/user-message.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/visual-truncate.js +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/dark.json +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/light.json +1 -1
- package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/theme/theme.js +1 -1
- package/postinstall.js +1 -1
|
@@ -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 "@
|
|
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 "@
|
|
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 "@
|
|
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 "@
|
|
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 {
|
|
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
|
-
|
|
212
|
+
registerOpportunityResearchTools(pi);
|
|
213
213
|
registerMeetingTools(pi);
|
|
214
214
|
registerMediaTools(pi);
|
|
215
215
|
registerWebTools(pi);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
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") {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
-
import { Text } from "@
|
|
3
|
-
import type { ExtensionAPI } from "@
|
|
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 "@
|
|
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 "@
|
|
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 "@
|
|
3
|
-
import type { ExtensionAPI } from "@
|
|
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 "@
|
|
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
|
|
9
|
+
type OpportunityResearchDecision = "pushing" | "passing" | "holding";
|
|
10
10
|
|
|
11
|
-
const
|
|
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
|
-
"
|
|
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):
|
|
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:
|
|
190
|
-
return api.post<any>(`/programs/${programSlug}/
|
|
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
|
|
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?:
|
|
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) ??
|
|
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
|
|
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
|
|
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
|
|
257
|
-
const ingestResponse = await api.post<any>(`/programs/${programSlug}/
|
|
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
|
|
272
|
+
return { error: "The API did not return a valid research document upload target.", response: ingestResponse };
|
|
271
273
|
}
|
|
272
274
|
|
|
273
|
-
runtime?.setWorkingMessage?.("Uploading
|
|
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}/
|
|
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,
|
|
321
|
-
: "Review the material, summarize Founder info, Company info,
|
|
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
|
|
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
|
|
390
|
+
export function registerOpportunityResearchTools(pi: ExtensionAPI) {
|
|
389
391
|
pi.registerTool({
|
|
390
|
-
name: "
|
|
391
|
-
label: "
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
419
|
-
renderCall: makeProgressCallRenderer(getToolCallLabel("
|
|
420
|
-
renderResult: makeProgressResultRenderer(getToolSuccessLabel("
|
|
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 "@
|
|
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 "@
|
|
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",
|
package/assets/theme/dark.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://raw.githubusercontent.com/
|
|
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,
|
package/assets/theme/light.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://raw.githubusercontent.com/
|
|
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.
|
|
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
|
-
"@
|
|
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 `@
|
|
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
|
|
|
@@ -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, "@
|
|
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 "@
|
|
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: "@
|
|
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.
|
|
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?.["@
|
|
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
|
-
"@
|
|
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 @
|
|
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 @
|
|
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 "@
|
|
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
|
-
{
|
|
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 =
|
|
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
|
|
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
|
-
"@
|
|
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
|
|
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
|
|
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 "@
|
|
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 "@
|
|
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 "@
|
|
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 */
|
|
@@ -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 "@
|
|
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 "@
|
|
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 "@
|
|
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";
|
package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/login-dialog.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container, Input, Spacer, Text } from "@
|
|
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";
|
package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/oauth-selector.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container, Spacer, TruncatedText } from "@
|
|
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";
|
package/packages/seedclub-tui/src/vendor/coding-agent/modes/interactive/components/tool-execution.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as os from "node:os";
|
|
2
|
-
import { Box, Container, getCapabilities, getImageDimensions, Image, imageFallback, Spacer, Text, truncateToWidth, } from "@
|
|
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";
|
|
@@ -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 "@
|
|
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/
|
|
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/
|
|
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("@
|
|
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?.["@
|
|
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
|
);
|