@growthub/cli 0.3.41 → 0.3.43
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/README.md +87 -220
- package/assets/shared-templates/ad-formats/INDEX.md +94 -0
- package/assets/shared-templates/ad-formats/bedroom-minimic-talk.md +197 -0
- package/assets/shared-templates/ad-formats/frame-analysis.md +209 -0
- package/assets/shared-templates/ad-formats/process-specialist-medical.md +105 -0
- package/assets/shared-templates/ad-formats/villain-animation.md +183 -0
- package/assets/shared-templates/manifest.json +23 -0
- package/assets/shared-templates/scene-modules/INDEX.md +151 -0
- package/assets/shared-templates/scene-modules/body/before-after-flatlay.md +143 -0
- package/assets/shared-templates/scene-modules/body/minimic-problem.md +109 -0
- package/assets/shared-templates/scene-modules/body/product-demo-glow.md +123 -0
- package/assets/shared-templates/scene-modules/body/tiktok-skeptic-pivot.md +119 -0
- package/assets/shared-templates/scene-modules/body/villain-agitation.md +156 -0
- package/assets/shared-templates/scene-modules/cta/bogo-meme-bookend.md +144 -0
- package/assets/shared-templates/scene-modules/cta/guarantee-close.md +143 -0
- package/assets/shared-templates/scene-modules/hooks/dollar-amount.md +105 -0
- package/assets/shared-templates/scene-modules/hooks/meme-overlay.md +104 -0
- package/assets/shared-templates/scene-modules/hooks/pov-confession.md +92 -0
- package/assets/shared-templates/scene-modules/hooks/tiktok-comment.md +116 -0
- package/assets/shared-templates/scene-modules/hooks/villain-hook.md +134 -0
- package/dist/index.js +2606 -600
- package/package.json +4 -4
- package/dist/index.js.map +0 -7
package/dist/index.js
CHANGED
|
@@ -10,15 +10,15 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// ../packages/shared/src/constants.ts
|
|
13
|
-
var COMPANY_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES,
|
|
13
|
+
var COMPANY_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, AUTH_BASE_URL_MODES, SURFACE_PROFILES, AGENT_STATUSES, AGENT_ADAPTER_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, TICKET_STAGE_KINDS, TICKET_STAGE_HANDOFF_MODES, TICKET_STATUSES, ISSUE_STATUSES, ISSUE_PRIORITIES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, APPROVAL_TYPES, SECRET_PROVIDERS, STORAGE_PROVIDERS, BILLING_TYPES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_UI_SLOT_TYPES, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
|
|
14
14
|
var init_constants = __esm({
|
|
15
15
|
"../packages/shared/src/constants.ts"() {
|
|
16
16
|
"use strict";
|
|
17
17
|
COMPANY_STATUSES = ["active", "paused", "archived"];
|
|
18
18
|
DEPLOYMENT_MODES = ["local_trusted", "authenticated"];
|
|
19
19
|
DEPLOYMENT_EXPOSURES = ["private", "public"];
|
|
20
|
-
SURFACE_PROFILES = ["dx", "gtm"];
|
|
21
20
|
AUTH_BASE_URL_MODES = ["auto", "explicit"];
|
|
21
|
+
SURFACE_PROFILES = ["dx", "gtm"];
|
|
22
22
|
AGENT_STATUSES = [
|
|
23
23
|
"active",
|
|
24
24
|
"paused",
|
|
@@ -95,9 +95,24 @@ var init_constants = __esm({
|
|
|
95
95
|
"pentagon",
|
|
96
96
|
"fingerprint"
|
|
97
97
|
];
|
|
98
|
+
TICKET_STAGE_KINDS = [
|
|
99
|
+
"planning",
|
|
100
|
+
"execution",
|
|
101
|
+
"review",
|
|
102
|
+
"qa",
|
|
103
|
+
"human",
|
|
104
|
+
"custom"
|
|
105
|
+
];
|
|
106
|
+
TICKET_STAGE_HANDOFF_MODES = [
|
|
107
|
+
"seamless",
|
|
108
|
+
"context_only",
|
|
109
|
+
"manual"
|
|
110
|
+
];
|
|
98
111
|
TICKET_STATUSES = [
|
|
99
112
|
"active",
|
|
100
113
|
"paused",
|
|
114
|
+
"completed",
|
|
115
|
+
"archived",
|
|
101
116
|
"done",
|
|
102
117
|
"cancelled"
|
|
103
118
|
];
|
|
@@ -893,17 +908,63 @@ var init_execution_workspace = __esm({
|
|
|
893
908
|
}
|
|
894
909
|
});
|
|
895
910
|
|
|
911
|
+
// ../packages/shared/src/ticket-stages.ts
|
|
912
|
+
function normalizeTicketStageKey(value) {
|
|
913
|
+
return value.trim().toLowerCase().replace(/\s+/g, "_");
|
|
914
|
+
}
|
|
915
|
+
var init_ticket_stages = __esm({
|
|
916
|
+
"../packages/shared/src/ticket-stages.ts"() {
|
|
917
|
+
"use strict";
|
|
918
|
+
init_constants();
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
|
|
896
922
|
// ../packages/shared/src/validators/ticket.ts
|
|
897
923
|
import { z as z11 } from "zod";
|
|
898
|
-
var createTicketSchema, updateTicketSchema, advanceTicketStageSchema;
|
|
924
|
+
var ticketStageDefinitionSchema, ticketStageDefinitionsSchema, createTicketSchema, updateTicketSchema, advanceTicketStageSchema;
|
|
899
925
|
var init_ticket = __esm({
|
|
900
926
|
"../packages/shared/src/validators/ticket.ts"() {
|
|
901
927
|
"use strict";
|
|
902
928
|
init_constants();
|
|
929
|
+
init_ticket_stages();
|
|
930
|
+
ticketStageDefinitionSchema = z11.object({
|
|
931
|
+
key: z11.string().min(1),
|
|
932
|
+
label: z11.string().min(1).max(120),
|
|
933
|
+
kind: z11.enum(TICKET_STAGE_KINDS).nullable().optional(),
|
|
934
|
+
ownerRole: z11.enum(AGENT_ROLES).nullable().optional(),
|
|
935
|
+
handoffMode: z11.enum(TICKET_STAGE_HANDOFF_MODES).nullable().optional(),
|
|
936
|
+
instructions: z11.string().nullable().optional(),
|
|
937
|
+
exitCriteria: z11.string().nullable().optional(),
|
|
938
|
+
metadata: z11.record(z11.unknown()).nullable().optional()
|
|
939
|
+
});
|
|
940
|
+
ticketStageDefinitionsSchema = z11.array(ticketStageDefinitionSchema).min(1).superRefine((value, ctx) => {
|
|
941
|
+
const seen = /* @__PURE__ */ new Set();
|
|
942
|
+
value.forEach((definition, index51) => {
|
|
943
|
+
const normalizedKey = normalizeTicketStageKey(String(definition.key));
|
|
944
|
+
if (!normalizedKey) {
|
|
945
|
+
ctx.addIssue({
|
|
946
|
+
code: z11.ZodIssueCode.custom,
|
|
947
|
+
path: [index51, "key"],
|
|
948
|
+
message: "Stage key must not be empty"
|
|
949
|
+
});
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
if (seen.has(normalizedKey)) {
|
|
953
|
+
ctx.addIssue({
|
|
954
|
+
code: z11.ZodIssueCode.custom,
|
|
955
|
+
path: [index51, "key"],
|
|
956
|
+
message: "Stage keys must be unique"
|
|
957
|
+
});
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
seen.add(normalizedKey);
|
|
961
|
+
});
|
|
962
|
+
});
|
|
903
963
|
createTicketSchema = z11.object({
|
|
904
964
|
title: z11.string().min(1).max(500),
|
|
905
965
|
description: z11.string().optional(),
|
|
906
|
-
stageOrder: z11.array(z11.string().min(1)).optional(),
|
|
966
|
+
stageOrder: z11.array(z11.string().min(1)).min(1).optional(),
|
|
967
|
+
stageDefinitions: ticketStageDefinitionsSchema.optional(),
|
|
907
968
|
metadata: z11.record(z11.unknown()).optional(),
|
|
908
969
|
instructions: z11.string().optional(),
|
|
909
970
|
leadAgentId: z11.string().uuid().nullable().optional()
|
|
@@ -913,7 +974,8 @@ var init_ticket = __esm({
|
|
|
913
974
|
description: z11.string().nullable().optional(),
|
|
914
975
|
status: z11.enum(TICKET_STATUSES).optional(),
|
|
915
976
|
currentStage: z11.string().min(1).optional(),
|
|
916
|
-
stageOrder: z11.array(z11.string().min(1)).optional(),
|
|
977
|
+
stageOrder: z11.array(z11.string().min(1)).min(1).optional(),
|
|
978
|
+
stageDefinitions: ticketStageDefinitionsSchema.optional(),
|
|
917
979
|
metadata: z11.record(z11.unknown()).optional(),
|
|
918
980
|
instructions: z11.string().optional(),
|
|
919
981
|
leadAgentId: z11.string().uuid().nullable().optional()
|
|
@@ -1619,11 +1681,11 @@ var init_config_schema = __esm({
|
|
|
1619
1681
|
baseUrlMode: z19.enum(AUTH_BASE_URL_MODES).default("auto"),
|
|
1620
1682
|
publicBaseUrl: z19.string().url().optional(),
|
|
1621
1683
|
disableSignUp: z19.boolean().default(false),
|
|
1622
|
-
token: z19.string().
|
|
1684
|
+
token: z19.string().optional(),
|
|
1623
1685
|
growthubBaseUrl: z19.string().url().optional(),
|
|
1624
1686
|
growthubPortalBaseUrl: z19.string().url().optional(),
|
|
1625
|
-
growthubMachineLabel: z19.string().
|
|
1626
|
-
growthubWorkspaceLabel: z19.string().
|
|
1687
|
+
growthubMachineLabel: z19.string().optional(),
|
|
1688
|
+
growthubWorkspaceLabel: z19.string().optional()
|
|
1627
1689
|
});
|
|
1628
1690
|
surfaceConfigSchema = z19.object({
|
|
1629
1691
|
profile: z19.enum(SURFACE_PROFILES).default("dx")
|
|
@@ -1768,6 +1830,13 @@ var init_surface_runtime = __esm({
|
|
|
1768
1830
|
}
|
|
1769
1831
|
});
|
|
1770
1832
|
|
|
1833
|
+
// ../packages/shared/src/agent-surface-metadata.ts
|
|
1834
|
+
var init_agent_surface_metadata = __esm({
|
|
1835
|
+
"../packages/shared/src/agent-surface-metadata.ts"() {
|
|
1836
|
+
"use strict";
|
|
1837
|
+
}
|
|
1838
|
+
});
|
|
1839
|
+
|
|
1771
1840
|
// ../packages/shared/src/gtm.ts
|
|
1772
1841
|
function humanizeToken(value) {
|
|
1773
1842
|
return value.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w/g, (match) => match.toUpperCase());
|
|
@@ -1860,7 +1929,7 @@ function coerceGtmState(raw) {
|
|
|
1860
1929
|
...candidate.knowledge?.table?.metadata
|
|
1861
1930
|
}
|
|
1862
1931
|
},
|
|
1863
|
-
items: Array.isArray(candidate.knowledge?.items) && candidate.knowledge.items.length > 0 ? candidate.knowledge.items.map((item,
|
|
1932
|
+
items: Array.isArray(candidate.knowledge?.items) && candidate.knowledge.items.length > 0 ? candidate.knowledge.items.map((item, index51) => ({
|
|
1864
1933
|
...fallbackItemTemplate,
|
|
1865
1934
|
...item,
|
|
1866
1935
|
metadata: {
|
|
@@ -1869,7 +1938,7 @@ function coerceGtmState(raw) {
|
|
|
1869
1938
|
}
|
|
1870
1939
|
})) : fallback.knowledge.items
|
|
1871
1940
|
},
|
|
1872
|
-
connectors: Array.isArray(candidate.connectors) && candidate.connectors.length > 0 ? candidate.connectors.map((connector,
|
|
1941
|
+
connectors: Array.isArray(candidate.connectors) && candidate.connectors.length > 0 ? candidate.connectors.map((connector, index51) => ({
|
|
1873
1942
|
...fallbackConnectorTemplate,
|
|
1874
1943
|
...connector,
|
|
1875
1944
|
config: {
|
|
@@ -1937,6 +2006,54 @@ var init_gtm = __esm({
|
|
|
1937
2006
|
}
|
|
1938
2007
|
});
|
|
1939
2008
|
|
|
2009
|
+
// ../packages/shared/src/growthub-query-engine.ts
|
|
2010
|
+
var init_growthub_query_engine = __esm({
|
|
2011
|
+
"../packages/shared/src/growthub-query-engine.ts"() {
|
|
2012
|
+
"use strict";
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
|
|
2016
|
+
// ../packages/shared/src/kb-skill-bundle/types.ts
|
|
2017
|
+
var init_types = __esm({
|
|
2018
|
+
"../packages/shared/src/kb-skill-bundle/types.ts"() {
|
|
2019
|
+
"use strict";
|
|
2020
|
+
}
|
|
2021
|
+
});
|
|
2022
|
+
|
|
2023
|
+
// ../packages/shared/src/kb-skill-bundle/metadata.ts
|
|
2024
|
+
var init_metadata = __esm({
|
|
2025
|
+
"../packages/shared/src/kb-skill-bundle/metadata.ts"() {
|
|
2026
|
+
"use strict";
|
|
2027
|
+
}
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
// ../packages/shared/src/kb-skill-bundle/bundle.ts
|
|
2031
|
+
var init_bundle = __esm({
|
|
2032
|
+
"../packages/shared/src/kb-skill-bundle/bundle.ts"() {
|
|
2033
|
+
"use strict";
|
|
2034
|
+
init_types();
|
|
2035
|
+
}
|
|
2036
|
+
});
|
|
2037
|
+
|
|
2038
|
+
// ../packages/shared/src/kb-skill-bundle/prompt.ts
|
|
2039
|
+
var init_prompt = __esm({
|
|
2040
|
+
"../packages/shared/src/kb-skill-bundle/prompt.ts"() {
|
|
2041
|
+
"use strict";
|
|
2042
|
+
init_bundle();
|
|
2043
|
+
}
|
|
2044
|
+
});
|
|
2045
|
+
|
|
2046
|
+
// ../packages/shared/src/kb-skill-bundle/index.ts
|
|
2047
|
+
var init_kb_skill_bundle = __esm({
|
|
2048
|
+
"../packages/shared/src/kb-skill-bundle/index.ts"() {
|
|
2049
|
+
"use strict";
|
|
2050
|
+
init_types();
|
|
2051
|
+
init_metadata();
|
|
2052
|
+
init_bundle();
|
|
2053
|
+
init_prompt();
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
|
|
1940
2057
|
// ../packages/shared/src/index.ts
|
|
1941
2058
|
var init_src = __esm({
|
|
1942
2059
|
"../packages/shared/src/index.ts"() {
|
|
@@ -1950,7 +2067,11 @@ var init_src = __esm({
|
|
|
1950
2067
|
init_project_mentions();
|
|
1951
2068
|
init_config_schema();
|
|
1952
2069
|
init_surface_runtime();
|
|
2070
|
+
init_ticket_stages();
|
|
2071
|
+
init_agent_surface_metadata();
|
|
1953
2072
|
init_gtm();
|
|
2073
|
+
init_growthub_query_engine();
|
|
2074
|
+
init_kb_skill_bundle();
|
|
1954
2075
|
}
|
|
1955
2076
|
});
|
|
1956
2077
|
|
|
@@ -4474,8 +4595,38 @@ var init_documents = __esm({
|
|
|
4474
4595
|
}
|
|
4475
4596
|
});
|
|
4476
4597
|
|
|
4598
|
+
// ../packages/db/src/schema/kb_skill_docs.ts
|
|
4599
|
+
import { pgTable as pgTable38, uuid as uuid37, text as text39, boolean as boolean8, timestamp as timestamp38, index as index34, jsonb as jsonb20 } from "drizzle-orm/pg-core";
|
|
4600
|
+
var kbSkillDocs;
|
|
4601
|
+
var init_kb_skill_docs = __esm({
|
|
4602
|
+
"../packages/db/src/schema/kb_skill_docs.ts"() {
|
|
4603
|
+
"use strict";
|
|
4604
|
+
init_companies();
|
|
4605
|
+
kbSkillDocs = pgTable38(
|
|
4606
|
+
"kb_skill_docs",
|
|
4607
|
+
{
|
|
4608
|
+
id: uuid37("id").primaryKey().defaultRandom(),
|
|
4609
|
+
companyId: uuid37("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
|
|
4610
|
+
name: text39("name").notNull(),
|
|
4611
|
+
description: text39("description").notNull().default(""),
|
|
4612
|
+
body: text39("body").notNull().default(""),
|
|
4613
|
+
format: text39("format").notNull().default("markdown"),
|
|
4614
|
+
source: text39("source").notNull().default("custom"),
|
|
4615
|
+
metadata: jsonb20("metadata").$type().notNull().default({}),
|
|
4616
|
+
isActive: boolean8("is_active").notNull().default(true),
|
|
4617
|
+
createdAt: timestamp38("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4618
|
+
updatedAt: timestamp38("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4619
|
+
},
|
|
4620
|
+
(table) => ({
|
|
4621
|
+
companyActiveIdx: index34("kb_skill_docs_company_active_idx").on(table.companyId, table.isActive),
|
|
4622
|
+
companyUpdatedIdx: index34("kb_skill_docs_company_updated_idx").on(table.companyId, table.updatedAt)
|
|
4623
|
+
})
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
});
|
|
4627
|
+
|
|
4477
4628
|
// ../packages/db/src/schema/document_revisions.ts
|
|
4478
|
-
import { pgTable as
|
|
4629
|
+
import { pgTable as pgTable39, uuid as uuid38, text as text40, integer as integer12, timestamp as timestamp39, index as index35, uniqueIndex as uniqueIndex18 } from "drizzle-orm/pg-core";
|
|
4479
4630
|
var documentRevisions;
|
|
4480
4631
|
var init_document_revisions = __esm({
|
|
4481
4632
|
"../packages/db/src/schema/document_revisions.ts"() {
|
|
@@ -4483,25 +4634,25 @@ var init_document_revisions = __esm({
|
|
|
4483
4634
|
init_companies();
|
|
4484
4635
|
init_agents();
|
|
4485
4636
|
init_documents();
|
|
4486
|
-
documentRevisions =
|
|
4637
|
+
documentRevisions = pgTable39(
|
|
4487
4638
|
"document_revisions",
|
|
4488
4639
|
{
|
|
4489
|
-
id:
|
|
4490
|
-
companyId:
|
|
4491
|
-
documentId:
|
|
4640
|
+
id: uuid38("id").primaryKey().defaultRandom(),
|
|
4641
|
+
companyId: uuid38("company_id").notNull().references(() => companies.id),
|
|
4642
|
+
documentId: uuid38("document_id").notNull().references(() => documents.id, { onDelete: "cascade" }),
|
|
4492
4643
|
revisionNumber: integer12("revision_number").notNull(),
|
|
4493
|
-
body:
|
|
4494
|
-
changeSummary:
|
|
4495
|
-
createdByAgentId:
|
|
4496
|
-
createdByUserId:
|
|
4497
|
-
createdAt:
|
|
4644
|
+
body: text40("body").notNull(),
|
|
4645
|
+
changeSummary: text40("change_summary"),
|
|
4646
|
+
createdByAgentId: uuid38("created_by_agent_id").references(() => agents.id, { onDelete: "set null" }),
|
|
4647
|
+
createdByUserId: text40("created_by_user_id"),
|
|
4648
|
+
createdAt: timestamp39("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
4498
4649
|
},
|
|
4499
4650
|
(table) => ({
|
|
4500
4651
|
documentRevisionUq: uniqueIndex18("document_revisions_document_revision_uq").on(
|
|
4501
4652
|
table.documentId,
|
|
4502
4653
|
table.revisionNumber
|
|
4503
4654
|
),
|
|
4504
|
-
companyDocumentCreatedIdx:
|
|
4655
|
+
companyDocumentCreatedIdx: index35("document_revisions_company_document_created_idx").on(
|
|
4505
4656
|
table.companyId,
|
|
4506
4657
|
table.documentId,
|
|
4507
4658
|
table.createdAt
|
|
@@ -4512,7 +4663,7 @@ var init_document_revisions = __esm({
|
|
|
4512
4663
|
});
|
|
4513
4664
|
|
|
4514
4665
|
// ../packages/db/src/schema/issue_documents.ts
|
|
4515
|
-
import { pgTable as
|
|
4666
|
+
import { pgTable as pgTable40, uuid as uuid39, text as text41, timestamp as timestamp40, index as index36, uniqueIndex as uniqueIndex19 } from "drizzle-orm/pg-core";
|
|
4516
4667
|
var issueDocuments;
|
|
4517
4668
|
var init_issue_documents = __esm({
|
|
4518
4669
|
"../packages/db/src/schema/issue_documents.ts"() {
|
|
@@ -4520,16 +4671,16 @@ var init_issue_documents = __esm({
|
|
|
4520
4671
|
init_companies();
|
|
4521
4672
|
init_issues();
|
|
4522
4673
|
init_documents();
|
|
4523
|
-
issueDocuments =
|
|
4674
|
+
issueDocuments = pgTable40(
|
|
4524
4675
|
"issue_documents",
|
|
4525
4676
|
{
|
|
4526
|
-
id:
|
|
4527
|
-
companyId:
|
|
4528
|
-
issueId:
|
|
4529
|
-
documentId:
|
|
4530
|
-
key:
|
|
4531
|
-
createdAt:
|
|
4532
|
-
updatedAt:
|
|
4677
|
+
id: uuid39("id").primaryKey().defaultRandom(),
|
|
4678
|
+
companyId: uuid39("company_id").notNull().references(() => companies.id),
|
|
4679
|
+
issueId: uuid39("issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
4680
|
+
documentId: uuid39("document_id").notNull().references(() => documents.id, { onDelete: "cascade" }),
|
|
4681
|
+
key: text41("key").notNull(),
|
|
4682
|
+
createdAt: timestamp40("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4683
|
+
updatedAt: timestamp40("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4533
4684
|
},
|
|
4534
4685
|
(table) => ({
|
|
4535
4686
|
companyIssueKeyUq: uniqueIndex19("issue_documents_company_issue_key_uq").on(
|
|
@@ -4538,7 +4689,7 @@ var init_issue_documents = __esm({
|
|
|
4538
4689
|
table.key
|
|
4539
4690
|
),
|
|
4540
4691
|
documentUq: uniqueIndex19("issue_documents_document_uq").on(table.documentId),
|
|
4541
|
-
companyIssueUpdatedIdx:
|
|
4692
|
+
companyIssueUpdatedIdx: index36("issue_documents_company_issue_updated_idx").on(
|
|
4542
4693
|
table.companyId,
|
|
4543
4694
|
table.issueId,
|
|
4544
4695
|
table.updatedAt
|
|
@@ -4549,7 +4700,7 @@ var init_issue_documents = __esm({
|
|
|
4549
4700
|
});
|
|
4550
4701
|
|
|
4551
4702
|
// ../packages/db/src/schema/heartbeat_run_events.ts
|
|
4552
|
-
import { pgTable as
|
|
4703
|
+
import { pgTable as pgTable41, uuid as uuid40, text as text42, timestamp as timestamp41, integer as integer13, jsonb as jsonb21, index as index37, bigserial } from "drizzle-orm/pg-core";
|
|
4553
4704
|
var heartbeatRunEvents;
|
|
4554
4705
|
var init_heartbeat_run_events = __esm({
|
|
4555
4706
|
"../packages/db/src/schema/heartbeat_run_events.ts"() {
|
|
@@ -4557,33 +4708,33 @@ var init_heartbeat_run_events = __esm({
|
|
|
4557
4708
|
init_companies();
|
|
4558
4709
|
init_agents();
|
|
4559
4710
|
init_heartbeat_runs();
|
|
4560
|
-
heartbeatRunEvents =
|
|
4711
|
+
heartbeatRunEvents = pgTable41(
|
|
4561
4712
|
"heartbeat_run_events",
|
|
4562
4713
|
{
|
|
4563
4714
|
id: bigserial("id", { mode: "number" }).primaryKey(),
|
|
4564
|
-
companyId:
|
|
4565
|
-
runId:
|
|
4566
|
-
agentId:
|
|
4715
|
+
companyId: uuid40("company_id").notNull().references(() => companies.id),
|
|
4716
|
+
runId: uuid40("run_id").notNull().references(() => heartbeatRuns.id),
|
|
4717
|
+
agentId: uuid40("agent_id").notNull().references(() => agents.id),
|
|
4567
4718
|
seq: integer13("seq").notNull(),
|
|
4568
|
-
eventType:
|
|
4569
|
-
stream:
|
|
4570
|
-
level:
|
|
4571
|
-
color:
|
|
4572
|
-
message:
|
|
4573
|
-
payload:
|
|
4574
|
-
createdAt:
|
|
4719
|
+
eventType: text42("event_type").notNull(),
|
|
4720
|
+
stream: text42("stream"),
|
|
4721
|
+
level: text42("level"),
|
|
4722
|
+
color: text42("color"),
|
|
4723
|
+
message: text42("message"),
|
|
4724
|
+
payload: jsonb21("payload").$type(),
|
|
4725
|
+
createdAt: timestamp41("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
4575
4726
|
},
|
|
4576
4727
|
(table) => ({
|
|
4577
|
-
runSeqIdx:
|
|
4578
|
-
companyRunIdx:
|
|
4579
|
-
companyCreatedIdx:
|
|
4728
|
+
runSeqIdx: index37("heartbeat_run_events_run_seq_idx").on(table.runId, table.seq),
|
|
4729
|
+
companyRunIdx: index37("heartbeat_run_events_company_run_idx").on(table.companyId, table.runId),
|
|
4730
|
+
companyCreatedIdx: index37("heartbeat_run_events_company_created_idx").on(table.companyId, table.createdAt)
|
|
4580
4731
|
})
|
|
4581
4732
|
);
|
|
4582
4733
|
}
|
|
4583
4734
|
});
|
|
4584
4735
|
|
|
4585
4736
|
// ../packages/db/src/schema/cost_events.ts
|
|
4586
|
-
import { pgTable as
|
|
4737
|
+
import { pgTable as pgTable42, uuid as uuid41, text as text43, timestamp as timestamp42, integer as integer14, index as index38 } from "drizzle-orm/pg-core";
|
|
4587
4738
|
var costEvents;
|
|
4588
4739
|
var init_cost_events = __esm({
|
|
4589
4740
|
"../packages/db/src/schema/cost_events.ts"() {
|
|
@@ -4594,46 +4745,46 @@ var init_cost_events = __esm({
|
|
|
4594
4745
|
init_projects();
|
|
4595
4746
|
init_goals();
|
|
4596
4747
|
init_heartbeat_runs();
|
|
4597
|
-
costEvents =
|
|
4748
|
+
costEvents = pgTable42(
|
|
4598
4749
|
"cost_events",
|
|
4599
4750
|
{
|
|
4600
|
-
id:
|
|
4601
|
-
companyId:
|
|
4602
|
-
agentId:
|
|
4603
|
-
issueId:
|
|
4604
|
-
projectId:
|
|
4605
|
-
goalId:
|
|
4606
|
-
heartbeatRunId:
|
|
4607
|
-
billingCode:
|
|
4608
|
-
provider:
|
|
4609
|
-
biller:
|
|
4610
|
-
billingType:
|
|
4611
|
-
model:
|
|
4751
|
+
id: uuid41("id").primaryKey().defaultRandom(),
|
|
4752
|
+
companyId: uuid41("company_id").notNull().references(() => companies.id),
|
|
4753
|
+
agentId: uuid41("agent_id").notNull().references(() => agents.id),
|
|
4754
|
+
issueId: uuid41("issue_id").references(() => issues.id),
|
|
4755
|
+
projectId: uuid41("project_id").references(() => projects.id),
|
|
4756
|
+
goalId: uuid41("goal_id").references(() => goals.id),
|
|
4757
|
+
heartbeatRunId: uuid41("heartbeat_run_id").references(() => heartbeatRuns.id),
|
|
4758
|
+
billingCode: text43("billing_code"),
|
|
4759
|
+
provider: text43("provider").notNull(),
|
|
4760
|
+
biller: text43("biller").notNull().default("unknown"),
|
|
4761
|
+
billingType: text43("billing_type").notNull().default("unknown"),
|
|
4762
|
+
model: text43("model").notNull(),
|
|
4612
4763
|
inputTokens: integer14("input_tokens").notNull().default(0),
|
|
4613
4764
|
cachedInputTokens: integer14("cached_input_tokens").notNull().default(0),
|
|
4614
4765
|
outputTokens: integer14("output_tokens").notNull().default(0),
|
|
4615
4766
|
costCents: integer14("cost_cents").notNull(),
|
|
4616
|
-
occurredAt:
|
|
4617
|
-
createdAt:
|
|
4767
|
+
occurredAt: timestamp42("occurred_at", { withTimezone: true }).notNull(),
|
|
4768
|
+
createdAt: timestamp42("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
4618
4769
|
},
|
|
4619
4770
|
(table) => ({
|
|
4620
|
-
companyOccurredIdx:
|
|
4621
|
-
companyAgentOccurredIdx:
|
|
4771
|
+
companyOccurredIdx: index38("cost_events_company_occurred_idx").on(table.companyId, table.occurredAt),
|
|
4772
|
+
companyAgentOccurredIdx: index38("cost_events_company_agent_occurred_idx").on(
|
|
4622
4773
|
table.companyId,
|
|
4623
4774
|
table.agentId,
|
|
4624
4775
|
table.occurredAt
|
|
4625
4776
|
),
|
|
4626
|
-
companyProviderOccurredIdx:
|
|
4777
|
+
companyProviderOccurredIdx: index38("cost_events_company_provider_occurred_idx").on(
|
|
4627
4778
|
table.companyId,
|
|
4628
4779
|
table.provider,
|
|
4629
4780
|
table.occurredAt
|
|
4630
4781
|
),
|
|
4631
|
-
companyBillerOccurredIdx:
|
|
4782
|
+
companyBillerOccurredIdx: index38("cost_events_company_biller_occurred_idx").on(
|
|
4632
4783
|
table.companyId,
|
|
4633
4784
|
table.biller,
|
|
4634
4785
|
table.occurredAt
|
|
4635
4786
|
),
|
|
4636
|
-
companyHeartbeatRunIdx:
|
|
4787
|
+
companyHeartbeatRunIdx: index38("cost_events_company_heartbeat_run_idx").on(
|
|
4637
4788
|
table.companyId,
|
|
4638
4789
|
table.heartbeatRunId
|
|
4639
4790
|
)
|
|
@@ -4643,7 +4794,7 @@ var init_cost_events = __esm({
|
|
|
4643
4794
|
});
|
|
4644
4795
|
|
|
4645
4796
|
// ../packages/db/src/schema/finance_events.ts
|
|
4646
|
-
import { pgTable as
|
|
4797
|
+
import { pgTable as pgTable43, uuid as uuid42, text as text44, timestamp as timestamp43, integer as integer15, index as index39, boolean as boolean9, jsonb as jsonb22 } from "drizzle-orm/pg-core";
|
|
4647
4798
|
var financeEvents;
|
|
4648
4799
|
var init_finance_events = __esm({
|
|
4649
4800
|
"../packages/db/src/schema/finance_events.ts"() {
|
|
@@ -4655,59 +4806,59 @@ var init_finance_events = __esm({
|
|
|
4655
4806
|
init_goals();
|
|
4656
4807
|
init_heartbeat_runs();
|
|
4657
4808
|
init_cost_events();
|
|
4658
|
-
financeEvents =
|
|
4809
|
+
financeEvents = pgTable43(
|
|
4659
4810
|
"finance_events",
|
|
4660
4811
|
{
|
|
4661
|
-
id:
|
|
4662
|
-
companyId:
|
|
4663
|
-
agentId:
|
|
4664
|
-
issueId:
|
|
4665
|
-
projectId:
|
|
4666
|
-
goalId:
|
|
4667
|
-
heartbeatRunId:
|
|
4668
|
-
costEventId:
|
|
4669
|
-
billingCode:
|
|
4670
|
-
description:
|
|
4671
|
-
eventKind:
|
|
4672
|
-
direction:
|
|
4673
|
-
biller:
|
|
4674
|
-
provider:
|
|
4675
|
-
executionAdapterType:
|
|
4676
|
-
pricingTier:
|
|
4677
|
-
region:
|
|
4678
|
-
model:
|
|
4812
|
+
id: uuid42("id").primaryKey().defaultRandom(),
|
|
4813
|
+
companyId: uuid42("company_id").notNull().references(() => companies.id),
|
|
4814
|
+
agentId: uuid42("agent_id").references(() => agents.id),
|
|
4815
|
+
issueId: uuid42("issue_id").references(() => issues.id),
|
|
4816
|
+
projectId: uuid42("project_id").references(() => projects.id),
|
|
4817
|
+
goalId: uuid42("goal_id").references(() => goals.id),
|
|
4818
|
+
heartbeatRunId: uuid42("heartbeat_run_id").references(() => heartbeatRuns.id),
|
|
4819
|
+
costEventId: uuid42("cost_event_id").references(() => costEvents.id),
|
|
4820
|
+
billingCode: text44("billing_code"),
|
|
4821
|
+
description: text44("description"),
|
|
4822
|
+
eventKind: text44("event_kind").notNull(),
|
|
4823
|
+
direction: text44("direction").notNull().default("debit"),
|
|
4824
|
+
biller: text44("biller").notNull(),
|
|
4825
|
+
provider: text44("provider"),
|
|
4826
|
+
executionAdapterType: text44("execution_adapter_type"),
|
|
4827
|
+
pricingTier: text44("pricing_tier"),
|
|
4828
|
+
region: text44("region"),
|
|
4829
|
+
model: text44("model"),
|
|
4679
4830
|
quantity: integer15("quantity"),
|
|
4680
|
-
unit:
|
|
4831
|
+
unit: text44("unit"),
|
|
4681
4832
|
amountCents: integer15("amount_cents").notNull(),
|
|
4682
|
-
currency:
|
|
4683
|
-
estimated:
|
|
4684
|
-
externalInvoiceId:
|
|
4685
|
-
metadataJson:
|
|
4686
|
-
occurredAt:
|
|
4687
|
-
createdAt:
|
|
4833
|
+
currency: text44("currency").notNull().default("USD"),
|
|
4834
|
+
estimated: boolean9("estimated").notNull().default(false),
|
|
4835
|
+
externalInvoiceId: text44("external_invoice_id"),
|
|
4836
|
+
metadataJson: jsonb22("metadata_json").$type(),
|
|
4837
|
+
occurredAt: timestamp43("occurred_at", { withTimezone: true }).notNull(),
|
|
4838
|
+
createdAt: timestamp43("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
4688
4839
|
},
|
|
4689
4840
|
(table) => ({
|
|
4690
|
-
companyOccurredIdx:
|
|
4691
|
-
companyBillerOccurredIdx:
|
|
4841
|
+
companyOccurredIdx: index39("finance_events_company_occurred_idx").on(table.companyId, table.occurredAt),
|
|
4842
|
+
companyBillerOccurredIdx: index39("finance_events_company_biller_occurred_idx").on(
|
|
4692
4843
|
table.companyId,
|
|
4693
4844
|
table.biller,
|
|
4694
4845
|
table.occurredAt
|
|
4695
4846
|
),
|
|
4696
|
-
companyKindOccurredIdx:
|
|
4847
|
+
companyKindOccurredIdx: index39("finance_events_company_kind_occurred_idx").on(
|
|
4697
4848
|
table.companyId,
|
|
4698
4849
|
table.eventKind,
|
|
4699
4850
|
table.occurredAt
|
|
4700
4851
|
),
|
|
4701
|
-
companyDirectionOccurredIdx:
|
|
4852
|
+
companyDirectionOccurredIdx: index39("finance_events_company_direction_occurred_idx").on(
|
|
4702
4853
|
table.companyId,
|
|
4703
4854
|
table.direction,
|
|
4704
4855
|
table.occurredAt
|
|
4705
4856
|
),
|
|
4706
|
-
companyHeartbeatRunIdx:
|
|
4857
|
+
companyHeartbeatRunIdx: index39("finance_events_company_heartbeat_run_idx").on(
|
|
4707
4858
|
table.companyId,
|
|
4708
4859
|
table.heartbeatRunId
|
|
4709
4860
|
),
|
|
4710
|
-
companyCostEventIdx:
|
|
4861
|
+
companyCostEventIdx: index39("finance_events_company_cost_event_idx").on(
|
|
4711
4862
|
table.companyId,
|
|
4712
4863
|
table.costEventId
|
|
4713
4864
|
)
|
|
@@ -4717,7 +4868,7 @@ var init_finance_events = __esm({
|
|
|
4717
4868
|
});
|
|
4718
4869
|
|
|
4719
4870
|
// ../packages/db/src/schema/approval_comments.ts
|
|
4720
|
-
import { pgTable as
|
|
4871
|
+
import { pgTable as pgTable44, uuid as uuid43, text as text45, timestamp as timestamp44, index as index40 } from "drizzle-orm/pg-core";
|
|
4721
4872
|
var approvalComments;
|
|
4722
4873
|
var init_approval_comments = __esm({
|
|
4723
4874
|
"../packages/db/src/schema/approval_comments.ts"() {
|
|
@@ -4725,22 +4876,22 @@ var init_approval_comments = __esm({
|
|
|
4725
4876
|
init_companies();
|
|
4726
4877
|
init_approvals();
|
|
4727
4878
|
init_agents();
|
|
4728
|
-
approvalComments =
|
|
4879
|
+
approvalComments = pgTable44(
|
|
4729
4880
|
"approval_comments",
|
|
4730
4881
|
{
|
|
4731
|
-
id:
|
|
4732
|
-
companyId:
|
|
4733
|
-
approvalId:
|
|
4734
|
-
authorAgentId:
|
|
4735
|
-
authorUserId:
|
|
4736
|
-
body:
|
|
4737
|
-
createdAt:
|
|
4738
|
-
updatedAt:
|
|
4882
|
+
id: uuid43("id").primaryKey().defaultRandom(),
|
|
4883
|
+
companyId: uuid43("company_id").notNull().references(() => companies.id),
|
|
4884
|
+
approvalId: uuid43("approval_id").notNull().references(() => approvals.id),
|
|
4885
|
+
authorAgentId: uuid43("author_agent_id").references(() => agents.id),
|
|
4886
|
+
authorUserId: text45("author_user_id"),
|
|
4887
|
+
body: text45("body").notNull(),
|
|
4888
|
+
createdAt: timestamp44("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4889
|
+
updatedAt: timestamp44("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4739
4890
|
},
|
|
4740
4891
|
(table) => ({
|
|
4741
|
-
companyIdx:
|
|
4742
|
-
approvalIdx:
|
|
4743
|
-
approvalCreatedIdx:
|
|
4892
|
+
companyIdx: index40("approval_comments_company_idx").on(table.companyId),
|
|
4893
|
+
approvalIdx: index40("approval_comments_approval_idx").on(table.approvalId),
|
|
4894
|
+
approvalCreatedIdx: index40("approval_comments_approval_created_idx").on(
|
|
4744
4895
|
table.approvalId,
|
|
4745
4896
|
table.createdAt
|
|
4746
4897
|
)
|
|
@@ -4750,7 +4901,7 @@ var init_approval_comments = __esm({
|
|
|
4750
4901
|
});
|
|
4751
4902
|
|
|
4752
4903
|
// ../packages/db/src/schema/activity_log.ts
|
|
4753
|
-
import { pgTable as
|
|
4904
|
+
import { pgTable as pgTable45, uuid as uuid44, text as text46, timestamp as timestamp45, jsonb as jsonb23, index as index41 } from "drizzle-orm/pg-core";
|
|
4754
4905
|
var activityLog;
|
|
4755
4906
|
var init_activity_log = __esm({
|
|
4756
4907
|
"../packages/db/src/schema/activity_log.ts"() {
|
|
@@ -4758,56 +4909,56 @@ var init_activity_log = __esm({
|
|
|
4758
4909
|
init_companies();
|
|
4759
4910
|
init_agents();
|
|
4760
4911
|
init_heartbeat_runs();
|
|
4761
|
-
activityLog =
|
|
4912
|
+
activityLog = pgTable45(
|
|
4762
4913
|
"activity_log",
|
|
4763
4914
|
{
|
|
4764
|
-
id:
|
|
4765
|
-
companyId:
|
|
4766
|
-
actorType:
|
|
4767
|
-
actorId:
|
|
4768
|
-
action:
|
|
4769
|
-
entityType:
|
|
4770
|
-
entityId:
|
|
4771
|
-
agentId:
|
|
4772
|
-
runId:
|
|
4773
|
-
details:
|
|
4774
|
-
createdAt:
|
|
4915
|
+
id: uuid44("id").primaryKey().defaultRandom(),
|
|
4916
|
+
companyId: uuid44("company_id").notNull().references(() => companies.id),
|
|
4917
|
+
actorType: text46("actor_type").notNull().default("system"),
|
|
4918
|
+
actorId: text46("actor_id").notNull(),
|
|
4919
|
+
action: text46("action").notNull(),
|
|
4920
|
+
entityType: text46("entity_type").notNull(),
|
|
4921
|
+
entityId: text46("entity_id").notNull(),
|
|
4922
|
+
agentId: uuid44("agent_id").references(() => agents.id),
|
|
4923
|
+
runId: uuid44("run_id").references(() => heartbeatRuns.id),
|
|
4924
|
+
details: jsonb23("details").$type(),
|
|
4925
|
+
createdAt: timestamp45("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
4775
4926
|
},
|
|
4776
4927
|
(table) => ({
|
|
4777
|
-
companyCreatedIdx:
|
|
4778
|
-
runIdIdx:
|
|
4779
|
-
entityIdx:
|
|
4928
|
+
companyCreatedIdx: index41("activity_log_company_created_idx").on(table.companyId, table.createdAt),
|
|
4929
|
+
runIdIdx: index41("activity_log_run_id_idx").on(table.runId),
|
|
4930
|
+
entityIdx: index41("activity_log_entity_type_id_idx").on(table.entityType, table.entityId)
|
|
4780
4931
|
})
|
|
4781
4932
|
);
|
|
4782
4933
|
}
|
|
4783
4934
|
});
|
|
4784
4935
|
|
|
4785
4936
|
// ../packages/db/src/schema/company_secrets.ts
|
|
4786
|
-
import { pgTable as
|
|
4937
|
+
import { pgTable as pgTable46, uuid as uuid45, text as text47, timestamp as timestamp46, integer as integer16, index as index42, uniqueIndex as uniqueIndex20 } from "drizzle-orm/pg-core";
|
|
4787
4938
|
var companySecrets;
|
|
4788
4939
|
var init_company_secrets = __esm({
|
|
4789
4940
|
"../packages/db/src/schema/company_secrets.ts"() {
|
|
4790
4941
|
"use strict";
|
|
4791
4942
|
init_companies();
|
|
4792
4943
|
init_agents();
|
|
4793
|
-
companySecrets =
|
|
4944
|
+
companySecrets = pgTable46(
|
|
4794
4945
|
"company_secrets",
|
|
4795
4946
|
{
|
|
4796
|
-
id:
|
|
4797
|
-
companyId:
|
|
4798
|
-
name:
|
|
4799
|
-
provider:
|
|
4800
|
-
externalRef:
|
|
4947
|
+
id: uuid45("id").primaryKey().defaultRandom(),
|
|
4948
|
+
companyId: uuid45("company_id").notNull().references(() => companies.id),
|
|
4949
|
+
name: text47("name").notNull(),
|
|
4950
|
+
provider: text47("provider").notNull().default("local_encrypted"),
|
|
4951
|
+
externalRef: text47("external_ref"),
|
|
4801
4952
|
latestVersion: integer16("latest_version").notNull().default(1),
|
|
4802
|
-
description:
|
|
4803
|
-
createdByAgentId:
|
|
4804
|
-
createdByUserId:
|
|
4805
|
-
createdAt:
|
|
4806
|
-
updatedAt:
|
|
4953
|
+
description: text47("description"),
|
|
4954
|
+
createdByAgentId: uuid45("created_by_agent_id").references(() => agents.id, { onDelete: "set null" }),
|
|
4955
|
+
createdByUserId: text47("created_by_user_id"),
|
|
4956
|
+
createdAt: timestamp46("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4957
|
+
updatedAt: timestamp46("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4807
4958
|
},
|
|
4808
4959
|
(table) => ({
|
|
4809
|
-
companyIdx:
|
|
4810
|
-
companyProviderIdx:
|
|
4960
|
+
companyIdx: index42("company_secrets_company_idx").on(table.companyId),
|
|
4961
|
+
companyProviderIdx: index42("company_secrets_company_provider_idx").on(table.companyId, table.provider),
|
|
4811
4962
|
companyNameUq: uniqueIndex20("company_secrets_company_name_uq").on(table.companyId, table.name)
|
|
4812
4963
|
})
|
|
4813
4964
|
);
|
|
@@ -4815,29 +4966,29 @@ var init_company_secrets = __esm({
|
|
|
4815
4966
|
});
|
|
4816
4967
|
|
|
4817
4968
|
// ../packages/db/src/schema/company_secret_versions.ts
|
|
4818
|
-
import { pgTable as
|
|
4969
|
+
import { pgTable as pgTable47, uuid as uuid46, text as text48, timestamp as timestamp47, integer as integer17, jsonb as jsonb24, index as index43, uniqueIndex as uniqueIndex21 } from "drizzle-orm/pg-core";
|
|
4819
4970
|
var companySecretVersions;
|
|
4820
4971
|
var init_company_secret_versions = __esm({
|
|
4821
4972
|
"../packages/db/src/schema/company_secret_versions.ts"() {
|
|
4822
4973
|
"use strict";
|
|
4823
4974
|
init_agents();
|
|
4824
4975
|
init_company_secrets();
|
|
4825
|
-
companySecretVersions =
|
|
4976
|
+
companySecretVersions = pgTable47(
|
|
4826
4977
|
"company_secret_versions",
|
|
4827
4978
|
{
|
|
4828
|
-
id:
|
|
4829
|
-
secretId:
|
|
4979
|
+
id: uuid46("id").primaryKey().defaultRandom(),
|
|
4980
|
+
secretId: uuid46("secret_id").notNull().references(() => companySecrets.id, { onDelete: "cascade" }),
|
|
4830
4981
|
version: integer17("version").notNull(),
|
|
4831
|
-
material:
|
|
4832
|
-
valueSha256:
|
|
4833
|
-
createdByAgentId:
|
|
4834
|
-
createdByUserId:
|
|
4835
|
-
createdAt:
|
|
4836
|
-
revokedAt:
|
|
4982
|
+
material: jsonb24("material").$type().notNull(),
|
|
4983
|
+
valueSha256: text48("value_sha256").notNull(),
|
|
4984
|
+
createdByAgentId: uuid46("created_by_agent_id").references(() => agents.id, { onDelete: "set null" }),
|
|
4985
|
+
createdByUserId: text48("created_by_user_id"),
|
|
4986
|
+
createdAt: timestamp47("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4987
|
+
revokedAt: timestamp47("revoked_at", { withTimezone: true })
|
|
4837
4988
|
},
|
|
4838
4989
|
(table) => ({
|
|
4839
|
-
secretIdx:
|
|
4840
|
-
valueHashIdx:
|
|
4990
|
+
secretIdx: index43("company_secret_versions_secret_idx").on(table.secretId, table.createdAt),
|
|
4991
|
+
valueHashIdx: index43("company_secret_versions_value_sha256_idx").on(table.valueSha256),
|
|
4841
4992
|
secretVersionUq: uniqueIndex21("company_secret_versions_secret_version_uq").on(table.secretId, table.version)
|
|
4842
4993
|
})
|
|
4843
4994
|
);
|
|
@@ -4846,61 +4997,61 @@ var init_company_secret_versions = __esm({
|
|
|
4846
4997
|
|
|
4847
4998
|
// ../packages/db/src/schema/plugins.ts
|
|
4848
4999
|
import {
|
|
4849
|
-
pgTable as
|
|
4850
|
-
uuid as
|
|
4851
|
-
text as
|
|
5000
|
+
pgTable as pgTable48,
|
|
5001
|
+
uuid as uuid47,
|
|
5002
|
+
text as text49,
|
|
4852
5003
|
integer as integer18,
|
|
4853
|
-
timestamp as
|
|
4854
|
-
jsonb as
|
|
4855
|
-
index as
|
|
5004
|
+
timestamp as timestamp48,
|
|
5005
|
+
jsonb as jsonb25,
|
|
5006
|
+
index as index44,
|
|
4856
5007
|
uniqueIndex as uniqueIndex22
|
|
4857
5008
|
} from "drizzle-orm/pg-core";
|
|
4858
5009
|
var plugins;
|
|
4859
5010
|
var init_plugins = __esm({
|
|
4860
5011
|
"../packages/db/src/schema/plugins.ts"() {
|
|
4861
5012
|
"use strict";
|
|
4862
|
-
plugins =
|
|
5013
|
+
plugins = pgTable48(
|
|
4863
5014
|
"plugins",
|
|
4864
5015
|
{
|
|
4865
|
-
id:
|
|
4866
|
-
pluginKey:
|
|
4867
|
-
packageName:
|
|
4868
|
-
version:
|
|
5016
|
+
id: uuid47("id").primaryKey().defaultRandom(),
|
|
5017
|
+
pluginKey: text49("plugin_key").notNull(),
|
|
5018
|
+
packageName: text49("package_name").notNull(),
|
|
5019
|
+
version: text49("version").notNull(),
|
|
4869
5020
|
apiVersion: integer18("api_version").notNull().default(1),
|
|
4870
|
-
categories:
|
|
4871
|
-
manifestJson:
|
|
4872
|
-
status:
|
|
5021
|
+
categories: jsonb25("categories").$type().notNull().default([]),
|
|
5022
|
+
manifestJson: jsonb25("manifest_json").$type().notNull(),
|
|
5023
|
+
status: text49("status").$type().notNull().default("installed"),
|
|
4873
5024
|
installOrder: integer18("install_order"),
|
|
4874
5025
|
/** Resolved package path for local-path installs; used to find worker entrypoint. */
|
|
4875
|
-
packagePath:
|
|
4876
|
-
lastError:
|
|
4877
|
-
installedAt:
|
|
4878
|
-
updatedAt:
|
|
5026
|
+
packagePath: text49("package_path"),
|
|
5027
|
+
lastError: text49("last_error"),
|
|
5028
|
+
installedAt: timestamp48("installed_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5029
|
+
updatedAt: timestamp48("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4879
5030
|
},
|
|
4880
5031
|
(table) => ({
|
|
4881
5032
|
pluginKeyIdx: uniqueIndex22("plugins_plugin_key_idx").on(table.pluginKey),
|
|
4882
|
-
statusIdx:
|
|
5033
|
+
statusIdx: index44("plugins_status_idx").on(table.status)
|
|
4883
5034
|
})
|
|
4884
5035
|
);
|
|
4885
5036
|
}
|
|
4886
5037
|
});
|
|
4887
5038
|
|
|
4888
5039
|
// ../packages/db/src/schema/plugin_config.ts
|
|
4889
|
-
import { pgTable as
|
|
5040
|
+
import { pgTable as pgTable49, uuid as uuid48, text as text50, timestamp as timestamp49, jsonb as jsonb26, uniqueIndex as uniqueIndex23 } from "drizzle-orm/pg-core";
|
|
4890
5041
|
var pluginConfig;
|
|
4891
5042
|
var init_plugin_config = __esm({
|
|
4892
5043
|
"../packages/db/src/schema/plugin_config.ts"() {
|
|
4893
5044
|
"use strict";
|
|
4894
5045
|
init_plugins();
|
|
4895
|
-
pluginConfig =
|
|
5046
|
+
pluginConfig = pgTable49(
|
|
4896
5047
|
"plugin_config",
|
|
4897
5048
|
{
|
|
4898
|
-
id:
|
|
4899
|
-
pluginId:
|
|
4900
|
-
configJson:
|
|
4901
|
-
lastError:
|
|
4902
|
-
createdAt:
|
|
4903
|
-
updatedAt:
|
|
5049
|
+
id: uuid48("id").primaryKey().defaultRandom(),
|
|
5050
|
+
pluginId: uuid48("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5051
|
+
configJson: jsonb26("config_json").$type().notNull().default({}),
|
|
5052
|
+
lastError: text50("last_error"),
|
|
5053
|
+
createdAt: timestamp49("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5054
|
+
updatedAt: timestamp49("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4904
5055
|
},
|
|
4905
5056
|
(table) => ({
|
|
4906
5057
|
pluginIdIdx: uniqueIndex23("plugin_config_plugin_id_idx").on(table.pluginId)
|
|
@@ -4910,28 +5061,28 @@ var init_plugin_config = __esm({
|
|
|
4910
5061
|
});
|
|
4911
5062
|
|
|
4912
5063
|
// ../packages/db/src/schema/plugin_company_settings.ts
|
|
4913
|
-
import { pgTable as
|
|
5064
|
+
import { pgTable as pgTable50, uuid as uuid49, text as text51, timestamp as timestamp50, jsonb as jsonb27, index as index45, uniqueIndex as uniqueIndex24, boolean as boolean10 } from "drizzle-orm/pg-core";
|
|
4914
5065
|
var pluginCompanySettings;
|
|
4915
5066
|
var init_plugin_company_settings = __esm({
|
|
4916
5067
|
"../packages/db/src/schema/plugin_company_settings.ts"() {
|
|
4917
5068
|
"use strict";
|
|
4918
5069
|
init_companies();
|
|
4919
5070
|
init_plugins();
|
|
4920
|
-
pluginCompanySettings =
|
|
5071
|
+
pluginCompanySettings = pgTable50(
|
|
4921
5072
|
"plugin_company_settings",
|
|
4922
5073
|
{
|
|
4923
|
-
id:
|
|
4924
|
-
companyId:
|
|
4925
|
-
pluginId:
|
|
4926
|
-
enabled:
|
|
4927
|
-
settingsJson:
|
|
4928
|
-
lastError:
|
|
4929
|
-
createdAt:
|
|
4930
|
-
updatedAt:
|
|
5074
|
+
id: uuid49("id").primaryKey().defaultRandom(),
|
|
5075
|
+
companyId: uuid49("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
|
|
5076
|
+
pluginId: uuid49("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5077
|
+
enabled: boolean10("enabled").notNull().default(true),
|
|
5078
|
+
settingsJson: jsonb27("settings_json").$type().notNull().default({}),
|
|
5079
|
+
lastError: text51("last_error"),
|
|
5080
|
+
createdAt: timestamp50("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5081
|
+
updatedAt: timestamp50("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4931
5082
|
},
|
|
4932
5083
|
(table) => ({
|
|
4933
|
-
companyIdx:
|
|
4934
|
-
pluginIdx:
|
|
5084
|
+
companyIdx: index45("plugin_company_settings_company_idx").on(table.companyId),
|
|
5085
|
+
pluginIdx: index45("plugin_company_settings_plugin_idx").on(table.pluginId),
|
|
4935
5086
|
companyPluginUq: uniqueIndex24("plugin_company_settings_company_plugin_uq").on(
|
|
4936
5087
|
table.companyId,
|
|
4937
5088
|
table.pluginId
|
|
@@ -4943,12 +5094,12 @@ var init_plugin_company_settings = __esm({
|
|
|
4943
5094
|
|
|
4944
5095
|
// ../packages/db/src/schema/plugin_state.ts
|
|
4945
5096
|
import {
|
|
4946
|
-
pgTable as
|
|
4947
|
-
uuid as
|
|
4948
|
-
text as
|
|
4949
|
-
timestamp as
|
|
4950
|
-
jsonb as
|
|
4951
|
-
index as
|
|
5097
|
+
pgTable as pgTable51,
|
|
5098
|
+
uuid as uuid50,
|
|
5099
|
+
text as text52,
|
|
5100
|
+
timestamp as timestamp51,
|
|
5101
|
+
jsonb as jsonb28,
|
|
5102
|
+
index as index46,
|
|
4952
5103
|
unique as unique2
|
|
4953
5104
|
} from "drizzle-orm/pg-core";
|
|
4954
5105
|
var pluginState;
|
|
@@ -4956,30 +5107,30 @@ var init_plugin_state = __esm({
|
|
|
4956
5107
|
"../packages/db/src/schema/plugin_state.ts"() {
|
|
4957
5108
|
"use strict";
|
|
4958
5109
|
init_plugins();
|
|
4959
|
-
pluginState =
|
|
5110
|
+
pluginState = pgTable51(
|
|
4960
5111
|
"plugin_state",
|
|
4961
5112
|
{
|
|
4962
|
-
id:
|
|
5113
|
+
id: uuid50("id").primaryKey().defaultRandom(),
|
|
4963
5114
|
/** FK to the owning plugin. Cascades on delete. */
|
|
4964
|
-
pluginId:
|
|
5115
|
+
pluginId: uuid50("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
4965
5116
|
/** Granularity of the scope (e.g. `"instance"`, `"project"`, `"issue"`). */
|
|
4966
|
-
scopeKind:
|
|
5117
|
+
scopeKind: text52("scope_kind").$type().notNull(),
|
|
4967
5118
|
/**
|
|
4968
5119
|
* UUID or text identifier for the scoped object.
|
|
4969
5120
|
* Null for `instance` scope (which has no associated entity).
|
|
4970
5121
|
*/
|
|
4971
|
-
scopeId:
|
|
5122
|
+
scopeId: text52("scope_id"),
|
|
4972
5123
|
/**
|
|
4973
5124
|
* Sub-namespace to avoid key collisions within a scope.
|
|
4974
5125
|
* Defaults to `"default"` if the plugin does not specify one.
|
|
4975
5126
|
*/
|
|
4976
|
-
namespace:
|
|
5127
|
+
namespace: text52("namespace").notNull().default("default"),
|
|
4977
5128
|
/** The key identifying this state entry within the namespace. */
|
|
4978
|
-
stateKey:
|
|
5129
|
+
stateKey: text52("state_key").notNull(),
|
|
4979
5130
|
/** JSON-serializable value stored by the plugin. */
|
|
4980
|
-
valueJson:
|
|
5131
|
+
valueJson: jsonb28("value_json").notNull(),
|
|
4981
5132
|
/** Timestamp of the most recent write. */
|
|
4982
|
-
updatedAt:
|
|
5133
|
+
updatedAt: timestamp51("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4983
5134
|
},
|
|
4984
5135
|
(table) => ({
|
|
4985
5136
|
/**
|
|
@@ -5001,7 +5152,7 @@ var init_plugin_state = __esm({
|
|
|
5001
5152
|
table.stateKey
|
|
5002
5153
|
).nullsNotDistinct(),
|
|
5003
5154
|
/** Speed up lookups by plugin + scope kind (most common access pattern). */
|
|
5004
|
-
pluginScopeIdx:
|
|
5155
|
+
pluginScopeIdx: index46("plugin_state_plugin_scope_idx").on(
|
|
5005
5156
|
table.pluginId,
|
|
5006
5157
|
table.scopeKind
|
|
5007
5158
|
)
|
|
@@ -5012,12 +5163,12 @@ var init_plugin_state = __esm({
|
|
|
5012
5163
|
|
|
5013
5164
|
// ../packages/db/src/schema/plugin_entities.ts
|
|
5014
5165
|
import {
|
|
5015
|
-
pgTable as
|
|
5016
|
-
uuid as
|
|
5017
|
-
text as
|
|
5018
|
-
timestamp as
|
|
5019
|
-
jsonb as
|
|
5020
|
-
index as
|
|
5166
|
+
pgTable as pgTable52,
|
|
5167
|
+
uuid as uuid51,
|
|
5168
|
+
text as text53,
|
|
5169
|
+
timestamp as timestamp52,
|
|
5170
|
+
jsonb as jsonb29,
|
|
5171
|
+
index as index47,
|
|
5021
5172
|
uniqueIndex as uniqueIndex25
|
|
5022
5173
|
} from "drizzle-orm/pg-core";
|
|
5023
5174
|
var pluginEntities;
|
|
@@ -5025,27 +5176,27 @@ var init_plugin_entities = __esm({
|
|
|
5025
5176
|
"../packages/db/src/schema/plugin_entities.ts"() {
|
|
5026
5177
|
"use strict";
|
|
5027
5178
|
init_plugins();
|
|
5028
|
-
pluginEntities =
|
|
5179
|
+
pluginEntities = pgTable52(
|
|
5029
5180
|
"plugin_entities",
|
|
5030
5181
|
{
|
|
5031
|
-
id:
|
|
5032
|
-
pluginId:
|
|
5033
|
-
entityType:
|
|
5034
|
-
scopeKind:
|
|
5035
|
-
scopeId:
|
|
5182
|
+
id: uuid51("id").primaryKey().defaultRandom(),
|
|
5183
|
+
pluginId: uuid51("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5184
|
+
entityType: text53("entity_type").notNull(),
|
|
5185
|
+
scopeKind: text53("scope_kind").$type().notNull(),
|
|
5186
|
+
scopeId: text53("scope_id"),
|
|
5036
5187
|
// NULL for global scope (text to match plugin_state.scope_id)
|
|
5037
|
-
externalId:
|
|
5188
|
+
externalId: text53("external_id"),
|
|
5038
5189
|
// ID in the external system
|
|
5039
|
-
title:
|
|
5040
|
-
status:
|
|
5041
|
-
data:
|
|
5042
|
-
createdAt:
|
|
5043
|
-
updatedAt:
|
|
5190
|
+
title: text53("title"),
|
|
5191
|
+
status: text53("status"),
|
|
5192
|
+
data: jsonb29("data").$type().notNull().default({}),
|
|
5193
|
+
createdAt: timestamp52("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5194
|
+
updatedAt: timestamp52("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5044
5195
|
},
|
|
5045
5196
|
(table) => ({
|
|
5046
|
-
pluginIdx:
|
|
5047
|
-
typeIdx:
|
|
5048
|
-
scopeIdx:
|
|
5197
|
+
pluginIdx: index47("plugin_entities_plugin_idx").on(table.pluginId),
|
|
5198
|
+
typeIdx: index47("plugin_entities_type_idx").on(table.entityType),
|
|
5199
|
+
scopeIdx: index47("plugin_entities_scope_idx").on(table.scopeKind, table.scopeId),
|
|
5049
5200
|
externalIdx: uniqueIndex25("plugin_entities_external_idx").on(
|
|
5050
5201
|
table.pluginId,
|
|
5051
5202
|
table.entityType,
|
|
@@ -5058,13 +5209,13 @@ var init_plugin_entities = __esm({
|
|
|
5058
5209
|
|
|
5059
5210
|
// ../packages/db/src/schema/plugin_jobs.ts
|
|
5060
5211
|
import {
|
|
5061
|
-
pgTable as
|
|
5062
|
-
uuid as
|
|
5063
|
-
text as
|
|
5212
|
+
pgTable as pgTable53,
|
|
5213
|
+
uuid as uuid52,
|
|
5214
|
+
text as text54,
|
|
5064
5215
|
integer as integer19,
|
|
5065
|
-
timestamp as
|
|
5066
|
-
jsonb as
|
|
5067
|
-
index as
|
|
5216
|
+
timestamp as timestamp53,
|
|
5217
|
+
jsonb as jsonb30,
|
|
5218
|
+
index as index48,
|
|
5068
5219
|
uniqueIndex as uniqueIndex26
|
|
5069
5220
|
} from "drizzle-orm/pg-core";
|
|
5070
5221
|
var pluginJobs, pluginJobRuns;
|
|
@@ -5072,57 +5223,57 @@ var init_plugin_jobs = __esm({
|
|
|
5072
5223
|
"../packages/db/src/schema/plugin_jobs.ts"() {
|
|
5073
5224
|
"use strict";
|
|
5074
5225
|
init_plugins();
|
|
5075
|
-
pluginJobs =
|
|
5226
|
+
pluginJobs = pgTable53(
|
|
5076
5227
|
"plugin_jobs",
|
|
5077
5228
|
{
|
|
5078
|
-
id:
|
|
5229
|
+
id: uuid52("id").primaryKey().defaultRandom(),
|
|
5079
5230
|
/** FK to the owning plugin. Cascades on delete. */
|
|
5080
|
-
pluginId:
|
|
5231
|
+
pluginId: uuid52("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5081
5232
|
/** Identifier matching the key in the plugin manifest's `jobs` array. */
|
|
5082
|
-
jobKey:
|
|
5233
|
+
jobKey: text54("job_key").notNull(),
|
|
5083
5234
|
/** Cron expression (e.g. `"0 * * * *"`) or interval string. */
|
|
5084
|
-
schedule:
|
|
5235
|
+
schedule: text54("schedule").notNull(),
|
|
5085
5236
|
/** Current scheduling state. */
|
|
5086
|
-
status:
|
|
5237
|
+
status: text54("status").$type().notNull().default("active"),
|
|
5087
5238
|
/** Timestamp of the most recent successful execution. */
|
|
5088
|
-
lastRunAt:
|
|
5239
|
+
lastRunAt: timestamp53("last_run_at", { withTimezone: true }),
|
|
5089
5240
|
/** Pre-computed timestamp of the next scheduled execution. */
|
|
5090
|
-
nextRunAt:
|
|
5091
|
-
createdAt:
|
|
5092
|
-
updatedAt:
|
|
5241
|
+
nextRunAt: timestamp53("next_run_at", { withTimezone: true }),
|
|
5242
|
+
createdAt: timestamp53("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5243
|
+
updatedAt: timestamp53("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5093
5244
|
},
|
|
5094
5245
|
(table) => ({
|
|
5095
|
-
pluginIdx:
|
|
5096
|
-
nextRunIdx:
|
|
5246
|
+
pluginIdx: index48("plugin_jobs_plugin_idx").on(table.pluginId),
|
|
5247
|
+
nextRunIdx: index48("plugin_jobs_next_run_idx").on(table.nextRunAt),
|
|
5097
5248
|
uniqueJobIdx: uniqueIndex26("plugin_jobs_unique_idx").on(table.pluginId, table.jobKey)
|
|
5098
5249
|
})
|
|
5099
5250
|
);
|
|
5100
|
-
pluginJobRuns =
|
|
5251
|
+
pluginJobRuns = pgTable53(
|
|
5101
5252
|
"plugin_job_runs",
|
|
5102
5253
|
{
|
|
5103
|
-
id:
|
|
5254
|
+
id: uuid52("id").primaryKey().defaultRandom(),
|
|
5104
5255
|
/** FK to the parent job definition. Cascades on delete. */
|
|
5105
|
-
jobId:
|
|
5256
|
+
jobId: uuid52("job_id").notNull().references(() => pluginJobs.id, { onDelete: "cascade" }),
|
|
5106
5257
|
/** Denormalized FK to the owning plugin for efficient querying. Cascades on delete. */
|
|
5107
|
-
pluginId:
|
|
5258
|
+
pluginId: uuid52("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5108
5259
|
/** What caused this run to start (`"scheduled"` or `"manual"`). */
|
|
5109
|
-
trigger:
|
|
5260
|
+
trigger: text54("trigger").$type().notNull(),
|
|
5110
5261
|
/** Current lifecycle state of this run. */
|
|
5111
|
-
status:
|
|
5262
|
+
status: text54("status").$type().notNull().default("pending"),
|
|
5112
5263
|
/** Wall-clock duration in milliseconds. Null until the run finishes. */
|
|
5113
5264
|
durationMs: integer19("duration_ms"),
|
|
5114
5265
|
/** Error message if `status === "failed"`. */
|
|
5115
|
-
error:
|
|
5266
|
+
error: text54("error"),
|
|
5116
5267
|
/** Ordered list of log lines emitted during this run. */
|
|
5117
|
-
logs:
|
|
5118
|
-
startedAt:
|
|
5119
|
-
finishedAt:
|
|
5120
|
-
createdAt:
|
|
5268
|
+
logs: jsonb30("logs").$type().notNull().default([]),
|
|
5269
|
+
startedAt: timestamp53("started_at", { withTimezone: true }),
|
|
5270
|
+
finishedAt: timestamp53("finished_at", { withTimezone: true }),
|
|
5271
|
+
createdAt: timestamp53("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5121
5272
|
},
|
|
5122
5273
|
(table) => ({
|
|
5123
|
-
jobIdx:
|
|
5124
|
-
pluginIdx:
|
|
5125
|
-
statusIdx:
|
|
5274
|
+
jobIdx: index48("plugin_job_runs_job_idx").on(table.jobId),
|
|
5275
|
+
pluginIdx: index48("plugin_job_runs_plugin_idx").on(table.pluginId),
|
|
5276
|
+
statusIdx: index48("plugin_job_runs_status_idx").on(table.status)
|
|
5126
5277
|
})
|
|
5127
5278
|
);
|
|
5128
5279
|
}
|
|
@@ -5130,47 +5281,47 @@ var init_plugin_jobs = __esm({
|
|
|
5130
5281
|
|
|
5131
5282
|
// ../packages/db/src/schema/plugin_webhooks.ts
|
|
5132
5283
|
import {
|
|
5133
|
-
pgTable as
|
|
5134
|
-
uuid as
|
|
5135
|
-
text as
|
|
5284
|
+
pgTable as pgTable54,
|
|
5285
|
+
uuid as uuid53,
|
|
5286
|
+
text as text55,
|
|
5136
5287
|
integer as integer20,
|
|
5137
|
-
timestamp as
|
|
5138
|
-
jsonb as
|
|
5139
|
-
index as
|
|
5288
|
+
timestamp as timestamp54,
|
|
5289
|
+
jsonb as jsonb31,
|
|
5290
|
+
index as index49
|
|
5140
5291
|
} from "drizzle-orm/pg-core";
|
|
5141
5292
|
var pluginWebhookDeliveries;
|
|
5142
5293
|
var init_plugin_webhooks = __esm({
|
|
5143
5294
|
"../packages/db/src/schema/plugin_webhooks.ts"() {
|
|
5144
5295
|
"use strict";
|
|
5145
5296
|
init_plugins();
|
|
5146
|
-
pluginWebhookDeliveries =
|
|
5297
|
+
pluginWebhookDeliveries = pgTable54(
|
|
5147
5298
|
"plugin_webhook_deliveries",
|
|
5148
5299
|
{
|
|
5149
|
-
id:
|
|
5300
|
+
id: uuid53("id").primaryKey().defaultRandom(),
|
|
5150
5301
|
/** FK to the owning plugin. Cascades on delete. */
|
|
5151
|
-
pluginId:
|
|
5302
|
+
pluginId: uuid53("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5152
5303
|
/** Identifier matching the key in the plugin manifest's `webhooks` array. */
|
|
5153
|
-
webhookKey:
|
|
5304
|
+
webhookKey: text55("webhook_key").notNull(),
|
|
5154
5305
|
/** Optional de-duplication ID provided by the external system. */
|
|
5155
|
-
externalId:
|
|
5306
|
+
externalId: text55("external_id"),
|
|
5156
5307
|
/** Current delivery state. */
|
|
5157
|
-
status:
|
|
5308
|
+
status: text55("status").$type().notNull().default("pending"),
|
|
5158
5309
|
/** Wall-clock processing duration in milliseconds. Null until delivery finishes. */
|
|
5159
5310
|
durationMs: integer20("duration_ms"),
|
|
5160
5311
|
/** Error message if `status === "failed"`. */
|
|
5161
|
-
error:
|
|
5312
|
+
error: text55("error"),
|
|
5162
5313
|
/** Raw JSON body of the inbound HTTP request. */
|
|
5163
|
-
payload:
|
|
5314
|
+
payload: jsonb31("payload").$type().notNull(),
|
|
5164
5315
|
/** Relevant HTTP headers from the inbound request (e.g. signature headers). */
|
|
5165
|
-
headers:
|
|
5166
|
-
startedAt:
|
|
5167
|
-
finishedAt:
|
|
5168
|
-
createdAt:
|
|
5316
|
+
headers: jsonb31("headers").$type().notNull().default({}),
|
|
5317
|
+
startedAt: timestamp54("started_at", { withTimezone: true }),
|
|
5318
|
+
finishedAt: timestamp54("finished_at", { withTimezone: true }),
|
|
5319
|
+
createdAt: timestamp54("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5169
5320
|
},
|
|
5170
5321
|
(table) => ({
|
|
5171
|
-
pluginIdx:
|
|
5172
|
-
statusIdx:
|
|
5173
|
-
keyIdx:
|
|
5322
|
+
pluginIdx: index49("plugin_webhook_deliveries_plugin_idx").on(table.pluginId),
|
|
5323
|
+
statusIdx: index49("plugin_webhook_deliveries_status_idx").on(table.status),
|
|
5324
|
+
keyIdx: index49("plugin_webhook_deliveries_key_idx").on(table.webhookKey)
|
|
5174
5325
|
})
|
|
5175
5326
|
);
|
|
5176
5327
|
}
|
|
@@ -5178,34 +5329,34 @@ var init_plugin_webhooks = __esm({
|
|
|
5178
5329
|
|
|
5179
5330
|
// ../packages/db/src/schema/plugin_logs.ts
|
|
5180
5331
|
import {
|
|
5181
|
-
pgTable as
|
|
5182
|
-
uuid as
|
|
5183
|
-
text as
|
|
5184
|
-
timestamp as
|
|
5185
|
-
jsonb as
|
|
5186
|
-
index as
|
|
5332
|
+
pgTable as pgTable55,
|
|
5333
|
+
uuid as uuid54,
|
|
5334
|
+
text as text56,
|
|
5335
|
+
timestamp as timestamp55,
|
|
5336
|
+
jsonb as jsonb32,
|
|
5337
|
+
index as index50
|
|
5187
5338
|
} from "drizzle-orm/pg-core";
|
|
5188
5339
|
var pluginLogs;
|
|
5189
5340
|
var init_plugin_logs = __esm({
|
|
5190
5341
|
"../packages/db/src/schema/plugin_logs.ts"() {
|
|
5191
5342
|
"use strict";
|
|
5192
5343
|
init_plugins();
|
|
5193
|
-
pluginLogs =
|
|
5344
|
+
pluginLogs = pgTable55(
|
|
5194
5345
|
"plugin_logs",
|
|
5195
5346
|
{
|
|
5196
|
-
id:
|
|
5197
|
-
pluginId:
|
|
5198
|
-
level:
|
|
5199
|
-
message:
|
|
5200
|
-
meta:
|
|
5201
|
-
createdAt:
|
|
5347
|
+
id: uuid54("id").primaryKey().defaultRandom(),
|
|
5348
|
+
pluginId: uuid54("plugin_id").notNull().references(() => plugins.id, { onDelete: "cascade" }),
|
|
5349
|
+
level: text56("level").notNull().default("info"),
|
|
5350
|
+
message: text56("message").notNull(),
|
|
5351
|
+
meta: jsonb32("meta").$type(),
|
|
5352
|
+
createdAt: timestamp55("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5202
5353
|
},
|
|
5203
5354
|
(table) => ({
|
|
5204
|
-
pluginTimeIdx:
|
|
5355
|
+
pluginTimeIdx: index50("plugin_logs_plugin_time_idx").on(
|
|
5205
5356
|
table.pluginId,
|
|
5206
5357
|
table.createdAt
|
|
5207
5358
|
),
|
|
5208
|
-
levelIdx:
|
|
5359
|
+
levelIdx: index50("plugin_logs_level_idx").on(table.level)
|
|
5209
5360
|
})
|
|
5210
5361
|
);
|
|
5211
5362
|
}
|
|
@@ -5255,6 +5406,7 @@ __export(schema_exports, {
|
|
|
5255
5406
|
issueWorkProducts: () => issueWorkProducts,
|
|
5256
5407
|
issues: () => issues,
|
|
5257
5408
|
joinRequests: () => joinRequests,
|
|
5409
|
+
kbSkillDocs: () => kbSkillDocs,
|
|
5258
5410
|
labels: () => labels,
|
|
5259
5411
|
pluginCompanySettings: () => pluginCompanySettings,
|
|
5260
5412
|
pluginConfig: () => pluginConfig,
|
|
@@ -5311,6 +5463,7 @@ var init_schema2 = __esm({
|
|
|
5311
5463
|
init_assets();
|
|
5312
5464
|
init_issue_attachments();
|
|
5313
5465
|
init_documents();
|
|
5466
|
+
init_kb_skill_docs();
|
|
5314
5467
|
init_document_revisions();
|
|
5315
5468
|
init_issue_documents();
|
|
5316
5469
|
init_heartbeat_runs();
|
|
@@ -5912,7 +6065,7 @@ function sanitizeRestoreErrorMessage(error) {
|
|
|
5912
6065
|
}
|
|
5913
6066
|
return error instanceof Error ? error.message : String(error);
|
|
5914
6067
|
}
|
|
5915
|
-
function
|
|
6068
|
+
function timestamp56(date2 = /* @__PURE__ */ new Date()) {
|
|
5916
6069
|
const pad = (n) => String(n).padStart(2, "0");
|
|
5917
6070
|
return `${date2.getFullYear()}${pad(date2.getMonth() + 1)}${pad(date2.getDate())}-${pad(date2.getHours())}${pad(date2.getMinutes())}${pad(date2.getSeconds())}`;
|
|
5918
6071
|
}
|
|
@@ -6115,9 +6268,9 @@ async function runDatabaseBackup(opts) {
|
|
|
6115
6268
|
WHERE n.nspname = ${schema_name} AND t.relname = ${tablename} AND c.contype = 'p'
|
|
6116
6269
|
GROUP BY c.conname
|
|
6117
6270
|
`;
|
|
6118
|
-
for (const
|
|
6119
|
-
const cols =
|
|
6120
|
-
colDefs.push(` CONSTRAINT "${
|
|
6271
|
+
for (const p19 of pk) {
|
|
6272
|
+
const cols = p19.column_names.map((c) => `"${c}"`).join(", ");
|
|
6273
|
+
colDefs.push(` CONSTRAINT "${p19.constraint_name}" PRIMARY KEY (${cols})`);
|
|
6121
6274
|
}
|
|
6122
6275
|
emit(`CREATE TABLE ${qualifiedTableName} (`);
|
|
6123
6276
|
emit(colDefs.join(",\n"));
|
|
@@ -6236,8 +6389,8 @@ async function runDatabaseBackup(opts) {
|
|
|
6236
6389
|
const rows = await sql2.unsafe(`SELECT * FROM ${qualifiedTableName}`).values();
|
|
6237
6390
|
const nullifiedColumns = nullifiedColumnsByTable.get(tablename) ?? /* @__PURE__ */ new Set();
|
|
6238
6391
|
for (const row of rows) {
|
|
6239
|
-
const values = row.map((rawValue,
|
|
6240
|
-
const columnName = cols[
|
|
6392
|
+
const values = row.map((rawValue, index51) => {
|
|
6393
|
+
const columnName = cols[index51]?.column_name;
|
|
6241
6394
|
const val = columnName && nullifiedColumns.has(columnName) ? null : rawValue;
|
|
6242
6395
|
if (val === null || val === void 0) return "NULL";
|
|
6243
6396
|
if (typeof val === "boolean") return val ? "true" : "false";
|
|
@@ -6267,7 +6420,7 @@ async function runDatabaseBackup(opts) {
|
|
|
6267
6420
|
emitStatement("COMMIT;");
|
|
6268
6421
|
emit("");
|
|
6269
6422
|
mkdirSync(opts.backupDir, { recursive: true });
|
|
6270
|
-
const backupFile = resolve(opts.backupDir, `${filenamePrefix}-${
|
|
6423
|
+
const backupFile = resolve(opts.backupDir, `${filenamePrefix}-${timestamp56()}.sql`);
|
|
6271
6424
|
await writeFile(backupFile, lines.join("\n"), "utf8");
|
|
6272
6425
|
const sizeBytes = statSync(backupFile).size;
|
|
6273
6426
|
const prunedCount = pruneOldBackups(opts.backupDir, retentionDays, filenamePrefix);
|
|
@@ -6364,6 +6517,7 @@ __export(src_exports, {
|
|
|
6364
6517
|
issueWorkProducts: () => issueWorkProducts,
|
|
6365
6518
|
issues: () => issues,
|
|
6366
6519
|
joinRequests: () => joinRequests,
|
|
6520
|
+
kbSkillDocs: () => kbSkillDocs,
|
|
6367
6521
|
labels: () => labels,
|
|
6368
6522
|
migratePostgresIfEmpty: () => migratePostgresIfEmpty,
|
|
6369
6523
|
pluginCompanySettings: () => pluginCompanySettings,
|
|
@@ -7862,6 +8016,9 @@ var init_onboard = __esm({
|
|
|
7862
8016
|
init_onboard();
|
|
7863
8017
|
init_doctor();
|
|
7864
8018
|
import { Command } from "commander";
|
|
8019
|
+
import * as p18 from "@clack/prompts";
|
|
8020
|
+
import fs16 from "node:fs";
|
|
8021
|
+
import path23 from "node:path";
|
|
7865
8022
|
|
|
7866
8023
|
// src/commands/env.ts
|
|
7867
8024
|
init_store();
|
|
@@ -8231,24 +8388,30 @@ ${err instanceof Error ? err.message : String(err)}`
|
|
|
8231
8388
|
p12.outro("");
|
|
8232
8389
|
return;
|
|
8233
8390
|
}
|
|
8234
|
-
let
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
})
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8391
|
+
let sectionsToConfigure;
|
|
8392
|
+
if (section) {
|
|
8393
|
+
sectionsToConfigure = [section];
|
|
8394
|
+
} else {
|
|
8395
|
+
const choices = await p12.multiselect({
|
|
8396
|
+
message: "Which sections do you want to configure?",
|
|
8397
|
+
options: Object.entries(SECTION_LABELS).map(([value, label]) => ({
|
|
8398
|
+
value,
|
|
8399
|
+
label
|
|
8400
|
+
}))
|
|
8401
|
+
});
|
|
8402
|
+
if (p12.isCancel(choices)) {
|
|
8403
|
+
p12.cancel("Configuration cancelled.");
|
|
8404
|
+
return;
|
|
8405
|
+
}
|
|
8406
|
+
sectionsToConfigure = choices;
|
|
8407
|
+
if (sectionsToConfigure.length === 0) {
|
|
8408
|
+
p12.cancel("No sections selected.");
|
|
8409
|
+
return;
|
|
8249
8410
|
}
|
|
8250
|
-
|
|
8251
|
-
|
|
8411
|
+
}
|
|
8412
|
+
for (const selectedSection of sectionsToConfigure) {
|
|
8413
|
+
p12.log.step(pc7.bold(SECTION_LABELS[selectedSection]));
|
|
8414
|
+
switch (selectedSection) {
|
|
8252
8415
|
case "database":
|
|
8253
8416
|
config.database = await promptDatabase(config.database);
|
|
8254
8417
|
break;
|
|
@@ -8296,20 +8459,7 @@ ${err instanceof Error ? err.message : String(err)}`
|
|
|
8296
8459
|
config.$meta.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8297
8460
|
config.$meta.source = "configure";
|
|
8298
8461
|
writeConfig(config, opts.config);
|
|
8299
|
-
p12.log.success(`${SECTION_LABELS[
|
|
8300
|
-
if (opts.section) {
|
|
8301
|
-
continueLoop = false;
|
|
8302
|
-
} else {
|
|
8303
|
-
const another = await p12.confirm({
|
|
8304
|
-
message: "Configure another section?",
|
|
8305
|
-
initialValue: false
|
|
8306
|
-
});
|
|
8307
|
-
if (p12.isCancel(another) || !another) {
|
|
8308
|
-
continueLoop = false;
|
|
8309
|
-
} else {
|
|
8310
|
-
section = void 0;
|
|
8311
|
-
}
|
|
8312
|
-
}
|
|
8462
|
+
p12.log.success(`${SECTION_LABELS[selectedSection]} configuration updated.`);
|
|
8313
8463
|
}
|
|
8314
8464
|
p12.outro("Configuration saved.");
|
|
8315
8465
|
}
|
|
@@ -8392,8 +8542,8 @@ function printClaudeStreamEvent(raw, debug) {
|
|
|
8392
8542
|
const block = blockRaw;
|
|
8393
8543
|
const blockType = typeof block.type === "string" ? block.type : "";
|
|
8394
8544
|
if (blockType === "text") {
|
|
8395
|
-
const
|
|
8396
|
-
if (
|
|
8545
|
+
const text58 = typeof block.text === "string" ? block.text : "";
|
|
8546
|
+
if (text58) console.log(pc9.green(`assistant: ${text58}`));
|
|
8397
8547
|
} else if (blockType === "tool_use") {
|
|
8398
8548
|
const name = typeof block.name === "string" ? block.name : "unknown";
|
|
8399
8549
|
console.log(pc9.yellow(`tool_call: ${name}`));
|
|
@@ -8485,13 +8635,13 @@ function printItemStarted(item) {
|
|
|
8485
8635
|
function printItemCompleted(item) {
|
|
8486
8636
|
const itemType = asString(item.type);
|
|
8487
8637
|
if (itemType === "agent_message") {
|
|
8488
|
-
const
|
|
8489
|
-
if (
|
|
8638
|
+
const text58 = asString(item.text);
|
|
8639
|
+
if (text58) console.log(pc10.green(`assistant: ${text58}`));
|
|
8490
8640
|
return true;
|
|
8491
8641
|
}
|
|
8492
8642
|
if (itemType === "reasoning") {
|
|
8493
|
-
const
|
|
8494
|
-
if (
|
|
8643
|
+
const text58 = asString(item.text);
|
|
8644
|
+
if (text58) console.log(pc10.gray(`thinking: ${text58}`));
|
|
8495
8645
|
return true;
|
|
8496
8646
|
}
|
|
8497
8647
|
if (itemType === "tool_use") {
|
|
@@ -8526,8 +8676,8 @@ function printItemCompleted(item) {
|
|
|
8526
8676
|
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
8527
8677
|
const entries = changes.map((changeRaw) => asRecord(changeRaw)).filter((change) => Boolean(change)).map((change) => {
|
|
8528
8678
|
const kind = asString(change.kind, "update");
|
|
8529
|
-
const
|
|
8530
|
-
return `${kind} ${
|
|
8679
|
+
const path24 = asString(change.path, "unknown");
|
|
8680
|
+
return `${kind} ${path24}`;
|
|
8531
8681
|
});
|
|
8532
8682
|
const preview = entries.length > 0 ? entries.slice(0, 6).join(", ") : "none";
|
|
8533
8683
|
const more = entries.length > 6 ? ` (+${entries.length - 6} more)` : "";
|
|
@@ -8541,9 +8691,9 @@ function printItemCompleted(item) {
|
|
|
8541
8691
|
}
|
|
8542
8692
|
if (itemType === "tool_result") {
|
|
8543
8693
|
const isError = item.is_error === true || asString(item.status) === "error";
|
|
8544
|
-
const
|
|
8694
|
+
const text58 = asString(item.content) || asString(item.result) || asString(item.output);
|
|
8545
8695
|
console.log((isError ? pc10.red : pc10.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
8546
|
-
if (
|
|
8696
|
+
if (text58) console.log((isError ? pc10.red : pc10.gray)(text58));
|
|
8547
8697
|
return true;
|
|
8548
8698
|
}
|
|
8549
8699
|
return false;
|
|
@@ -8624,13 +8774,14 @@ function printCodexStreamEvent(raw, _debug) {
|
|
|
8624
8774
|
console.log(line);
|
|
8625
8775
|
}
|
|
8626
8776
|
|
|
8627
|
-
//
|
|
8777
|
+
// ../../node_modules/@paperclipai/adapter-cursor-local/dist/cli/format-event.js
|
|
8628
8778
|
import pc11 from "picocolors";
|
|
8629
8779
|
|
|
8630
|
-
//
|
|
8780
|
+
// ../../node_modules/@paperclipai/adapter-cursor-local/dist/shared/stream.js
|
|
8631
8781
|
function normalizeCursorStreamLine(rawLine) {
|
|
8632
8782
|
const trimmed = rawLine.trim();
|
|
8633
|
-
if (!trimmed)
|
|
8783
|
+
if (!trimmed)
|
|
8784
|
+
return { stream: null, line: "" };
|
|
8634
8785
|
const prefixed = trimmed.match(/^(stdout|stderr)\s*[:=]?\s*([\[{].*)$/i);
|
|
8635
8786
|
if (!prefixed) {
|
|
8636
8787
|
return { stream: null, line: trimmed };
|
|
@@ -8640,9 +8791,10 @@ function normalizeCursorStreamLine(rawLine) {
|
|
|
8640
8791
|
return { stream, line };
|
|
8641
8792
|
}
|
|
8642
8793
|
|
|
8643
|
-
//
|
|
8794
|
+
// ../../node_modules/@paperclipai/adapter-cursor-local/dist/cli/format-event.js
|
|
8644
8795
|
function asRecord2(value) {
|
|
8645
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8796
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8797
|
+
return null;
|
|
8646
8798
|
return value;
|
|
8647
8799
|
}
|
|
8648
8800
|
function asString2(value, fallback = "") {
|
|
@@ -8652,8 +8804,10 @@ function asNumber2(value, fallback = 0) {
|
|
|
8652
8804
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
8653
8805
|
}
|
|
8654
8806
|
function stringifyUnknown(value) {
|
|
8655
|
-
if (typeof value === "string")
|
|
8656
|
-
|
|
8807
|
+
if (typeof value === "string")
|
|
8808
|
+
return value;
|
|
8809
|
+
if (value === null || value === void 0)
|
|
8810
|
+
return "";
|
|
8657
8811
|
try {
|
|
8658
8812
|
return JSON.stringify(value, null, 2);
|
|
8659
8813
|
} catch {
|
|
@@ -8662,47 +8816,59 @@ function stringifyUnknown(value) {
|
|
|
8662
8816
|
}
|
|
8663
8817
|
function printUserMessage(messageRaw) {
|
|
8664
8818
|
if (typeof messageRaw === "string") {
|
|
8665
|
-
const
|
|
8666
|
-
if (
|
|
8819
|
+
const text58 = messageRaw.trim();
|
|
8820
|
+
if (text58)
|
|
8821
|
+
console.log(pc11.gray(`user: ${text58}`));
|
|
8667
8822
|
return;
|
|
8668
8823
|
}
|
|
8669
8824
|
const message = asRecord2(messageRaw);
|
|
8670
|
-
if (!message)
|
|
8825
|
+
if (!message)
|
|
8826
|
+
return;
|
|
8671
8827
|
const directText = asString2(message.text).trim();
|
|
8672
|
-
if (directText)
|
|
8828
|
+
if (directText)
|
|
8829
|
+
console.log(pc11.gray(`user: ${directText}`));
|
|
8673
8830
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8674
8831
|
for (const partRaw of content) {
|
|
8675
8832
|
const part = asRecord2(partRaw);
|
|
8676
|
-
if (!part)
|
|
8833
|
+
if (!part)
|
|
8834
|
+
continue;
|
|
8677
8835
|
const type = asString2(part.type).trim();
|
|
8678
|
-
if (type !== "output_text" && type !== "text")
|
|
8679
|
-
|
|
8680
|
-
|
|
8836
|
+
if (type !== "output_text" && type !== "text")
|
|
8837
|
+
continue;
|
|
8838
|
+
const text58 = asString2(part.text).trim();
|
|
8839
|
+
if (text58)
|
|
8840
|
+
console.log(pc11.gray(`user: ${text58}`));
|
|
8681
8841
|
}
|
|
8682
8842
|
}
|
|
8683
8843
|
function printAssistantMessage(messageRaw) {
|
|
8684
8844
|
if (typeof messageRaw === "string") {
|
|
8685
|
-
const
|
|
8686
|
-
if (
|
|
8845
|
+
const text58 = messageRaw.trim();
|
|
8846
|
+
if (text58)
|
|
8847
|
+
console.log(pc11.green(`assistant: ${text58}`));
|
|
8687
8848
|
return;
|
|
8688
8849
|
}
|
|
8689
8850
|
const message = asRecord2(messageRaw);
|
|
8690
|
-
if (!message)
|
|
8851
|
+
if (!message)
|
|
8852
|
+
return;
|
|
8691
8853
|
const directText = asString2(message.text).trim();
|
|
8692
|
-
if (directText)
|
|
8854
|
+
if (directText)
|
|
8855
|
+
console.log(pc11.green(`assistant: ${directText}`));
|
|
8693
8856
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8694
8857
|
for (const partRaw of content) {
|
|
8695
8858
|
const part = asRecord2(partRaw);
|
|
8696
|
-
if (!part)
|
|
8859
|
+
if (!part)
|
|
8860
|
+
continue;
|
|
8697
8861
|
const type = asString2(part.type).trim();
|
|
8698
8862
|
if (type === "output_text" || type === "text") {
|
|
8699
|
-
const
|
|
8700
|
-
if (
|
|
8863
|
+
const text58 = asString2(part.text).trim();
|
|
8864
|
+
if (text58)
|
|
8865
|
+
console.log(pc11.green(`assistant: ${text58}`));
|
|
8701
8866
|
continue;
|
|
8702
8867
|
}
|
|
8703
8868
|
if (type === "thinking") {
|
|
8704
|
-
const
|
|
8705
|
-
if (
|
|
8869
|
+
const text58 = asString2(part.text).trim();
|
|
8870
|
+
if (text58)
|
|
8871
|
+
console.log(pc11.gray(`thinking: ${text58}`));
|
|
8706
8872
|
continue;
|
|
8707
8873
|
}
|
|
8708
8874
|
if (type === "tool_call") {
|
|
@@ -8722,7 +8888,8 @@ function printAssistantMessage(messageRaw) {
|
|
|
8722
8888
|
const isError = part.is_error === true || asString2(part.status).toLowerCase() === "error";
|
|
8723
8889
|
const contentText = asString2(part.output) || asString2(part.text) || asString2(part.result) || stringifyUnknown(part.output ?? part.result ?? part.text ?? part);
|
|
8724
8890
|
console.log((isError ? pc11.red : pc11.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
8725
|
-
if (contentText)
|
|
8891
|
+
if (contentText)
|
|
8892
|
+
console.log((isError ? pc11.red : pc11.gray)(contentText));
|
|
8726
8893
|
}
|
|
8727
8894
|
}
|
|
8728
8895
|
}
|
|
@@ -8792,7 +8959,8 @@ function printLegacyToolEvent(part) {
|
|
|
8792
8959
|
}
|
|
8793
8960
|
function printCursorStreamEvent(raw, _debug) {
|
|
8794
8961
|
const line = normalizeCursorStreamLine(raw).line;
|
|
8795
|
-
if (!line)
|
|
8962
|
+
if (!line)
|
|
8963
|
+
return;
|
|
8796
8964
|
let parsed = null;
|
|
8797
8965
|
try {
|
|
8798
8966
|
parsed = JSON.parse(line);
|
|
@@ -8822,8 +8990,9 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8822
8990
|
return;
|
|
8823
8991
|
}
|
|
8824
8992
|
if (type === "thinking") {
|
|
8825
|
-
const
|
|
8826
|
-
if (
|
|
8993
|
+
const text58 = asString2(parsed.text).trim() || asString2(asRecord2(parsed.delta)?.text).trim();
|
|
8994
|
+
if (text58)
|
|
8995
|
+
console.log(pc11.gray(`thinking: ${text58}`));
|
|
8827
8996
|
return;
|
|
8828
8997
|
}
|
|
8829
8998
|
if (type === "tool_call") {
|
|
@@ -8834,19 +9003,18 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8834
9003
|
const usage = asRecord2(parsed.usage);
|
|
8835
9004
|
const input = asNumber2(usage?.input_tokens, asNumber2(usage?.inputTokens));
|
|
8836
9005
|
const output = asNumber2(usage?.output_tokens, asNumber2(usage?.outputTokens));
|
|
8837
|
-
const cached = asNumber2(
|
|
8838
|
-
usage?.cached_input_tokens,
|
|
8839
|
-
asNumber2(usage?.cachedInputTokens, asNumber2(usage?.cache_read_input_tokens))
|
|
8840
|
-
);
|
|
9006
|
+
const cached = asNumber2(usage?.cached_input_tokens, asNumber2(usage?.cachedInputTokens, asNumber2(usage?.cache_read_input_tokens)));
|
|
8841
9007
|
const cost = asNumber2(parsed.total_cost_usd, asNumber2(parsed.cost_usd, asNumber2(parsed.cost)));
|
|
8842
9008
|
const subtype = asString2(parsed.subtype, "result");
|
|
8843
9009
|
const isError = parsed.is_error === true || subtype === "error" || subtype === "failed";
|
|
8844
9010
|
console.log(pc11.blue(`result: subtype=${subtype}`));
|
|
8845
9011
|
console.log(pc11.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`));
|
|
8846
9012
|
const resultText = asString2(parsed.result).trim();
|
|
8847
|
-
if (resultText)
|
|
9013
|
+
if (resultText)
|
|
9014
|
+
console.log((isError ? pc11.red : pc11.green)(`assistant: ${resultText}`));
|
|
8848
9015
|
const errors = Array.isArray(parsed.errors) ? parsed.errors.map((value) => stringifyUnknown(value)).filter(Boolean) : [];
|
|
8849
|
-
if (errors.length > 0)
|
|
9016
|
+
if (errors.length > 0)
|
|
9017
|
+
console.log(pc11.red(`errors: ${errors.join(" | ")}`));
|
|
8850
9018
|
return;
|
|
8851
9019
|
}
|
|
8852
9020
|
if (type === "error") {
|
|
@@ -8861,8 +9029,9 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8861
9029
|
}
|
|
8862
9030
|
if (type === "text") {
|
|
8863
9031
|
const part = asRecord2(parsed.part);
|
|
8864
|
-
const
|
|
8865
|
-
if (
|
|
9032
|
+
const text58 = asString2(part?.text);
|
|
9033
|
+
if (text58)
|
|
9034
|
+
console.log(pc11.green(`assistant: ${text58}`));
|
|
8866
9035
|
return;
|
|
8867
9036
|
}
|
|
8868
9037
|
if (type === "tool_use") {
|
|
@@ -8890,10 +9059,11 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8890
9059
|
console.log(line);
|
|
8891
9060
|
}
|
|
8892
9061
|
|
|
8893
|
-
//
|
|
9062
|
+
// ../../node_modules/@paperclipai/adapter-gemini-local/dist/cli/format-event.js
|
|
8894
9063
|
import pc12 from "picocolors";
|
|
8895
9064
|
function asRecord3(value) {
|
|
8896
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9065
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9066
|
+
return null;
|
|
8897
9067
|
return value;
|
|
8898
9068
|
}
|
|
8899
9069
|
function asString3(value, fallback = "") {
|
|
@@ -8903,8 +9073,10 @@ function asNumber3(value, fallback = 0) {
|
|
|
8903
9073
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
8904
9074
|
}
|
|
8905
9075
|
function stringifyUnknown2(value) {
|
|
8906
|
-
if (typeof value === "string")
|
|
8907
|
-
|
|
9076
|
+
if (typeof value === "string")
|
|
9077
|
+
return value;
|
|
9078
|
+
if (value === null || value === void 0)
|
|
9079
|
+
return "";
|
|
8908
9080
|
try {
|
|
8909
9081
|
return JSON.stringify(value, null, 2);
|
|
8910
9082
|
} catch {
|
|
@@ -8912,11 +9084,14 @@ function stringifyUnknown2(value) {
|
|
|
8912
9084
|
}
|
|
8913
9085
|
}
|
|
8914
9086
|
function errorText2(value) {
|
|
8915
|
-
if (typeof value === "string")
|
|
9087
|
+
if (typeof value === "string")
|
|
9088
|
+
return value;
|
|
8916
9089
|
const rec = asRecord3(value);
|
|
8917
|
-
if (!rec)
|
|
9090
|
+
if (!rec)
|
|
9091
|
+
return "";
|
|
8918
9092
|
const msg = typeof rec.message === "string" && rec.message || typeof rec.error === "string" && rec.error || typeof rec.code === "string" && rec.code || "";
|
|
8919
|
-
if (msg)
|
|
9093
|
+
if (msg)
|
|
9094
|
+
return msg;
|
|
8920
9095
|
try {
|
|
8921
9096
|
return JSON.stringify(rec);
|
|
8922
9097
|
} catch {
|
|
@@ -8925,41 +9100,49 @@ function errorText2(value) {
|
|
|
8925
9100
|
}
|
|
8926
9101
|
function printTextMessage(prefix, colorize, messageRaw) {
|
|
8927
9102
|
if (typeof messageRaw === "string") {
|
|
8928
|
-
const
|
|
8929
|
-
if (
|
|
9103
|
+
const text58 = messageRaw.trim();
|
|
9104
|
+
if (text58)
|
|
9105
|
+
console.log(colorize(`${prefix}: ${text58}`));
|
|
8930
9106
|
return;
|
|
8931
9107
|
}
|
|
8932
9108
|
const message = asRecord3(messageRaw);
|
|
8933
|
-
if (!message)
|
|
9109
|
+
if (!message)
|
|
9110
|
+
return;
|
|
8934
9111
|
const directText = asString3(message.text).trim();
|
|
8935
|
-
if (directText)
|
|
9112
|
+
if (directText)
|
|
9113
|
+
console.log(colorize(`${prefix}: ${directText}`));
|
|
8936
9114
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8937
9115
|
for (const partRaw of content) {
|
|
8938
9116
|
const part = asRecord3(partRaw);
|
|
8939
|
-
if (!part)
|
|
9117
|
+
if (!part)
|
|
9118
|
+
continue;
|
|
8940
9119
|
const type = asString3(part.type).trim();
|
|
8941
9120
|
if (type === "output_text" || type === "text" || type === "content") {
|
|
8942
|
-
const
|
|
8943
|
-
if (
|
|
9121
|
+
const text58 = asString3(part.text).trim() || asString3(part.content).trim();
|
|
9122
|
+
if (text58)
|
|
9123
|
+
console.log(colorize(`${prefix}: ${text58}`));
|
|
8944
9124
|
continue;
|
|
8945
9125
|
}
|
|
8946
9126
|
if (type === "thinking") {
|
|
8947
|
-
const
|
|
8948
|
-
if (
|
|
9127
|
+
const text58 = asString3(part.text).trim();
|
|
9128
|
+
if (text58)
|
|
9129
|
+
console.log(pc12.gray(`thinking: ${text58}`));
|
|
8949
9130
|
continue;
|
|
8950
9131
|
}
|
|
8951
9132
|
if (type === "tool_call") {
|
|
8952
9133
|
const name = asString3(part.name, asString3(part.tool, "tool"));
|
|
8953
9134
|
console.log(pc12.yellow(`tool_call: ${name}`));
|
|
8954
9135
|
const input = part.input ?? part.arguments ?? part.args;
|
|
8955
|
-
if (input !== void 0)
|
|
9136
|
+
if (input !== void 0)
|
|
9137
|
+
console.log(pc12.gray(stringifyUnknown2(input)));
|
|
8956
9138
|
continue;
|
|
8957
9139
|
}
|
|
8958
9140
|
if (type === "tool_result" || type === "tool_response") {
|
|
8959
9141
|
const isError = part.is_error === true || asString3(part.status).toLowerCase() === "error";
|
|
8960
9142
|
const contentText = asString3(part.output) || asString3(part.text) || asString3(part.result) || stringifyUnknown2(part.output ?? part.result ?? part.text ?? part.response);
|
|
8961
9143
|
console.log((isError ? pc12.red : pc12.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
8962
|
-
if (contentText)
|
|
9144
|
+
if (contentText)
|
|
9145
|
+
console.log((isError ? pc12.red : pc12.gray)(contentText));
|
|
8963
9146
|
}
|
|
8964
9147
|
}
|
|
8965
9148
|
}
|
|
@@ -8969,16 +9152,14 @@ function printUsage(parsed) {
|
|
|
8969
9152
|
const source = usageMetadata ?? usage ?? {};
|
|
8970
9153
|
const input = asNumber3(source.input_tokens, asNumber3(source.inputTokens, asNumber3(source.promptTokenCount)));
|
|
8971
9154
|
const output = asNumber3(source.output_tokens, asNumber3(source.outputTokens, asNumber3(source.candidatesTokenCount)));
|
|
8972
|
-
const cached = asNumber3(
|
|
8973
|
-
source.cached_input_tokens,
|
|
8974
|
-
asNumber3(source.cachedInputTokens, asNumber3(source.cachedContentTokenCount))
|
|
8975
|
-
);
|
|
9155
|
+
const cached = asNumber3(source.cached_input_tokens, asNumber3(source.cachedInputTokens, asNumber3(source.cachedContentTokenCount)));
|
|
8976
9156
|
const cost = asNumber3(parsed.total_cost_usd, asNumber3(parsed.cost_usd, asNumber3(parsed.cost)));
|
|
8977
9157
|
console.log(pc12.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`));
|
|
8978
9158
|
}
|
|
8979
9159
|
function printGeminiStreamEvent(raw, _debug) {
|
|
8980
9160
|
const line = raw.trim();
|
|
8981
|
-
if (!line)
|
|
9161
|
+
if (!line)
|
|
9162
|
+
return;
|
|
8982
9163
|
let parsed = null;
|
|
8983
9164
|
try {
|
|
8984
9165
|
parsed = JSON.parse(line);
|
|
@@ -8997,8 +9178,9 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
8997
9178
|
return;
|
|
8998
9179
|
}
|
|
8999
9180
|
if (subtype === "error") {
|
|
9000
|
-
const
|
|
9001
|
-
if (
|
|
9181
|
+
const text58 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
|
|
9182
|
+
if (text58)
|
|
9183
|
+
console.log(pc12.red(`error: ${text58}`));
|
|
9002
9184
|
return;
|
|
9003
9185
|
}
|
|
9004
9186
|
console.log(pc12.blue(`system: ${subtype || "event"}`));
|
|
@@ -9013,8 +9195,9 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
9013
9195
|
return;
|
|
9014
9196
|
}
|
|
9015
9197
|
if (type === "thinking") {
|
|
9016
|
-
const
|
|
9017
|
-
if (
|
|
9198
|
+
const text58 = asString3(parsed.text).trim() || asString3(asRecord3(parsed.delta)?.text).trim();
|
|
9199
|
+
if (text58)
|
|
9200
|
+
console.log(pc12.gray(`thinking: ${text58}`));
|
|
9018
9201
|
return;
|
|
9019
9202
|
}
|
|
9020
9203
|
if (type === "tool_call") {
|
|
@@ -9050,24 +9233,26 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
9050
9233
|
return;
|
|
9051
9234
|
}
|
|
9052
9235
|
if (type === "error") {
|
|
9053
|
-
const
|
|
9054
|
-
if (
|
|
9236
|
+
const text58 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
|
|
9237
|
+
if (text58)
|
|
9238
|
+
console.log(pc12.red(`error: ${text58}`));
|
|
9055
9239
|
return;
|
|
9056
9240
|
}
|
|
9057
9241
|
console.log(line);
|
|
9058
9242
|
}
|
|
9059
9243
|
|
|
9060
|
-
//
|
|
9244
|
+
// ../../node_modules/@paperclipai/adapter-opencode-local/dist/cli/format-event.js
|
|
9061
9245
|
import pc13 from "picocolors";
|
|
9062
|
-
function safeJsonParse(
|
|
9246
|
+
function safeJsonParse(text58) {
|
|
9063
9247
|
try {
|
|
9064
|
-
return JSON.parse(
|
|
9248
|
+
return JSON.parse(text58);
|
|
9065
9249
|
} catch {
|
|
9066
9250
|
return null;
|
|
9067
9251
|
}
|
|
9068
9252
|
}
|
|
9069
9253
|
function asRecord4(value) {
|
|
9070
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9254
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9255
|
+
return null;
|
|
9071
9256
|
return value;
|
|
9072
9257
|
}
|
|
9073
9258
|
function asString4(value, fallback = "") {
|
|
@@ -9077,12 +9262,15 @@ function asNumber4(value, fallback = 0) {
|
|
|
9077
9262
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
9078
9263
|
}
|
|
9079
9264
|
function errorText3(value) {
|
|
9080
|
-
if (typeof value === "string")
|
|
9265
|
+
if (typeof value === "string")
|
|
9266
|
+
return value;
|
|
9081
9267
|
const rec = asRecord4(value);
|
|
9082
|
-
if (!rec)
|
|
9268
|
+
if (!rec)
|
|
9269
|
+
return "";
|
|
9083
9270
|
const data = asRecord4(rec.data);
|
|
9084
9271
|
const message = asString4(rec.message) || asString4(data?.message) || asString4(rec.name) || "";
|
|
9085
|
-
if (message)
|
|
9272
|
+
if (message)
|
|
9273
|
+
return message;
|
|
9086
9274
|
try {
|
|
9087
9275
|
return JSON.stringify(rec);
|
|
9088
9276
|
} catch {
|
|
@@ -9091,7 +9279,8 @@ function errorText3(value) {
|
|
|
9091
9279
|
}
|
|
9092
9280
|
function printOpenCodeStreamEvent(raw, _debug) {
|
|
9093
9281
|
const line = raw.trim();
|
|
9094
|
-
if (!line)
|
|
9282
|
+
if (!line)
|
|
9283
|
+
return;
|
|
9095
9284
|
const parsed = asRecord4(safeJsonParse(line));
|
|
9096
9285
|
if (!parsed) {
|
|
9097
9286
|
console.log(line);
|
|
@@ -9105,14 +9294,16 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9105
9294
|
}
|
|
9106
9295
|
if (type === "text") {
|
|
9107
9296
|
const part = asRecord4(parsed.part);
|
|
9108
|
-
const
|
|
9109
|
-
if (
|
|
9297
|
+
const text58 = asString4(part?.text).trim();
|
|
9298
|
+
if (text58)
|
|
9299
|
+
console.log(pc13.green(`assistant: ${text58}`));
|
|
9110
9300
|
return;
|
|
9111
9301
|
}
|
|
9112
9302
|
if (type === "reasoning") {
|
|
9113
9303
|
const part = asRecord4(parsed.part);
|
|
9114
|
-
const
|
|
9115
|
-
if (
|
|
9304
|
+
const text58 = asString4(part?.text).trim();
|
|
9305
|
+
if (text58)
|
|
9306
|
+
console.log(pc13.gray(`thinking: ${text58}`));
|
|
9116
9307
|
return;
|
|
9117
9308
|
}
|
|
9118
9309
|
if (type === "tool_use") {
|
|
@@ -9128,13 +9319,15 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9128
9319
|
const metaParts = [`status=${status}`];
|
|
9129
9320
|
if (metadata) {
|
|
9130
9321
|
for (const [key, value] of Object.entries(metadata)) {
|
|
9131
|
-
if (value !== void 0 && value !== null)
|
|
9322
|
+
if (value !== void 0 && value !== null)
|
|
9323
|
+
metaParts.push(`${key}=${value}`);
|
|
9132
9324
|
}
|
|
9133
9325
|
}
|
|
9134
9326
|
console.log((isError ? pc13.red : pc13.gray)(`tool_result ${metaParts.join(" ")}`));
|
|
9135
9327
|
}
|
|
9136
9328
|
const output = (asString4(state?.output) || asString4(state?.error)).trim();
|
|
9137
|
-
if (output)
|
|
9329
|
+
if (output)
|
|
9330
|
+
console.log((isError ? pc13.red : pc13.gray)(output));
|
|
9138
9331
|
return;
|
|
9139
9332
|
}
|
|
9140
9333
|
if (type === "step_finish") {
|
|
@@ -9152,36 +9345,41 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9152
9345
|
}
|
|
9153
9346
|
if (type === "error") {
|
|
9154
9347
|
const message = errorText3(parsed.error ?? parsed.message);
|
|
9155
|
-
if (message)
|
|
9348
|
+
if (message)
|
|
9349
|
+
console.log(pc13.red(`error: ${message}`));
|
|
9156
9350
|
return;
|
|
9157
9351
|
}
|
|
9158
9352
|
console.log(line);
|
|
9159
9353
|
}
|
|
9160
9354
|
|
|
9161
|
-
//
|
|
9355
|
+
// ../../node_modules/@paperclipai/adapter-pi-local/dist/cli/format-event.js
|
|
9162
9356
|
import pc14 from "picocolors";
|
|
9163
|
-
function safeJsonParse2(
|
|
9357
|
+
function safeJsonParse2(text58) {
|
|
9164
9358
|
try {
|
|
9165
|
-
return JSON.parse(
|
|
9359
|
+
return JSON.parse(text58);
|
|
9166
9360
|
} catch {
|
|
9167
9361
|
return null;
|
|
9168
9362
|
}
|
|
9169
9363
|
}
|
|
9170
9364
|
function asRecord5(value) {
|
|
9171
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9365
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9366
|
+
return null;
|
|
9172
9367
|
return value;
|
|
9173
9368
|
}
|
|
9174
9369
|
function asString5(value, fallback = "") {
|
|
9175
9370
|
return typeof value === "string" ? value : fallback;
|
|
9176
9371
|
}
|
|
9177
9372
|
function extractTextContent(content) {
|
|
9178
|
-
if (typeof content === "string")
|
|
9179
|
-
|
|
9373
|
+
if (typeof content === "string")
|
|
9374
|
+
return content;
|
|
9375
|
+
if (!Array.isArray(content))
|
|
9376
|
+
return "";
|
|
9180
9377
|
return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("");
|
|
9181
9378
|
}
|
|
9182
9379
|
function printPiStreamEvent(raw, _debug) {
|
|
9183
9380
|
const line = raw.trim();
|
|
9184
|
-
if (!line)
|
|
9381
|
+
if (!line)
|
|
9382
|
+
return;
|
|
9185
9383
|
const parsed = asRecord5(safeJsonParse2(line));
|
|
9186
9384
|
if (!parsed) {
|
|
9187
9385
|
console.log(line);
|
|
@@ -9204,9 +9402,9 @@ function printPiStreamEvent(raw, _debug) {
|
|
|
9204
9402
|
const message = asRecord5(parsed.message);
|
|
9205
9403
|
if (message) {
|
|
9206
9404
|
const content = message.content;
|
|
9207
|
-
const
|
|
9208
|
-
if (
|
|
9209
|
-
console.log(pc14.green(`assistant: ${
|
|
9405
|
+
const text58 = extractTextContent(content);
|
|
9406
|
+
if (text58) {
|
|
9407
|
+
console.log(pc14.green(`assistant: ${text58}`));
|
|
9210
9408
|
}
|
|
9211
9409
|
}
|
|
9212
9410
|
return;
|
|
@@ -9497,26 +9695,26 @@ var PaperclipApiClient = class {
|
|
|
9497
9695
|
this.apiKey = opts.apiKey?.trim() || void 0;
|
|
9498
9696
|
this.runId = opts.runId?.trim() || void 0;
|
|
9499
9697
|
}
|
|
9500
|
-
get(
|
|
9501
|
-
return this.request(
|
|
9698
|
+
get(path24, opts) {
|
|
9699
|
+
return this.request(path24, { method: "GET" }, opts);
|
|
9502
9700
|
}
|
|
9503
|
-
post(
|
|
9504
|
-
return this.request(
|
|
9701
|
+
post(path24, body, opts) {
|
|
9702
|
+
return this.request(path24, {
|
|
9505
9703
|
method: "POST",
|
|
9506
9704
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
9507
9705
|
}, opts);
|
|
9508
9706
|
}
|
|
9509
|
-
patch(
|
|
9510
|
-
return this.request(
|
|
9707
|
+
patch(path24, body, opts) {
|
|
9708
|
+
return this.request(path24, {
|
|
9511
9709
|
method: "PATCH",
|
|
9512
9710
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
9513
9711
|
}, opts);
|
|
9514
9712
|
}
|
|
9515
|
-
delete(
|
|
9516
|
-
return this.request(
|
|
9713
|
+
delete(path24, opts) {
|
|
9714
|
+
return this.request(path24, { method: "DELETE" }, opts);
|
|
9517
9715
|
}
|
|
9518
|
-
async request(
|
|
9519
|
-
const url = buildUrl(this.apiBase,
|
|
9716
|
+
async request(path24, init, opts) {
|
|
9717
|
+
const url = buildUrl(this.apiBase, path24);
|
|
9520
9718
|
const headers = {
|
|
9521
9719
|
accept: "application/json",
|
|
9522
9720
|
...toStringRecord(init.headers)
|
|
@@ -9543,31 +9741,31 @@ var PaperclipApiClient = class {
|
|
|
9543
9741
|
if (response.status === 204) {
|
|
9544
9742
|
return null;
|
|
9545
9743
|
}
|
|
9546
|
-
const
|
|
9547
|
-
if (!
|
|
9744
|
+
const text58 = await response.text();
|
|
9745
|
+
if (!text58.trim()) {
|
|
9548
9746
|
return null;
|
|
9549
9747
|
}
|
|
9550
|
-
return safeParseJson(
|
|
9748
|
+
return safeParseJson(text58);
|
|
9551
9749
|
}
|
|
9552
9750
|
};
|
|
9553
|
-
function buildUrl(apiBase,
|
|
9554
|
-
const normalizedPath =
|
|
9751
|
+
function buildUrl(apiBase, path24) {
|
|
9752
|
+
const normalizedPath = path24.startsWith("/") ? path24 : `/${path24}`;
|
|
9555
9753
|
const [pathname, query] = normalizedPath.split("?");
|
|
9556
9754
|
const url = new URL2(apiBase);
|
|
9557
9755
|
url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
|
|
9558
9756
|
if (query) url.search = query;
|
|
9559
9757
|
return url.toString();
|
|
9560
9758
|
}
|
|
9561
|
-
function safeParseJson(
|
|
9759
|
+
function safeParseJson(text58) {
|
|
9562
9760
|
try {
|
|
9563
|
-
return JSON.parse(
|
|
9761
|
+
return JSON.parse(text58);
|
|
9564
9762
|
} catch {
|
|
9565
|
-
return
|
|
9763
|
+
return text58;
|
|
9566
9764
|
}
|
|
9567
9765
|
}
|
|
9568
9766
|
async function toApiError(response) {
|
|
9569
|
-
const
|
|
9570
|
-
const parsed = safeParseJson(
|
|
9767
|
+
const text58 = await response.text();
|
|
9768
|
+
const parsed = safeParseJson(text58);
|
|
9571
9769
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
9572
9770
|
const body = parsed;
|
|
9573
9771
|
const message = typeof body.error === "string" && body.error.trim() || typeof body.message === "string" && body.message.trim() || `Request failed with status ${response.status}`;
|
|
@@ -10459,8 +10657,8 @@ function registerIssueCommands(program2) {
|
|
|
10459
10657
|
if (opts.assigneeAgentId) params.set("assigneeAgentId", opts.assigneeAgentId);
|
|
10460
10658
|
if (opts.projectId) params.set("projectId", opts.projectId);
|
|
10461
10659
|
const query = params.toString();
|
|
10462
|
-
const
|
|
10463
|
-
const rows = await ctx.api.get(
|
|
10660
|
+
const path24 = `/api/companies/${ctx.companyId}/issues${query ? `?${query}` : ""}`;
|
|
10661
|
+
const rows = await ctx.api.get(path24) ?? [];
|
|
10464
10662
|
const filtered = filterIssueRows(rows, opts.match);
|
|
10465
10663
|
if (ctx.json) {
|
|
10466
10664
|
printOutput(filtered, { json: true });
|
|
@@ -10616,8 +10814,8 @@ function filterIssueRows(rows, match) {
|
|
|
10616
10814
|
if (!match?.trim()) return rows;
|
|
10617
10815
|
const needle = match.trim().toLowerCase();
|
|
10618
10816
|
return rows.filter((row) => {
|
|
10619
|
-
const
|
|
10620
|
-
return
|
|
10817
|
+
const text58 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
|
|
10818
|
+
return text58.includes(needle);
|
|
10621
10819
|
});
|
|
10622
10820
|
}
|
|
10623
10821
|
|
|
@@ -11066,8 +11264,8 @@ function registerActivityCommands(program2) {
|
|
|
11066
11264
|
if (opts.entityType) params.set("entityType", opts.entityType);
|
|
11067
11265
|
if (opts.entityId) params.set("entityId", opts.entityId);
|
|
11068
11266
|
const query = params.toString();
|
|
11069
|
-
const
|
|
11070
|
-
const rows = await ctx.api.get(
|
|
11267
|
+
const path24 = `/api/companies/${ctx.companyId}/activity${query ? `?${query}` : ""}`;
|
|
11268
|
+
const rows = await ctx.api.get(path24) ?? [];
|
|
11071
11269
|
if (ctx.json) {
|
|
11072
11270
|
printOutput(rows, { json: true });
|
|
11073
11271
|
return;
|
|
@@ -12073,6 +12271,15 @@ async function worktreeMakeCommand(nameArg, opts) {
|
|
|
12073
12271
|
} finally {
|
|
12074
12272
|
process.chdir(originalCwd);
|
|
12075
12273
|
}
|
|
12274
|
+
const bootstrapScript = path17.resolve(sourceCwd, "scripts/worktree-bootstrap.mjs");
|
|
12275
|
+
if (existsSync2(bootstrapScript)) {
|
|
12276
|
+
p15.log.message(pc21.dim(`Running worktree bootstrap in ${targetPath}...`));
|
|
12277
|
+
try {
|
|
12278
|
+
execFileSync("node", [bootstrapScript], { cwd: targetPath, stdio: "inherit" });
|
|
12279
|
+
} catch (error) {
|
|
12280
|
+
p15.log.warning(`Bootstrap failed: ${extractExecSyncErrorMessage(error) ?? String(error)}`);
|
|
12281
|
+
}
|
|
12282
|
+
}
|
|
12076
12283
|
}
|
|
12077
12284
|
function parseGitWorktreeList(cwd) {
|
|
12078
12285
|
const raw = execFileSync("git", ["worktree", "list", "--porcelain"], {
|
|
@@ -12294,16 +12501,16 @@ function resolvePackageArg(packageArg, isLocal) {
|
|
|
12294
12501
|
}
|
|
12295
12502
|
return path18.resolve(process.cwd(), packageArg);
|
|
12296
12503
|
}
|
|
12297
|
-
function formatPlugin(
|
|
12298
|
-
const statusColor =
|
|
12504
|
+
function formatPlugin(p19) {
|
|
12505
|
+
const statusColor = p19.status === "ready" ? pc22.green(p19.status) : p19.status === "error" ? pc22.red(p19.status) : p19.status === "disabled" ? pc22.dim(p19.status) : pc22.yellow(p19.status);
|
|
12299
12506
|
const parts = [
|
|
12300
|
-
`key=${pc22.bold(
|
|
12507
|
+
`key=${pc22.bold(p19.pluginKey)}`,
|
|
12301
12508
|
`status=${statusColor}`,
|
|
12302
|
-
`version=${
|
|
12303
|
-
`id=${pc22.dim(
|
|
12509
|
+
`version=${p19.version}`,
|
|
12510
|
+
`id=${pc22.dim(p19.id)}`
|
|
12304
12511
|
];
|
|
12305
|
-
if (
|
|
12306
|
-
parts.push(`error=${pc22.red(
|
|
12512
|
+
if (p19.lastError) {
|
|
12513
|
+
parts.push(`error=${pc22.red(p19.lastError.slice(0, 80))}`);
|
|
12307
12514
|
}
|
|
12308
12515
|
return parts.join(" ");
|
|
12309
12516
|
}
|
|
@@ -12324,8 +12531,8 @@ function registerPluginCommands(program2) {
|
|
|
12324
12531
|
console.log(pc22.dim("No plugins installed."));
|
|
12325
12532
|
return;
|
|
12326
12533
|
}
|
|
12327
|
-
for (const
|
|
12328
|
-
console.log(formatPlugin(
|
|
12534
|
+
for (const p19 of rows) {
|
|
12535
|
+
console.log(formatPlugin(p19));
|
|
12329
12536
|
}
|
|
12330
12537
|
} catch (err) {
|
|
12331
12538
|
handleCommandError(err);
|
|
@@ -12489,48 +12696,482 @@ ${result.lastError}`);
|
|
|
12489
12696
|
);
|
|
12490
12697
|
}
|
|
12491
12698
|
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12699
|
+
// src/commands/kit.ts
|
|
12700
|
+
import path20 from "node:path";
|
|
12701
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
12702
|
+
import * as p16 from "@clack/prompts";
|
|
12703
|
+
import pc23 from "picocolors";
|
|
12704
|
+
|
|
12705
|
+
// src/kits/service.ts
|
|
12706
|
+
init_home();
|
|
12707
|
+
import fs14 from "node:fs";
|
|
12708
|
+
import path19 from "node:path";
|
|
12709
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
12710
|
+
|
|
12711
|
+
// src/kits/catalog.ts
|
|
12712
|
+
var BUNDLED_KIT_CATALOG = [
|
|
12713
|
+
{
|
|
12714
|
+
id: "creative-strategist-v1",
|
|
12715
|
+
packageDirName: "creative-strategist-v1",
|
|
12716
|
+
defaultBundleId: "creative-strategist-v1",
|
|
12717
|
+
type: "worker",
|
|
12718
|
+
executionMode: "export",
|
|
12719
|
+
activationModes: ["export"],
|
|
12720
|
+
family: "workflow"
|
|
12721
|
+
},
|
|
12722
|
+
{
|
|
12723
|
+
id: "growthub-email-marketing-v1",
|
|
12724
|
+
packageDirName: "growthub-email-marketing-v1",
|
|
12725
|
+
defaultBundleId: "growthub-email-marketing-v1",
|
|
12726
|
+
type: "worker",
|
|
12727
|
+
executionMode: "export",
|
|
12728
|
+
activationModes: ["export"],
|
|
12729
|
+
family: "operator"
|
|
12730
|
+
},
|
|
12731
|
+
{
|
|
12732
|
+
id: "growthub-open-higgsfield-studio-v1",
|
|
12733
|
+
packageDirName: "growthub-open-higgsfield-studio-v1",
|
|
12734
|
+
defaultBundleId: "growthub-open-higgsfield-studio-v1",
|
|
12735
|
+
type: "worker",
|
|
12736
|
+
executionMode: "export",
|
|
12737
|
+
activationModes: ["export"],
|
|
12738
|
+
family: "studio"
|
|
12497
12739
|
}
|
|
12498
|
-
|
|
12740
|
+
];
|
|
12741
|
+
|
|
12742
|
+
// src/kits/contract.ts
|
|
12743
|
+
function isManifestV2(manifest) {
|
|
12744
|
+
return manifest.schemaVersion === 2;
|
|
12745
|
+
}
|
|
12746
|
+
function isBundleManifestV2(manifest) {
|
|
12747
|
+
return manifest.schemaVersion === 2;
|
|
12748
|
+
}
|
|
12749
|
+
function normalizeManifest(manifest) {
|
|
12750
|
+
if (isManifestV2(manifest)) return manifest;
|
|
12751
|
+
return {
|
|
12752
|
+
schemaVersion: 2,
|
|
12753
|
+
kit: {
|
|
12754
|
+
...manifest.kit,
|
|
12755
|
+
type: "worker"
|
|
12756
|
+
},
|
|
12757
|
+
entrypoint: manifest.entrypoint,
|
|
12758
|
+
workerIds: manifest.workerIds,
|
|
12759
|
+
agentContractPath: manifest.agentContractPath,
|
|
12760
|
+
brandTemplatePath: manifest.brandTemplatePath,
|
|
12761
|
+
publicExampleBrandPaths: manifest.publicExampleBrandPaths,
|
|
12762
|
+
frozenAssetPaths: manifest.frozenAssetPaths,
|
|
12763
|
+
outputStandard: manifest.outputStandard,
|
|
12764
|
+
bundles: manifest.bundles,
|
|
12765
|
+
executionMode: "export",
|
|
12766
|
+
activationModes: ["export"],
|
|
12767
|
+
compatibility: {},
|
|
12768
|
+
provenance: manifest.kit.sourceRepo ? { sourceRepo: manifest.kit.sourceRepo } : void 0
|
|
12769
|
+
};
|
|
12499
12770
|
}
|
|
12500
|
-
function
|
|
12501
|
-
if (
|
|
12502
|
-
|
|
12771
|
+
function normalizeBundleManifest(manifest) {
|
|
12772
|
+
if (isBundleManifestV2(manifest)) return manifest;
|
|
12773
|
+
return {
|
|
12774
|
+
schemaVersion: 2,
|
|
12775
|
+
bundle: manifest.bundle,
|
|
12776
|
+
briefType: manifest.briefType,
|
|
12777
|
+
publicExampleBrandPaths: manifest.publicExampleBrandPaths,
|
|
12778
|
+
requiredFrozenAssets: manifest.requiredFrozenAssets,
|
|
12779
|
+
optionalPresets: manifest.optionalPresets,
|
|
12780
|
+
export: manifest.export,
|
|
12781
|
+
activationModes: ["export"]
|
|
12782
|
+
};
|
|
12783
|
+
}
|
|
12784
|
+
var SUPPORTED_SCHEMA_VERSIONS = [1, 2];
|
|
12785
|
+
var KIT_CAPABILITY_TYPES = [
|
|
12786
|
+
"worker",
|
|
12787
|
+
"workflow",
|
|
12788
|
+
"output",
|
|
12789
|
+
"ui"
|
|
12790
|
+
];
|
|
12791
|
+
var KIT_ACTIVATION_MODES = [
|
|
12792
|
+
"export",
|
|
12793
|
+
"install",
|
|
12794
|
+
"mount",
|
|
12795
|
+
"run"
|
|
12796
|
+
];
|
|
12797
|
+
|
|
12798
|
+
// src/kits/service.ts
|
|
12799
|
+
var ZIP_TIMESTAMP = /* @__PURE__ */ new Date("2026-04-09T00:00:00.000Z");
|
|
12800
|
+
function resolveBundledKitAssetsRoot() {
|
|
12801
|
+
const moduleDir = path19.dirname(fileURLToPath4(import.meta.url));
|
|
12802
|
+
const candidates = [
|
|
12803
|
+
path19.resolve(moduleDir, "../../assets/worker-kits"),
|
|
12804
|
+
path19.resolve(moduleDir, "../assets/worker-kits")
|
|
12805
|
+
];
|
|
12806
|
+
for (const candidate of candidates) {
|
|
12807
|
+
if (fs14.existsSync(candidate)) return candidate;
|
|
12503
12808
|
}
|
|
12504
|
-
|
|
12809
|
+
throw new Error("Could not locate bundled worker kit assets.");
|
|
12505
12810
|
}
|
|
12506
|
-
function
|
|
12507
|
-
|
|
12811
|
+
function resolveRequestedOutputRoot(outDir) {
|
|
12812
|
+
if (outDir?.trim()) {
|
|
12813
|
+
return path19.resolve(expandHomePrefix(outDir.trim()));
|
|
12814
|
+
}
|
|
12815
|
+
return path19.resolve(resolvePaperclipHomeDir(), "kits", "exports");
|
|
12508
12816
|
}
|
|
12509
|
-
function
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12817
|
+
function readJsonFile(filePath) {
|
|
12818
|
+
return JSON.parse(fs14.readFileSync(filePath, "utf8"));
|
|
12819
|
+
}
|
|
12820
|
+
function assertRelativePathExists(assetRoot, relativePath, label) {
|
|
12821
|
+
const fullPath = path19.resolve(assetRoot, relativePath);
|
|
12822
|
+
if (!fs14.existsSync(fullPath)) {
|
|
12823
|
+
throw new Error(`${label} is missing required path: ${relativePath}`);
|
|
12824
|
+
}
|
|
12825
|
+
}
|
|
12826
|
+
function listRelativeFiles(rootDir) {
|
|
12827
|
+
const files = [];
|
|
12828
|
+
const walk = (currentDir) => {
|
|
12829
|
+
for (const entry of fs14.readdirSync(currentDir, { withFileTypes: true })) {
|
|
12830
|
+
const fullPath = path19.join(currentDir, entry.name);
|
|
12831
|
+
if (entry.isDirectory()) {
|
|
12832
|
+
walk(fullPath);
|
|
12833
|
+
continue;
|
|
12834
|
+
}
|
|
12835
|
+
files.push(path19.relative(rootDir, fullPath).split(path19.sep).join("/"));
|
|
12516
12836
|
}
|
|
12517
|
-
|
|
12837
|
+
};
|
|
12838
|
+
walk(rootDir);
|
|
12839
|
+
return files.sort();
|
|
12840
|
+
}
|
|
12841
|
+
function parseManifest(assetRoot) {
|
|
12842
|
+
const raw = readJsonFile(path19.resolve(assetRoot, "kit.json"));
|
|
12843
|
+
if (!SUPPORTED_SCHEMA_VERSIONS.includes(raw.schemaVersion)) {
|
|
12844
|
+
throw new Error(`Unsupported kit schema version for ${assetRoot}: ${raw.schemaVersion}`);
|
|
12518
12845
|
}
|
|
12519
|
-
return
|
|
12846
|
+
return normalizeManifest(raw);
|
|
12520
12847
|
}
|
|
12521
|
-
function
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12848
|
+
function parseBundleManifest(assetRoot, manifest, bundleId) {
|
|
12849
|
+
const bundleRef = manifest.bundles.find((item) => item.id === bundleId);
|
|
12850
|
+
if (!bundleRef) {
|
|
12851
|
+
throw new Error(`Kit ${manifest.kit.id} does not declare bundle ${bundleId}.`);
|
|
12852
|
+
}
|
|
12853
|
+
const raw = readJsonFile(path19.resolve(assetRoot, bundleRef.path));
|
|
12854
|
+
if (!SUPPORTED_SCHEMA_VERSIONS.includes(raw.schemaVersion)) {
|
|
12855
|
+
throw new Error(
|
|
12856
|
+
`Unsupported bundle schema version for ${bundleRef.path}: ${raw.schemaVersion}`
|
|
12857
|
+
);
|
|
12858
|
+
}
|
|
12859
|
+
return normalizeBundleManifest(raw);
|
|
12860
|
+
}
|
|
12861
|
+
function validateBundledKit(resolved) {
|
|
12862
|
+
const { assetRoot, manifest, bundleManifest } = resolved;
|
|
12863
|
+
if (manifest.kit.id !== resolved.catalogEntry.id) {
|
|
12864
|
+
throw new Error(
|
|
12865
|
+
`Bundled catalog mismatch: expected ${resolved.catalogEntry.id}, got ${manifest.kit.id}.`
|
|
12866
|
+
);
|
|
12867
|
+
}
|
|
12868
|
+
if (bundleManifest.bundle.kitId !== manifest.kit.id) {
|
|
12869
|
+
throw new Error(
|
|
12870
|
+
`Bundle ${bundleManifest.bundle.id} points at ${bundleManifest.bundle.kitId}, expected ${manifest.kit.id}.`
|
|
12871
|
+
);
|
|
12872
|
+
}
|
|
12873
|
+
if (bundleManifest.bundle.workerId !== manifest.entrypoint.workerId) {
|
|
12874
|
+
throw new Error(
|
|
12875
|
+
`Bundle ${bundleManifest.bundle.id} worker mismatch: ${bundleManifest.bundle.workerId} vs ${manifest.entrypoint.workerId}.`
|
|
12876
|
+
);
|
|
12877
|
+
}
|
|
12878
|
+
assertRelativePathExists(assetRoot, manifest.entrypoint.path, "Kit manifest");
|
|
12879
|
+
assertRelativePathExists(assetRoot, manifest.agentContractPath, "Kit manifest");
|
|
12880
|
+
assertRelativePathExists(assetRoot, manifest.brandTemplatePath, "Kit manifest");
|
|
12881
|
+
for (const bundle of manifest.bundles) {
|
|
12882
|
+
assertRelativePathExists(assetRoot, bundle.path, "Kit manifest bundle");
|
|
12883
|
+
}
|
|
12884
|
+
for (const relativePath of manifest.frozenAssetPaths) {
|
|
12885
|
+
assertRelativePathExists(assetRoot, relativePath, "Kit manifest");
|
|
12886
|
+
}
|
|
12887
|
+
for (const requiredPath of manifest.outputStandard.requiredPaths) {
|
|
12888
|
+
assertRelativePathExists(assetRoot, requiredPath, "Output standard");
|
|
12889
|
+
}
|
|
12890
|
+
for (const relativePath of bundleManifest.requiredFrozenAssets) {
|
|
12891
|
+
assertRelativePathExists(assetRoot, relativePath, "Bundle manifest");
|
|
12892
|
+
}
|
|
12893
|
+
const kitPublicBrands = new Set(manifest.publicExampleBrandPaths ?? []);
|
|
12894
|
+
const bundlePublicBrands = new Set(bundleManifest.publicExampleBrandPaths ?? []);
|
|
12895
|
+
for (const brandPath of kitPublicBrands) {
|
|
12896
|
+
if (!bundlePublicBrands.has(brandPath)) {
|
|
12897
|
+
throw new Error(`Bundle ${bundleManifest.bundle.id} is missing declared public brand ${brandPath}.`);
|
|
12898
|
+
}
|
|
12899
|
+
}
|
|
12900
|
+
const bundledFiles = listRelativeFiles(assetRoot);
|
|
12901
|
+
const brandKitFiles = bundledFiles.filter((filePath) => filePath.startsWith("brands/") && filePath.endsWith("/brand-kit.md"));
|
|
12902
|
+
const allowedBrandPaths = /* @__PURE__ */ new Set([
|
|
12903
|
+
manifest.brandTemplatePath,
|
|
12904
|
+
...manifest.publicExampleBrandPaths ?? []
|
|
12905
|
+
]);
|
|
12906
|
+
const disallowedBrandFiles = brandKitFiles.filter((filePath) => !allowedBrandPaths.has(filePath));
|
|
12907
|
+
if (disallowedBrandFiles.length > 0) {
|
|
12908
|
+
throw new Error(
|
|
12909
|
+
`Bundled kit ${manifest.kit.id} includes non-public brand kits: ${disallowedBrandFiles.join(", ")}`
|
|
12910
|
+
);
|
|
12911
|
+
}
|
|
12912
|
+
}
|
|
12913
|
+
function validateKitDirectory(kitPath) {
|
|
12914
|
+
const errors = [];
|
|
12915
|
+
const warnings = [];
|
|
12916
|
+
let schemaVersion = 0;
|
|
12917
|
+
let kitId = "<unknown>";
|
|
12918
|
+
const kitJsonPath = path19.resolve(kitPath, "kit.json");
|
|
12919
|
+
if (!fs14.existsSync(kitJsonPath)) {
|
|
12920
|
+
errors.push({ field: "kit.json", message: "kit.json not found in kit directory" });
|
|
12921
|
+
return { valid: false, schemaVersion, kitId, errors, warnings };
|
|
12922
|
+
}
|
|
12923
|
+
let raw;
|
|
12924
|
+
try {
|
|
12925
|
+
raw = JSON.parse(fs14.readFileSync(kitJsonPath, "utf8"));
|
|
12926
|
+
} catch {
|
|
12927
|
+
errors.push({ field: "kit.json", message: "kit.json is not valid JSON" });
|
|
12928
|
+
return { valid: false, schemaVersion, kitId, errors, warnings };
|
|
12929
|
+
}
|
|
12930
|
+
schemaVersion = typeof raw.schemaVersion === "number" ? raw.schemaVersion : 0;
|
|
12931
|
+
if (!SUPPORTED_SCHEMA_VERSIONS.includes(schemaVersion)) {
|
|
12932
|
+
errors.push({
|
|
12933
|
+
field: "schemaVersion",
|
|
12934
|
+
message: `Unsupported schema version ${schemaVersion}. Supported: ${SUPPORTED_SCHEMA_VERSIONS.join(", ")}`
|
|
12935
|
+
});
|
|
12936
|
+
return { valid: false, schemaVersion, kitId, errors, warnings };
|
|
12937
|
+
}
|
|
12938
|
+
const kitBlock = raw.kit;
|
|
12939
|
+
if (!kitBlock || typeof kitBlock !== "object") {
|
|
12940
|
+
errors.push({ field: "kit", message: "Missing required 'kit' block" });
|
|
12941
|
+
return { valid: false, schemaVersion, kitId, errors, warnings };
|
|
12942
|
+
}
|
|
12943
|
+
kitId = typeof kitBlock.id === "string" ? kitBlock.id : "<unknown>";
|
|
12944
|
+
for (const field of ["id", "version", "name", "description"]) {
|
|
12945
|
+
if (typeof kitBlock[field] !== "string" || kitBlock[field].trim() === "") {
|
|
12946
|
+
errors.push({ field: `kit.${field}`, message: `Missing or empty required field 'kit.${field}'` });
|
|
12947
|
+
}
|
|
12948
|
+
}
|
|
12949
|
+
if (schemaVersion === 2) {
|
|
12950
|
+
const kitType = kitBlock.type;
|
|
12951
|
+
if (!kitType || !KIT_CAPABILITY_TYPES.includes(kitType)) {
|
|
12952
|
+
errors.push({
|
|
12953
|
+
field: "kit.type",
|
|
12954
|
+
message: `Invalid or missing kit.type. Expected one of: ${KIT_CAPABILITY_TYPES.join(", ")}`
|
|
12955
|
+
});
|
|
12956
|
+
}
|
|
12957
|
+
const execMode = raw.executionMode;
|
|
12958
|
+
if (!execMode) {
|
|
12959
|
+
errors.push({ field: "executionMode", message: "Missing required field 'executionMode'" });
|
|
12960
|
+
} else if (!KIT_ACTIVATION_MODES.includes(execMode)) {
|
|
12961
|
+
errors.push({
|
|
12962
|
+
field: "executionMode",
|
|
12963
|
+
message: `Invalid executionMode '${execMode}'. Expected one of: ${KIT_ACTIVATION_MODES.join(", ")}`
|
|
12964
|
+
});
|
|
12965
|
+
}
|
|
12966
|
+
const activationModes = raw.activationModes;
|
|
12967
|
+
if (!Array.isArray(activationModes) || activationModes.length === 0) {
|
|
12968
|
+
errors.push({ field: "activationModes", message: "Missing or empty 'activationModes' array" });
|
|
12969
|
+
} else {
|
|
12970
|
+
for (const mode of activationModes) {
|
|
12971
|
+
if (!KIT_ACTIVATION_MODES.includes(mode)) {
|
|
12972
|
+
errors.push({
|
|
12973
|
+
field: "activationModes",
|
|
12974
|
+
message: `Invalid activation mode '${mode}'. Expected one of: ${KIT_ACTIVATION_MODES.join(", ")}`
|
|
12975
|
+
});
|
|
12976
|
+
}
|
|
12977
|
+
}
|
|
12978
|
+
}
|
|
12979
|
+
} else {
|
|
12980
|
+
warnings.push({ field: "schemaVersion", message: "Kit uses schema v1. Consider upgrading to v2 for capability metadata." });
|
|
12981
|
+
}
|
|
12982
|
+
const entrypoint = raw.entrypoint;
|
|
12983
|
+
if (!entrypoint || typeof entrypoint !== "object") {
|
|
12984
|
+
errors.push({ field: "entrypoint", message: "Missing required 'entrypoint' block" });
|
|
12985
|
+
} else {
|
|
12986
|
+
if (typeof entrypoint.workerId !== "string") {
|
|
12987
|
+
errors.push({ field: "entrypoint.workerId", message: "Missing required field 'entrypoint.workerId'" });
|
|
12988
|
+
}
|
|
12989
|
+
if (typeof entrypoint.path !== "string") {
|
|
12990
|
+
errors.push({ field: "entrypoint.path", message: "Missing required field 'entrypoint.path'" });
|
|
12991
|
+
} else {
|
|
12992
|
+
const fullPath = path19.resolve(kitPath, entrypoint.path);
|
|
12993
|
+
if (!fs14.existsSync(fullPath)) {
|
|
12994
|
+
errors.push({ field: "entrypoint.path", message: `Entrypoint file not found: ${entrypoint.path}` });
|
|
12995
|
+
}
|
|
12529
12996
|
}
|
|
12530
|
-
copyFileSync(sourcePath, targetPath);
|
|
12531
12997
|
}
|
|
12998
|
+
if (typeof raw.agentContractPath !== "string") {
|
|
12999
|
+
errors.push({ field: "agentContractPath", message: "Missing required field 'agentContractPath'" });
|
|
13000
|
+
} else {
|
|
13001
|
+
const fullPath = path19.resolve(kitPath, raw.agentContractPath);
|
|
13002
|
+
if (!fs14.existsSync(fullPath)) {
|
|
13003
|
+
errors.push({ field: "agentContractPath", message: `Agent contract not found: ${raw.agentContractPath}` });
|
|
13004
|
+
}
|
|
13005
|
+
}
|
|
13006
|
+
if (typeof raw.brandTemplatePath !== "string") {
|
|
13007
|
+
errors.push({ field: "brandTemplatePath", message: "Missing required field 'brandTemplatePath'" });
|
|
13008
|
+
} else {
|
|
13009
|
+
const fullPath = path19.resolve(kitPath, raw.brandTemplatePath);
|
|
13010
|
+
if (!fs14.existsSync(fullPath)) {
|
|
13011
|
+
errors.push({ field: "brandTemplatePath", message: `Brand template not found: ${raw.brandTemplatePath}` });
|
|
13012
|
+
}
|
|
13013
|
+
}
|
|
13014
|
+
const frozenAssets = raw.frozenAssetPaths;
|
|
13015
|
+
if (!Array.isArray(frozenAssets)) {
|
|
13016
|
+
errors.push({ field: "frozenAssetPaths", message: "Missing required 'frozenAssetPaths' array" });
|
|
13017
|
+
} else {
|
|
13018
|
+
for (const assetPath of frozenAssets) {
|
|
13019
|
+
if (typeof assetPath !== "string") continue;
|
|
13020
|
+
const fullPath = path19.resolve(kitPath, assetPath);
|
|
13021
|
+
if (!fs14.existsSync(fullPath)) {
|
|
13022
|
+
errors.push({ field: "frozenAssetPaths", message: `Frozen asset not found: ${assetPath}` });
|
|
13023
|
+
}
|
|
13024
|
+
}
|
|
13025
|
+
}
|
|
13026
|
+
const outputStandard = raw.outputStandard;
|
|
13027
|
+
if (!outputStandard || typeof outputStandard !== "object") {
|
|
13028
|
+
errors.push({ field: "outputStandard", message: "Missing required 'outputStandard' block" });
|
|
13029
|
+
} else {
|
|
13030
|
+
if (typeof outputStandard.type !== "string") {
|
|
13031
|
+
errors.push({ field: "outputStandard.type", message: "Missing required field 'outputStandard.type'" });
|
|
13032
|
+
}
|
|
13033
|
+
const requiredPaths = outputStandard.requiredPaths;
|
|
13034
|
+
if (!Array.isArray(requiredPaths)) {
|
|
13035
|
+
errors.push({ field: "outputStandard.requiredPaths", message: "Missing required 'outputStandard.requiredPaths' array" });
|
|
13036
|
+
} else {
|
|
13037
|
+
for (const reqPath of requiredPaths) {
|
|
13038
|
+
if (typeof reqPath !== "string") continue;
|
|
13039
|
+
const fullPath = path19.resolve(kitPath, reqPath);
|
|
13040
|
+
if (!fs14.existsSync(fullPath)) {
|
|
13041
|
+
errors.push({ field: "outputStandard.requiredPaths", message: `Required output path not found: ${reqPath}` });
|
|
13042
|
+
}
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
13045
|
+
}
|
|
13046
|
+
const bundles = raw.bundles;
|
|
13047
|
+
if (!Array.isArray(bundles) || bundles.length === 0) {
|
|
13048
|
+
errors.push({ field: "bundles", message: "Missing or empty 'bundles' array" });
|
|
13049
|
+
} else {
|
|
13050
|
+
for (const bundleRef of bundles) {
|
|
13051
|
+
const ref = bundleRef;
|
|
13052
|
+
if (typeof ref.path !== "string") {
|
|
13053
|
+
errors.push({ field: "bundles[].path", message: "Bundle ref missing 'path' field" });
|
|
13054
|
+
continue;
|
|
13055
|
+
}
|
|
13056
|
+
const bundlePath = path19.resolve(kitPath, ref.path);
|
|
13057
|
+
if (!fs14.existsSync(bundlePath)) {
|
|
13058
|
+
errors.push({ field: "bundles[].path", message: `Bundle manifest not found: ${ref.path}` });
|
|
13059
|
+
continue;
|
|
13060
|
+
}
|
|
13061
|
+
try {
|
|
13062
|
+
const bundleRaw = JSON.parse(fs14.readFileSync(bundlePath, "utf8"));
|
|
13063
|
+
const bundleBlock = bundleRaw.bundle;
|
|
13064
|
+
if (!bundleBlock || typeof bundleBlock !== "object") {
|
|
13065
|
+
errors.push({ field: `bundle(${ref.id})`, message: "Bundle manifest missing 'bundle' block" });
|
|
13066
|
+
} else {
|
|
13067
|
+
if (bundleBlock.kitId !== kitId) {
|
|
13068
|
+
errors.push({
|
|
13069
|
+
field: `bundle(${ref.id}).kitId`,
|
|
13070
|
+
message: `Bundle kitId '${bundleBlock.kitId}' does not match kit id '${kitId}'`
|
|
13071
|
+
});
|
|
13072
|
+
}
|
|
13073
|
+
}
|
|
13074
|
+
if (!bundleRaw.export || typeof bundleRaw.export !== "object") {
|
|
13075
|
+
errors.push({ field: `bundle(${ref.id}).export`, message: "Bundle manifest missing 'export' block" });
|
|
13076
|
+
}
|
|
13077
|
+
} catch {
|
|
13078
|
+
errors.push({ field: `bundle(${ref.id})`, message: `Bundle manifest at ${ref.path} is not valid JSON` });
|
|
13079
|
+
}
|
|
13080
|
+
}
|
|
13081
|
+
}
|
|
13082
|
+
return {
|
|
13083
|
+
valid: errors.length === 0,
|
|
13084
|
+
schemaVersion,
|
|
13085
|
+
kitId,
|
|
13086
|
+
errors,
|
|
13087
|
+
warnings
|
|
13088
|
+
};
|
|
13089
|
+
}
|
|
13090
|
+
function loadResolvedBundledKit(assetRoot, catalogEntry) {
|
|
13091
|
+
const manifest = parseManifest(assetRoot);
|
|
13092
|
+
const bundleManifest = parseBundleManifest(assetRoot, manifest, catalogEntry.defaultBundleId);
|
|
13093
|
+
const resolved = { catalogEntry, assetRoot, manifest, bundleManifest };
|
|
13094
|
+
validateBundledKit(resolved);
|
|
13095
|
+
return resolved;
|
|
13096
|
+
}
|
|
13097
|
+
function fuzzyResolveKitId(input) {
|
|
13098
|
+
const needle = input.toLowerCase().trim();
|
|
13099
|
+
const exact = BUNDLED_KIT_CATALOG.find((e) => e.id === needle);
|
|
13100
|
+
if (exact) return exact.id;
|
|
13101
|
+
const suffix = BUNDLED_KIT_CATALOG.find((e) => e.id.endsWith(needle));
|
|
13102
|
+
if (suffix) return suffix.id;
|
|
13103
|
+
const contains = BUNDLED_KIT_CATALOG.find((e) => e.id.includes(needle));
|
|
13104
|
+
if (contains) return contains.id;
|
|
13105
|
+
const tokens = needle.split(/[-\s]+/).filter((t) => t.length > 2);
|
|
13106
|
+
for (const token of tokens) {
|
|
13107
|
+
const tokenMatch = BUNDLED_KIT_CATALOG.find((e) => e.id.includes(token));
|
|
13108
|
+
if (tokenMatch) return tokenMatch.id;
|
|
13109
|
+
}
|
|
13110
|
+
return null;
|
|
13111
|
+
}
|
|
13112
|
+
function resolveBundledKit(kitId) {
|
|
13113
|
+
const resolvedId = fuzzyResolveKitId(kitId);
|
|
13114
|
+
if (!resolvedId) {
|
|
13115
|
+
const available = BUNDLED_KIT_CATALOG.map((e) => e.id).join(", ");
|
|
13116
|
+
throw new Error(
|
|
13117
|
+
`Unknown kit '${kitId}'. Run 'growthub kit list' to browse available kits.
|
|
13118
|
+
Available: ${available}`
|
|
13119
|
+
);
|
|
13120
|
+
}
|
|
13121
|
+
const catalogEntry = BUNDLED_KIT_CATALOG.find((e) => e.id === resolvedId);
|
|
13122
|
+
const assetRoot = path19.resolve(resolveBundledKitAssetsRoot(), catalogEntry.packageDirName);
|
|
13123
|
+
return loadResolvedBundledKit(assetRoot, catalogEntry);
|
|
13124
|
+
}
|
|
13125
|
+
function toListItem(resolved) {
|
|
13126
|
+
return {
|
|
13127
|
+
id: resolved.manifest.kit.id,
|
|
13128
|
+
version: resolved.manifest.kit.version,
|
|
13129
|
+
name: resolved.manifest.kit.name,
|
|
13130
|
+
description: resolved.manifest.kit.description,
|
|
13131
|
+
type: resolved.manifest.kit.type,
|
|
13132
|
+
family: resolved.catalogEntry.family,
|
|
13133
|
+
executionMode: resolved.manifest.executionMode,
|
|
13134
|
+
activationModes: resolved.manifest.activationModes,
|
|
13135
|
+
bundleId: resolved.bundleManifest.bundle.id,
|
|
13136
|
+
bundleVersion: resolved.bundleManifest.bundle.version,
|
|
13137
|
+
briefType: resolved.bundleManifest.briefType
|
|
13138
|
+
};
|
|
12532
13139
|
}
|
|
12533
|
-
function
|
|
13140
|
+
function resolveOutputPaths(resolved, outDir) {
|
|
13141
|
+
const outputRoot = resolveRequestedOutputRoot(outDir);
|
|
13142
|
+
const folderPath = path19.resolve(outputRoot, resolved.bundleManifest.export.folderName);
|
|
13143
|
+
const zipPath = path19.resolve(outputRoot, resolved.bundleManifest.export.zipFileName);
|
|
13144
|
+
return { outputRoot, folderPath, zipPath };
|
|
13145
|
+
}
|
|
13146
|
+
function listBundledKits() {
|
|
13147
|
+
return BUNDLED_KIT_CATALOG.map((entry) => toListItem(resolveBundledKit(entry.id)));
|
|
13148
|
+
}
|
|
13149
|
+
function inspectBundledKit(kitId, outDir) {
|
|
13150
|
+
const resolved = resolveBundledKit(kitId);
|
|
13151
|
+
const outputPaths = resolveOutputPaths(resolved, outDir);
|
|
13152
|
+
return {
|
|
13153
|
+
...toListItem(resolved),
|
|
13154
|
+
entrypointPath: resolved.manifest.entrypoint.path,
|
|
13155
|
+
agentContractPath: resolved.manifest.agentContractPath,
|
|
13156
|
+
brandTemplatePath: resolved.manifest.brandTemplatePath,
|
|
13157
|
+
publicExampleBrandPaths: resolved.manifest.publicExampleBrandPaths ?? [],
|
|
13158
|
+
frozenAssetCount: resolved.manifest.frozenAssetPaths.length,
|
|
13159
|
+
requiredFrozenAssetCount: resolved.bundleManifest.requiredFrozenAssets.length,
|
|
13160
|
+
outputRoot: outputPaths.outputRoot,
|
|
13161
|
+
exportFolderName: resolved.bundleManifest.export.folderName,
|
|
13162
|
+
exportFolderPath: outputPaths.folderPath,
|
|
13163
|
+
exportZipName: resolved.bundleManifest.export.zipFileName,
|
|
13164
|
+
exportZipPath: outputPaths.zipPath,
|
|
13165
|
+
requiredPaths: resolved.manifest.outputStandard.requiredPaths,
|
|
13166
|
+
compatibility: resolved.manifest.compatibility,
|
|
13167
|
+
schemaVersion: resolved.manifest.schemaVersion
|
|
13168
|
+
};
|
|
13169
|
+
}
|
|
13170
|
+
function resolveKitPath(kitId, outDir) {
|
|
13171
|
+
const resolved = resolveBundledKit(kitId);
|
|
13172
|
+
return resolveOutputPaths(resolved, outDir).folderPath;
|
|
13173
|
+
}
|
|
13174
|
+
function crc32(buffer) {
|
|
12534
13175
|
let crc = 4294967295;
|
|
12535
13176
|
for (const byte of buffer) {
|
|
12536
13177
|
crc ^= byte;
|
|
@@ -12540,27 +13181,27 @@ function crc32Dist(buffer) {
|
|
|
12540
13181
|
}
|
|
12541
13182
|
return (crc ^ 4294967295) >>> 0;
|
|
12542
13183
|
}
|
|
12543
|
-
function
|
|
12544
|
-
const year = Math.max(
|
|
12545
|
-
const month =
|
|
12546
|
-
const day =
|
|
12547
|
-
const hours =
|
|
12548
|
-
const minutes =
|
|
12549
|
-
const seconds = Math.floor(
|
|
13184
|
+
function toDosTimeParts(date2) {
|
|
13185
|
+
const year = Math.max(date2.getUTCFullYear(), 1980);
|
|
13186
|
+
const month = date2.getUTCMonth() + 1;
|
|
13187
|
+
const day = date2.getUTCDate();
|
|
13188
|
+
const hours = date2.getUTCHours();
|
|
13189
|
+
const minutes = date2.getUTCMinutes();
|
|
13190
|
+
const seconds = Math.floor(date2.getUTCSeconds() / 2);
|
|
12550
13191
|
return {
|
|
12551
13192
|
dosTime: hours << 11 | minutes << 5 | seconds,
|
|
12552
13193
|
dosDate: year - 1980 << 9 | month << 5 | day
|
|
12553
13194
|
};
|
|
12554
13195
|
}
|
|
12555
|
-
function
|
|
13196
|
+
function buildStoredZip(entries) {
|
|
12556
13197
|
const parts = [];
|
|
12557
|
-
const
|
|
13198
|
+
const centralDirectoryParts = [];
|
|
12558
13199
|
let offset = 0;
|
|
12559
|
-
const { dosTime, dosDate } =
|
|
13200
|
+
const { dosTime, dosDate } = toDosTimeParts(ZIP_TIMESTAMP);
|
|
12560
13201
|
for (const entry of entries) {
|
|
12561
13202
|
const nameBuffer = Buffer.from(entry.name, "utf8");
|
|
12562
13203
|
const data = entry.data;
|
|
12563
|
-
const checksum =
|
|
13204
|
+
const checksum = crc32(data);
|
|
12564
13205
|
const localHeader = Buffer.alloc(30 + nameBuffer.length);
|
|
12565
13206
|
localHeader.writeUInt32LE(67324752, 0);
|
|
12566
13207
|
localHeader.writeUInt16LE(20, 4);
|
|
@@ -12594,10 +13235,10 @@ function buildStoredZipDist(entries) {
|
|
|
12594
13235
|
centralHeader.writeUInt32LE(0, 38);
|
|
12595
13236
|
centralHeader.writeUInt32LE(offset, 42);
|
|
12596
13237
|
nameBuffer.copy(centralHeader, 46);
|
|
12597
|
-
|
|
13238
|
+
centralDirectoryParts.push(centralHeader);
|
|
12598
13239
|
offset += localHeader.length + data.length;
|
|
12599
13240
|
}
|
|
12600
|
-
const centralDirectory = Buffer.concat(
|
|
13241
|
+
const centralDirectory = Buffer.concat(centralDirectoryParts);
|
|
12601
13242
|
const endRecord = Buffer.alloc(22);
|
|
12602
13243
|
endRecord.writeUInt32LE(101010256, 0);
|
|
12603
13244
|
endRecord.writeUInt16LE(0, 4);
|
|
@@ -12609,106 +13250,1247 @@ function buildStoredZipDist(entries) {
|
|
|
12609
13250
|
endRecord.writeUInt16LE(0, 20);
|
|
12610
13251
|
return Buffer.concat([...parts, centralDirectory, endRecord]);
|
|
12611
13252
|
}
|
|
12612
|
-
function
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
13253
|
+
function reportProgress(onProgress, progress) {
|
|
13254
|
+
onProgress?.(progress);
|
|
13255
|
+
}
|
|
13256
|
+
function copyDirectoryWithProgress(sourceRoot, targetRoot, onProgress) {
|
|
13257
|
+
const files = listRelativeFiles(sourceRoot);
|
|
13258
|
+
const total = Math.max(files.length, 1);
|
|
13259
|
+
fs14.mkdirSync(targetRoot, { recursive: true });
|
|
13260
|
+
reportProgress(onProgress, {
|
|
13261
|
+
phase: "copying",
|
|
13262
|
+
completed: 0,
|
|
13263
|
+
total,
|
|
13264
|
+
percent: 10,
|
|
13265
|
+
detail: "Preparing files"
|
|
13266
|
+
});
|
|
13267
|
+
files.forEach((relativePath, index51) => {
|
|
13268
|
+
const sourcePath = path19.resolve(sourceRoot, relativePath);
|
|
13269
|
+
const targetPath = path19.resolve(targetRoot, relativePath);
|
|
13270
|
+
fs14.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
13271
|
+
fs14.copyFileSync(sourcePath, targetPath);
|
|
13272
|
+
const completed = index51 + 1;
|
|
13273
|
+
const percent = 10 + Math.round(completed / total * 55);
|
|
13274
|
+
reportProgress(onProgress, {
|
|
13275
|
+
phase: "copying",
|
|
13276
|
+
completed,
|
|
13277
|
+
total,
|
|
13278
|
+
percent,
|
|
13279
|
+
detail: relativePath
|
|
13280
|
+
});
|
|
13281
|
+
});
|
|
13282
|
+
}
|
|
13283
|
+
function buildZipEntriesWithProgress(sourceRoot, exportFolderName, onProgress) {
|
|
13284
|
+
const files = listRelativeFiles(sourceRoot);
|
|
13285
|
+
const total = Math.max(files.length, 1);
|
|
13286
|
+
return files.map((relativePath, index51) => {
|
|
13287
|
+
const completed = index51 + 1;
|
|
13288
|
+
const percent = 65 + Math.round(completed / total * 30);
|
|
13289
|
+
reportProgress(onProgress, {
|
|
13290
|
+
phase: "zipping",
|
|
13291
|
+
completed,
|
|
13292
|
+
total,
|
|
13293
|
+
percent,
|
|
13294
|
+
detail: relativePath
|
|
13295
|
+
});
|
|
13296
|
+
return {
|
|
13297
|
+
name: path19.posix.join(exportFolderName, relativePath),
|
|
13298
|
+
data: fs14.readFileSync(path19.resolve(sourceRoot, relativePath))
|
|
13299
|
+
};
|
|
13300
|
+
});
|
|
12625
13301
|
}
|
|
12626
|
-
function
|
|
12627
|
-
const
|
|
12628
|
-
const
|
|
12629
|
-
const
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
13302
|
+
function downloadBundledKit(kitId, outDir, options = {}) {
|
|
13303
|
+
const resolved = resolveBundledKit(kitId);
|
|
13304
|
+
const outputPaths = resolveOutputPaths(resolved, outDir);
|
|
13305
|
+
const onProgress = options.onProgress;
|
|
13306
|
+
reportProgress(onProgress, {
|
|
13307
|
+
phase: "preparing",
|
|
13308
|
+
completed: 0,
|
|
13309
|
+
total: 1,
|
|
13310
|
+
percent: 0,
|
|
13311
|
+
detail: "Resolving export target"
|
|
13312
|
+
});
|
|
13313
|
+
fs14.mkdirSync(outputPaths.outputRoot, { recursive: true });
|
|
13314
|
+
fs14.rmSync(outputPaths.folderPath, { recursive: true, force: true });
|
|
13315
|
+
copyDirectoryWithProgress(resolved.assetRoot, outputPaths.folderPath, onProgress);
|
|
13316
|
+
const zipBuffer = buildStoredZip(
|
|
13317
|
+
buildZipEntriesWithProgress(outputPaths.folderPath, resolved.bundleManifest.export.folderName, onProgress)
|
|
13318
|
+
);
|
|
13319
|
+
reportProgress(onProgress, {
|
|
13320
|
+
phase: "writing_zip",
|
|
13321
|
+
completed: 1,
|
|
13322
|
+
total: 1,
|
|
13323
|
+
percent: 98,
|
|
13324
|
+
detail: path19.basename(outputPaths.zipPath)
|
|
13325
|
+
});
|
|
13326
|
+
fs14.writeFileSync(outputPaths.zipPath, zipBuffer);
|
|
13327
|
+
reportProgress(onProgress, {
|
|
13328
|
+
phase: "done",
|
|
13329
|
+
completed: 1,
|
|
13330
|
+
total: 1,
|
|
13331
|
+
percent: 100,
|
|
13332
|
+
detail: "Export complete"
|
|
13333
|
+
});
|
|
12633
13334
|
return {
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
bundleManifest,
|
|
12637
|
-
outputRoot,
|
|
12638
|
-
folderPath: path17.resolve(outputRoot, bundleManifest.export.folderName),
|
|
12639
|
-
zipPath: path17.resolve(outputRoot, bundleManifest.export.zipFileName)
|
|
13335
|
+
folderPath: outputPaths.folderPath,
|
|
13336
|
+
zipPath: outputPaths.zipPath
|
|
12640
13337
|
};
|
|
12641
13338
|
}
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
}
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
const
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
13339
|
+
|
|
13340
|
+
// src/commands/kit.ts
|
|
13341
|
+
var TYPE_CONFIG = {
|
|
13342
|
+
studio: { color: pc23.cyan, emoji: "\u{1F6E0}\uFE0F", label: "Custom Workspaces" },
|
|
13343
|
+
specialized_agents: { color: pc23.magenta, emoji: "\u{1F9E0}", label: "Specialized Agents" },
|
|
13344
|
+
ops: { color: pc23.yellow, emoji: "\u2699\uFE0F ", label: "Ops" }
|
|
13345
|
+
};
|
|
13346
|
+
function displayTypeForFamily(family) {
|
|
13347
|
+
if (family === "workflow" || family === "operator") return "specialized_agents";
|
|
13348
|
+
if (family === "studio" || family === "ops") return family;
|
|
13349
|
+
return family;
|
|
13350
|
+
}
|
|
13351
|
+
function typeColor(family, text58) {
|
|
13352
|
+
const type = displayTypeForFamily(family);
|
|
13353
|
+
return TYPE_CONFIG[type]?.color(text58) ?? text58;
|
|
13354
|
+
}
|
|
13355
|
+
function typeBadge(family) {
|
|
13356
|
+
const type = displayTypeForFamily(family);
|
|
13357
|
+
const cfg = TYPE_CONFIG[type];
|
|
13358
|
+
if (!cfg) return String(type);
|
|
13359
|
+
return cfg.color(`${cfg.emoji} ${cfg.label}`);
|
|
13360
|
+
}
|
|
13361
|
+
function truncate(str, max) {
|
|
13362
|
+
if (str.length <= max) return str;
|
|
13363
|
+
return str.slice(0, max - 1) + "\u2026";
|
|
13364
|
+
}
|
|
13365
|
+
function displayKitName(name) {
|
|
13366
|
+
return name.replace(/^Growthub Agent Worker Kit\s+[—-]\s+/u, "").trim();
|
|
13367
|
+
}
|
|
13368
|
+
function hr(width = 72) {
|
|
13369
|
+
return pc23.dim("\u2500".repeat(width));
|
|
13370
|
+
}
|
|
13371
|
+
function box(lines) {
|
|
13372
|
+
const padded = lines.map((l) => " " + l);
|
|
13373
|
+
const width = Math.max(...padded.map((l) => stripAnsi(l).length)) + 4;
|
|
13374
|
+
const top = pc23.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
|
|
13375
|
+
const bottom = pc23.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
|
|
13376
|
+
const body = padded.map((l) => {
|
|
13377
|
+
const pad = width - stripAnsi(l).length;
|
|
13378
|
+
return pc23.dim("\u2502") + l + " ".repeat(pad) + pc23.dim("\u2502");
|
|
13379
|
+
});
|
|
13380
|
+
return [top, ...body, bottom].join("\n");
|
|
13381
|
+
}
|
|
13382
|
+
function stripAnsi(str) {
|
|
13383
|
+
return str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
13384
|
+
}
|
|
13385
|
+
function terminalLink(label, href) {
|
|
13386
|
+
return `\x1B]8;;${href}\x07${label}\x1B]8;;\x07`;
|
|
13387
|
+
}
|
|
13388
|
+
function folderOpenLabel(folderPath) {
|
|
13389
|
+
const href = pathToFileURL2(folderPath).href;
|
|
13390
|
+
const label = process.platform === "darwin" ? "Open in Finder" : process.platform === "win32" ? "Open in Explorer" : "Open folder";
|
|
13391
|
+
return terminalLink(label, href);
|
|
13392
|
+
}
|
|
13393
|
+
function renderProgressBar(progress) {
|
|
13394
|
+
if (!process.stdout.isTTY) return;
|
|
13395
|
+
const width = 24;
|
|
13396
|
+
const filled = Math.max(0, Math.min(width, Math.round(progress.percent / 100 * width)));
|
|
13397
|
+
const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
13398
|
+
const detail = truncate(progress.detail, 48);
|
|
13399
|
+
const line = `\r${pc23.cyan("Exporting kit")} ${pc23.dim("[")}${pc23.green(bar)}${pc23.dim("]")} ${String(progress.percent).padStart(3)}% ${pc23.dim(detail)}`;
|
|
13400
|
+
process.stdout.write(line);
|
|
13401
|
+
if (progress.phase === "done") {
|
|
13402
|
+
process.stdout.write("\n");
|
|
13403
|
+
}
|
|
13404
|
+
}
|
|
13405
|
+
function printKitCard(item) {
|
|
13406
|
+
const badge2 = typeBadge(item.family);
|
|
13407
|
+
console.log("");
|
|
13408
|
+
console.log(box([
|
|
13409
|
+
`${pc23.bold(item.name)} ${pc23.dim("v" + item.version)}`,
|
|
13410
|
+
`${badge2} ${pc23.dim(item.id)}`,
|
|
13411
|
+
"",
|
|
13412
|
+
truncate(item.description, 62),
|
|
13413
|
+
"",
|
|
13414
|
+
`${pc23.dim("Brief:")} ${pc23.dim(item.briefType)} ${pc23.dim("Mode:")} ${pc23.dim(item.executionMode)}`
|
|
13415
|
+
]));
|
|
13416
|
+
}
|
|
13417
|
+
async function confirmKitActions(input) {
|
|
13418
|
+
const actionLabels = input.actions.map((action) => {
|
|
13419
|
+
if (action === "download") return "download";
|
|
13420
|
+
if (action === "inspect") return "inspect";
|
|
13421
|
+
if (action === "copy-id") return "print id";
|
|
13422
|
+
return action;
|
|
13423
|
+
});
|
|
13424
|
+
const summaryLines = [
|
|
13425
|
+
pc23.bold("Selected kits"),
|
|
13426
|
+
...input.kits.map((kit) => `${typeBadge(kit.family)} ${displayKitName(kit.name)}`),
|
|
13427
|
+
"",
|
|
13428
|
+
pc23.bold("Selected actions"),
|
|
13429
|
+
actionLabels.join(", ")
|
|
13430
|
+
];
|
|
13431
|
+
console.log("");
|
|
13432
|
+
console.log(box(summaryLines));
|
|
13433
|
+
const confirmed = await p16.confirm({
|
|
13434
|
+
message: "Continue with these worker kit actions?",
|
|
13435
|
+
initialValue: false
|
|
13436
|
+
});
|
|
13437
|
+
if (p16.isCancel(confirmed)) {
|
|
13438
|
+
p16.cancel("Cancelled.");
|
|
13439
|
+
process.exit(0);
|
|
13440
|
+
}
|
|
13441
|
+
return Boolean(confirmed);
|
|
13442
|
+
}
|
|
13443
|
+
function printGroupedList(kits) {
|
|
13444
|
+
const byType = {};
|
|
13445
|
+
for (const kit of kits) {
|
|
13446
|
+
const type = displayTypeForFamily(kit.family);
|
|
13447
|
+
(byType[type] ??= []).push(kit);
|
|
13448
|
+
}
|
|
13449
|
+
const types = Object.keys(byType).sort();
|
|
13450
|
+
const totalTypes = types.length;
|
|
13451
|
+
console.log("");
|
|
13452
|
+
console.log(
|
|
13453
|
+
pc23.bold("Growthub Agent Worker Kits") + pc23.dim(` ${kits.length} kit${kits.length !== 1 ? "s" : ""} \xB7 ${totalTypes} type${totalTypes !== 1 ? "s" : ""}`)
|
|
13454
|
+
);
|
|
13455
|
+
console.log(hr());
|
|
13456
|
+
for (const type of types) {
|
|
13457
|
+
const groupKits = byType[type];
|
|
13458
|
+
const header = typeBadge(type);
|
|
13459
|
+
console.log(`
|
|
13460
|
+
${header} ${pc23.dim("(" + groupKits.length + ")")}`);
|
|
13461
|
+
for (const kit of groupKits) {
|
|
13462
|
+
console.log(` ${typeColor(kit.family, pc23.bold(kit.id))} ${pc23.dim("v" + kit.version)}`);
|
|
13463
|
+
console.log(` ${pc23.dim(truncate(kit.description, 62))}`);
|
|
13464
|
+
console.log(` ${pc23.dim("\u2192")} ${pc23.cyan("growthub kit download " + kit.id)}`);
|
|
13465
|
+
console.log("");
|
|
13466
|
+
}
|
|
13467
|
+
}
|
|
13468
|
+
console.log(hr());
|
|
13469
|
+
console.log(pc23.dim(" growthub kit download <id> \xB7 growthub kit inspect <id> \xB7 growthub kit families"));
|
|
13470
|
+
console.log("");
|
|
13471
|
+
}
|
|
13472
|
+
async function runInteractivePicker(opts) {
|
|
13473
|
+
p16.intro(pc23.bold("Growthub Agent Worker Kits"));
|
|
13474
|
+
let kits;
|
|
13475
|
+
try {
|
|
13476
|
+
kits = listBundledKits();
|
|
13477
|
+
} catch (err) {
|
|
13478
|
+
p16.log.error("Failed to load kits: " + err.message);
|
|
13479
|
+
process.exit(1);
|
|
13480
|
+
}
|
|
13481
|
+
const familiesAvailable = [...new Set(kits.map((k) => k.family))].sort();
|
|
13482
|
+
const typeOptions = Array.from(new Set(familiesAvailable.map((family) => displayTypeForFamily(family))));
|
|
13483
|
+
while (true) {
|
|
13484
|
+
const typeChoice = await p16.select({
|
|
13485
|
+
message: "Filter by type",
|
|
13486
|
+
options: [
|
|
13487
|
+
{ value: "all", label: "All Types" },
|
|
13488
|
+
...typeOptions.map((type) => {
|
|
13489
|
+
const cfg = TYPE_CONFIG[type];
|
|
13490
|
+
return {
|
|
13491
|
+
value: type,
|
|
13492
|
+
label: cfg ? cfg.emoji + " " + cfg.label : String(type)
|
|
13493
|
+
};
|
|
13494
|
+
}),
|
|
13495
|
+
...opts.allowBackToHub ? [{ value: "__back_to_hub", label: "\u2190 Back to main menu" }] : []
|
|
13496
|
+
]
|
|
13497
|
+
});
|
|
13498
|
+
if (p16.isCancel(typeChoice)) {
|
|
13499
|
+
p16.cancel("Cancelled.");
|
|
13500
|
+
process.exit(0);
|
|
13501
|
+
}
|
|
13502
|
+
if (typeChoice === "__back_to_hub") return "back";
|
|
13503
|
+
const filtered = typeChoice === "all" ? kits : kits.filter((k) => displayTypeForFamily(k.family) === typeChoice);
|
|
13504
|
+
const showTypeBadgeInKitChoices = typeChoice === "all";
|
|
13505
|
+
if (filtered.length === 0) {
|
|
13506
|
+
p16.note("No kits are available for that type yet.", "Nothing found");
|
|
13507
|
+
continue;
|
|
13508
|
+
}
|
|
13509
|
+
while (true) {
|
|
13510
|
+
const kitChoice = await p16.select({
|
|
13511
|
+
message: "Select kit",
|
|
13512
|
+
options: [
|
|
13513
|
+
...filtered.map((k) => ({
|
|
13514
|
+
value: k.id,
|
|
13515
|
+
label: (showTypeBadgeInKitChoices ? typeBadge(k.family) + " " : "") + pc23.bold(displayKitName(k.name)) + " " + pc23.dim("v" + k.version),
|
|
13516
|
+
hint: truncate(k.description, 55)
|
|
13517
|
+
})),
|
|
13518
|
+
{ value: "__back_to_type", label: "\u2190 Back to type filter" }
|
|
13519
|
+
]
|
|
13520
|
+
});
|
|
13521
|
+
if (p16.isCancel(kitChoice)) {
|
|
13522
|
+
p16.cancel("Cancelled.");
|
|
13523
|
+
process.exit(0);
|
|
13524
|
+
}
|
|
13525
|
+
if (kitChoice === "__back_to_type") break;
|
|
13526
|
+
const selected = filtered.find((kit) => kit.id === kitChoice);
|
|
13527
|
+
if (!selected) {
|
|
13528
|
+
p16.cancel("Selected kit was not found.");
|
|
13529
|
+
process.exit(1);
|
|
13530
|
+
}
|
|
13531
|
+
printKitCard(selected);
|
|
13532
|
+
const nextStep = await p16.select({
|
|
13533
|
+
message: "Next step",
|
|
13534
|
+
options: [
|
|
13535
|
+
{ value: "actions", label: "Choose action(s)" },
|
|
13536
|
+
{ value: "back_to_kits", label: "\u2190 Back to kit list" }
|
|
13537
|
+
]
|
|
13538
|
+
});
|
|
13539
|
+
if (p16.isCancel(nextStep)) {
|
|
13540
|
+
p16.cancel("Cancelled.");
|
|
13541
|
+
process.exit(0);
|
|
13542
|
+
}
|
|
13543
|
+
if (nextStep === "back_to_kits") continue;
|
|
13544
|
+
while (true) {
|
|
13545
|
+
const actionOptions = [
|
|
13546
|
+
{ value: "download", label: "\u2B07\uFE0F Download kit", hint: "growthub kit download <id>" },
|
|
13547
|
+
{ value: "inspect", label: "\u{1F50D} Inspect manifest", hint: "growthub kit inspect <id>" },
|
|
13548
|
+
{ value: "copy-id", label: "\u{1F4CB} Print ID to stdout", hint: "echo <kit-id>" }
|
|
13549
|
+
];
|
|
13550
|
+
const actions = await p16.multiselect({
|
|
13551
|
+
message: "What would you like to do?",
|
|
13552
|
+
options: actionOptions,
|
|
13553
|
+
required: false
|
|
13554
|
+
});
|
|
13555
|
+
if (p16.isCancel(actions)) {
|
|
13556
|
+
p16.cancel("Cancelled.");
|
|
13557
|
+
process.exit(0);
|
|
13558
|
+
}
|
|
13559
|
+
const selectedActions = actions;
|
|
13560
|
+
if (selectedActions.length === 0) {
|
|
13561
|
+
const emptyActionChoice = await p16.select({
|
|
13562
|
+
message: "No actions selected",
|
|
13563
|
+
options: [
|
|
13564
|
+
{ value: "retry", label: "Choose action(s)" },
|
|
13565
|
+
{ value: "back_to_kits", label: "\u2190 Back to kit list" }
|
|
13566
|
+
]
|
|
13567
|
+
});
|
|
13568
|
+
if (p16.isCancel(emptyActionChoice)) {
|
|
13569
|
+
p16.cancel("Cancelled.");
|
|
13570
|
+
process.exit(0);
|
|
13571
|
+
}
|
|
13572
|
+
if (emptyActionChoice === "back_to_kits") break;
|
|
13573
|
+
continue;
|
|
13574
|
+
}
|
|
13575
|
+
const confirmed = await confirmKitActions({
|
|
13576
|
+
kits: [selected],
|
|
13577
|
+
actions: selectedActions
|
|
13578
|
+
});
|
|
13579
|
+
if (!confirmed) {
|
|
13580
|
+
const reviewChoice = await p16.select({
|
|
13581
|
+
message: "Review selection",
|
|
13582
|
+
options: [
|
|
13583
|
+
{ value: "actions", label: "Choose action(s) again" },
|
|
13584
|
+
{ value: "back_to_kits", label: "\u2190 Back to kit list" }
|
|
13585
|
+
]
|
|
13586
|
+
});
|
|
13587
|
+
if (p16.isCancel(reviewChoice)) {
|
|
13588
|
+
p16.cancel("Cancelled.");
|
|
13589
|
+
process.exit(0);
|
|
13590
|
+
}
|
|
13591
|
+
if (reviewChoice === "back_to_kits") break;
|
|
13592
|
+
continue;
|
|
13593
|
+
}
|
|
13594
|
+
for (const action of selectedActions) {
|
|
13595
|
+
if (action === "copy-id") {
|
|
13596
|
+
console.log(selected.id);
|
|
13597
|
+
continue;
|
|
13598
|
+
}
|
|
13599
|
+
if (action === "inspect") {
|
|
13600
|
+
runInspect(selected.id, opts.out);
|
|
13601
|
+
continue;
|
|
13602
|
+
}
|
|
13603
|
+
if (action === "download") {
|
|
13604
|
+
await runDownload(selected.id, opts);
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
if (selectedActions.includes("copy-id")) {
|
|
13608
|
+
p16.outro(pc23.dim("Kit ID printed above."));
|
|
13609
|
+
return "done";
|
|
13610
|
+
}
|
|
13611
|
+
p16.outro(pc23.dim("Done."));
|
|
13612
|
+
return "done";
|
|
13613
|
+
}
|
|
13614
|
+
}
|
|
13615
|
+
}
|
|
13616
|
+
}
|
|
13617
|
+
async function runDownload(kitId, opts) {
|
|
13618
|
+
const resolvedId = fuzzyResolveKitId(kitId);
|
|
13619
|
+
if (!resolvedId) {
|
|
13620
|
+
console.error(pc23.red("Unknown kit '" + kitId + "'.") + pc23.dim(" Run `growthub kit list` to browse."));
|
|
13621
|
+
process.exit(1);
|
|
13622
|
+
}
|
|
13623
|
+
if (resolvedId !== kitId) {
|
|
13624
|
+
console.log(pc23.dim("Resolved '" + kitId + "' \u2192 " + resolvedId));
|
|
13625
|
+
}
|
|
13626
|
+
const kits = listBundledKits();
|
|
13627
|
+
const item = kits.find((k) => k.id === resolvedId);
|
|
13628
|
+
printKitCard(item);
|
|
13629
|
+
if (!opts.yes) {
|
|
13630
|
+
const confirmed = await p16.confirm({ message: "Download " + pc23.bold(displayKitName(item.name)) + "?" });
|
|
13631
|
+
if (p16.isCancel(confirmed) || !confirmed) {
|
|
13632
|
+
p16.cancel("Cancelled.");
|
|
13633
|
+
process.exit(0);
|
|
13634
|
+
}
|
|
13635
|
+
}
|
|
13636
|
+
const result = downloadBundledKit(resolvedId, opts.out, {
|
|
13637
|
+
onProgress: renderProgressBar
|
|
13638
|
+
});
|
|
13639
|
+
const nextSteps = [
|
|
13640
|
+
pc23.bold("Next steps"),
|
|
13641
|
+
"",
|
|
13642
|
+
pc23.dim("1.") + " Point Working Directory at:",
|
|
13643
|
+
" " + pc23.cyan(result.folderPath),
|
|
13644
|
+
"",
|
|
13645
|
+
pc23.dim("2.") + " " + pc23.cyan("cp .env.example .env") + " \u2192 add your API key",
|
|
13646
|
+
pc23.dim("3.") + " " + pc23.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio",
|
|
13647
|
+
pc23.dim("4.") + " Open Growthub local \u2014 the agent loads automatically",
|
|
13648
|
+
"",
|
|
13649
|
+
pc23.dim("Docs: QUICKSTART.md \xB7 validation-checklist.md")
|
|
13650
|
+
];
|
|
13651
|
+
console.log("");
|
|
13652
|
+
console.log(box(nextSteps));
|
|
13653
|
+
console.log("");
|
|
13654
|
+
console.log(pc23.bold("Open folder: ") + folderOpenLabel(result.folderPath));
|
|
13655
|
+
console.log(pc23.dim("Folder: ") + result.folderPath);
|
|
13656
|
+
console.log("");
|
|
13657
|
+
console.log(pc23.dim("Zip: ") + result.zipPath);
|
|
13658
|
+
console.log("");
|
|
13659
|
+
}
|
|
13660
|
+
function runInspect(kitId, outDir) {
|
|
13661
|
+
const info = inspectBundledKit(kitId, outDir);
|
|
13662
|
+
const kv = (label, value) => console.log(" " + pc23.bold(label.padEnd(24)) + " " + value);
|
|
13663
|
+
console.log("");
|
|
13664
|
+
console.log(pc23.bold("Kit: " + info.id) + pc23.dim(" v" + info.version));
|
|
13665
|
+
console.log(typeBadge(info.family) + pc23.dim(" schema v" + info.schemaVersion));
|
|
13666
|
+
console.log(hr());
|
|
13667
|
+
kv("Name:", info.name);
|
|
13668
|
+
kv("Description:", truncate(info.description, 55));
|
|
13669
|
+
kv("Entrypoint:", info.entrypointPath);
|
|
13670
|
+
kv("Agent Contract:", info.agentContractPath);
|
|
13671
|
+
kv("Bundle:", info.bundleId + " @ " + info.bundleVersion);
|
|
13672
|
+
kv("Brief Type:", info.briefType);
|
|
13673
|
+
kv("Frozen Assets:", String(info.frozenAssetCount));
|
|
13674
|
+
kv("Required Assets:", String(info.requiredFrozenAssetCount));
|
|
13675
|
+
kv("Export Folder:", info.exportFolderPath);
|
|
13676
|
+
kv("Export Zip:", info.exportZipPath);
|
|
13677
|
+
if (Object.keys(info.compatibility).length > 0) {
|
|
13678
|
+
kv("Compatibility:", JSON.stringify(info.compatibility));
|
|
13679
|
+
}
|
|
13680
|
+
console.log(hr());
|
|
13681
|
+
console.log(pc23.bold(" Required Paths:"));
|
|
13682
|
+
for (const rp of info.requiredPaths) console.log(" " + pc23.dim("\xB7") + " " + rp);
|
|
13683
|
+
console.log("");
|
|
13684
|
+
}
|
|
13685
|
+
function registerKitCommands(program2) {
|
|
13686
|
+
const kit = program2.command("kit").description("Browse, inspect, and download Growthub Agent Worker Kits").addHelpText("after", `
|
|
13687
|
+
Examples:
|
|
13688
|
+
$ growthub kit # interactive browser
|
|
13689
|
+
$ growthub kit list # all kits grouped by type
|
|
13690
|
+
$ growthub kit list --family studio # filter by family
|
|
13691
|
+
$ growthub kit list --json # machine-readable output
|
|
13692
|
+
$ growthub kit download higgsfield # fuzzy slug \u2014 resolves automatically
|
|
13693
|
+
$ growthub kit download growthub-open-higgsfield-studio-v1
|
|
13694
|
+
$ growthub kit inspect higgsfield-studio-v1
|
|
13695
|
+
$ growthub kit families # show family taxonomy
|
|
13696
|
+
`);
|
|
13697
|
+
kit.action(async () => {
|
|
13698
|
+
await runInteractivePicker({});
|
|
13699
|
+
});
|
|
13700
|
+
kit.command("list").description("List all available kits grouped by type").option("--family <families>", "Filter by family (comma-separated: studio,workflow,operator,ops)").option("--json", "Output raw JSON for scripting").addHelpText("after", `
|
|
13701
|
+
Examples:
|
|
13702
|
+
$ growthub kit list
|
|
13703
|
+
$ growthub kit list --family studio
|
|
13704
|
+
$ growthub kit list --family studio,operator
|
|
13705
|
+
$ growthub kit list --json
|
|
13706
|
+
`).action((opts) => {
|
|
13707
|
+
let kits = listBundledKits();
|
|
13708
|
+
if (opts.family) {
|
|
13709
|
+
const wanted = opts.family.split(",").map((f) => f.trim().toLowerCase());
|
|
13710
|
+
kits = kits.filter((k) => wanted.includes(k.family));
|
|
13711
|
+
if (kits.length === 0) {
|
|
13712
|
+
console.error(pc23.yellow("No kits found for family: " + opts.family));
|
|
13713
|
+
console.error(pc23.dim("Valid families: studio, workflow, operator, ops"));
|
|
13714
|
+
process.exitCode = 1;
|
|
13715
|
+
return;
|
|
13716
|
+
}
|
|
13717
|
+
}
|
|
13718
|
+
if (opts.json) {
|
|
13719
|
+
console.log(JSON.stringify(kits, null, 2));
|
|
13720
|
+
return;
|
|
13721
|
+
}
|
|
13722
|
+
printGroupedList(kits);
|
|
13723
|
+
});
|
|
13724
|
+
kit.command("inspect").description("Inspect a kit manifest (supports fuzzy slug)").argument("<kit-id>", "Kit id or slug (e.g. 'higgsfield', 'studio-v1')").option("--out <path>", "Override the export root for resolved paths").option("--json", "Output raw JSON").addHelpText("after", `
|
|
13725
|
+
Examples:
|
|
13726
|
+
$ growthub kit inspect higgsfield-studio-v1
|
|
13727
|
+
$ growthub kit inspect growthub-email-marketing-v1 --json
|
|
13728
|
+
`).action((kitId, opts) => {
|
|
13729
|
+
const resolvedId = fuzzyResolveKitId(kitId);
|
|
13730
|
+
if (!resolvedId) {
|
|
13731
|
+
console.error(pc23.red("Unknown kit '" + kitId + "'.") + pc23.dim(" Run `growthub kit list` to browse."));
|
|
13732
|
+
process.exitCode = 1;
|
|
12665
13733
|
return;
|
|
12666
13734
|
}
|
|
12667
|
-
|
|
12668
|
-
console.log(
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
13735
|
+
if (opts.json) {
|
|
13736
|
+
console.log(JSON.stringify(inspectBundledKit(resolvedId, opts.out), null, 2));
|
|
13737
|
+
return;
|
|
13738
|
+
}
|
|
13739
|
+
runInspect(resolvedId, opts.out);
|
|
13740
|
+
});
|
|
13741
|
+
kit.command("download").description("Download a kit \u2014 interactive if no kit-id given").argument("[kit-id]", "Kit id or fuzzy slug (omit for interactive picker)").option("--out <path>", "Output directory for the generated artifacts").option("--yes", "Skip confirmation prompt").addHelpText("after", `
|
|
13742
|
+
Examples:
|
|
13743
|
+
$ growthub kit download # interactive
|
|
13744
|
+
$ growthub kit download higgsfield # fuzzy slug
|
|
13745
|
+
$ growthub kit download growthub-open-higgsfield-studio-v1
|
|
13746
|
+
$ growthub kit download studio-v1 --out ~/kits
|
|
13747
|
+
$ growthub kit download studio-v1 --yes
|
|
13748
|
+
`).action(async (kitId, opts) => {
|
|
13749
|
+
if (!kitId) {
|
|
13750
|
+
await runInteractivePicker(opts);
|
|
13751
|
+
return;
|
|
12675
13752
|
}
|
|
13753
|
+
const resolvedId = fuzzyResolveKitId(kitId);
|
|
13754
|
+
if (!resolvedId) {
|
|
13755
|
+
console.error(pc23.red("Unknown kit '" + kitId + "'.") + pc23.dim(" Run `growthub kit list` to browse."));
|
|
13756
|
+
process.exitCode = 1;
|
|
13757
|
+
return;
|
|
13758
|
+
}
|
|
13759
|
+
if (opts.yes) {
|
|
13760
|
+
const result = downloadBundledKit(resolvedId, opts.out, {
|
|
13761
|
+
onProgress: renderProgressBar
|
|
13762
|
+
});
|
|
13763
|
+
console.log("");
|
|
13764
|
+
console.log(pc23.bold("Exported folder:"), pc23.cyan(result.folderPath));
|
|
13765
|
+
console.log(pc23.bold("Open folder: "), folderOpenLabel(result.folderPath));
|
|
13766
|
+
console.log(pc23.bold("Zip: "), pc23.dim(result.zipPath));
|
|
13767
|
+
console.log("");
|
|
13768
|
+
console.log(pc23.bold("Next steps:"));
|
|
13769
|
+
console.log(" 1. Point Working Directory at: " + pc23.cyan(result.folderPath));
|
|
13770
|
+
console.log(" 2. " + pc23.cyan("cp .env.example .env") + " \u2192 add your API key");
|
|
13771
|
+
console.log(" 3. " + pc23.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio");
|
|
13772
|
+
console.log(" 4. Open Growthub local \u2014 the agent loads automatically");
|
|
13773
|
+
console.log("");
|
|
13774
|
+
return;
|
|
13775
|
+
}
|
|
13776
|
+
await runDownload(resolvedId, opts);
|
|
13777
|
+
});
|
|
13778
|
+
kit.command("path").description("Resolve the expected export folder path without exporting").argument("<kit-id>", "Kit id or fuzzy slug").option("--out <path>", "Override the export root").action((kitId, opts) => {
|
|
13779
|
+
const resolvedId = fuzzyResolveKitId(kitId);
|
|
13780
|
+
if (!resolvedId) {
|
|
13781
|
+
console.error(pc23.red("Unknown kit '" + kitId + "'."));
|
|
13782
|
+
process.exitCode = 1;
|
|
13783
|
+
return;
|
|
13784
|
+
}
|
|
13785
|
+
console.log(resolveKitPath(resolvedId, opts.out));
|
|
13786
|
+
});
|
|
13787
|
+
kit.command("validate").description("Validate a kit directory against the kit contract schema").argument("<path>", "Path to the kit directory").addHelpText("after", `
|
|
13788
|
+
Examples:
|
|
13789
|
+
$ growthub kit validate ./my-kit
|
|
13790
|
+
$ growthub kit validate ~/kits/growthub-open-higgsfield-studio-v1
|
|
13791
|
+
`).action((kitPath) => {
|
|
13792
|
+
const resolvedPath = path20.resolve(kitPath);
|
|
13793
|
+
const result = validateKitDirectory(resolvedPath);
|
|
13794
|
+
console.log("");
|
|
13795
|
+
console.log(pc23.bold("Kit: " + result.kitId) + pc23.dim(" schema v" + result.schemaVersion));
|
|
13796
|
+
console.log(hr());
|
|
13797
|
+
for (const w of result.warnings) {
|
|
13798
|
+
console.log(pc23.yellow(" WARN " + w.field + ": " + w.message));
|
|
13799
|
+
}
|
|
13800
|
+
for (const e of result.errors) {
|
|
13801
|
+
console.log(pc23.red(" ERROR " + e.field + ": " + e.message));
|
|
13802
|
+
}
|
|
13803
|
+
if (result.errors.length > 0) {
|
|
13804
|
+
console.log("");
|
|
13805
|
+
console.log(pc23.red(pc23.bold(" Result: INVALID")) + pc23.dim(" (" + result.errors.length + " error" + (result.errors.length !== 1 ? "s" : "") + ")"));
|
|
13806
|
+
process.exitCode = 1;
|
|
13807
|
+
} else {
|
|
13808
|
+
console.log(pc23.green(pc23.bold(" Result: VALID")));
|
|
13809
|
+
}
|
|
13810
|
+
console.log("");
|
|
13811
|
+
});
|
|
13812
|
+
kit.command("families").description("Show the kit family taxonomy with descriptions and examples").action(() => {
|
|
13813
|
+
const defs = [
|
|
13814
|
+
{ family: "studio", tagline: "AI generation studio backed by a local fork", surfaces: "local-fork, browser-hosted, desktop-app", example: "growthub-open-higgsfield-studio-v1" },
|
|
13815
|
+
{ family: "workflow", tagline: "Multi-step pipeline operator across tools or APIs", surfaces: "browser-hosted (primary)", example: "creative-strategist-v1" },
|
|
13816
|
+
{ family: "operator", tagline: "Domain vertical specialist \u2014 one provider, structured deliverables", surfaces: "browser-hosted", example: "growthub-email-marketing-v1" },
|
|
13817
|
+
{ family: "ops", tagline: "Infrastructure / toolchain operator (provider optional)", surfaces: "local-fork (primary)", example: "(coming soon)" }
|
|
13818
|
+
];
|
|
13819
|
+
console.log("");
|
|
13820
|
+
console.log(pc23.bold("Kit Family Taxonomy"));
|
|
13821
|
+
console.log(hr());
|
|
13822
|
+
for (const def of defs) {
|
|
13823
|
+
console.log("\n " + familyBadge(def.family));
|
|
13824
|
+
console.log(" " + pc23.dim(def.tagline));
|
|
13825
|
+
console.log(" " + pc23.dim("Surfaces: ") + pc23.dim(def.surfaces));
|
|
13826
|
+
console.log(" " + pc23.dim("Example: ") + pc23.cyan(def.example));
|
|
13827
|
+
}
|
|
13828
|
+
console.log("");
|
|
13829
|
+
console.log(hr());
|
|
13830
|
+
console.log(pc23.dim(" growthub kit list --family <family> to filter by internal family"));
|
|
13831
|
+
console.log("");
|
|
13832
|
+
});
|
|
13833
|
+
}
|
|
13834
|
+
|
|
13835
|
+
// src/commands/template.ts
|
|
13836
|
+
import path22 from "node:path";
|
|
13837
|
+
import * as p17 from "@clack/prompts";
|
|
13838
|
+
import pc24 from "picocolors";
|
|
13839
|
+
|
|
13840
|
+
// src/templates/service.ts
|
|
13841
|
+
import fs15 from "node:fs";
|
|
13842
|
+
import path21 from "node:path";
|
|
13843
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
13844
|
+
|
|
13845
|
+
// src/templates/catalog.ts
|
|
13846
|
+
var AD_FORMATS = [
|
|
13847
|
+
{
|
|
13848
|
+
type: "ad-format",
|
|
13849
|
+
slug: "bedroom-minimic-talk",
|
|
13850
|
+
id: "ad-formats/bedroom-minimic-talk",
|
|
13851
|
+
name: "Bedroom Mini-Mic Talk",
|
|
13852
|
+
family: "video-creative",
|
|
13853
|
+
category: "Skincare / Beauty Tech / Consumer Product",
|
|
13854
|
+
tags: ["ugc", "skincare", "beauty-tech", "tiktok", "23s", "proven"],
|
|
13855
|
+
scenes: 6,
|
|
13856
|
+
hookVariations: 5,
|
|
13857
|
+
compatibleFormats: [],
|
|
13858
|
+
frozen: true,
|
|
13859
|
+
path: "ad-formats/bedroom-minimic-talk.md"
|
|
13860
|
+
},
|
|
13861
|
+
{
|
|
13862
|
+
type: "ad-format",
|
|
13863
|
+
slug: "villain-animation",
|
|
13864
|
+
id: "ad-formats/villain-animation",
|
|
13865
|
+
name: "Villain Object Animation",
|
|
13866
|
+
family: "video-creative",
|
|
13867
|
+
category: "Pet / Home / Supplement / Displacement products",
|
|
13868
|
+
tags: ["animated", "villain", "long-form", "agitation-stack", "proven"],
|
|
13869
|
+
scenes: 9,
|
|
13870
|
+
hookVariations: 5,
|
|
13871
|
+
compatibleFormats: [],
|
|
13872
|
+
frozen: true,
|
|
13873
|
+
path: "ad-formats/villain-animation.md"
|
|
13874
|
+
},
|
|
13875
|
+
{
|
|
13876
|
+
type: "ad-format",
|
|
13877
|
+
slug: "process-specialist-medical",
|
|
13878
|
+
id: "ad-formats/process-specialist-medical",
|
|
13879
|
+
name: "The Process Specialist",
|
|
13880
|
+
family: "video-creative",
|
|
13881
|
+
category: "Medical / Regenerative Medicine / Healthcare Authority",
|
|
13882
|
+
tags: ["medical", "authority", "doctor", "ugc", "50s", "proven"],
|
|
13883
|
+
scenes: 5,
|
|
13884
|
+
hookVariations: 5,
|
|
13885
|
+
compatibleFormats: [],
|
|
13886
|
+
frozen: true,
|
|
13887
|
+
path: "ad-formats/process-specialist-medical.md"
|
|
13888
|
+
},
|
|
13889
|
+
{
|
|
13890
|
+
type: "ad-format",
|
|
13891
|
+
slug: "frame-analysis",
|
|
13892
|
+
id: "ad-formats/frame-analysis",
|
|
13893
|
+
name: "Frame-by-Frame Analysis Methodology",
|
|
13894
|
+
family: "video-creative",
|
|
13895
|
+
category: "Methodology \u2014 use when no frozen format matches a muse",
|
|
13896
|
+
tags: ["methodology", "muse", "frame-extraction"],
|
|
13897
|
+
scenes: null,
|
|
13898
|
+
hookVariations: null,
|
|
13899
|
+
compatibleFormats: [],
|
|
13900
|
+
frozen: true,
|
|
13901
|
+
path: "ad-formats/frame-analysis.md"
|
|
13902
|
+
}
|
|
13903
|
+
];
|
|
13904
|
+
var HOOKS = [
|
|
13905
|
+
{
|
|
13906
|
+
type: "scene-module",
|
|
13907
|
+
subtype: "hook",
|
|
13908
|
+
slug: "meme-overlay",
|
|
13909
|
+
id: "scene-modules/hooks/meme-overlay",
|
|
13910
|
+
name: "Meme Overlay Hook",
|
|
13911
|
+
family: "video-creative",
|
|
13912
|
+
category: "Relatable lifestyle pain \u2014 tired, stressed, broke",
|
|
13913
|
+
tags: ["meme", "scene-1", "scroll-stop", "proven"],
|
|
13914
|
+
scenes: null,
|
|
13915
|
+
frozen: true,
|
|
13916
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
13917
|
+
path: "scene-modules/hooks/meme-overlay.md"
|
|
13918
|
+
},
|
|
13919
|
+
{
|
|
13920
|
+
type: "scene-module",
|
|
13921
|
+
subtype: "hook",
|
|
13922
|
+
slug: "tiktok-comment",
|
|
13923
|
+
id: "scene-modules/hooks/tiktok-comment",
|
|
13924
|
+
name: "TikTok Comment Hook",
|
|
13925
|
+
family: "video-creative",
|
|
13926
|
+
category: "High-skepticism categories \u2014 objection-first open",
|
|
13927
|
+
tags: ["tiktok-comment", "scene-1", "skepticism", "proven"],
|
|
13928
|
+
scenes: null,
|
|
13929
|
+
frozen: true,
|
|
13930
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
13931
|
+
path: "scene-modules/hooks/tiktok-comment.md"
|
|
13932
|
+
},
|
|
13933
|
+
{
|
|
13934
|
+
type: "scene-module",
|
|
13935
|
+
subtype: "hook",
|
|
13936
|
+
slug: "pov-confession",
|
|
13937
|
+
id: "scene-modules/hooks/pov-confession",
|
|
13938
|
+
name: "POV Mirror Confession Hook",
|
|
13939
|
+
family: "video-creative",
|
|
13940
|
+
category: "Skincare / Beauty \u2014 female 25\u201335 demo",
|
|
13941
|
+
tags: ["pov", "mirror", "scene-1", "tiktok", "proven"],
|
|
13942
|
+
scenes: null,
|
|
13943
|
+
frozen: true,
|
|
13944
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
13945
|
+
path: "scene-modules/hooks/pov-confession.md"
|
|
13946
|
+
},
|
|
13947
|
+
{
|
|
13948
|
+
type: "scene-module",
|
|
13949
|
+
subtype: "hook",
|
|
13950
|
+
slug: "dollar-amount",
|
|
13951
|
+
id: "scene-modules/hooks/dollar-amount",
|
|
13952
|
+
name: "Dollar Amount Confession Hook",
|
|
13953
|
+
family: "video-creative",
|
|
13954
|
+
category: "Any category where overspending is the shared pain",
|
|
13955
|
+
tags: ["dollar-amount", "scene-1", "cross-format", "proven"],
|
|
13956
|
+
scenes: null,
|
|
13957
|
+
frozen: true,
|
|
13958
|
+
compatibleFormats: ["bedroom-minimic-talk", "villain-animation"],
|
|
13959
|
+
path: "scene-modules/hooks/dollar-amount.md"
|
|
13960
|
+
},
|
|
13961
|
+
{
|
|
13962
|
+
type: "scene-module",
|
|
13963
|
+
subtype: "hook",
|
|
13964
|
+
slug: "villain-hook",
|
|
13965
|
+
id: "scene-modules/hooks/villain-hook",
|
|
13966
|
+
name: "Villain Character Hook",
|
|
13967
|
+
family: "video-creative",
|
|
13968
|
+
category: "Animated \u2014 product displacing an incumbent",
|
|
13969
|
+
tags: ["villain", "animated", "scene-1", "proven"],
|
|
13970
|
+
scenes: null,
|
|
13971
|
+
frozen: true,
|
|
13972
|
+
compatibleFormats: ["villain-animation"],
|
|
13973
|
+
path: "scene-modules/hooks/villain-hook.md"
|
|
13974
|
+
}
|
|
13975
|
+
];
|
|
13976
|
+
var BODY = [
|
|
13977
|
+
{
|
|
13978
|
+
type: "scene-module",
|
|
13979
|
+
subtype: "body",
|
|
13980
|
+
slug: "minimic-problem",
|
|
13981
|
+
id: "scene-modules/body/minimic-problem",
|
|
13982
|
+
name: "Mini-Mic Problem Confession",
|
|
13983
|
+
family: "video-creative",
|
|
13984
|
+
category: "Authority + failed solutions \u2014 Scene 2",
|
|
13985
|
+
tags: ["minimic", "scene-2", "authority", "proven"],
|
|
13986
|
+
scenes: null,
|
|
13987
|
+
frozen: true,
|
|
13988
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
13989
|
+
path: "scene-modules/body/minimic-problem.md"
|
|
13990
|
+
},
|
|
13991
|
+
{
|
|
13992
|
+
type: "scene-module",
|
|
13993
|
+
subtype: "body",
|
|
13994
|
+
slug: "tiktok-skeptic-pivot",
|
|
13995
|
+
id: "scene-modules/body/tiktok-skeptic-pivot",
|
|
13996
|
+
name: "TikTok Skeptic Pivot",
|
|
13997
|
+
family: "video-creative",
|
|
13998
|
+
category: "Skeptic disarm + product intro \u2014 Scene 3",
|
|
13999
|
+
tags: ["tiktok-comment", "scene-3", "skeptic", "pivot", "proven"],
|
|
14000
|
+
scenes: null,
|
|
14001
|
+
frozen: true,
|
|
14002
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
14003
|
+
path: "scene-modules/body/tiktok-skeptic-pivot.md"
|
|
14004
|
+
},
|
|
14005
|
+
{
|
|
14006
|
+
type: "scene-module",
|
|
14007
|
+
subtype: "body",
|
|
14008
|
+
slug: "product-demo-glow",
|
|
14009
|
+
id: "scene-modules/body/product-demo-glow",
|
|
14010
|
+
name: "Product Demo \u2014 Glow / Active Effect",
|
|
14011
|
+
family: "video-creative",
|
|
14012
|
+
category: "Products with a visible active state \u2014 Scene 4",
|
|
14013
|
+
tags: ["demo", "scene-4", "glow", "active-state", "proven"],
|
|
14014
|
+
scenes: null,
|
|
14015
|
+
frozen: true,
|
|
14016
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
14017
|
+
path: "scene-modules/body/product-demo-glow.md"
|
|
14018
|
+
},
|
|
14019
|
+
{
|
|
14020
|
+
type: "scene-module",
|
|
14021
|
+
subtype: "body",
|
|
14022
|
+
slug: "villain-agitation",
|
|
14023
|
+
id: "scene-modules/body/villain-agitation",
|
|
14024
|
+
name: "Villain Agitation Stack",
|
|
14025
|
+
family: "video-creative",
|
|
14026
|
+
category: "4\xD7 stacked failed solutions \u2014 Scenes 2\u20135",
|
|
14027
|
+
tags: ["villain", "agitation", "scenes-2-5", "animated", "proven"],
|
|
14028
|
+
scenes: null,
|
|
14029
|
+
frozen: true,
|
|
14030
|
+
compatibleFormats: ["villain-animation"],
|
|
14031
|
+
path: "scene-modules/body/villain-agitation.md"
|
|
14032
|
+
},
|
|
14033
|
+
{
|
|
14034
|
+
type: "scene-module",
|
|
14035
|
+
subtype: "body",
|
|
14036
|
+
slug: "before-after-flatlay",
|
|
14037
|
+
id: "scene-modules/body/before-after-flatlay",
|
|
14038
|
+
name: "Before/After + Product Flat Lay",
|
|
14039
|
+
family: "video-creative",
|
|
14040
|
+
category: "Social proof + product authority \u2014 Scene 5",
|
|
14041
|
+
tags: ["before-after", "flatlay", "scene-5", "social-proof", "proven"],
|
|
14042
|
+
scenes: null,
|
|
14043
|
+
frozen: true,
|
|
14044
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
14045
|
+
path: "scene-modules/body/before-after-flatlay.md"
|
|
14046
|
+
}
|
|
14047
|
+
];
|
|
14048
|
+
var CTA = [
|
|
14049
|
+
{
|
|
14050
|
+
type: "scene-module",
|
|
14051
|
+
subtype: "cta",
|
|
14052
|
+
slug: "bogo-meme-bookend",
|
|
14053
|
+
id: "scene-modules/cta/bogo-meme-bookend",
|
|
14054
|
+
name: "BOGO + Meme Bookend Close",
|
|
14055
|
+
family: "video-creative",
|
|
14056
|
+
category: "BOGO / % off / flash offer \u2014 Scene 6",
|
|
14057
|
+
tags: ["bogo", "meme-bookend", "cta", "proven"],
|
|
14058
|
+
scenes: null,
|
|
14059
|
+
frozen: true,
|
|
14060
|
+
compatibleFormats: ["bedroom-minimic-talk"],
|
|
14061
|
+
path: "scene-modules/cta/bogo-meme-bookend.md"
|
|
14062
|
+
},
|
|
14063
|
+
{
|
|
14064
|
+
type: "scene-module",
|
|
14065
|
+
subtype: "cta",
|
|
14066
|
+
slug: "guarantee-close",
|
|
14067
|
+
id: "scene-modules/cta/guarantee-close",
|
|
14068
|
+
name: "Guarantee Calendar Close",
|
|
14069
|
+
family: "video-creative",
|
|
14070
|
+
category: "30/60-day satisfaction guarantee \u2014 Scene 9",
|
|
14071
|
+
tags: ["guarantee", "calendar", "cta", "animated", "proven"],
|
|
14072
|
+
scenes: null,
|
|
14073
|
+
frozen: true,
|
|
14074
|
+
compatibleFormats: ["villain-animation"],
|
|
14075
|
+
path: "scene-modules/cta/guarantee-close.md"
|
|
14076
|
+
}
|
|
14077
|
+
];
|
|
14078
|
+
var TEMPLATE_CATALOG = [
|
|
14079
|
+
...AD_FORMATS,
|
|
14080
|
+
...HOOKS,
|
|
14081
|
+
...BODY,
|
|
14082
|
+
...CTA
|
|
14083
|
+
// ...EMAIL_TEMPLATES,
|
|
14084
|
+
// ...MOTION_TEMPLATES,
|
|
14085
|
+
];
|
|
14086
|
+
|
|
14087
|
+
// src/templates/service.ts
|
|
14088
|
+
function resolveSharedTemplatesRoot() {
|
|
14089
|
+
const moduleDir = path21.dirname(fileURLToPath5(import.meta.url));
|
|
14090
|
+
for (const candidate of [
|
|
14091
|
+
path21.resolve(moduleDir, "../../assets/shared-templates"),
|
|
14092
|
+
path21.resolve(moduleDir, "../assets/shared-templates")
|
|
14093
|
+
]) {
|
|
14094
|
+
if (fs15.existsSync(candidate)) return candidate;
|
|
14095
|
+
}
|
|
14096
|
+
throw new Error("Shared template assets not found at cli/assets/shared-templates/");
|
|
14097
|
+
}
|
|
14098
|
+
function resolveSlug(input) {
|
|
14099
|
+
const needle = input.toLowerCase().trim();
|
|
14100
|
+
return TEMPLATE_CATALOG.find((a) => a.id === needle) ?? TEMPLATE_CATALOG.find((a) => a.slug === needle) ?? TEMPLATE_CATALOG.find((a) => a.id.endsWith("/" + needle)) ?? TEMPLATE_CATALOG.find((a) => a.id.includes(needle) || a.slug.includes(needle)) ?? (() => {
|
|
14101
|
+
const tokens = needle.split(/[-_/\s]+/).filter((t) => t.length > 2);
|
|
14102
|
+
for (const token of tokens) {
|
|
14103
|
+
const match = TEMPLATE_CATALOG.find((a) => a.slug.includes(token) || a.id.includes(token));
|
|
14104
|
+
if (match) return match;
|
|
14105
|
+
}
|
|
14106
|
+
return null;
|
|
14107
|
+
})();
|
|
14108
|
+
}
|
|
14109
|
+
function listArtifacts(filter = {}) {
|
|
14110
|
+
let results = [...TEMPLATE_CATALOG];
|
|
14111
|
+
if (filter.type) results = results.filter((a) => a.type === filter.type);
|
|
14112
|
+
if (filter.subtype) results = results.filter((a) => a.type === "scene-module" && a.subtype === filter.subtype);
|
|
14113
|
+
if (filter.family) results = results.filter((a) => a.family === filter.family);
|
|
14114
|
+
if (filter.format) {
|
|
14115
|
+
const fmt = filter.format.toLowerCase();
|
|
14116
|
+
results = results.filter(
|
|
14117
|
+
(a) => a.compatibleFormats.length === 0 || a.compatibleFormats.some((f) => f.includes(fmt))
|
|
14118
|
+
);
|
|
14119
|
+
}
|
|
14120
|
+
if (filter.tags?.length) {
|
|
14121
|
+
results = results.filter((a) => filter.tags.some((tag) => a.tags.includes(tag)));
|
|
14122
|
+
}
|
|
14123
|
+
return results;
|
|
14124
|
+
}
|
|
14125
|
+
function getArtifact(slugOrId) {
|
|
14126
|
+
const artifact = resolveSlug(slugOrId);
|
|
14127
|
+
if (!artifact) throw new Error(`Unknown template '${slugOrId}'. Run 'growthub template list' to browse.`);
|
|
14128
|
+
const root = resolveSharedTemplatesRoot();
|
|
14129
|
+
const absolutePath = path21.resolve(root, artifact.path);
|
|
14130
|
+
if (!fs15.existsSync(absolutePath)) throw new Error(`Template file missing: ${absolutePath}`);
|
|
14131
|
+
return { artifact, content: fs15.readFileSync(absolutePath, "utf8"), absolutePath };
|
|
14132
|
+
}
|
|
14133
|
+
function copyArtifact(slugOrId, destDir) {
|
|
14134
|
+
const resolved = getArtifact(slugOrId);
|
|
14135
|
+
fs15.mkdirSync(destDir, { recursive: true });
|
|
14136
|
+
const destPath = path21.resolve(destDir, path21.basename(resolved.absolutePath));
|
|
14137
|
+
fs15.copyFileSync(resolved.absolutePath, destPath);
|
|
14138
|
+
return destPath;
|
|
14139
|
+
}
|
|
14140
|
+
var GROUP_ORDER = ["ad-formats", "scene-modules/hooks", "scene-modules/body", "scene-modules/cta"];
|
|
14141
|
+
var GROUP_META = {
|
|
14142
|
+
"ad-formats": { label: "Ad Formats", description: "Complete frozen video ad structures \u2014 scene count, sacred elements, adaptation rules" },
|
|
14143
|
+
"scene-modules/hooks": { label: "Scene Modules \u2014 Hooks", description: "Scene 1 \u2014 pattern interrupt, scroll stop, opening emotional beat" },
|
|
14144
|
+
"scene-modules/body": { label: "Scene Modules \u2014 Body", description: "Scenes 2\u2013N \u2014 problem confession, skeptic pivot, demo, social proof" },
|
|
14145
|
+
"scene-modules/cta": { label: "Scene Modules \u2014 CTA", description: "Final scene \u2014 offer close, guarantee, conversion" }
|
|
14146
|
+
};
|
|
14147
|
+
function groupKey(a) {
|
|
14148
|
+
if (a.type === "ad-format") return "ad-formats";
|
|
14149
|
+
return `scene-modules/${a.subtype}`;
|
|
14150
|
+
}
|
|
14151
|
+
function groupArtifacts(artifacts) {
|
|
14152
|
+
const map = /* @__PURE__ */ new Map();
|
|
14153
|
+
for (const a of artifacts) {
|
|
14154
|
+
const key = groupKey(a);
|
|
14155
|
+
if (!map.has(key)) map.set(key, []);
|
|
14156
|
+
map.get(key).push(a);
|
|
14157
|
+
}
|
|
14158
|
+
const ordered = [];
|
|
14159
|
+
for (const key of GROUP_ORDER) {
|
|
14160
|
+
if (!map.has(key)) continue;
|
|
14161
|
+
const items = map.get(key);
|
|
14162
|
+
const meta = GROUP_META[key] ?? { label: key, description: "" };
|
|
14163
|
+
ordered.push({ key, label: meta.label, description: meta.description, count: items.length, artifacts: items });
|
|
14164
|
+
}
|
|
14165
|
+
for (const [key, items] of map) {
|
|
14166
|
+
if (GROUP_ORDER.includes(key)) continue;
|
|
14167
|
+
ordered.push({ key, label: key, description: "", count: items.length, artifacts: items });
|
|
14168
|
+
}
|
|
14169
|
+
return ordered;
|
|
14170
|
+
}
|
|
14171
|
+
function getCatalogStats() {
|
|
14172
|
+
const all = [...TEMPLATE_CATALOG];
|
|
14173
|
+
const byFamily = {};
|
|
14174
|
+
const byType = {};
|
|
14175
|
+
for (const a of all) {
|
|
14176
|
+
byFamily[a.family] = (byFamily[a.family] ?? 0) + 1;
|
|
14177
|
+
byType[a.type] = (byType[a.type] ?? 0) + 1;
|
|
14178
|
+
}
|
|
14179
|
+
return { total: all.length, byFamily, byType };
|
|
14180
|
+
}
|
|
14181
|
+
|
|
14182
|
+
// src/commands/template.ts
|
|
14183
|
+
function stripAnsi2(s) {
|
|
14184
|
+
return s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
14185
|
+
}
|
|
14186
|
+
function hr2(w = 72) {
|
|
14187
|
+
return pc24.dim("\u2500".repeat(w));
|
|
14188
|
+
}
|
|
14189
|
+
function truncate2(s, max) {
|
|
14190
|
+
return s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
|
|
14191
|
+
}
|
|
14192
|
+
function box2(lines) {
|
|
14193
|
+
const padded = lines.map((l) => " " + l);
|
|
14194
|
+
const width = Math.max(...padded.map((l) => stripAnsi2(l).length)) + 4;
|
|
14195
|
+
const top = pc24.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
|
|
14196
|
+
const bottom = pc24.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
|
|
14197
|
+
const body = padded.map((l) => pc24.dim("\u2502") + l + " ".repeat(width - stripAnsi2(l).length) + pc24.dim("\u2502"));
|
|
14198
|
+
return [top, ...body, bottom].join("\n");
|
|
14199
|
+
}
|
|
14200
|
+
function badge(a) {
|
|
14201
|
+
if (a.type === "ad-format") return pc24.cyan("\u{1F3AC} Ad Format");
|
|
14202
|
+
if (a.type === "scene-module") {
|
|
14203
|
+
if (a.subtype === "hook") return pc24.yellow("\u{1FA9D} Hook");
|
|
14204
|
+
if (a.subtype === "body") return pc24.blue("\u{1F9E9} Body");
|
|
14205
|
+
if (a.subtype === "cta") return pc24.green("\u{1F3AF} CTA");
|
|
14206
|
+
}
|
|
14207
|
+
return pc24.magenta("\u{1F9E9} Module");
|
|
14208
|
+
}
|
|
14209
|
+
function printCard(a) {
|
|
14210
|
+
const compat = a.compatibleFormats.length ? pc24.dim("Works with: ") + a.compatibleFormats.map((f) => pc24.cyan(f)).join(", ") : pc24.dim("Works with: any format");
|
|
14211
|
+
const rows = [
|
|
14212
|
+
pc24.bold(a.name),
|
|
14213
|
+
`${badge(a)} ${pc24.dim(a.id)}`,
|
|
14214
|
+
"",
|
|
14215
|
+
truncate2(a.category, 62),
|
|
14216
|
+
"",
|
|
14217
|
+
compat
|
|
14218
|
+
];
|
|
14219
|
+
if (a.type === "ad-format" && a.scenes != null) {
|
|
14220
|
+
rows.push(pc24.dim("Scenes: ") + a.scenes + (a.hookVariations ? pc24.dim(" \xB7 Hook variations: ") + a.hookVariations : ""));
|
|
14221
|
+
}
|
|
14222
|
+
console.log("");
|
|
14223
|
+
console.log(box2(rows));
|
|
14224
|
+
}
|
|
14225
|
+
function printSummary2(filter) {
|
|
14226
|
+
const artifacts = listArtifacts(filter);
|
|
14227
|
+
if (!artifacts.length) {
|
|
14228
|
+
console.log(pc24.yellow("No templates matched. Try: growthub template list"));
|
|
14229
|
+
return;
|
|
14230
|
+
}
|
|
14231
|
+
const stats = getCatalogStats();
|
|
14232
|
+
const groups = groupArtifacts(artifacts);
|
|
14233
|
+
console.log("");
|
|
14234
|
+
console.log(pc24.bold("Growthub Shared Template Library") + pc24.dim(` ${artifacts.length} of ${stats.total} artifacts`));
|
|
14235
|
+
console.log(pc24.dim(" " + Object.entries(stats.byFamily).map(([f, n]) => `${f} (${n})`).join(" \xB7 ")));
|
|
14236
|
+
console.log(hr2());
|
|
14237
|
+
for (const g of groups) {
|
|
14238
|
+
console.log(`
|
|
14239
|
+
${pc24.bold(g.label)} ${pc24.dim("(" + g.count + ")")}`);
|
|
14240
|
+
console.log(pc24.dim(" " + g.description));
|
|
14241
|
+
console.log("");
|
|
14242
|
+
for (const a of g.artifacts) {
|
|
14243
|
+
const compat = a.compatibleFormats.length ? pc24.dim(" \xB7 " + a.compatibleFormats.join(", ")) : "";
|
|
14244
|
+
console.log(` ${pc24.cyan(pc24.bold(a.name))}${compat}`);
|
|
14245
|
+
console.log(` ${pc24.dim("growthub template get " + a.slug)}`);
|
|
14246
|
+
console.log("");
|
|
14247
|
+
}
|
|
14248
|
+
}
|
|
14249
|
+
console.log(hr2());
|
|
14250
|
+
console.log(pc24.dim(" growthub template get <slug>"));
|
|
14251
|
+
console.log(pc24.dim(" growthub template list --type ad-formats"));
|
|
14252
|
+
console.log(pc24.dim(" growthub template list --type scene-modules --subtype hooks"));
|
|
14253
|
+
console.log(pc24.dim(" growthub template (interactive picker)"));
|
|
14254
|
+
console.log("");
|
|
14255
|
+
}
|
|
14256
|
+
var TEMPLATE_FAMILY_META = {
|
|
14257
|
+
"video-creative": {
|
|
14258
|
+
label: "Video Ads",
|
|
14259
|
+
emoji: "\u{1F3AC}",
|
|
14260
|
+
hint: "Ad formats, hooks, body modules, and CTA modules"
|
|
14261
|
+
},
|
|
14262
|
+
email: {
|
|
14263
|
+
label: "Email",
|
|
14264
|
+
emoji: "\u2709\uFE0F",
|
|
14265
|
+
hint: "Email-native templates"
|
|
14266
|
+
},
|
|
14267
|
+
motion: {
|
|
14268
|
+
label: "Motion",
|
|
14269
|
+
emoji: "\u{1F39E}\uFE0F",
|
|
14270
|
+
hint: "Motion and animation artifacts"
|
|
14271
|
+
},
|
|
14272
|
+
general: {
|
|
14273
|
+
label: "General",
|
|
14274
|
+
emoji: "\u{1F9E9}",
|
|
14275
|
+
hint: "Shared general-purpose templates"
|
|
14276
|
+
}
|
|
14277
|
+
};
|
|
14278
|
+
async function runTemplatePicker(opts) {
|
|
14279
|
+
p17.intro(pc24.bold("Growthub Shared Template Library"));
|
|
14280
|
+
let artifacts;
|
|
14281
|
+
try {
|
|
14282
|
+
artifacts = listArtifacts();
|
|
14283
|
+
} catch (err) {
|
|
14284
|
+
p17.log.error(err.message);
|
|
14285
|
+
process.exit(1);
|
|
14286
|
+
}
|
|
14287
|
+
const families = [...new Set(artifacts.map((artifact) => artifact.family))];
|
|
14288
|
+
const familyChoice = await p17.select({
|
|
14289
|
+
message: "What template type do you want to browse?",
|
|
14290
|
+
options: [
|
|
14291
|
+
...families.map((family) => {
|
|
14292
|
+
const meta = TEMPLATE_FAMILY_META[family] ?? {
|
|
14293
|
+
label: family,
|
|
14294
|
+
emoji: "\u{1F9E9}",
|
|
14295
|
+
hint: `${family} templates`
|
|
14296
|
+
};
|
|
14297
|
+
const familyCount = artifacts.filter((artifact) => artifact.family === family).length;
|
|
14298
|
+
return {
|
|
14299
|
+
value: family,
|
|
14300
|
+
label: `${meta.emoji} ${meta.label}`,
|
|
14301
|
+
hint: `${familyCount} available \xB7 ${meta.hint}`
|
|
14302
|
+
};
|
|
14303
|
+
}),
|
|
14304
|
+
...opts?.allowBackToHub ? [{ value: "__back_to_hub", label: "\u2190 Back to main menu" }] : []
|
|
14305
|
+
]
|
|
14306
|
+
});
|
|
14307
|
+
if (p17.isCancel(familyChoice)) {
|
|
14308
|
+
p17.cancel("Cancelled.");
|
|
14309
|
+
process.exit(0);
|
|
14310
|
+
}
|
|
14311
|
+
if (familyChoice === "__back_to_hub") return "back";
|
|
14312
|
+
const filteredArtifacts = artifacts.filter((artifact) => artifact.family === familyChoice);
|
|
14313
|
+
const groups = groupArtifacts(filteredArtifacts);
|
|
14314
|
+
const groupChoice = await p17.select({
|
|
14315
|
+
message: "What kind of template?",
|
|
14316
|
+
options: groups.map((g) => ({
|
|
14317
|
+
value: g.key,
|
|
14318
|
+
label: g.label,
|
|
14319
|
+
hint: `${g.count} available \xB7 ${g.description}`
|
|
14320
|
+
}))
|
|
14321
|
+
});
|
|
14322
|
+
if (p17.isCancel(groupChoice)) {
|
|
14323
|
+
p17.cancel("Cancelled.");
|
|
14324
|
+
process.exit(0);
|
|
14325
|
+
}
|
|
14326
|
+
const group = groups.find((g) => g.key === groupChoice);
|
|
14327
|
+
const artifactChoice = await p17.select({
|
|
14328
|
+
message: `Select from: ${group.label}`,
|
|
14329
|
+
options: group.artifacts.map((a) => ({
|
|
14330
|
+
value: a.id,
|
|
14331
|
+
label: pc24.bold(a.name),
|
|
14332
|
+
hint: truncate2(a.category, 52)
|
|
14333
|
+
}))
|
|
14334
|
+
});
|
|
14335
|
+
if (p17.isCancel(artifactChoice)) {
|
|
14336
|
+
p17.cancel("Cancelled.");
|
|
14337
|
+
process.exit(0);
|
|
14338
|
+
}
|
|
14339
|
+
const selected = filteredArtifacts.find((a) => a.id === artifactChoice);
|
|
14340
|
+
printCard(selected);
|
|
14341
|
+
const action = await p17.select({
|
|
14342
|
+
message: "What would you like to do?",
|
|
14343
|
+
options: [
|
|
14344
|
+
{ value: "print", label: "\u{1F4C4} Print to terminal" },
|
|
14345
|
+
{ value: "copy", label: "\u{1F4C1} Copy to directory" },
|
|
14346
|
+
{ value: "slug", label: "\u{1F4CB} Print slug" },
|
|
14347
|
+
{ value: "cancel", label: "Cancel" }
|
|
14348
|
+
]
|
|
12676
14349
|
});
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
console.log(
|
|
12683
|
-
|
|
12684
|
-
|
|
14350
|
+
if (p17.isCancel(action) || action === "cancel") {
|
|
14351
|
+
p17.cancel("Cancelled.");
|
|
14352
|
+
process.exit(0);
|
|
14353
|
+
}
|
|
14354
|
+
if (action === "slug") {
|
|
14355
|
+
console.log(selected.slug);
|
|
14356
|
+
p17.outro(pc24.dim("Use with: growthub template get " + selected.slug));
|
|
14357
|
+
return "done";
|
|
14358
|
+
}
|
|
14359
|
+
if (action === "print") {
|
|
14360
|
+
const r = getArtifact(selected.id);
|
|
14361
|
+
console.log("\n" + hr2());
|
|
14362
|
+
console.log(r.content);
|
|
14363
|
+
console.log(hr2());
|
|
14364
|
+
p17.outro(pc24.dim("Source: " + r.absolutePath));
|
|
14365
|
+
return "done";
|
|
14366
|
+
}
|
|
14367
|
+
if (action === "copy") {
|
|
14368
|
+
const destInput = await p17.text({
|
|
14369
|
+
message: "Output directory:",
|
|
14370
|
+
placeholder: "~/Downloads/templates",
|
|
14371
|
+
validate: (v) => !v?.trim() ? "Path is required" : void 0
|
|
14372
|
+
});
|
|
14373
|
+
if (p17.isCancel(destInput)) {
|
|
14374
|
+
p17.cancel("Cancelled.");
|
|
14375
|
+
process.exit(0);
|
|
14376
|
+
}
|
|
14377
|
+
const destDir = path22.resolve(destInput.replace(/^~/, process.env["HOME"] ?? ""));
|
|
14378
|
+
const destPath = copyArtifact(selected.id, destDir);
|
|
14379
|
+
p17.outro(pc24.green("Copied \u2192 ") + destPath);
|
|
14380
|
+
return "done";
|
|
14381
|
+
}
|
|
14382
|
+
return "done";
|
|
14383
|
+
}
|
|
14384
|
+
function registerTemplateCommands(program2) {
|
|
14385
|
+
const cmd = program2.command("template").description("Browse and pull from the shared creative template library").addHelpText("after", `
|
|
14386
|
+
Shared templates are frozen artifact primitives \u2014 distinct from kits.
|
|
14387
|
+
Any agent or kit resolves them by slug.
|
|
14388
|
+
|
|
14389
|
+
$ growthub template Interactive picker
|
|
14390
|
+
$ growthub template list Grouped summary
|
|
14391
|
+
$ growthub template list --type ad-formats
|
|
14392
|
+
$ growthub template list --type scene-modules --subtype hooks
|
|
14393
|
+
$ growthub template list --format villain-animation
|
|
14394
|
+
$ growthub template get villain-animation Fuzzy slug
|
|
14395
|
+
$ growthub template get meme-overlay --out ~/kit/hooks/
|
|
14396
|
+
$ growthub template get villain-animation --json
|
|
14397
|
+
`);
|
|
14398
|
+
cmd.action(async () => {
|
|
14399
|
+
await runTemplatePicker();
|
|
12685
14400
|
});
|
|
12686
|
-
|
|
12687
|
-
const
|
|
12688
|
-
|
|
12689
|
-
|
|
14401
|
+
cmd.command("list").description("Grouped template summary \u2014 filter before browsing").option("--type <type>", "ad-formats | scene-modules").option("--subtype <subtype>", "hooks | body | cta (scene-modules only)").option("--format <format>", "Filter by compatible ad format slug").option("--json", "Raw JSON for scripting").action((opts) => {
|
|
14402
|
+
const filter = {};
|
|
14403
|
+
if (opts.type) {
|
|
14404
|
+
const t = opts.type.replace(/s$/, "");
|
|
14405
|
+
if (t !== "ad-format" && t !== "scene-module") {
|
|
14406
|
+
console.error(pc24.red(`Unknown --type '${opts.type}'.`) + pc24.dim(" Valid: ad-formats, scene-modules"));
|
|
14407
|
+
process.exitCode = 1;
|
|
14408
|
+
return;
|
|
14409
|
+
}
|
|
14410
|
+
filter.type = t;
|
|
14411
|
+
}
|
|
14412
|
+
if (opts.subtype) {
|
|
14413
|
+
const sub = opts.subtype.replace(/s$/, "");
|
|
14414
|
+
if (!["hook", "body", "cta"].includes(sub)) {
|
|
14415
|
+
console.error(pc24.red(`Unknown --subtype '${opts.subtype}'.`) + pc24.dim(" Valid: hooks, body, cta"));
|
|
14416
|
+
process.exitCode = 1;
|
|
14417
|
+
return;
|
|
14418
|
+
}
|
|
14419
|
+
filter.subtype = sub;
|
|
14420
|
+
}
|
|
14421
|
+
if (opts.format) filter.format = opts.format;
|
|
14422
|
+
if (opts.json) {
|
|
14423
|
+
console.log(JSON.stringify(listArtifacts(filter), null, 2));
|
|
14424
|
+
return;
|
|
14425
|
+
}
|
|
14426
|
+
printSummary2(filter);
|
|
12690
14427
|
});
|
|
12691
|
-
|
|
12692
|
-
const
|
|
12693
|
-
|
|
14428
|
+
cmd.command("get").description("Print or copy a template \u2014 fuzzy slug resolution").argument("<slug>", "Artifact slug (e.g. villain-animation, meme-overlay)").option("--out <path>", "Copy to this directory").option("--json", "Artifact metadata + content as JSON").action((slug, opts) => {
|
|
14429
|
+
const artifact = resolveSlug(slug);
|
|
14430
|
+
if (!artifact) {
|
|
14431
|
+
console.error(pc24.red(`Unknown template '${slug}'.`) + pc24.dim(" Run `growthub template list` to browse."));
|
|
14432
|
+
process.exitCode = 1;
|
|
14433
|
+
return;
|
|
14434
|
+
}
|
|
14435
|
+
if (artifact.id !== slug && artifact.slug !== slug) {
|
|
14436
|
+
console.error(pc24.dim(`Resolved '${slug}' \u2192 ${artifact.slug}`));
|
|
14437
|
+
}
|
|
14438
|
+
let resolved;
|
|
14439
|
+
try {
|
|
14440
|
+
resolved = getArtifact(artifact.id);
|
|
14441
|
+
} catch (err) {
|
|
14442
|
+
console.error(pc24.red(err.message));
|
|
14443
|
+
process.exitCode = 1;
|
|
14444
|
+
return;
|
|
14445
|
+
}
|
|
14446
|
+
if (opts.json) {
|
|
14447
|
+
console.log(JSON.stringify({ artifact: resolved.artifact, content: resolved.content }, null, 2));
|
|
14448
|
+
return;
|
|
14449
|
+
}
|
|
14450
|
+
if (opts.out) {
|
|
14451
|
+
const destDir = path22.resolve(opts.out.replace(/^~/, process.env["HOME"] ?? ""));
|
|
14452
|
+
try {
|
|
14453
|
+
const dest = copyArtifact(artifact.id, destDir);
|
|
14454
|
+
console.log(pc24.green("Copied \u2192 ") + dest);
|
|
14455
|
+
} catch (err) {
|
|
14456
|
+
console.error(pc24.red(err.message));
|
|
14457
|
+
process.exitCode = 1;
|
|
14458
|
+
}
|
|
14459
|
+
return;
|
|
14460
|
+
}
|
|
14461
|
+
printCard(resolved.artifact);
|
|
14462
|
+
console.log(hr2());
|
|
14463
|
+
console.log(resolved.content);
|
|
14464
|
+
console.log(hr2());
|
|
14465
|
+
console.log(pc24.dim("Source: " + resolved.absolutePath));
|
|
14466
|
+
console.log("");
|
|
12694
14467
|
});
|
|
12695
14468
|
}
|
|
12696
14469
|
|
|
12697
14470
|
// src/index.ts
|
|
14471
|
+
init_banner();
|
|
14472
|
+
init_home();
|
|
12698
14473
|
var program = new Command();
|
|
12699
14474
|
var DATA_DIR_OPTION_HELP = "Growthub data directory root (isolates local instance state)";
|
|
14475
|
+
function resolveSurfaceProfile(config) {
|
|
14476
|
+
if (typeof config !== "object" || config === null) return null;
|
|
14477
|
+
const surface = config.surface;
|
|
14478
|
+
if (typeof surface !== "object" || surface === null) return null;
|
|
14479
|
+
const profile = surface.profile;
|
|
14480
|
+
return profile === "dx" || profile === "gtm" ? profile : null;
|
|
14481
|
+
}
|
|
12700
14482
|
function resolveBootstrapOptions(argv) {
|
|
12701
14483
|
const options = {};
|
|
12702
|
-
for (let
|
|
12703
|
-
const value = argv[
|
|
12704
|
-
if ((value === "-c" || value === "--config") && argv[
|
|
12705
|
-
options.config = argv[
|
|
12706
|
-
|
|
14484
|
+
for (let index51 = 0; index51 < argv.length; index51 += 1) {
|
|
14485
|
+
const value = argv[index51];
|
|
14486
|
+
if ((value === "-c" || value === "--config") && argv[index51 + 1]) {
|
|
14487
|
+
options.config = argv[index51 + 1];
|
|
14488
|
+
index51 += 1;
|
|
12707
14489
|
continue;
|
|
12708
14490
|
}
|
|
12709
|
-
if ((value === "-d" || value === "--data-dir") && argv[
|
|
12710
|
-
options.dataDir = argv[
|
|
12711
|
-
|
|
14491
|
+
if ((value === "-d" || value === "--data-dir") && argv[index51 + 1]) {
|
|
14492
|
+
options.dataDir = argv[index51 + 1];
|
|
14493
|
+
index51 += 1;
|
|
12712
14494
|
}
|
|
12713
14495
|
}
|
|
12714
14496
|
return options;
|
|
@@ -12725,10 +14507,201 @@ function registerSharedCommands(target) {
|
|
|
12725
14507
|
});
|
|
12726
14508
|
target.command("allowed-hostname").description("Allow a hostname for authenticated/private mode access").argument("<host>", "Hostname to allow (for example dotta-macbook-pro)").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).action(addAllowedHostname);
|
|
12727
14509
|
target.command("run").description("Bootstrap local setup (onboard + doctor) and run Growthub").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("-i, --instance <id>", "Local instance id (default: default)").option("--repair", "Attempt automatic repairs during doctor", true).option("--no-repair", "Disable automatic repairs during doctor").action(runCommand);
|
|
12728
|
-
|
|
14510
|
+
target.command("discover").description("Shared discovery entry for local app install, worker kits, and templates").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--run", "Start Growthub immediately after saving config", false).action(async (opts) => {
|
|
14511
|
+
await runDiscoveryHub(opts);
|
|
14512
|
+
});
|
|
14513
|
+
registerKitCommands(target);
|
|
14514
|
+
registerTemplateCommands(target);
|
|
12729
14515
|
const auth = target.command("auth").description("Authentication and bootstrap utilities");
|
|
12730
14516
|
auth.command("bootstrap-ceo").description("Create a one-time bootstrap invite URL for first instance admin").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--force", "Create new invite even if admin already exists", false).option("--expires-hours <hours>", "Invite expiration window in hours", (value) => Number(value)).option("--base-url <url>", "Public base URL used to print invite link").action(bootstrapCeoInvite);
|
|
12731
14517
|
}
|
|
14518
|
+
async function runDiscoveryHub(opts) {
|
|
14519
|
+
printPaperclipCliBanner();
|
|
14520
|
+
p18.intro("Growthub Local");
|
|
14521
|
+
while (true) {
|
|
14522
|
+
const surfaceChoice = await p18.select({
|
|
14523
|
+
message: "What do you want to do first?",
|
|
14524
|
+
options: [
|
|
14525
|
+
{
|
|
14526
|
+
value: "app",
|
|
14527
|
+
label: "\u{1F4E6} Full Local App",
|
|
14528
|
+
hint: "Work from existing app or build from scratch"
|
|
14529
|
+
},
|
|
14530
|
+
{
|
|
14531
|
+
value: "kits",
|
|
14532
|
+
label: "\u{1F9F0} Worker Kits",
|
|
14533
|
+
hint: "Self-contained workspace environments for agents"
|
|
14534
|
+
},
|
|
14535
|
+
{
|
|
14536
|
+
value: "templates",
|
|
14537
|
+
label: "\u{1F4DA} Templates",
|
|
14538
|
+
hint: "Artifact template library"
|
|
14539
|
+
},
|
|
14540
|
+
{
|
|
14541
|
+
value: "help",
|
|
14542
|
+
label: "\u2753 Help CLI",
|
|
14543
|
+
hint: "See the main commands and what each path does"
|
|
14544
|
+
}
|
|
14545
|
+
]
|
|
14546
|
+
});
|
|
14547
|
+
if (p18.isCancel(surfaceChoice)) {
|
|
14548
|
+
p18.cancel("Cancelled.");
|
|
14549
|
+
process.exit(0);
|
|
14550
|
+
}
|
|
14551
|
+
if (surfaceChoice === "help") {
|
|
14552
|
+
p18.note(
|
|
14553
|
+
[
|
|
14554
|
+
"\u{1F4E6} Full Local App: open an existing local surface or create a new GTM/DX profile.",
|
|
14555
|
+
"\u{1F9F0} Worker Kits: browse specialized agents and custom workspaces.",
|
|
14556
|
+
"\u{1F4DA} Templates: browse reusable artifact templates by library type.",
|
|
14557
|
+
"",
|
|
14558
|
+
"Direct commands:",
|
|
14559
|
+
"growthub run",
|
|
14560
|
+
"growthub kit",
|
|
14561
|
+
"growthub template",
|
|
14562
|
+
"growthub doctor",
|
|
14563
|
+
"growthub configure"
|
|
14564
|
+
].join("\n"),
|
|
14565
|
+
"Growthub CLI Help"
|
|
14566
|
+
);
|
|
14567
|
+
continue;
|
|
14568
|
+
}
|
|
14569
|
+
if (surfaceChoice === "app") {
|
|
14570
|
+
while (true) {
|
|
14571
|
+
const appModeChoice = await p18.select({
|
|
14572
|
+
message: "How do you want to open Growthub Local?",
|
|
14573
|
+
options: [
|
|
14574
|
+
{
|
|
14575
|
+
value: "create",
|
|
14576
|
+
label: "\u{1F195} Create New Profile",
|
|
14577
|
+
hint: "Build a new local app surface."
|
|
14578
|
+
},
|
|
14579
|
+
{
|
|
14580
|
+
value: "load",
|
|
14581
|
+
label: "\u{1F4C2} Load Existing Profile",
|
|
14582
|
+
hint: "Work from a profile already on this machine."
|
|
14583
|
+
},
|
|
14584
|
+
{
|
|
14585
|
+
value: "__back_to_hub",
|
|
14586
|
+
label: "\u2190 Back to main menu"
|
|
14587
|
+
}
|
|
14588
|
+
]
|
|
14589
|
+
});
|
|
14590
|
+
if (p18.isCancel(appModeChoice)) {
|
|
14591
|
+
p18.cancel("Cancelled.");
|
|
14592
|
+
process.exit(0);
|
|
14593
|
+
}
|
|
14594
|
+
if (appModeChoice === "__back_to_hub") break;
|
|
14595
|
+
if (appModeChoice === "load") {
|
|
14596
|
+
const existingSurfaces = listLocalSurfaces();
|
|
14597
|
+
if (existingSurfaces.length === 0) {
|
|
14598
|
+
p18.note("No existing local app profiles were found on this machine.", "Nothing found");
|
|
14599
|
+
continue;
|
|
14600
|
+
}
|
|
14601
|
+
const existingChoice = await p18.select({
|
|
14602
|
+
message: "Select an existing app surface",
|
|
14603
|
+
options: [
|
|
14604
|
+
...existingSurfaces.map((surface) => ({
|
|
14605
|
+
value: surface.instanceId,
|
|
14606
|
+
label: `${surface.profile === "gtm" ? "\u{1F4C8}" : "\u{1F9E0}"} ${surface.profile.toUpperCase()} \xB7 ${surface.instanceId}`,
|
|
14607
|
+
hint: surface.configPath
|
|
14608
|
+
})),
|
|
14609
|
+
{ value: "__back_to_app_mode", label: "\u2190 Back to app options" }
|
|
14610
|
+
]
|
|
14611
|
+
});
|
|
14612
|
+
if (p18.isCancel(existingChoice)) {
|
|
14613
|
+
p18.cancel("Cancelled.");
|
|
14614
|
+
process.exit(0);
|
|
14615
|
+
}
|
|
14616
|
+
if (existingChoice === "__back_to_app_mode") {
|
|
14617
|
+
continue;
|
|
14618
|
+
}
|
|
14619
|
+
const selectedSurface = existingSurfaces.find((surface) => surface.instanceId === existingChoice);
|
|
14620
|
+
if (!selectedSurface) {
|
|
14621
|
+
p18.cancel("Selected profile not found.");
|
|
14622
|
+
process.exit(1);
|
|
14623
|
+
}
|
|
14624
|
+
process.env.PAPERCLIP_SURFACE_PROFILE = selectedSurface.profile;
|
|
14625
|
+
await runCommand({
|
|
14626
|
+
config: selectedSurface.configPath,
|
|
14627
|
+
instance: selectedSurface.instanceId,
|
|
14628
|
+
repair: true,
|
|
14629
|
+
yes: true
|
|
14630
|
+
});
|
|
14631
|
+
return;
|
|
14632
|
+
}
|
|
14633
|
+
const profileChoice = await p18.select({
|
|
14634
|
+
message: "Which new app surface do you want to create?",
|
|
14635
|
+
options: [
|
|
14636
|
+
{
|
|
14637
|
+
value: "gtm",
|
|
14638
|
+
label: "\u{1F4C8} GTM",
|
|
14639
|
+
hint: "Go-to-Market surface."
|
|
14640
|
+
},
|
|
14641
|
+
{
|
|
14642
|
+
value: "dx",
|
|
14643
|
+
label: "\u{1F9E0} DX",
|
|
14644
|
+
hint: "Developer Experience surface."
|
|
14645
|
+
},
|
|
14646
|
+
{
|
|
14647
|
+
value: "__back_to_app_mode",
|
|
14648
|
+
label: "\u2190 Back to app options"
|
|
14649
|
+
}
|
|
14650
|
+
]
|
|
14651
|
+
});
|
|
14652
|
+
if (p18.isCancel(profileChoice)) {
|
|
14653
|
+
p18.cancel("Cancelled.");
|
|
14654
|
+
process.exit(0);
|
|
14655
|
+
}
|
|
14656
|
+
if (profileChoice === "__back_to_app_mode") {
|
|
14657
|
+
continue;
|
|
14658
|
+
}
|
|
14659
|
+
process.env.PAPERCLIP_SURFACE_PROFILE = profileChoice;
|
|
14660
|
+
await onboard({
|
|
14661
|
+
config: opts?.config,
|
|
14662
|
+
run: opts?.run ?? isInstallerMode(),
|
|
14663
|
+
yes: isInstallerMode()
|
|
14664
|
+
});
|
|
14665
|
+
return;
|
|
14666
|
+
}
|
|
14667
|
+
continue;
|
|
14668
|
+
}
|
|
14669
|
+
if (surfaceChoice === "kits") {
|
|
14670
|
+
const result2 = await runInteractivePicker({ allowBackToHub: true });
|
|
14671
|
+
if (result2 === "back") continue;
|
|
14672
|
+
return;
|
|
14673
|
+
}
|
|
14674
|
+
const result = await runTemplatePicker({ allowBackToHub: true });
|
|
14675
|
+
if (result === "back") continue;
|
|
14676
|
+
return;
|
|
14677
|
+
}
|
|
14678
|
+
}
|
|
14679
|
+
function isInstallerMode() {
|
|
14680
|
+
return process.env.GROWTHUB_INSTALLER_MODE === "true";
|
|
14681
|
+
}
|
|
14682
|
+
function listLocalSurfaces() {
|
|
14683
|
+
const homeDir = resolvePaperclipHomeDir();
|
|
14684
|
+
const instancesDir = path23.resolve(homeDir, "instances");
|
|
14685
|
+
if (!fs16.existsSync(instancesDir)) return [];
|
|
14686
|
+
return fs16.readdirSync(instancesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => {
|
|
14687
|
+
const instanceId = entry.name;
|
|
14688
|
+
const configPath = path23.resolve(instancesDir, instanceId, "config.json");
|
|
14689
|
+
if (!fs16.existsSync(configPath)) return null;
|
|
14690
|
+
try {
|
|
14691
|
+
const config = readConfig(configPath);
|
|
14692
|
+
if (!config) return null;
|
|
14693
|
+
const profile = resolveSurfaceProfile(config);
|
|
14694
|
+
if (!profile) return null;
|
|
14695
|
+
return {
|
|
14696
|
+
instanceId,
|
|
14697
|
+
profile,
|
|
14698
|
+
configPath
|
|
14699
|
+
};
|
|
14700
|
+
} catch {
|
|
14701
|
+
return null;
|
|
14702
|
+
}
|
|
14703
|
+
}).filter((entry) => entry !== null).sort((left, right) => left.instanceId.localeCompare(right.instanceId));
|
|
14704
|
+
}
|
|
12732
14705
|
function registerDxCommands(target) {
|
|
12733
14706
|
const heartbeat = target.command("heartbeat").description("Heartbeat utilities");
|
|
12734
14707
|
heartbeat.command("run").description("Run one agent heartbeat and stream live logs").requiredOption("-a, --agent-id <agentId>", "Agent ID to invoke").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--context <path>", "Path to CLI context file").option("--profile <name>", "CLI context profile name").option("--api-base <url>", "Base URL for the Growthub server API").option("--api-key <token>", "Bearer token for agent-authenticated calls").option(
|
|
@@ -12753,8 +14726,42 @@ applyDataDirOverride(bootstrapOptions, {
|
|
|
12753
14726
|
});
|
|
12754
14727
|
loadPaperclipEnvFile(bootstrapOptions.config);
|
|
12755
14728
|
var bootstrapConfig = readConfig(resolveConfigPath(bootstrapOptions.config));
|
|
12756
|
-
var surfaceRuntime = initializeSurfaceRuntimeContract(bootstrapConfig
|
|
12757
|
-
program.name("growthub").description("Growthub CLI \u2014 setup,
|
|
14729
|
+
var surfaceRuntime = initializeSurfaceRuntimeContract(resolveSurfaceProfile(bootstrapConfig) ?? void 0);
|
|
14730
|
+
program.name("growthub").description("Growthub CLI \u2014 setup, configure, and run your local Growthub instance").version("0.3.43").addHelpText("after", `
|
|
14731
|
+
Worker Kits (agent execution environments):
|
|
14732
|
+
|
|
14733
|
+
Discovery:
|
|
14734
|
+
$ growthub kit Interactive browser \u2014 pick, preview, download
|
|
14735
|
+
$ growthub kit list All kits grouped by family (studio \xB7 workflow \xB7 operator \xB7 ops)
|
|
14736
|
+
$ growthub kit list --family studio Filter by family
|
|
14737
|
+
$ growthub kit families Show family taxonomy with descriptions
|
|
14738
|
+
|
|
14739
|
+
Download:
|
|
14740
|
+
$ growthub kit download Interactive (no arg = picker)
|
|
14741
|
+
$ growthub kit download higgsfield Fuzzy slug \u2014 resolves automatically
|
|
14742
|
+
$ growthub kit download higgsfield --yes Skip confirmation (scripting / agent use)
|
|
14743
|
+
$ growthub kit download growthub-open-higgsfield-studio-v1 --out ~/kits
|
|
14744
|
+
|
|
14745
|
+
Inspect & validate:
|
|
14746
|
+
$ growthub kit inspect higgsfield-studio-v1
|
|
14747
|
+
$ growthub kit inspect growthub-email-marketing-v1 --json
|
|
14748
|
+
$ growthub kit validate ./path/to/kit
|
|
14749
|
+
|
|
14750
|
+
After download:
|
|
14751
|
+
1. Point Growthub local (or Claude Code) Working Directory at the exported folder
|
|
14752
|
+
2. cp .env.example .env \u2192 add your API key
|
|
14753
|
+
3. Open a new session \u2014 the operator agent loads automatically
|
|
14754
|
+
|
|
14755
|
+
Instance setup:
|
|
14756
|
+
$ growthub onboard First-run interactive wizard
|
|
14757
|
+
$ growthub run Onboard + doctor + start server
|
|
14758
|
+
$ growthub doctor Diagnose and optionally repair
|
|
14759
|
+
$ growthub configure Update config sections
|
|
14760
|
+
$ growthub Interactive discovery hub
|
|
14761
|
+
`);
|
|
14762
|
+
program.action(async () => {
|
|
14763
|
+
await runDiscoveryHub();
|
|
14764
|
+
});
|
|
12758
14765
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
12759
14766
|
const options = actionCommand.optsWithGlobals();
|
|
12760
14767
|
const optionNames = new Set(actionCommand.options.map((option) => option.attributeName()));
|
|
@@ -12774,4 +14781,3 @@ program.parseAsync().catch((err) => {
|
|
|
12774
14781
|
console.error(err instanceof Error ? err.message : String(err));
|
|
12775
14782
|
process.exit(1);
|
|
12776
14783
|
});
|
|
12777
|
-
//# sourceMappingURL=index.js.map
|