@starlein/paperclip-plugin-company-wizard 0.2.4 → 0.3.18
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 +59 -3
- package/dist/manifest.js +4 -5
- package/dist/manifest.js.map +2 -2
- package/dist/ui/index.css +563 -578
- package/dist/ui/index.css.map +2 -2
- package/dist/ui/index.js +1151 -559
- package/dist/ui/index.js.map +4 -4
- package/dist/worker.js +702 -253
- package/dist/worker.js.map +4 -4
- package/package.json +12 -7
- package/templates/ai-wizard/config-format.md +12 -4
- package/templates/ai-wizard/interview-system.md +3 -2
- package/templates/ai-wizard/messages.json +1 -1
- package/templates/ai-wizard/single-shot-system.md +4 -0
- package/templates/bootstrap-instructions.md +12 -2
- package/templates/modules/auto-assign/agents/ceo/heartbeat-section.md +1 -1
- package/templates/modules/auto-assign/agents/ceo/skills/auto-assign.fallback.md +1 -1
- package/templates/modules/auto-assign/agents/product-owner/heartbeat-section.md +1 -1
- package/templates/modules/auto-assign/module.meta.json +1 -1
- package/templates/modules/auto-assign/skills/auto-assign.md +1 -1
- package/templates/modules/backlog/module.meta.json +4 -3
- package/templates/modules/build-api/module.meta.json +1 -0
- package/templates/modules/ci-cd/module.meta.json +2 -1
- package/templates/modules/game-design/module.meta.json +18 -0
- package/templates/modules/game-design/skills/audio-design.fallback.md +16 -0
- package/templates/modules/game-design/skills/audio-design.md +28 -0
- package/templates/modules/game-design/skills/level-design.fallback.md +17 -0
- package/templates/modules/game-design/skills/level-design.md +29 -0
- package/templates/modules/github-repo/README.md +1 -0
- package/templates/modules/github-repo/module.meta.json +5 -2
- package/templates/modules/pr-review/README.md +5 -5
- package/templates/modules/pr-review/agents/code-reviewer/skills/code-review.md +7 -6
- package/templates/modules/pr-review/agents/devops/skills/infra-review.md +6 -6
- package/templates/modules/pr-review/agents/engineer/skills/pr-workflow.md +11 -6
- package/templates/modules/pr-review/agents/product-owner/skills/product-review.md +7 -6
- package/templates/modules/pr-review/agents/qa/skills/qa-review.md +6 -6
- package/templates/modules/pr-review/agents/ui-designer/skills/design-review.md +6 -6
- package/templates/modules/pr-review/agents/ux-researcher/skills/ux-review.md +6 -6
- package/templates/modules/pr-review/docs/pr-conventions.md +16 -15
- package/templates/modules/pr-review/module.meta.json +8 -3
- package/templates/modules/stall-detection/module.meta.json +1 -1
- package/templates/modules/website-relaunch/module.meta.json +2 -1
- package/templates/presets/build-game/preset.meta.json +2 -1
- package/templates/presets/content/preset.meta.json +3 -1
- package/templates/presets/full/preset.meta.json +1 -0
- package/templates/presets/gtm/preset.meta.json +3 -1
- package/templates/presets/launch-pack/preset.meta.json +1 -0
- package/templates/presets/quality/preset.meta.json +2 -1
- package/templates/presets/repo-maintenance/preset.meta.json +2 -1
- package/templates/presets/secure/preset.meta.json +1 -0
- package/templates/roles/security-engineer/role.meta.json +1 -1
- package/templates/roles/cfo/AGENTS.md +0 -31
- package/templates/roles/cfo/HEARTBEAT.md +0 -37
- package/templates/roles/cfo/SOUL.md +0 -17
- package/templates/roles/cfo/TOOLS.md +0 -3
- package/templates/roles/cfo/role.meta.json +0 -17
package/dist/worker.js
CHANGED
|
@@ -4,7 +4,7 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// node_modules/.pnpm/@paperclipai+plugin-sdk@
|
|
7
|
+
// node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/define-plugin.js
|
|
8
8
|
function definePlugin(definition) {
|
|
9
9
|
return Object.freeze({ definition });
|
|
10
10
|
}
|
|
@@ -4050,7 +4050,7 @@ var coerce = {
|
|
|
4050
4050
|
};
|
|
4051
4051
|
var NEVER = INVALID;
|
|
4052
4052
|
|
|
4053
|
-
//
|
|
4053
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/constants.js
|
|
4054
4054
|
var COMPANY_STATUSES = ["active", "paused", "archived"];
|
|
4055
4055
|
var DEFAULT_COMPANY_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
|
|
4056
4056
|
var MAX_COMPANY_ATTACHMENT_MAX_BYTES = 1024 * 1024 * 1024;
|
|
@@ -4171,7 +4171,8 @@ var ISSUE_COMMENT_METADATA_ROW_TYPES = [
|
|
|
4171
4171
|
"run_link"
|
|
4172
4172
|
];
|
|
4173
4173
|
function clampIssueRequestDepth(value) {
|
|
4174
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
4174
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
4175
|
+
return 0;
|
|
4175
4176
|
return Math.min(MAX_ISSUE_REQUEST_DEPTH, Math.max(0, Math.floor(value)));
|
|
4176
4177
|
}
|
|
4177
4178
|
var ISSUE_THREAD_INTERACTION_KINDS = [
|
|
@@ -4586,11 +4587,11 @@ var PLUGIN_STATE_SCOPE_KINDS = [
|
|
|
4586
4587
|
"run"
|
|
4587
4588
|
];
|
|
4588
4589
|
|
|
4589
|
-
//
|
|
4590
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/adapter-type.js
|
|
4590
4591
|
var agentAdapterTypeSchema = external_exports.string().trim().min(1).default("process").describe(`Known built-in adapters: ${AGENT_ADAPTER_TYPES.join(", ")}. External adapters may register additional non-empty string types at runtime.`);
|
|
4591
4592
|
var optionalAgentAdapterTypeSchema = external_exports.string().trim().min(1).optional();
|
|
4592
4593
|
|
|
4593
|
-
//
|
|
4594
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/network-bind.js
|
|
4594
4595
|
function normalizeHost(host) {
|
|
4595
4596
|
const trimmed = host?.trim();
|
|
4596
4597
|
return trimmed ? trimmed : void 0;
|
|
@@ -4606,9 +4607,12 @@ function isAllInterfacesHost(host) {
|
|
|
4606
4607
|
function inferBindModeFromHost(host, opts) {
|
|
4607
4608
|
const normalized = normalizeHost(host);
|
|
4608
4609
|
const tailnetBindHost = normalizeHost(opts?.tailnetBindHost);
|
|
4609
|
-
if (!normalized || isLoopbackHost(normalized))
|
|
4610
|
-
|
|
4611
|
-
if (
|
|
4610
|
+
if (!normalized || isLoopbackHost(normalized))
|
|
4611
|
+
return "loopback";
|
|
4612
|
+
if (isAllInterfacesHost(normalized))
|
|
4613
|
+
return "lan";
|
|
4614
|
+
if (tailnetBindHost && normalized === tailnetBindHost)
|
|
4615
|
+
return "tailnet";
|
|
4612
4616
|
return "custom";
|
|
4613
4617
|
}
|
|
4614
4618
|
function validateConfiguredBindMode(input) {
|
|
@@ -4630,7 +4634,7 @@ function validateConfiguredBindMode(input) {
|
|
|
4630
4634
|
return errors;
|
|
4631
4635
|
}
|
|
4632
4636
|
|
|
4633
|
-
//
|
|
4637
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/instance.js
|
|
4634
4638
|
var DAILY_RETENTION_PRESETS = [3, 7, 14];
|
|
4635
4639
|
var WEEKLY_RETENTION_PRESETS = [1, 2, 4];
|
|
4636
4640
|
var MONTHLY_RETENTION_PRESETS = [1, 3, 6];
|
|
@@ -4643,13 +4647,13 @@ var DEFAULT_BACKUP_RETENTION = {
|
|
|
4643
4647
|
monthlyMonths: 1
|
|
4644
4648
|
};
|
|
4645
4649
|
|
|
4646
|
-
//
|
|
4650
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/search.js
|
|
4647
4651
|
var COMPANY_SEARCH_SCOPES = ["all", "issues", "comments", "documents", "agents", "projects"];
|
|
4648
4652
|
|
|
4649
|
-
//
|
|
4653
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/resource-memberships.js
|
|
4650
4654
|
var RESOURCE_MEMBERSHIP_STATES = ["joined", "left"];
|
|
4651
4655
|
|
|
4652
|
-
//
|
|
4656
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/sidebar-preferences.js
|
|
4653
4657
|
var sidebarOrderedIdSchema = external_exports.string().uuid();
|
|
4654
4658
|
var sidebarOrderPreferenceSchema = external_exports.object({
|
|
4655
4659
|
orderedIds: external_exports.array(sidebarOrderedIdSchema),
|
|
@@ -4659,13 +4663,13 @@ var upsertSidebarOrderPreferenceSchema = external_exports.object({
|
|
|
4659
4663
|
orderedIds: external_exports.array(sidebarOrderedIdSchema)
|
|
4660
4664
|
});
|
|
4661
4665
|
|
|
4662
|
-
//
|
|
4666
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/resource-memberships.js
|
|
4663
4667
|
var resourceMembershipStateSchema = external_exports.enum(RESOURCE_MEMBERSHIP_STATES);
|
|
4664
4668
|
var updateResourceMembershipSchema = external_exports.object({
|
|
4665
4669
|
state: resourceMembershipStateSchema
|
|
4666
4670
|
});
|
|
4667
4671
|
|
|
4668
|
-
//
|
|
4672
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/execution-workspace.js
|
|
4669
4673
|
var executionWorkspaceStatusSchema = external_exports.enum([
|
|
4670
4674
|
"active",
|
|
4671
4675
|
"idle",
|
|
@@ -4785,14 +4789,14 @@ var updateExecutionWorkspaceSchema = external_exports.object({
|
|
|
4785
4789
|
metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
|
|
4786
4790
|
}).strict();
|
|
4787
4791
|
|
|
4788
|
-
//
|
|
4792
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/feedback.js
|
|
4789
4793
|
var FEEDBACK_TARGET_TYPES = ["issue_comment", "issue_document_revision"];
|
|
4790
4794
|
var FEEDBACK_VOTE_VALUES = ["up", "down"];
|
|
4791
4795
|
var FEEDBACK_DATA_SHARING_PREFERENCES = ["allowed", "not_allowed", "prompt"];
|
|
4792
4796
|
var DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE = "prompt";
|
|
4793
4797
|
var FEEDBACK_TRACE_STATUSES = ["local_only", "pending", "sent", "failed"];
|
|
4794
4798
|
|
|
4795
|
-
//
|
|
4799
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/feedback.js
|
|
4796
4800
|
var feedbackTargetTypeSchema = external_exports.enum(FEEDBACK_TARGET_TYPES);
|
|
4797
4801
|
var feedbackTraceStatusSchema = external_exports.enum(FEEDBACK_TRACE_STATUSES);
|
|
4798
4802
|
var feedbackVoteValueSchema = external_exports.enum(FEEDBACK_VOTE_VALUES);
|
|
@@ -4805,12 +4809,9 @@ var upsertIssueFeedbackVoteSchema = external_exports.object({
|
|
|
4805
4809
|
allowSharing: external_exports.boolean().optional()
|
|
4806
4810
|
});
|
|
4807
4811
|
|
|
4808
|
-
//
|
|
4812
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/instance.js
|
|
4809
4813
|
function presetSchema(presets, label) {
|
|
4810
|
-
return external_exports.number().refine(
|
|
4811
|
-
(v) => presets.includes(v),
|
|
4812
|
-
{ message: `${label} must be one of: ${presets.join(", ")}` }
|
|
4813
|
-
);
|
|
4814
|
+
return external_exports.number().refine((v) => presets.includes(v), { message: `${label} must be one of: ${presets.join(", ")}` });
|
|
4814
4815
|
}
|
|
4815
4816
|
var backupRetentionPolicySchema = external_exports.object({
|
|
4816
4817
|
dailyDays: presetSchema(DAILY_RETENTION_PRESETS, "dailyDays").default(DEFAULT_BACKUP_RETENTION.dailyDays),
|
|
@@ -4820,9 +4821,7 @@ var backupRetentionPolicySchema = external_exports.object({
|
|
|
4820
4821
|
var instanceGeneralSettingsSchema = external_exports.object({
|
|
4821
4822
|
censorUsernameInLogs: external_exports.boolean().default(false),
|
|
4822
4823
|
keyboardShortcuts: external_exports.boolean().default(false),
|
|
4823
|
-
feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(
|
|
4824
|
-
DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE
|
|
4825
|
-
),
|
|
4824
|
+
feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE),
|
|
4826
4825
|
backupRetention: backupRetentionPolicySchema.default(DEFAULT_BACKUP_RETENTION)
|
|
4827
4826
|
}).strict();
|
|
4828
4827
|
var patchInstanceGeneralSettingsSchema = instanceGeneralSettingsSchema.partial();
|
|
@@ -4840,7 +4839,7 @@ var issueGraphLivenessAutoRecoveryRequestSchema = external_exports.object({
|
|
|
4840
4839
|
lookbackHours: external_exports.number().int().min(MIN_ISSUE_GRAPH_LIVENESS_AUTO_RECOVERY_LOOKBACK_HOURS).max(MAX_ISSUE_GRAPH_LIVENESS_AUTO_RECOVERY_LOOKBACK_HOURS).optional()
|
|
4841
4840
|
}).strict();
|
|
4842
4841
|
|
|
4843
|
-
//
|
|
4842
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/budget.js
|
|
4844
4843
|
var upsertBudgetPolicySchema = external_exports.object({
|
|
4845
4844
|
scopeType: external_exports.enum(BUDGET_SCOPE_TYPES),
|
|
4846
4845
|
scopeId: external_exports.string().uuid(),
|
|
@@ -4866,7 +4865,7 @@ var resolveBudgetIncidentSchema = external_exports.object({
|
|
|
4866
4865
|
}
|
|
4867
4866
|
});
|
|
4868
4867
|
|
|
4869
|
-
//
|
|
4868
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company.js
|
|
4870
4869
|
var logoAssetIdSchema = external_exports.string().uuid().nullable().optional();
|
|
4871
4870
|
var brandColorSchema = external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
|
|
4872
4871
|
var feedbackDataSharingTermsVersionSchema = external_exports.string().min(1).nullable().optional();
|
|
@@ -4894,12 +4893,9 @@ var updateCompanyBrandingSchema = external_exports.object({
|
|
|
4894
4893
|
description: external_exports.string().nullable().optional(),
|
|
4895
4894
|
brandColor: brandColorSchema,
|
|
4896
4895
|
logoAssetId: logoAssetIdSchema
|
|
4897
|
-
}).strict().refine(
|
|
4898
|
-
(value) => value.name !== void 0 || value.description !== void 0 || value.brandColor !== void 0 || value.logoAssetId !== void 0,
|
|
4899
|
-
"At least one branding field must be provided"
|
|
4900
|
-
);
|
|
4896
|
+
}).strict().refine((value) => value.name !== void 0 || value.description !== void 0 || value.brandColor !== void 0 || value.logoAssetId !== void 0, "At least one branding field must be provided");
|
|
4901
4897
|
|
|
4902
|
-
//
|
|
4898
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/environment.js
|
|
4903
4899
|
var environmentDriverSchema = external_exports.enum(ENVIRONMENT_DRIVERS);
|
|
4904
4900
|
var environmentStatusSchema = external_exports.enum(ENVIRONMENT_STATUSES);
|
|
4905
4901
|
var environmentLeaseStatusSchema = external_exports.enum(ENVIRONMENT_LEASE_STATUSES);
|
|
@@ -4929,7 +4925,7 @@ var probeEnvironmentConfigSchema = external_exports.object({
|
|
|
4929
4925
|
metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
|
|
4930
4926
|
}).strict();
|
|
4931
4927
|
|
|
4932
|
-
//
|
|
4928
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company-skill.js
|
|
4933
4929
|
var companySkillSourceTypeSchema = external_exports.enum(["local_path", "github", "url", "catalog", "skills_sh"]);
|
|
4934
4930
|
var companySkillTrustLevelSchema = external_exports.enum(["markdown_only", "assets", "scripts_executables"]);
|
|
4935
4931
|
var companySkillCompatibilitySchema = external_exports.enum(["compatible", "unknown", "invalid"]);
|
|
@@ -4973,9 +4969,7 @@ var companySkillUsageAgentSchema = external_exports.object({
|
|
|
4973
4969
|
urlKey: external_exports.string().min(1),
|
|
4974
4970
|
adapterType: external_exports.string().min(1),
|
|
4975
4971
|
desired: external_exports.boolean(),
|
|
4976
|
-
actualState: external_exports.string().nullable().describe(
|
|
4977
|
-
"Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes."
|
|
4978
|
-
)
|
|
4972
|
+
actualState: external_exports.string().nullable().describe("Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes.")
|
|
4979
4973
|
});
|
|
4980
4974
|
var companySkillDetailSchema = companySkillSchema.extend({
|
|
4981
4975
|
attachedAgentCount: external_exports.number().int().nonnegative(),
|
|
@@ -5137,7 +5131,7 @@ var companySkillInstallCatalogResultSchema = external_exports.object({
|
|
|
5137
5131
|
warnings: external_exports.array(external_exports.string())
|
|
5138
5132
|
});
|
|
5139
5133
|
|
|
5140
|
-
//
|
|
5134
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/adapter-skills.js
|
|
5141
5135
|
var agentSkillStateSchema = external_exports.enum([
|
|
5142
5136
|
"available",
|
|
5143
5137
|
"configured",
|
|
@@ -5185,13 +5179,13 @@ var agentSkillSyncSchema = external_exports.object({
|
|
|
5185
5179
|
desiredSkills: external_exports.array(external_exports.string().min(1))
|
|
5186
5180
|
});
|
|
5187
5181
|
|
|
5188
|
-
//
|
|
5182
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/text.js
|
|
5189
5183
|
function normalizeEscapedLineBreaks(value) {
|
|
5190
5184
|
return value.replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\\r/g, "\n");
|
|
5191
5185
|
}
|
|
5192
5186
|
var multilineTextSchema = external_exports.string().transform(normalizeEscapedLineBreaks);
|
|
5193
5187
|
|
|
5194
|
-
//
|
|
5188
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/issue.js
|
|
5195
5189
|
var issueBlockedInboxStateSchema = external_exports.enum([
|
|
5196
5190
|
"needs_attention",
|
|
5197
5191
|
"awaiting_decision",
|
|
@@ -5462,9 +5456,11 @@ function resolveCreateIssueStatusDefault(input) {
|
|
|
5462
5456
|
}
|
|
5463
5457
|
function withCreateIssueStatusDefault(schema) {
|
|
5464
5458
|
return external_exports.preprocess((input) => {
|
|
5465
|
-
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
5459
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
5460
|
+
return input;
|
|
5466
5461
|
const raw = input;
|
|
5467
|
-
if (raw.status !== void 0)
|
|
5462
|
+
if (raw.status !== void 0)
|
|
5463
|
+
return input;
|
|
5468
5464
|
return {
|
|
5469
5465
|
...raw,
|
|
5470
5466
|
status: resolveCreateIssueStatusDefault(raw).status
|
|
@@ -5606,9 +5602,7 @@ var addIssueCommentSchema = external_exports.object({
|
|
|
5606
5602
|
});
|
|
5607
5603
|
var issueThreadInteractionStatusSchema = external_exports.enum(ISSUE_THREAD_INTERACTION_STATUSES);
|
|
5608
5604
|
var issueThreadInteractionKindSchema = external_exports.enum(ISSUE_THREAD_INTERACTION_KINDS);
|
|
5609
|
-
var issueThreadInteractionContinuationPolicySchema = external_exports.enum(
|
|
5610
|
-
ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES
|
|
5611
|
-
);
|
|
5605
|
+
var issueThreadInteractionContinuationPolicySchema = external_exports.enum(ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES);
|
|
5612
5606
|
var issueDocumentKeySchema = external_exports.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/, "Document key must be lowercase letters, numbers, _ or -");
|
|
5613
5607
|
var suggestedTaskDraftSchema = external_exports.object({
|
|
5614
5608
|
clientKey: external_exports.string().trim().min(1).max(120),
|
|
@@ -5840,7 +5834,7 @@ var upsertIssueDocumentSchema = external_exports.object({
|
|
|
5840
5834
|
});
|
|
5841
5835
|
var restoreIssueDocumentRevisionSchema = external_exports.object({});
|
|
5842
5836
|
|
|
5843
|
-
//
|
|
5837
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/secret.js
|
|
5844
5838
|
var envBindingPlainSchema = external_exports.object({
|
|
5845
5839
|
type: external_exports.literal("plain"),
|
|
5846
5840
|
value: external_exports.string()
|
|
@@ -5923,9 +5917,11 @@ var safeShortText = external_exports.string().trim().min(1).max(160);
|
|
|
5923
5917
|
var optionalSafeShortText = safeShortText.optional().nullable();
|
|
5924
5918
|
var deniedProviderConfigKeyPattern = /^(access[-_]?key([-_]?id)?|secret[-_]?access[-_]?key|secret[-_]?key|token|password|passwd|credential|credentials|private[-_]?key|pem|jwt|session[-_]?token|service[-_]?account([-_]?json)?|client[-_]?secret|secret[-_]?id|unseal[-_]?key|recovery[-_]?key|key[-_]?file([-_]?path)?|token[-_]?file([-_]?path)?)$/i;
|
|
5925
5919
|
function rejectSensitiveProviderConfigKeys(value, ctx) {
|
|
5926
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
5920
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
5921
|
+
return;
|
|
5927
5922
|
for (const key of Object.keys(value)) {
|
|
5928
|
-
if (!deniedProviderConfigKeyPattern.test(key))
|
|
5923
|
+
if (!deniedProviderConfigKeyPattern.test(key))
|
|
5924
|
+
continue;
|
|
5929
5925
|
ctx.addIssue({
|
|
5930
5926
|
code: external_exports.ZodIssueCode.custom,
|
|
5931
5927
|
path: ["config", key],
|
|
@@ -5950,28 +5946,27 @@ var gcpSecretManagerProviderConfigSchema = external_exports.object({
|
|
|
5950
5946
|
namespace: optionalSafeShortText,
|
|
5951
5947
|
secretNamePrefix: optionalSafeShortText
|
|
5952
5948
|
}).strict();
|
|
5953
|
-
var vaultAddressSchema = external_exports.preprocess(
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
}
|
|
5969
|
-
}).transform((value) => new URL(value).origin)
|
|
5970
|
-
);
|
|
5949
|
+
var vaultAddressSchema = external_exports.preprocess((value) => typeof value === "string" ? value.trim() : value, external_exports.string().url().superRefine((value, ctx) => {
|
|
5950
|
+
let url;
|
|
5951
|
+
try {
|
|
5952
|
+
url = new URL(value);
|
|
5953
|
+
} catch {
|
|
5954
|
+
return;
|
|
5955
|
+
}
|
|
5956
|
+
const hasPath = url.pathname !== "" && url.pathname !== "/";
|
|
5957
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password || url.search || url.hash || hasPath) {
|
|
5958
|
+
ctx.addIssue({
|
|
5959
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5960
|
+
message: "Vault address must be an origin-only HTTP(S) URL without credentials, path, query, or fragment"
|
|
5961
|
+
});
|
|
5962
|
+
}
|
|
5963
|
+
}).transform((value) => new URL(value).origin));
|
|
5971
5964
|
function rejectUnsafeVaultAddress(value, ctx) {
|
|
5972
|
-
if (value === void 0 || value === null)
|
|
5965
|
+
if (value === void 0 || value === null)
|
|
5966
|
+
return;
|
|
5973
5967
|
const parsed = vaultAddressSchema.safeParse(value);
|
|
5974
|
-
if (parsed.success)
|
|
5968
|
+
if (parsed.success)
|
|
5969
|
+
return;
|
|
5975
5970
|
for (const issue of parsed.error.issues) {
|
|
5976
5971
|
ctx.addIssue({
|
|
5977
5972
|
...issue,
|
|
@@ -6085,7 +6080,7 @@ var remoteSecretImportSchema = external_exports.object({
|
|
|
6085
6080
|
secrets: external_exports.array(remoteSecretImportSelectionSchema).min(1).max(100)
|
|
6086
6081
|
});
|
|
6087
6082
|
|
|
6088
|
-
//
|
|
6083
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/routine.js
|
|
6089
6084
|
var routineVariableValueSchema = external_exports.union([external_exports.string(), external_exports.number().finite(), external_exports.boolean()]);
|
|
6090
6085
|
var routineVariableSchema = external_exports.object({
|
|
6091
6086
|
name: external_exports.string().trim().regex(/^[A-Za-z][A-Za-z0-9_]*$/),
|
|
@@ -6209,7 +6204,7 @@ var runRoutineSchema = external_exports.object({
|
|
|
6209
6204
|
});
|
|
6210
6205
|
var rotateRoutineTriggerSecretSchema = external_exports.object({});
|
|
6211
6206
|
|
|
6212
|
-
//
|
|
6207
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company-portability.js
|
|
6213
6208
|
var portabilityIncludeSchema = external_exports.object({
|
|
6214
6209
|
company: external_exports.boolean().optional(),
|
|
6215
6210
|
agents: external_exports.boolean().optional(),
|
|
@@ -6433,7 +6428,7 @@ var companyPortabilityImportSchema = companyPortabilityPreviewSchema.extend({
|
|
|
6433
6428
|
adapterOverrides: external_exports.record(external_exports.string().min(1), portabilityAdapterOverrideSchema).optional()
|
|
6434
6429
|
});
|
|
6435
6430
|
|
|
6436
|
-
//
|
|
6431
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/agent.js
|
|
6437
6432
|
var agentPermissionsSchema = external_exports.object({
|
|
6438
6433
|
canCreateAgents: external_exports.boolean().optional().default(false)
|
|
6439
6434
|
});
|
|
@@ -6451,7 +6446,8 @@ var upsertAgentInstructionsFileSchema = external_exports.object({
|
|
|
6451
6446
|
});
|
|
6452
6447
|
var adapterConfigSchema = external_exports.record(external_exports.string(), external_exports.unknown()).superRefine((value, ctx) => {
|
|
6453
6448
|
const envValue = value.env;
|
|
6454
|
-
if (envValue === void 0)
|
|
6449
|
+
if (envValue === void 0)
|
|
6450
|
+
return;
|
|
6455
6451
|
const parsed = envConfigSchema.safeParse(envValue);
|
|
6456
6452
|
if (!parsed.success) {
|
|
6457
6453
|
ctx.addIssue({
|
|
@@ -6521,10 +6517,7 @@ var wakeAgentSchema = external_exports.object({
|
|
|
6521
6517
|
reason: external_exports.string().optional().nullable(),
|
|
6522
6518
|
payload: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable(),
|
|
6523
6519
|
idempotencyKey: external_exports.string().optional().nullable(),
|
|
6524
|
-
forceFreshSession: external_exports.preprocess(
|
|
6525
|
-
(value) => value === null ? void 0 : value,
|
|
6526
|
-
external_exports.boolean().optional().default(false)
|
|
6527
|
-
)
|
|
6520
|
+
forceFreshSession: external_exports.preprocess((value) => value === null ? void 0 : value, external_exports.boolean().optional().default(false))
|
|
6528
6521
|
});
|
|
6529
6522
|
var resetAgentSessionSchema = external_exports.object({
|
|
6530
6523
|
taskKey: external_exports.string().min(1).optional().nullable()
|
|
@@ -6544,7 +6537,7 @@ var updateAgentPermissionsSchema = external_exports.object({
|
|
|
6544
6537
|
canAssignTasks: external_exports.boolean()
|
|
6545
6538
|
});
|
|
6546
6539
|
|
|
6547
|
-
//
|
|
6540
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/project.js
|
|
6548
6541
|
var executionWorkspaceStrategySchema2 = external_exports.object({
|
|
6549
6542
|
type: external_exports.enum(["project_primary", "git_worktree", "adapter_managed", "cloud_sandbox"]).optional(),
|
|
6550
6543
|
baseRef: external_exports.string().optional().nullable(),
|
|
@@ -6640,7 +6633,7 @@ var createProjectSchema = external_exports.object({
|
|
|
6640
6633
|
});
|
|
6641
6634
|
var updateProjectSchema = external_exports.object(projectFields).partial();
|
|
6642
6635
|
|
|
6643
|
-
//
|
|
6636
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/document-annotation.js
|
|
6644
6637
|
var documentAnnotationThreadStatusSchema = external_exports.enum(DOCUMENT_ANNOTATION_THREAD_STATUSES);
|
|
6645
6638
|
var documentAnnotationAnchorStateSchema = external_exports.enum(DOCUMENT_ANNOTATION_ANCHOR_STATES);
|
|
6646
6639
|
var documentAnnotationAnchorConfidenceSchema = external_exports.enum(DOCUMENT_ANNOTATION_ANCHOR_CONFIDENCES);
|
|
@@ -6689,7 +6682,7 @@ var updateDocumentAnnotationThreadSchema = external_exports.object({
|
|
|
6689
6682
|
message: "At least one field must be provided"
|
|
6690
6683
|
});
|
|
6691
6684
|
|
|
6692
|
-
//
|
|
6685
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/search.js
|
|
6693
6686
|
var COMPANY_SEARCH_MAX_QUERY_LENGTH = 200;
|
|
6694
6687
|
var COMPANY_SEARCH_DEFAULT_LIMIT = 20;
|
|
6695
6688
|
var COMPANY_SEARCH_MAX_LIMIT = 50;
|
|
@@ -6700,7 +6693,8 @@ function firstQueryValue(value) {
|
|
|
6700
6693
|
function clampInteger(value, fallback, min, max) {
|
|
6701
6694
|
const raw = firstQueryValue(value);
|
|
6702
6695
|
const numeric = typeof raw === "number" ? raw : typeof raw === "string" && raw.trim().length > 0 ? Number.parseInt(raw, 10) : Number.NaN;
|
|
6703
|
-
if (!Number.isFinite(numeric))
|
|
6696
|
+
if (!Number.isFinite(numeric))
|
|
6697
|
+
return fallback;
|
|
6704
6698
|
return Math.min(max, Math.max(min, Math.floor(numeric)));
|
|
6705
6699
|
}
|
|
6706
6700
|
var companySearchQuerySchema = external_exports.object({
|
|
@@ -6710,7 +6704,7 @@ var companySearchQuerySchema = external_exports.object({
|
|
|
6710
6704
|
offset: external_exports.unknown().optional().transform((value) => clampInteger(value, 0, 0, COMPANY_SEARCH_MAX_OFFSET))
|
|
6711
6705
|
});
|
|
6712
6706
|
|
|
6713
|
-
//
|
|
6707
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/issue-tree-control.js
|
|
6714
6708
|
var issueTreeControlModeSchema = external_exports.enum(ISSUE_TREE_CONTROL_MODES);
|
|
6715
6709
|
var issueTreeHoldReleasePolicySchema = external_exports.object({
|
|
6716
6710
|
strategy: external_exports.enum(ISSUE_TREE_HOLD_RELEASE_POLICY_STRATEGIES).default("manual"),
|
|
@@ -6732,10 +6726,7 @@ var releaseIssueTreeHoldSchema = external_exports.object({
|
|
|
6732
6726
|
metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
|
|
6733
6727
|
}).strict();
|
|
6734
6728
|
|
|
6735
|
-
//
|
|
6736
|
-
function attachmentContentPath(attachmentId) {
|
|
6737
|
-
return `/api/attachments/${attachmentId}/content`;
|
|
6738
|
-
}
|
|
6729
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/work-product.js
|
|
6739
6730
|
var issueWorkProductTypeSchema = external_exports.enum([
|
|
6740
6731
|
"preview_url",
|
|
6741
6732
|
"runtime_service",
|
|
@@ -6762,38 +6753,6 @@ var issueWorkProductReviewStateSchema = external_exports.enum([
|
|
|
6762
6753
|
"approved",
|
|
6763
6754
|
"changes_requested"
|
|
6764
6755
|
]);
|
|
6765
|
-
var attachmentArtifactWorkProductMetadataSchema = external_exports.object({
|
|
6766
|
-
attachmentId: external_exports.string().uuid(),
|
|
6767
|
-
contentType: external_exports.string().min(1),
|
|
6768
|
-
byteSize: external_exports.number().int().nonnegative(),
|
|
6769
|
-
contentPath: external_exports.string().min(1),
|
|
6770
|
-
openPath: external_exports.string().min(1),
|
|
6771
|
-
downloadPath: external_exports.string().min(1),
|
|
6772
|
-
originalFilename: external_exports.string().optional().nullable()
|
|
6773
|
-
}).superRefine((value, ctx) => {
|
|
6774
|
-
const contentPath = attachmentContentPath(value.attachmentId);
|
|
6775
|
-
if (value.contentPath !== contentPath) {
|
|
6776
|
-
ctx.addIssue({
|
|
6777
|
-
code: external_exports.ZodIssueCode.custom,
|
|
6778
|
-
path: ["contentPath"],
|
|
6779
|
-
message: "contentPath must point to the same-origin attachment content route"
|
|
6780
|
-
});
|
|
6781
|
-
}
|
|
6782
|
-
if (value.openPath !== contentPath) {
|
|
6783
|
-
ctx.addIssue({
|
|
6784
|
-
code: external_exports.ZodIssueCode.custom,
|
|
6785
|
-
path: ["openPath"],
|
|
6786
|
-
message: "openPath must point to the same-origin attachment content route"
|
|
6787
|
-
});
|
|
6788
|
-
}
|
|
6789
|
-
if (value.downloadPath !== `${contentPath}?download=1`) {
|
|
6790
|
-
ctx.addIssue({
|
|
6791
|
-
code: external_exports.ZodIssueCode.custom,
|
|
6792
|
-
path: ["downloadPath"],
|
|
6793
|
-
message: "downloadPath must point to the same-origin attachment download route"
|
|
6794
|
-
});
|
|
6795
|
-
}
|
|
6796
|
-
});
|
|
6797
6756
|
var createIssueWorkProductSchema = external_exports.object({
|
|
6798
6757
|
projectId: external_exports.string().uuid().optional().nullable(),
|
|
6799
6758
|
executionWorkspaceId: external_exports.string().uuid().optional().nullable(),
|
|
@@ -6813,7 +6772,7 @@ var createIssueWorkProductSchema = external_exports.object({
|
|
|
6813
6772
|
});
|
|
6814
6773
|
var updateIssueWorkProductSchema = createIssueWorkProductSchema.partial();
|
|
6815
6774
|
|
|
6816
|
-
//
|
|
6775
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/goal.js
|
|
6817
6776
|
var createGoalSchema = external_exports.object({
|
|
6818
6777
|
title: external_exports.string().min(1),
|
|
6819
6778
|
description: external_exports.string().optional().nullable(),
|
|
@@ -6824,7 +6783,7 @@ var createGoalSchema = external_exports.object({
|
|
|
6824
6783
|
});
|
|
6825
6784
|
var updateGoalSchema = createGoalSchema.partial();
|
|
6826
6785
|
|
|
6827
|
-
//
|
|
6786
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/approval.js
|
|
6828
6787
|
var createApprovalSchema = external_exports.object({
|
|
6829
6788
|
type: external_exports.enum(APPROVAL_TYPES),
|
|
6830
6789
|
requestedByAgentId: external_exports.string().uuid().optional().nullable(),
|
|
@@ -6844,7 +6803,7 @@ var addApprovalCommentSchema = external_exports.object({
|
|
|
6844
6803
|
body: multilineTextSchema.pipe(external_exports.string().min(1))
|
|
6845
6804
|
});
|
|
6846
6805
|
|
|
6847
|
-
//
|
|
6806
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/cost.js
|
|
6848
6807
|
var createCostEventSchema = external_exports.object({
|
|
6849
6808
|
agentId: external_exports.string().uuid(),
|
|
6850
6809
|
issueId: external_exports.string().uuid().optional().nullable(),
|
|
@@ -6869,7 +6828,7 @@ var updateBudgetSchema = external_exports.object({
|
|
|
6869
6828
|
budgetMonthlyCents: external_exports.number().int().nonnegative()
|
|
6870
6829
|
});
|
|
6871
6830
|
|
|
6872
|
-
//
|
|
6831
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/finance.js
|
|
6873
6832
|
var createFinanceEventSchema = external_exports.object({
|
|
6874
6833
|
agentId: external_exports.string().uuid().optional().nullable(),
|
|
6875
6834
|
issueId: external_exports.string().uuid().optional().nullable(),
|
|
@@ -6900,12 +6859,12 @@ var createFinanceEventSchema = external_exports.object({
|
|
|
6900
6859
|
currency: value.currency.toUpperCase()
|
|
6901
6860
|
}));
|
|
6902
6861
|
|
|
6903
|
-
//
|
|
6862
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/asset.js
|
|
6904
6863
|
var createAssetImageMetadataSchema = external_exports.object({
|
|
6905
6864
|
namespace: external_exports.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9/_-]+$/).optional()
|
|
6906
6865
|
});
|
|
6907
6866
|
|
|
6908
|
-
//
|
|
6867
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/access.js
|
|
6909
6868
|
var createCompanyInviteSchema = external_exports.object({
|
|
6910
6869
|
allowedJoinTypes: external_exports.enum(INVITE_JOIN_TYPES).default("both"),
|
|
6911
6870
|
humanRole: external_exports.enum(HUMAN_COMPANY_MEMBERSHIP_ROLES).optional().nullable(),
|
|
@@ -6954,12 +6913,10 @@ var resolveCliAuthChallengeSchema = external_exports.object({
|
|
|
6954
6913
|
token: external_exports.string().min(16).max(256)
|
|
6955
6914
|
});
|
|
6956
6915
|
var updateMemberPermissionsSchema = external_exports.object({
|
|
6957
|
-
grants: external_exports.array(
|
|
6958
|
-
external_exports.
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
})
|
|
6962
|
-
)
|
|
6916
|
+
grants: external_exports.array(external_exports.object({
|
|
6917
|
+
permissionKey: external_exports.enum(PERMISSION_KEYS),
|
|
6918
|
+
scope: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
|
|
6919
|
+
}))
|
|
6963
6920
|
});
|
|
6964
6921
|
var editableMembershipStatuses = ["pending", "active", "suspended"];
|
|
6965
6922
|
var updateCompanyMemberSchema = external_exports.object({
|
|
@@ -6997,7 +6954,8 @@ var searchAdminUsersQuerySchema = external_exports.object({
|
|
|
6997
6954
|
});
|
|
6998
6955
|
var profileImageAssetPathPattern = /^\/api\/assets\/[^/?#]+\/content(?:\?[^#]*)?(?:#.*)?$/;
|
|
6999
6956
|
function isValidProfileImage(value) {
|
|
7000
|
-
if (profileImageAssetPathPattern.test(value))
|
|
6957
|
+
if (profileImageAssetPathPattern.test(value))
|
|
6958
|
+
return true;
|
|
7001
6959
|
try {
|
|
7002
6960
|
const url = new URL(value);
|
|
7003
6961
|
return url.protocol === "https:" || url.protocol === "http:";
|
|
@@ -7024,30 +6982,27 @@ var updateCurrentUserProfileSchema = external_exports.object({
|
|
|
7024
6982
|
image: external_exports.union([profileImageSchema, external_exports.literal(""), external_exports.null()]).optional().transform((value) => value === "" ? null : value)
|
|
7025
6983
|
});
|
|
7026
6984
|
|
|
7027
|
-
//
|
|
7028
|
-
var jsonSchemaSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine(
|
|
7029
|
-
(val)
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
{ message: "Must be a valid JSON Schema object (requires at least a 'type', '$ref', or composition keyword)" }
|
|
7034
|
-
);
|
|
6985
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/plugin.js
|
|
6986
|
+
var jsonSchemaSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine((val) => {
|
|
6987
|
+
if (Object.keys(val).length === 0)
|
|
6988
|
+
return true;
|
|
6989
|
+
return typeof val.type === "string" || val.$ref !== void 0 || val.oneOf !== void 0 || val.anyOf !== void 0 || val.allOf !== void 0;
|
|
6990
|
+
}, { message: "Must be a valid JSON Schema object (requires at least a 'type', '$ref', or composition keyword)" });
|
|
7035
6991
|
var CRON_FIELD_PATTERN = /^(\*(?:\/[0-9]+)?|[0-9]+(?:-[0-9]+)?(?:\/[0-9]+)?)(?:,(\*(?:\/[0-9]+)?|[0-9]+(?:-[0-9]+)?(?:\/[0-9]+)?))*$/;
|
|
7036
6992
|
function isValidCronExpression(expression) {
|
|
7037
6993
|
const trimmed = expression.trim();
|
|
7038
|
-
if (!trimmed)
|
|
6994
|
+
if (!trimmed)
|
|
6995
|
+
return false;
|
|
7039
6996
|
const fields = trimmed.split(/\s+/);
|
|
7040
|
-
if (fields.length !== 5)
|
|
6997
|
+
if (fields.length !== 5)
|
|
6998
|
+
return false;
|
|
7041
6999
|
return fields.every((f) => CRON_FIELD_PATTERN.test(f));
|
|
7042
7000
|
}
|
|
7043
7001
|
var pluginJobDeclarationSchema = external_exports.object({
|
|
7044
7002
|
jobKey: external_exports.string().min(1),
|
|
7045
7003
|
displayName: external_exports.string().min(1),
|
|
7046
7004
|
description: external_exports.string().optional(),
|
|
7047
|
-
schedule: external_exports.string().refine(
|
|
7048
|
-
(val) => isValidCronExpression(val),
|
|
7049
|
-
{ message: "schedule must be a valid 5-field cron expression (e.g. '*/15 * * * *')" }
|
|
7050
|
-
).optional()
|
|
7005
|
+
schedule: external_exports.string().refine((val) => isValidCronExpression(val), { message: "schedule must be a valid 5-field cron expression (e.g. '*/15 * * * *')" }).optional()
|
|
7051
7006
|
});
|
|
7052
7007
|
var pluginWebhookDeclarationSchema = external_exports.object({
|
|
7053
7008
|
endpointKey: external_exports.string().min(1),
|
|
@@ -7061,10 +7016,7 @@ var pluginToolDeclarationSchema = external_exports.object({
|
|
|
7061
7016
|
parametersSchema: jsonSchemaSchema
|
|
7062
7017
|
});
|
|
7063
7018
|
var pluginEnvironmentDriverDeclarationSchema = external_exports.object({
|
|
7064
|
-
driverKey: external_exports.string().min(1).regex(
|
|
7065
|
-
/^[a-z0-9][a-z0-9._-]*$/,
|
|
7066
|
-
"Environment driver key must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"
|
|
7067
|
-
),
|
|
7019
|
+
driverKey: external_exports.string().min(1).regex(/^[a-z0-9][a-z0-9._-]*$/, "Environment driver key must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"),
|
|
7068
7020
|
kind: external_exports.enum(["environment_driver", "sandbox_provider"]).optional(),
|
|
7069
7021
|
displayName: external_exports.string().min(1).max(100),
|
|
7070
7022
|
description: external_exports.string().max(500).optional(),
|
|
@@ -7139,10 +7091,7 @@ var pluginManagedRoutineDeclarationSchema = external_exports.object({
|
|
|
7139
7091
|
billingCode: external_exports.string().trim().max(200).nullable().optional()
|
|
7140
7092
|
}).optional()
|
|
7141
7093
|
});
|
|
7142
|
-
var pluginLocalFolderRelativePathSchema = external_exports.string().min(1).max(500).refine(
|
|
7143
|
-
(value) => !value.startsWith("/") && !value.includes("..") && !value.includes("\\") && !value.split("/").some((segment) => segment === "" || segment === "."),
|
|
7144
|
-
{ message: "local folder paths must be relative paths without traversal, empty segments, or backslashes" }
|
|
7145
|
-
);
|
|
7094
|
+
var pluginLocalFolderRelativePathSchema = external_exports.string().min(1).max(500).refine((value) => !value.startsWith("/") && !value.includes("..") && !value.includes("\\") && !value.split("/").some((segment) => segment === "" || segment === "."), { message: "local folder paths must be relative paths without traversal, empty segments, or backslashes" });
|
|
7146
7095
|
var pluginLocalFolderDeclarationSchema = external_exports.object({
|
|
7147
7096
|
folderKey: external_exports.string().min(1).max(100).regex(/^[a-z0-9][a-z0-9._:-]*$/, {
|
|
7148
7097
|
message: "folderKey must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, colons, underscores, or hyphens"
|
|
@@ -7154,10 +7103,7 @@ var pluginLocalFolderDeclarationSchema = external_exports.object({
|
|
|
7154
7103
|
requiredFiles: external_exports.array(pluginLocalFolderRelativePathSchema).optional()
|
|
7155
7104
|
});
|
|
7156
7105
|
var pluginManagedSkillFileDeclarationSchema = external_exports.object({
|
|
7157
|
-
path: pluginLocalFolderRelativePathSchema.refine(
|
|
7158
|
-
(value) => value.toLowerCase() !== "skill.md",
|
|
7159
|
-
{ message: "managed skill files cannot replace SKILL.md; use markdown for the main skill file" }
|
|
7160
|
-
),
|
|
7106
|
+
path: pluginLocalFolderRelativePathSchema.refine((value) => value.toLowerCase() !== "skill.md", { message: "managed skill files cannot replace SKILL.md; use markdown for the main skill file" }),
|
|
7161
7107
|
content: external_exports.string().max(2e5)
|
|
7162
7108
|
});
|
|
7163
7109
|
var pluginManagedSkillDeclarationSchema = external_exports.object({
|
|
@@ -7374,10 +7320,7 @@ var pluginDatabaseDeclarationSchema = external_exports.object({
|
|
|
7374
7320
|
namespaceSlug: external_exports.string().regex(/^[a-z0-9][a-z0-9_]*$/, {
|
|
7375
7321
|
message: "namespaceSlug must be lowercase letters, digits, or underscores and start with a letter or digit"
|
|
7376
7322
|
}).max(40).optional(),
|
|
7377
|
-
migrationsDir: external_exports.string().min(1).refine(
|
|
7378
|
-
(value) => !value.startsWith("/") && !value.includes("..") && !/[\\]/.test(value),
|
|
7379
|
-
{ message: "migrationsDir must be a relative package path without '..' or backslashes" }
|
|
7380
|
-
),
|
|
7323
|
+
migrationsDir: external_exports.string().min(1).refine((value) => !value.startsWith("/") && !value.includes("..") && !/[\\]/.test(value), { message: "migrationsDir must be a relative package path without '..' or backslashes" }),
|
|
7381
7324
|
coreReadTables: external_exports.array(external_exports.enum(PLUGIN_DATABASE_CORE_READ_TABLES)).optional()
|
|
7382
7325
|
});
|
|
7383
7326
|
var pluginApiRouteDeclarationSchema = external_exports.object({
|
|
@@ -7387,10 +7330,7 @@ var pluginApiRouteDeclarationSchema = external_exports.object({
|
|
|
7387
7330
|
method: external_exports.enum(PLUGIN_API_ROUTE_METHODS),
|
|
7388
7331
|
path: external_exports.string().min(1).regex(/^\/[a-zA-Z0-9:_./-]*$/, {
|
|
7389
7332
|
message: "path must start with / and contain only path-safe literal or :param segments"
|
|
7390
|
-
}).refine(
|
|
7391
|
-
(value) => !value.includes("..") && !value.includes("//") && value !== "/api" && !value.startsWith("/api/") && value !== "/plugins" && !value.startsWith("/plugins/"),
|
|
7392
|
-
{ message: "path must stay inside the plugin api namespace" }
|
|
7393
|
-
),
|
|
7333
|
+
}).refine((value) => !value.includes("..") && !value.includes("//") && value !== "/api" && !value.startsWith("/api/") && value !== "/plugins" && !value.startsWith("/plugins/"), { message: "path must stay inside the plugin api namespace" }),
|
|
7394
7334
|
auth: external_exports.enum(PLUGIN_API_ROUTE_AUTH_MODES),
|
|
7395
7335
|
capability: external_exports.literal("api.routes.register"),
|
|
7396
7336
|
checkoutPolicy: external_exports.enum(PLUGIN_API_ROUTE_CHECKOUT_POLICIES).optional(),
|
|
@@ -7401,27 +7341,15 @@ var pluginApiRouteDeclarationSchema = external_exports.object({
|
|
|
7401
7341
|
]).optional()
|
|
7402
7342
|
});
|
|
7403
7343
|
var pluginManifestV1Schema = external_exports.object({
|
|
7404
|
-
id: external_exports.string().min(1).regex(
|
|
7405
|
-
/^[a-z0-9][a-z0-9._-]*$/,
|
|
7406
|
-
"Plugin id must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"
|
|
7407
|
-
),
|
|
7344
|
+
id: external_exports.string().min(1).regex(/^[a-z0-9][a-z0-9._-]*$/, "Plugin id must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"),
|
|
7408
7345
|
apiVersion: external_exports.literal(1),
|
|
7409
|
-
version: external_exports.string().min(1).regex(
|
|
7410
|
-
/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/,
|
|
7411
|
-
"Version must follow semver (e.g. 1.0.0 or 1.0.0-beta.1)"
|
|
7412
|
-
),
|
|
7346
|
+
version: external_exports.string().min(1).regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "Version must follow semver (e.g. 1.0.0 or 1.0.0-beta.1)"),
|
|
7413
7347
|
displayName: external_exports.string().min(1).max(100),
|
|
7414
7348
|
description: external_exports.string().min(1).max(500),
|
|
7415
7349
|
author: external_exports.string().min(1).max(200),
|
|
7416
7350
|
categories: external_exports.array(external_exports.enum(PLUGIN_CATEGORIES)).min(1),
|
|
7417
|
-
minimumHostVersion: external_exports.string().regex(
|
|
7418
|
-
|
|
7419
|
-
"minimumHostVersion must follow semver (e.g. 1.0.0)"
|
|
7420
|
-
).optional(),
|
|
7421
|
-
minimumPaperclipVersion: external_exports.string().regex(
|
|
7422
|
-
/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/,
|
|
7423
|
-
"minimumPaperclipVersion must follow semver (e.g. 1.0.0)"
|
|
7424
|
-
).optional(),
|
|
7351
|
+
minimumHostVersion: external_exports.string().regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "minimumHostVersion must follow semver (e.g. 1.0.0)").optional(),
|
|
7352
|
+
minimumPaperclipVersion: external_exports.string().regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "minimumPaperclipVersion must follow semver (e.g. 1.0.0)").optional(),
|
|
7425
7353
|
capabilities: external_exports.array(external_exports.enum(PLUGIN_CAPABILITIES)).min(1),
|
|
7426
7354
|
entrypoints: external_exports.object({
|
|
7427
7355
|
worker: external_exports.string().min(1),
|
|
@@ -7762,7 +7690,7 @@ var listPluginStateSchema = external_exports.object({
|
|
|
7762
7690
|
namespace: external_exports.string().min(1).optional()
|
|
7763
7691
|
});
|
|
7764
7692
|
|
|
7765
|
-
//
|
|
7693
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/api.js
|
|
7766
7694
|
var API_PREFIX = "/api";
|
|
7767
7695
|
var API = {
|
|
7768
7696
|
health: `${API_PREFIX}/health`,
|
|
@@ -7789,7 +7717,7 @@ var API = {
|
|
|
7789
7717
|
admin: `${API_PREFIX}/admin`
|
|
7790
7718
|
};
|
|
7791
7719
|
|
|
7792
|
-
//
|
|
7720
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/routine-variables.js
|
|
7793
7721
|
var HUMAN_TIMESTAMP_FORMATTER = new Intl.DateTimeFormat("en-US", {
|
|
7794
7722
|
year: "numeric",
|
|
7795
7723
|
month: "long",
|
|
@@ -7801,7 +7729,7 @@ var HUMAN_TIMESTAMP_FORMATTER = new Intl.DateTimeFormat("en-US", {
|
|
|
7801
7729
|
timeZoneName: "short"
|
|
7802
7730
|
});
|
|
7803
7731
|
|
|
7804
|
-
//
|
|
7732
|
+
// node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/config-schema.js
|
|
7805
7733
|
var configMetaSchema = external_exports.object({
|
|
7806
7734
|
version: external_exports.literal(1),
|
|
7807
7735
|
updatedAt: external_exports.string(),
|
|
@@ -7957,14 +7885,14 @@ var paperclipConfigSchema = external_exports.object({
|
|
|
7957
7885
|
}
|
|
7958
7886
|
});
|
|
7959
7887
|
|
|
7960
|
-
// node_modules/.pnpm/@paperclipai+plugin-sdk@
|
|
7888
|
+
// node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
|
|
7961
7889
|
import fs from "node:fs";
|
|
7962
7890
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7963
7891
|
import path from "node:path";
|
|
7964
7892
|
import { createInterface } from "node:readline";
|
|
7965
7893
|
import { fileURLToPath } from "node:url";
|
|
7966
7894
|
|
|
7967
|
-
// node_modules/.pnpm/@paperclipai+plugin-sdk@
|
|
7895
|
+
// node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/protocol.js
|
|
7968
7896
|
var JSONRPC_VERSION = "2.0";
|
|
7969
7897
|
var JSONRPC_ERROR_CODES = {
|
|
7970
7898
|
/** Invalid JSON was received by the server. */
|
|
@@ -8096,7 +8024,7 @@ var JsonRpcCallError = class extends Error {
|
|
|
8096
8024
|
}
|
|
8097
8025
|
};
|
|
8098
8026
|
|
|
8099
|
-
// node_modules/.pnpm/@paperclipai+plugin-sdk@
|
|
8027
|
+
// node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
|
|
8100
8028
|
var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
8101
8029
|
function realpathOrResolvedPath(filePath) {
|
|
8102
8030
|
const resolvedPath = path.resolve(filePath);
|
|
@@ -9400,6 +9328,15 @@ function buildCeoAgentRuntimeConfig() {
|
|
|
9400
9328
|
}
|
|
9401
9329
|
};
|
|
9402
9330
|
}
|
|
9331
|
+
function buildWorkerAgentRuntimeConfig() {
|
|
9332
|
+
return {
|
|
9333
|
+
heartbeat: {
|
|
9334
|
+
enabled: false,
|
|
9335
|
+
intervalSec: DEFAULT_CEO_HEARTBEAT_INTERVAL_SEC,
|
|
9336
|
+
maxConcurrentRuns: DEFAULT_CEO_MAX_CONCURRENT_RUNS
|
|
9337
|
+
}
|
|
9338
|
+
};
|
|
9339
|
+
}
|
|
9403
9340
|
|
|
9404
9341
|
// src/logic/assemble.js
|
|
9405
9342
|
async function exists(p) {
|
|
@@ -9436,6 +9373,17 @@ async function readJson(p) {
|
|
|
9436
9373
|
function toPascalCase(name) {
|
|
9437
9374
|
return name.replace(/[^a-zA-Z0-9\s\-_]/g, "").split(/[\s\-_]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
9438
9375
|
}
|
|
9376
|
+
function normalizeExecutionBaseRef(ref, fallbackRef) {
|
|
9377
|
+
const candidates = [ref, fallbackRef].filter(
|
|
9378
|
+
(value) => typeof value === "string" && value.trim()
|
|
9379
|
+
);
|
|
9380
|
+
const selected = candidates.length > 0 ? String(candidates[0]).trim() : "";
|
|
9381
|
+
if (!selected) return "origin/main";
|
|
9382
|
+
if (selected.startsWith("origin/") || selected.startsWith("refs/")) {
|
|
9383
|
+
return selected;
|
|
9384
|
+
}
|
|
9385
|
+
return `origin/${selected}`;
|
|
9386
|
+
}
|
|
9439
9387
|
async function assembleCompany({
|
|
9440
9388
|
companyName,
|
|
9441
9389
|
companyDescription = "",
|
|
@@ -9444,6 +9392,11 @@ async function assembleCompany({
|
|
|
9444
9392
|
moduleNames,
|
|
9445
9393
|
extraRoleNames,
|
|
9446
9394
|
inlineGoals = [],
|
|
9395
|
+
userIssues = [],
|
|
9396
|
+
presetIssues = [],
|
|
9397
|
+
presetRoutines = [],
|
|
9398
|
+
presetLabels = [],
|
|
9399
|
+
enableIsolatedWorktrees = false,
|
|
9447
9400
|
outputDir,
|
|
9448
9401
|
templatesDir,
|
|
9449
9402
|
onProgress = () => {
|
|
@@ -9548,9 +9501,20 @@ async function assembleCompany({
|
|
|
9548
9501
|
}
|
|
9549
9502
|
onProgress(`+ agents/${roleName}/ (role)`);
|
|
9550
9503
|
}
|
|
9551
|
-
const initialIssues = [];
|
|
9552
|
-
const initialRoutines = [];
|
|
9504
|
+
const initialIssues = Array.isArray(presetIssues) ? presetIssues.map((issue) => ({ ...issue, source: issue.source || "preset" })) : [];
|
|
9505
|
+
const initialRoutines = Array.isArray(presetRoutines) ? presetRoutines.map((routine) => ({ ...routine, source: routine.source || "preset" })) : [];
|
|
9506
|
+
const explicitBootstrapLabels = Array.isArray(presetLabels) ? [...presetLabels] : [];
|
|
9553
9507
|
const roleAdapterOverrides = /* @__PURE__ */ new Map();
|
|
9508
|
+
const docRoleMap = /* @__PURE__ */ new Map();
|
|
9509
|
+
const addDocRoles = (docName, roles) => {
|
|
9510
|
+
const set = docRoleMap.get(docName) ?? /* @__PURE__ */ new Set();
|
|
9511
|
+
for (const r of roles) set.add(r);
|
|
9512
|
+
docRoleMap.set(docName, set);
|
|
9513
|
+
};
|
|
9514
|
+
const normalizeIssueTitle = (title) => String(title || "").trim().toLowerCase();
|
|
9515
|
+
const seenIssueTitles = new Set(
|
|
9516
|
+
initialIssues.map((issue) => normalizeIssueTitle(issue.title)).filter(Boolean)
|
|
9517
|
+
);
|
|
9554
9518
|
const resolveAssignee = (assignee, moduleJson) => {
|
|
9555
9519
|
if (assignee?.startsWith("capability:")) {
|
|
9556
9520
|
const capName = assignee.slice("capability:".length);
|
|
@@ -9561,6 +9525,55 @@ async function assembleCompany({
|
|
|
9561
9525
|
}
|
|
9562
9526
|
return assignee;
|
|
9563
9527
|
};
|
|
9528
|
+
const resolveReviewGate = (reviewGate) => {
|
|
9529
|
+
if (!reviewGate || typeof reviewGate !== "object") return null;
|
|
9530
|
+
const reviewersRaw = Array.isArray(reviewGate.reviewers) ? reviewGate.reviewers : [];
|
|
9531
|
+
const reviewers = [];
|
|
9532
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9533
|
+
for (const role of reviewersRaw) {
|
|
9534
|
+
if (typeof role !== "string") continue;
|
|
9535
|
+
if (!allRoles.has(role)) continue;
|
|
9536
|
+
if (seen.has(role)) continue;
|
|
9537
|
+
seen.add(role);
|
|
9538
|
+
reviewers.push(role);
|
|
9539
|
+
}
|
|
9540
|
+
const approver = typeof reviewGate.approver === "string" && allRoles.has(reviewGate.approver) ? reviewGate.approver : void 0;
|
|
9541
|
+
if (approver) {
|
|
9542
|
+
const idx = reviewers.indexOf(approver);
|
|
9543
|
+
if (idx !== -1) reviewers.splice(idx, 1);
|
|
9544
|
+
}
|
|
9545
|
+
if (reviewers.length === 0 && !approver) return null;
|
|
9546
|
+
return { reviewers, approver };
|
|
9547
|
+
};
|
|
9548
|
+
const renderReviewGate = (gate) => {
|
|
9549
|
+
const stages = [];
|
|
9550
|
+
for (const role of gate.reviewers) {
|
|
9551
|
+
stages.push(` - stage ${stages.length + 1} (review) \u2192 assign ${JSON.stringify(role)}`);
|
|
9552
|
+
}
|
|
9553
|
+
if (gate.approver) {
|
|
9554
|
+
stages.push(
|
|
9555
|
+
` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
|
|
9556
|
+
);
|
|
9557
|
+
}
|
|
9558
|
+
return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
|
|
9559
|
+
${stages.join("\n")}
|
|
9560
|
+
|
|
9561
|
+
`;
|
|
9562
|
+
};
|
|
9563
|
+
const isFoundationIssue = (issue) => issue?.bootstrapPhase === "foundation" || issue?.phase === "foundation" || issue?.bootstrapOrder === "foundation" || issue?.foundation === true;
|
|
9564
|
+
const resolvedUserIssues = [];
|
|
9565
|
+
for (const issue of Array.isArray(userIssues) ? userIssues : []) {
|
|
9566
|
+
if (!issue || !issue.title) continue;
|
|
9567
|
+
const titleKey = normalizeIssueTitle(issue.title);
|
|
9568
|
+
if (titleKey && seenIssueTitles.has(titleKey)) continue;
|
|
9569
|
+
if (titleKey) seenIssueTitles.add(titleKey);
|
|
9570
|
+
resolvedUserIssues.push({
|
|
9571
|
+
...issue,
|
|
9572
|
+
assignTo: resolveAssignee(issue.assignTo, null),
|
|
9573
|
+
source: "user"
|
|
9574
|
+
});
|
|
9575
|
+
}
|
|
9576
|
+
initialIssues.unshift(...resolvedUserIssues);
|
|
9564
9577
|
for (const moduleName of moduleNames) {
|
|
9565
9578
|
const moduleDir = join(templatesDir, "modules", moduleName);
|
|
9566
9579
|
if (!await exists(moduleDir)) {
|
|
@@ -9575,8 +9588,17 @@ async function assembleCompany({
|
|
|
9575
9588
|
continue;
|
|
9576
9589
|
}
|
|
9577
9590
|
}
|
|
9591
|
+
if (Array.isArray(moduleJson?.labels)) {
|
|
9592
|
+
explicitBootstrapLabels.push(...moduleJson.labels);
|
|
9593
|
+
}
|
|
9578
9594
|
const moduleIssues = moduleJson?.issues || moduleJson?.tasks || [];
|
|
9579
9595
|
for (const issue of moduleIssues) {
|
|
9596
|
+
const titleKey = normalizeIssueTitle(issue.title);
|
|
9597
|
+
if (titleKey && seenIssueTitles.has(titleKey)) {
|
|
9598
|
+
onProgress(`\u25CB issue "${issue.title}" (already provided by preset or earlier module)`);
|
|
9599
|
+
continue;
|
|
9600
|
+
}
|
|
9601
|
+
if (titleKey) seenIssueTitles.add(titleKey);
|
|
9580
9602
|
initialIssues.push({
|
|
9581
9603
|
...issue,
|
|
9582
9604
|
assignTo: resolveAssignee(issue.assignTo, moduleJson),
|
|
@@ -9595,8 +9617,21 @@ async function assembleCompany({
|
|
|
9595
9617
|
const docsDir = join(moduleDir, "docs");
|
|
9596
9618
|
if (await exists(docsDir)) {
|
|
9597
9619
|
await copyDir(docsDir, join(companyDir, "docs"));
|
|
9620
|
+
const moduleRoles = /* @__PURE__ */ new Set();
|
|
9621
|
+
for (const cap of moduleJson?.capabilities ?? []) {
|
|
9622
|
+
for (const owner of cap.owners ?? []) if (allRoles.has(owner)) moduleRoles.add(owner);
|
|
9623
|
+
}
|
|
9624
|
+
for (const issue of moduleIssues) {
|
|
9625
|
+
if (issue.assignTo && allRoles.has(issue.assignTo)) moduleRoles.add(issue.assignTo);
|
|
9626
|
+
}
|
|
9627
|
+
for (const routine of moduleJson?.routines ?? []) {
|
|
9628
|
+
if (routine.assignTo && allRoles.has(routine.assignTo)) moduleRoles.add(routine.assignTo);
|
|
9629
|
+
}
|
|
9630
|
+
for (const r of moduleJson?.activatesWithRoles ?? []) if (allRoles.has(r)) moduleRoles.add(r);
|
|
9631
|
+
const rolesForDocs = moduleRoles.size > 0 ? moduleRoles : /* @__PURE__ */ new Set(["*"]);
|
|
9598
9632
|
const docs = await readdir(docsDir);
|
|
9599
9633
|
for (const doc of docs) {
|
|
9634
|
+
addDocRoles(doc, rolesForDocs);
|
|
9600
9635
|
onProgress(`+ docs/${doc} (${moduleName})`);
|
|
9601
9636
|
}
|
|
9602
9637
|
}
|
|
@@ -9711,25 +9746,53 @@ Read and follow: \`$AGENT_HOME/skills/${skillFile}\`
|
|
|
9711
9746
|
}
|
|
9712
9747
|
const finalDocsDir = join(companyDir, "docs");
|
|
9713
9748
|
if (await exists(finalDocsDir)) {
|
|
9714
|
-
const docs = await readdir(finalDocsDir);
|
|
9749
|
+
const docs = (await readdir(finalDocsDir)).sort();
|
|
9715
9750
|
if (docs.length > 0) {
|
|
9716
9751
|
const agentsBaseDir = join(companyDir, "agents");
|
|
9717
9752
|
const agentRoles = await readdir(agentsBaseDir, { withFileTypes: true });
|
|
9718
9753
|
for (const role of agentRoles) {
|
|
9719
9754
|
if (!role.isDirectory()) continue;
|
|
9720
9755
|
const agentsMd = join(agentsBaseDir, role.name, "AGENTS.md");
|
|
9721
|
-
if (await exists(agentsMd))
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9756
|
+
if (!await exists(agentsMd)) continue;
|
|
9757
|
+
const relevantDocs = docs.filter((doc) => {
|
|
9758
|
+
if (role.name === "ceo") return true;
|
|
9759
|
+
const roles = docRoleMap.get(doc);
|
|
9760
|
+
return !roles || roles.has("*") || roles.has(role.name);
|
|
9761
|
+
});
|
|
9762
|
+
if (relevantDocs.length === 0) continue;
|
|
9763
|
+
let docRefs = "\n## Shared Documentation\n\nReference docs relevant to your role (paths are relative to your workspace home):\n";
|
|
9764
|
+
for (const doc of relevantDocs) {
|
|
9765
|
+
docRefs += `
|
|
9725
9766
|
Read: \`docs/${doc}\`
|
|
9726
9767
|
`;
|
|
9727
|
-
}
|
|
9728
|
-
await appendToFile(agentsMd, docRefs);
|
|
9729
9768
|
}
|
|
9769
|
+
await appendToFile(agentsMd, docRefs);
|
|
9730
9770
|
}
|
|
9731
9771
|
}
|
|
9732
9772
|
}
|
|
9773
|
+
const agentsBaseDirForSubst = join(companyDir, "agents");
|
|
9774
|
+
if (await exists(agentsBaseDirForSubst)) {
|
|
9775
|
+
const agentRoleDirs = await readdir(agentsBaseDirForSubst, { withFileTypes: true });
|
|
9776
|
+
for (const roleDir of agentRoleDirs) {
|
|
9777
|
+
if (!roleDir.isDirectory()) continue;
|
|
9778
|
+
const absoluteAgentHome = join(agentsBaseDirForSubst, roleDir.name);
|
|
9779
|
+
const subst = async (dir) => {
|
|
9780
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
9781
|
+
for (const entry of entries) {
|
|
9782
|
+
const full = join(dir, entry.name);
|
|
9783
|
+
if (entry.isDirectory()) {
|
|
9784
|
+
await subst(full);
|
|
9785
|
+
} else if (entry.name.endsWith(".md")) {
|
|
9786
|
+
const content = await readFile(full, "utf-8");
|
|
9787
|
+
if (content.includes("$AGENT_HOME")) {
|
|
9788
|
+
await writeFile(full, content.split("$AGENT_HOME").join(absoluteAgentHome));
|
|
9789
|
+
}
|
|
9790
|
+
}
|
|
9791
|
+
}
|
|
9792
|
+
};
|
|
9793
|
+
await subst(join(agentsBaseDirForSubst, roleDir.name));
|
|
9794
|
+
}
|
|
9795
|
+
}
|
|
9733
9796
|
const rolesList = [...allRoles];
|
|
9734
9797
|
const DEFAULT_BOOTSTRAP_LABELS = [
|
|
9735
9798
|
{ name: "feature", color: "#0075ca", useFor: "New user-facing capability" },
|
|
@@ -9824,16 +9887,23 @@ Read: \`docs/${doc}\`
|
|
|
9824
9887
|
}
|
|
9825
9888
|
return "feature";
|
|
9826
9889
|
};
|
|
9827
|
-
const buildBootstrapLabels = (issues) => {
|
|
9828
|
-
if (issues.length === 0) return [];
|
|
9890
|
+
const buildBootstrapLabels = (issues, explicitLabels = []) => {
|
|
9891
|
+
if (issues.length === 0 && explicitLabels.length === 0) return [];
|
|
9829
9892
|
const labelsByName2 = new Map(
|
|
9830
9893
|
DEFAULT_BOOTSTRAP_LABELS.map((label) => [label.name, { ...label }])
|
|
9831
9894
|
);
|
|
9895
|
+
for (const label of explicitLabels) {
|
|
9896
|
+
for (const parsedLabel of parseIssueLabels({ labels: [label] })) {
|
|
9897
|
+
labelsByName2.set(parsedLabel.name, parsedLabel);
|
|
9898
|
+
}
|
|
9899
|
+
}
|
|
9832
9900
|
for (const issue of issues) {
|
|
9833
|
-
const
|
|
9834
|
-
if (
|
|
9835
|
-
for (const label of
|
|
9836
|
-
labelsByName2.
|
|
9901
|
+
const explicitLabels2 = parseIssueLabels(issue);
|
|
9902
|
+
if (explicitLabels2.length > 0) {
|
|
9903
|
+
for (const label of explicitLabels2) {
|
|
9904
|
+
if (!labelsByName2.has(label.name)) {
|
|
9905
|
+
labelsByName2.set(label.name, label);
|
|
9906
|
+
}
|
|
9837
9907
|
}
|
|
9838
9908
|
continue;
|
|
9839
9909
|
}
|
|
@@ -9848,7 +9918,17 @@ Read: \`docs/${doc}\`
|
|
|
9848
9918
|
}
|
|
9849
9919
|
return [...labelsByName2.values()];
|
|
9850
9920
|
};
|
|
9851
|
-
const
|
|
9921
|
+
const orderInitialIssuesForBootstrap = () => {
|
|
9922
|
+
const originalOrder = new Map(initialIssues.map((issue, index) => [issue, index]));
|
|
9923
|
+
const rank = (issue) => {
|
|
9924
|
+
if (isFoundationIssue(issue)) return 0;
|
|
9925
|
+
if (issue?.source === "user") return 1;
|
|
9926
|
+
return 2;
|
|
9927
|
+
};
|
|
9928
|
+
initialIssues.sort((a, b) => rank(a) - rank(b) || originalOrder.get(a) - originalOrder.get(b));
|
|
9929
|
+
};
|
|
9930
|
+
orderInitialIssuesForBootstrap();
|
|
9931
|
+
const bootstrapLabels = buildBootstrapLabels(initialIssues, explicitBootstrapLabels);
|
|
9852
9932
|
const labelsByName = new Map(bootstrapLabels.map((label) => [label.name, label]));
|
|
9853
9933
|
const getIssueLabelNames = (issue) => {
|
|
9854
9934
|
const explicit = parseIssueLabels(issue).map((label) => label.name);
|
|
@@ -9860,7 +9940,11 @@ Read: \`docs/${doc}\`
|
|
|
9860
9940
|
if (lines.length === 0) return "";
|
|
9861
9941
|
return lines.map(([k, v]) => `- **${k}**: ${v}`).join("\n") + "\n\n";
|
|
9862
9942
|
};
|
|
9863
|
-
const
|
|
9943
|
+
const redactSecrets = (text) => String(text || "").replace(
|
|
9944
|
+
/\b(GH_TOKEN|GITHUB_TOKEN|API_KEY|SECRET|TOKEN|PASSWORD|PASS|PRIVATE_KEY)\s*=\s*[^\s`'"<>]+/gi,
|
|
9945
|
+
"$1=[REDACTED]"
|
|
9946
|
+
).replace(/\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g, "[REDACTED]").replace(/\b(sk-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,})\b/g, "[REDACTED]");
|
|
9947
|
+
const escapeBody = (text) => redactSecrets(text).split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
|
|
9864
9948
|
let bootstrap = `# Bootstrap: ${companyName}
|
|
9865
9949
|
|
|
9866
9950
|
`;
|
|
@@ -9875,7 +9959,7 @@ Read: \`docs/${doc}\`
|
|
|
9875
9959
|
bootstrap += `## Company
|
|
9876
9960
|
|
|
9877
9961
|
`;
|
|
9878
|
-
bootstrap += `${companyDescription}
|
|
9962
|
+
bootstrap += `${escapeBody(companyDescription)}
|
|
9879
9963
|
|
|
9880
9964
|
`;
|
|
9881
9965
|
}
|
|
@@ -9899,6 +9983,87 @@ Read: \`docs/${doc}\`
|
|
|
9899
9983
|
}
|
|
9900
9984
|
}
|
|
9901
9985
|
}
|
|
9986
|
+
const normalizeProjectWorkspace = (proj) => {
|
|
9987
|
+
const explicitWorkspace = proj && typeof proj.workspace === "object" && proj.workspace !== null ? proj.workspace : {};
|
|
9988
|
+
const sourceType = typeof explicitWorkspace.sourceType === "string" && explicitWorkspace.sourceType.trim() ? explicitWorkspace.sourceType.trim() : typeof proj?.workspaceSourceType === "string" && proj.workspaceSourceType.trim() ? proj.workspaceSourceType.trim() : typeof proj?.repoUrl === "string" && proj.repoUrl.trim() ? "git_repo" : "local_path";
|
|
9989
|
+
const localCwd = join(companyDir, "projects", toPascalCase(proj.name));
|
|
9990
|
+
const workspace = {
|
|
9991
|
+
sourceType,
|
|
9992
|
+
...explicitWorkspace,
|
|
9993
|
+
isPrimary: explicitWorkspace.isPrimary ?? proj?.isPrimary ?? true
|
|
9994
|
+
};
|
|
9995
|
+
if (sourceType === "git_repo") {
|
|
9996
|
+
const repoUrl = explicitWorkspace.repoUrl || proj?.repoUrl;
|
|
9997
|
+
const repoRef = explicitWorkspace.repoRef || proj?.repoRef || proj?.defaultRef;
|
|
9998
|
+
const defaultRef = explicitWorkspace.defaultRef || proj?.defaultRef || repoRef;
|
|
9999
|
+
if (repoUrl) workspace.repoUrl = repoUrl;
|
|
10000
|
+
if (repoRef) workspace.repoRef = repoRef;
|
|
10001
|
+
if (defaultRef) workspace.defaultRef = defaultRef;
|
|
10002
|
+
delete workspace.cwd;
|
|
10003
|
+
} else {
|
|
10004
|
+
if (!workspace.cwd) workspace.cwd = localCwd;
|
|
10005
|
+
const trimmedSetup = typeof workspace.setupCommand === "string" ? workspace.setupCommand.trim() : "";
|
|
10006
|
+
if (!trimmedSetup || trimmedSetup === "git init -b main" || trimmedSetup === "git init") {
|
|
10007
|
+
workspace.setupCommand = "git init -b main && git -c user.email=bootstrap@paperclip.local -c user.name='Paperclip Bootstrap' commit --allow-empty -m 'chore: initialize repository'";
|
|
10008
|
+
}
|
|
10009
|
+
}
|
|
10010
|
+
return workspace;
|
|
10011
|
+
};
|
|
10012
|
+
const renderWorkspaceMetaFields = (workspace) => {
|
|
10013
|
+
const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
|
|
10014
|
+
const keys = [
|
|
10015
|
+
...orderedKeys.filter((key) => workspace[key] !== void 0),
|
|
10016
|
+
...Object.keys(workspace).filter((key) => !orderedKeys.includes(key))
|
|
10017
|
+
];
|
|
10018
|
+
return keys.map((key) => [`workspace.${key}`, String(workspace[key])]);
|
|
10019
|
+
};
|
|
10020
|
+
const formatWorkspaceObject = (workspace) => {
|
|
10021
|
+
const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
|
|
10022
|
+
const entries = [
|
|
10023
|
+
...orderedKeys.filter((key) => workspace[key] !== void 0).map((key) => [key, workspace[key]]),
|
|
10024
|
+
...Object.entries(workspace).filter(([key]) => !orderedKeys.includes(key))
|
|
10025
|
+
];
|
|
10026
|
+
const fields = entries.filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([key, value]) => {
|
|
10027
|
+
if (typeof value === "boolean") return `${key}: ${value}`;
|
|
10028
|
+
return `${key}: "${String(value)}"`;
|
|
10029
|
+
});
|
|
10030
|
+
return `{ ${fields.join(", ")} }`;
|
|
10031
|
+
};
|
|
10032
|
+
const isFreshLocalRepo = (workspace) => workspace?.sourceType !== "git_repo";
|
|
10033
|
+
const effectiveExecutionPolicy = (proj, workspace) => {
|
|
10034
|
+
const policy = proj?.executionWorkspacePolicy;
|
|
10035
|
+
if (!policy || typeof policy !== "object") return null;
|
|
10036
|
+
if (policy.defaultMode === "isolated_workspace") {
|
|
10037
|
+
if (!enableIsolatedWorktrees || isFreshLocalRepo(workspace)) return null;
|
|
10038
|
+
const strategy = policy.workspaceStrategy;
|
|
10039
|
+
if (!strategy || typeof strategy !== "object") return policy;
|
|
10040
|
+
if (strategy.type !== "git_worktree") return policy;
|
|
10041
|
+
const workspaceStrategy = { ...strategy };
|
|
10042
|
+
const normalizedBaseRef = normalizeExecutionBaseRef(
|
|
10043
|
+
workspaceStrategy.baseRef,
|
|
10044
|
+
workspace?.repoRef || workspace?.defaultRef
|
|
10045
|
+
);
|
|
10046
|
+
if (normalizedBaseRef) {
|
|
10047
|
+
workspaceStrategy.baseRef = normalizedBaseRef;
|
|
10048
|
+
}
|
|
10049
|
+
return { ...policy, workspaceStrategy };
|
|
10050
|
+
}
|
|
10051
|
+
return policy;
|
|
10052
|
+
};
|
|
10053
|
+
const renderExecutionPolicyMetaFields = (proj, workspace) => {
|
|
10054
|
+
const policy = effectiveExecutionPolicy(proj, workspace);
|
|
10055
|
+
if (!policy) return [];
|
|
10056
|
+
const rows = [];
|
|
10057
|
+
if (policy.defaultMode) rows.push(["executionWorkspacePolicy.defaultMode", policy.defaultMode]);
|
|
10058
|
+
const strategy = policy.workspaceStrategy;
|
|
10059
|
+
if (strategy && typeof strategy === "object") {
|
|
10060
|
+
if (strategy.type)
|
|
10061
|
+
rows.push(["executionWorkspacePolicy.workspaceStrategy.type", strategy.type]);
|
|
10062
|
+
if (strategy.baseRef)
|
|
10063
|
+
rows.push(["executionWorkspacePolicy.workspaceStrategy.baseRef", strategy.baseRef]);
|
|
10064
|
+
}
|
|
10065
|
+
return rows;
|
|
10066
|
+
};
|
|
9902
10067
|
const mainProject = resolvedProjects[0];
|
|
9903
10068
|
const mainProjectName = mainProject?.name || companyName;
|
|
9904
10069
|
if (resolvedProjects.length > 0) {
|
|
@@ -9906,14 +10071,13 @@ Read: \`docs/${doc}\`
|
|
|
9906
10071
|
|
|
9907
10072
|
`;
|
|
9908
10073
|
for (const proj of resolvedProjects) {
|
|
9909
|
-
const
|
|
10074
|
+
const workspace = normalizeProjectWorkspace(proj);
|
|
9910
10075
|
bootstrap += `### ${proj.name}
|
|
9911
10076
|
|
|
9912
10077
|
`;
|
|
9913
10078
|
bootstrap += renderMeta([
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
["workspace.isPrimary", "true"],
|
|
10079
|
+
...renderWorkspaceMetaFields(workspace),
|
|
10080
|
+
...renderExecutionPolicyMetaFields(proj, workspace),
|
|
9917
10081
|
[
|
|
9918
10082
|
"goalIds",
|
|
9919
10083
|
proj.goals?.length > 0 ? proj.goals.map((g) => `"${g}"`).join(", ") : void 0
|
|
@@ -9947,6 +10111,9 @@ Read: \`docs/${doc}\`
|
|
|
9947
10111
|
}
|
|
9948
10112
|
bootstrap += `## Agents
|
|
9949
10113
|
|
|
10114
|
+
`;
|
|
10115
|
+
bootstrap += `> **The Company Wizard has already created all agents listed below**, each with its full instructions bundle. Do NOT create new agents. Match them by \`metadata.templateRole\` when assigning issues; only re-create one if it is genuinely missing.
|
|
10116
|
+
|
|
9950
10117
|
`;
|
|
9951
10118
|
for (const role of rolesList) {
|
|
9952
10119
|
const roleMeta = roleMetaByName.get(role) || {};
|
|
@@ -9998,6 +10165,8 @@ Read: \`docs/${doc}\`
|
|
|
9998
10165
|
const explicitProjectRef = typeof issue.projectIdRef === "string" ? issue.projectIdRef : typeof issue.projectName === "string" ? issue.projectName : typeof issue.project === "string" ? issue.project : void 0;
|
|
9999
10166
|
const resolvedProjectRef = explicitProjectRef || mainProjectName;
|
|
10000
10167
|
const issueLabelNames = getIssueLabelNames(issue);
|
|
10168
|
+
const goalRefRaw = issue.goalId || issue.goalIdRef || issue.goal || issue.goalTitle;
|
|
10169
|
+
const goalRef = typeof goalRefRaw === "string" && goalRefRaw.trim().length > 0 ? goalRefRaw.trim() : void 0;
|
|
10001
10170
|
for (const labelName of issueLabelNames) {
|
|
10002
10171
|
if (!labelsByName.has(labelName)) {
|
|
10003
10172
|
labelsByName.set(labelName, {
|
|
@@ -10016,8 +10185,13 @@ Read: \`docs/${doc}\`
|
|
|
10016
10185
|
["priority", issue.priority || "medium"],
|
|
10017
10186
|
["parentId", parentRef ? `\u2192 "${parentRef}"` : void 0],
|
|
10018
10187
|
["projectId", `\u2192 "${resolvedProjectRef}"`],
|
|
10188
|
+
["goalId", goalRef ? `\u2192 "${goalRef}"` : void 0],
|
|
10019
10189
|
["labelIds", `\u2192 [${issueLabelNames.map((name) => `"${name}"`).join(", ")}]`]
|
|
10020
10190
|
]);
|
|
10191
|
+
const issueReviewGate = resolveReviewGate(issue.reviewGate);
|
|
10192
|
+
if (issueReviewGate) {
|
|
10193
|
+
bootstrap += renderReviewGate(issueReviewGate);
|
|
10194
|
+
}
|
|
10021
10195
|
if (issue.description) {
|
|
10022
10196
|
bootstrap += `${escapeBody(issue.description)}
|
|
10023
10197
|
|
|
@@ -10036,12 +10210,20 @@ Read: \`docs/${doc}\`
|
|
|
10036
10210
|
bootstrap += `- Do not reopen \`done\` parent/subissues without an explicit reason in a comment.
|
|
10037
10211
|
`;
|
|
10038
10212
|
bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
|
|
10039
|
-
|
|
10213
|
+
`;
|
|
10214
|
+
if (moduleNames.includes("pr-review")) {
|
|
10215
|
+
bootstrap += `- Required PR reviews use the issue's \`executionPolicy\`: a \`review\` stage for the Code Reviewer (plus any relevant domain reviewer \u2014 QA/UI/UX/DevOps), then a final \`approval\` stage for the Product Owner. Resolve each reviewer/approver role to its agentId. Do not create separate child review issues and do not use @-mentions.
|
|
10216
|
+
`;
|
|
10217
|
+
}
|
|
10218
|
+
bootstrap += `
|
|
10040
10219
|
`;
|
|
10041
10220
|
}
|
|
10042
10221
|
if (initialRoutines.length > 0) {
|
|
10043
10222
|
bootstrap += `## Routines
|
|
10044
10223
|
|
|
10224
|
+
`;
|
|
10225
|
+
bootstrap += `> **The Company Wizard has already created the routines listed below** (with board authority, so each could be assigned to its owning agent). Do NOT recreate them. Note: an agent may only create routines assigned to itself, so never try to create another agent's routine.
|
|
10226
|
+
|
|
10045
10227
|
`;
|
|
10046
10228
|
for (const routine of initialRoutines) {
|
|
10047
10229
|
bootstrap += `### ${routine.title}
|
|
@@ -10080,23 +10262,25 @@ Read: \`docs/${doc}\`
|
|
|
10080
10262
|
`;
|
|
10081
10263
|
}
|
|
10082
10264
|
for (const proj of resolvedProjects) {
|
|
10083
|
-
const
|
|
10265
|
+
const workspace = normalizeProjectWorkspace(proj);
|
|
10084
10266
|
const goalLinks = proj.goals?.length > 0 ? `, goalIds \u2192 [${proj.goals.map((g) => `"${g}"`).join(", ")}]` : "";
|
|
10085
|
-
|
|
10267
|
+
const activePolicy = effectiveExecutionPolicy(proj, workspace);
|
|
10268
|
+
const policy = activePolicy?.defaultMode ? `, executionWorkspacePolicy.defaultMode: "${activePolicy.defaultMode}"` : "";
|
|
10269
|
+
bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: ${formatWorkspaceObject(workspace)}${policy}${goalLinks})
|
|
10086
10270
|
`;
|
|
10087
10271
|
}
|
|
10088
10272
|
if (bootstrapLabels.length > 0) {
|
|
10089
10273
|
bootstrap += `${stepN++}. **Create labels** \u2014 create each label exactly as listed in the Labels section before creating issues
|
|
10090
10274
|
`;
|
|
10091
10275
|
}
|
|
10092
|
-
bootstrap += `${stepN++}. **
|
|
10276
|
+
bootstrap += `${stepN++}. **Agents already created** \u2014 the Company Wizard provisioned every agent above with its full instructions bundle. Match them by metadata.templateRole when assigning issues; only hire via governance if one is genuinely missing
|
|
10093
10277
|
`;
|
|
10094
10278
|
if (initialIssues.length > 0) {
|
|
10095
10279
|
bootstrap += `${stepN++}. **Create issues** \u2014 every issue, including subtasks, must carry explicit projectId; subtasks also require parentId
|
|
10096
10280
|
`;
|
|
10097
10281
|
}
|
|
10098
10282
|
if (initialRoutines.length > 0) {
|
|
10099
|
-
bootstrap += `${stepN++}. **
|
|
10283
|
+
bootstrap += `${stepN++}. **Routines already created** \u2014 the Company Wizard provisioned the routines above (with their cron triggers) using board authority. Do not recreate them; an agent can only create routines assigned to itself
|
|
10100
10284
|
`;
|
|
10101
10285
|
}
|
|
10102
10286
|
bootstrap += `${stepN}. **Start CEO heartbeat** (one-time initial wakeup)
|
|
@@ -10220,6 +10404,12 @@ var PaperclipClient = class {
|
|
|
10220
10404
|
return false;
|
|
10221
10405
|
}
|
|
10222
10406
|
}
|
|
10407
|
+
/**
|
|
10408
|
+
* Read instance-wide experimental settings (including enableIsolatedWorkspaces).
|
|
10409
|
+
*/
|
|
10410
|
+
async getInstanceExperimentalSettings() {
|
|
10411
|
+
return this._fetch("/api/instance/settings/experimental");
|
|
10412
|
+
}
|
|
10223
10413
|
async createCompany({ name, description }) {
|
|
10224
10414
|
return this._fetch("/api/companies", {
|
|
10225
10415
|
method: "POST",
|
|
@@ -10406,6 +10596,12 @@ var PaperclipClient = class {
|
|
|
10406
10596
|
})
|
|
10407
10597
|
});
|
|
10408
10598
|
}
|
|
10599
|
+
async updateIssue(issueId, updates = {}) {
|
|
10600
|
+
return this._fetch(`/api/issues/${issueId}`, {
|
|
10601
|
+
method: "PATCH",
|
|
10602
|
+
body: JSON.stringify(updates || {})
|
|
10603
|
+
});
|
|
10604
|
+
}
|
|
10409
10605
|
async createRoutine(companyId, {
|
|
10410
10606
|
title,
|
|
10411
10607
|
description,
|
|
@@ -10504,14 +10700,16 @@ async function loadModules(templatesDir) {
|
|
|
10504
10700
|
for (const dir of dirs) {
|
|
10505
10701
|
if (!dir.isDirectory()) continue;
|
|
10506
10702
|
const moduleJson = await readJson2(join2(modulesDir, dir.name, "module.meta.json"));
|
|
10507
|
-
const
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10703
|
+
const mod = { name: dir.name, ...moduleJson || {} };
|
|
10704
|
+
if (!mod.description) {
|
|
10705
|
+
const readmePath = join2(modulesDir, dir.name, "README.md");
|
|
10706
|
+
if (await exists2(readmePath)) {
|
|
10707
|
+
const content = await readFile2(readmePath, "utf-8");
|
|
10708
|
+
const descLine = content.split("\n").find((l) => l.length > 0 && !l.startsWith("#"));
|
|
10709
|
+
mod.description = descLine?.trim() || "";
|
|
10710
|
+
}
|
|
10711
|
+
}
|
|
10712
|
+
if (mod.description === void 0) mod.description = "";
|
|
10515
10713
|
if (mod.tasks && !mod.issues) {
|
|
10516
10714
|
mod.issues = mod.tasks;
|
|
10517
10715
|
delete mod.tasks;
|
|
@@ -10586,6 +10784,39 @@ function collectGoals(preset, modules, selectedModules) {
|
|
|
10586
10784
|
}
|
|
10587
10785
|
return goals;
|
|
10588
10786
|
}
|
|
10787
|
+
function resolveEffectiveModules(preset, modules, selectedModules) {
|
|
10788
|
+
const known = new Set(modules.map((m) => m.name));
|
|
10789
|
+
const requiresByName = new Map(
|
|
10790
|
+
modules.map((m) => [m.name, Array.isArray(m.requires) ? m.requires : []])
|
|
10791
|
+
);
|
|
10792
|
+
const effective = /* @__PURE__ */ new Set();
|
|
10793
|
+
const queue = [];
|
|
10794
|
+
const add = (name) => {
|
|
10795
|
+
if (typeof name !== "string" || !known.has(name) || effective.has(name)) return;
|
|
10796
|
+
effective.add(name);
|
|
10797
|
+
queue.push(name);
|
|
10798
|
+
};
|
|
10799
|
+
for (const moduleName of Array.isArray(preset?.modules) ? preset.modules : []) {
|
|
10800
|
+
add(moduleName);
|
|
10801
|
+
}
|
|
10802
|
+
for (const moduleName of selectedModules ?? []) {
|
|
10803
|
+
add(moduleName);
|
|
10804
|
+
}
|
|
10805
|
+
while (queue.length > 0) {
|
|
10806
|
+
const moduleName = queue.shift();
|
|
10807
|
+
for (const dep of requiresByName.get(moduleName) ?? []) {
|
|
10808
|
+
add(dep);
|
|
10809
|
+
}
|
|
10810
|
+
}
|
|
10811
|
+
return [...effective];
|
|
10812
|
+
}
|
|
10813
|
+
function collectPresetBootstrapData(preset) {
|
|
10814
|
+
return {
|
|
10815
|
+
labels: Array.isArray(preset?.labels) ? preset.labels.map((label) => ({ ...label })) : [],
|
|
10816
|
+
issues: Array.isArray(preset?.issues) ? preset.issues.map((issue) => ({ ...issue })) : [],
|
|
10817
|
+
routines: Array.isArray(preset?.routines) ? preset.routines.map((routine) => ({ ...routine })) : []
|
|
10818
|
+
};
|
|
10819
|
+
}
|
|
10589
10820
|
|
|
10590
10821
|
// src/worker.ts
|
|
10591
10822
|
var __dirname = path2.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -10656,6 +10887,61 @@ async function ensureTemplatesDir(cfg) {
|
|
|
10656
10887
|
);
|
|
10657
10888
|
}
|
|
10658
10889
|
}
|
|
10890
|
+
function isLikelyAnthropicApiKey(value) {
|
|
10891
|
+
return value.startsWith("sk-ant-");
|
|
10892
|
+
}
|
|
10893
|
+
async function resolveAnthropicApiKey(ctx, configuredValue) {
|
|
10894
|
+
if (typeof configuredValue !== "string") return "";
|
|
10895
|
+
const value = configuredValue.trim();
|
|
10896
|
+
if (!value) return "";
|
|
10897
|
+
if (isLikelyAnthropicApiKey(value)) return value;
|
|
10898
|
+
try {
|
|
10899
|
+
const resolved = await ctx.secrets.resolve(value);
|
|
10900
|
+
return resolved.trim();
|
|
10901
|
+
} catch (err) {
|
|
10902
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
10903
|
+
throw new Error(
|
|
10904
|
+
`Anthropic API key could not be resolved. Re-save the plugin setting with a valid Anthropic API key (sk-ant-...). ${detail}`
|
|
10905
|
+
);
|
|
10906
|
+
}
|
|
10907
|
+
}
|
|
10908
|
+
async function callAnthropic(apiKey, system, messages) {
|
|
10909
|
+
try {
|
|
10910
|
+
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
10911
|
+
method: "POST",
|
|
10912
|
+
headers: {
|
|
10913
|
+
"Content-Type": "application/json",
|
|
10914
|
+
"x-api-key": apiKey,
|
|
10915
|
+
"anthropic-version": "2023-06-01"
|
|
10916
|
+
},
|
|
10917
|
+
body: JSON.stringify({
|
|
10918
|
+
model: "claude-opus-4-8",
|
|
10919
|
+
// High ceiling so the wizard's final config — which reproduces the user's
|
|
10920
|
+
// full spec in the first goal — is never truncated mid-JSON. This is only
|
|
10921
|
+
// an upper bound; generation time tracks the tokens actually produced.
|
|
10922
|
+
max_tokens: 32768,
|
|
10923
|
+
...system ? { system } : {},
|
|
10924
|
+
messages
|
|
10925
|
+
})
|
|
10926
|
+
});
|
|
10927
|
+
if (!response.ok) {
|
|
10928
|
+
const body = await response.text();
|
|
10929
|
+
return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
|
|
10930
|
+
}
|
|
10931
|
+
const data = await response.json();
|
|
10932
|
+
return { text: data.content?.[0]?.text || "" };
|
|
10933
|
+
} catch (err) {
|
|
10934
|
+
return { text: "", error: err instanceof Error ? err.message : String(err) };
|
|
10935
|
+
}
|
|
10936
|
+
}
|
|
10937
|
+
var aiChatJobs = /* @__PURE__ */ new Map();
|
|
10938
|
+
var AI_CHAT_JOB_TTL_MS = 10 * 60 * 1e3;
|
|
10939
|
+
function sweepAiChatJobs() {
|
|
10940
|
+
const now = Date.now();
|
|
10941
|
+
for (const [id, job] of aiChatJobs) {
|
|
10942
|
+
if (now - job.createdAt > AI_CHAT_JOB_TTL_MS) aiChatJobs.delete(id);
|
|
10943
|
+
}
|
|
10944
|
+
}
|
|
10659
10945
|
function loadJsonFiles(dir, filename) {
|
|
10660
10946
|
const items = [];
|
|
10661
10947
|
const errors = [];
|
|
@@ -10701,10 +10987,37 @@ function loadTemplates(templatesDir) {
|
|
|
10701
10987
|
loadErrors: [...presetLoad.errors, ...moduleLoad.errors, ...roleLoad.errors]
|
|
10702
10988
|
};
|
|
10703
10989
|
}
|
|
10990
|
+
function cfgBool(cfg, key) {
|
|
10991
|
+
const raw = cfg[key];
|
|
10992
|
+
return raw === true || typeof raw === "string" && raw.toLowerCase() === "true";
|
|
10993
|
+
}
|
|
10994
|
+
async function resolveEnableIsolatedWorkspacesFromInstance(cfg, log) {
|
|
10995
|
+
const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
|
|
10996
|
+
const paperclipEmail = cfg.paperclipEmail || "";
|
|
10997
|
+
const paperclipPassword = cfg.paperclipPassword || "";
|
|
10998
|
+
const instanceClient = new PaperclipClient(paperclipUrl, {
|
|
10999
|
+
email: paperclipEmail,
|
|
11000
|
+
password: paperclipPassword
|
|
11001
|
+
});
|
|
11002
|
+
try {
|
|
11003
|
+
await instanceClient.connect();
|
|
11004
|
+
const experimentalSettings = await instanceClient.getInstanceExperimentalSettings();
|
|
11005
|
+
return experimentalSettings?.enableIsolatedWorkspaces === true;
|
|
11006
|
+
} catch (err) {
|
|
11007
|
+
if (log) {
|
|
11008
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
11009
|
+
log(`\u26A0 Could not read instance experimental settings: ${detail}. Using fallback false.`);
|
|
11010
|
+
}
|
|
11011
|
+
return false;
|
|
11012
|
+
}
|
|
11013
|
+
}
|
|
10704
11014
|
function resolveCompaniesDir(cfg) {
|
|
10705
11015
|
if (cfg.companiesDir) return cfg.companiesDir;
|
|
10706
11016
|
return path2.join(os.homedir(), ".paperclip", "instances", "default", "companies");
|
|
10707
11017
|
}
|
|
11018
|
+
function formatRoleName(role) {
|
|
11019
|
+
return role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
11020
|
+
}
|
|
10708
11021
|
function collectInstructionFiles(rootDir) {
|
|
10709
11022
|
const out = {};
|
|
10710
11023
|
if (!fs2.existsSync(rootDir)) return out;
|
|
@@ -10815,20 +11128,28 @@ var plugin = definePlugin({
|
|
|
10815
11128
|
loadModules(templatesDir)
|
|
10816
11129
|
]);
|
|
10817
11130
|
const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
|
|
10818
|
-
const
|
|
11131
|
+
const effectiveModules = resolveEffectiveModules(
|
|
10819
11132
|
selectedPreset,
|
|
10820
11133
|
allModules,
|
|
10821
|
-
|
|
11134
|
+
params.selectedModules ?? []
|
|
10822
11135
|
);
|
|
11136
|
+
const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
|
|
11137
|
+
const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
|
|
10823
11138
|
const previewGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
|
|
10824
11139
|
const previewProjects = Array.isArray(params.projects) ? params.projects : [];
|
|
11140
|
+
const previewIssues = Array.isArray(params.issues) ? params.issues : [];
|
|
10825
11141
|
const result = await assembleCompany({
|
|
10826
11142
|
companyName,
|
|
10827
11143
|
userGoals: previewGoals,
|
|
10828
11144
|
userProjects: previewProjects,
|
|
10829
|
-
moduleNames:
|
|
11145
|
+
moduleNames: effectiveModules,
|
|
10830
11146
|
extraRoleNames: params.selectedRoles ?? [],
|
|
10831
11147
|
inlineGoals: goals,
|
|
11148
|
+
userIssues: previewIssues,
|
|
11149
|
+
presetIssues: presetBootstrapData.issues,
|
|
11150
|
+
presetRoutines: presetBootstrapData.routines,
|
|
11151
|
+
presetLabels: presetBootstrapData.labels,
|
|
11152
|
+
enableIsolatedWorktrees: await resolveEnableIsolatedWorkspacesFromInstance(cfg),
|
|
10832
11153
|
outputDir: tmpDir,
|
|
10833
11154
|
templatesDir
|
|
10834
11155
|
});
|
|
@@ -10863,34 +11184,42 @@ var plugin = definePlugin({
|
|
|
10863
11184
|
});
|
|
10864
11185
|
ctx.actions.register("ai-chat", async (params) => {
|
|
10865
11186
|
try {
|
|
11187
|
+
if (params.mode === "poll") {
|
|
11188
|
+
const jobId = typeof params.jobId === "string" ? params.jobId : "";
|
|
11189
|
+
const job = jobId ? aiChatJobs.get(jobId) : void 0;
|
|
11190
|
+
if (!job) {
|
|
11191
|
+
return {
|
|
11192
|
+
text: "",
|
|
11193
|
+
status: "error",
|
|
11194
|
+
error: "Unknown or expired generation job. Please retry."
|
|
11195
|
+
};
|
|
11196
|
+
}
|
|
11197
|
+
if (job.status === "pending") return { status: "pending" };
|
|
11198
|
+
aiChatJobs.delete(jobId);
|
|
11199
|
+
if (job.status === "error") return { text: "", status: "error", error: job.error };
|
|
11200
|
+
return { text: job.text, status: "done" };
|
|
11201
|
+
}
|
|
10866
11202
|
const cfg = await ctx.config.get() ?? {};
|
|
10867
|
-
const apiKey = cfg.anthropicApiKey
|
|
11203
|
+
const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
|
|
10868
11204
|
if (!apiKey) {
|
|
10869
11205
|
return {
|
|
10870
11206
|
text: "",
|
|
10871
11207
|
error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
|
|
10872
11208
|
};
|
|
10873
11209
|
}
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
|
|
10884
|
-
|
|
10885
|
-
messages: params.messages
|
|
10886
|
-
})
|
|
10887
|
-
});
|
|
10888
|
-
if (!response.ok) {
|
|
10889
|
-
const body = await response.text();
|
|
10890
|
-
return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
|
|
11210
|
+
if (params.mode === "start") {
|
|
11211
|
+
sweepAiChatJobs();
|
|
11212
|
+
const jobId = `aichat-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
11213
|
+
aiChatJobs.set(jobId, { status: "pending", createdAt: Date.now() });
|
|
11214
|
+
void callAnthropic(apiKey, params.system, params.messages).then((result) => {
|
|
11215
|
+
aiChatJobs.set(
|
|
11216
|
+
jobId,
|
|
11217
|
+
result.error ? { status: "error", error: result.error, createdAt: Date.now() } : { status: "done", text: result.text, createdAt: Date.now() }
|
|
11218
|
+
);
|
|
11219
|
+
});
|
|
11220
|
+
return { jobId, status: "pending" };
|
|
10891
11221
|
}
|
|
10892
|
-
|
|
10893
|
-
return { text: data.content?.[0]?.text || "" };
|
|
11222
|
+
return await callAnthropic(apiKey, params.system, params.messages);
|
|
10894
11223
|
} catch (err) {
|
|
10895
11224
|
return { text: "", error: err instanceof Error ? err.message : String(err) };
|
|
10896
11225
|
}
|
|
@@ -10898,7 +11227,8 @@ var plugin = definePlugin({
|
|
|
10898
11227
|
ctx.actions.register("check-ai-config", async () => {
|
|
10899
11228
|
try {
|
|
10900
11229
|
const cfg = await ctx.config.get() ?? {};
|
|
10901
|
-
|
|
11230
|
+
const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
|
|
11231
|
+
if (!apiKey) {
|
|
10902
11232
|
return {
|
|
10903
11233
|
ok: false,
|
|
10904
11234
|
error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
|
|
@@ -10920,8 +11250,11 @@ var plugin = definePlugin({
|
|
|
10920
11250
|
const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
|
|
10921
11251
|
const paperclipEmail = cfg.paperclipEmail || "";
|
|
10922
11252
|
const paperclipPassword = cfg.paperclipPassword || "";
|
|
10923
|
-
const
|
|
10924
|
-
|
|
11253
|
+
const disableBoardApprovalOnNewCompanies = cfgBool(
|
|
11254
|
+
cfg,
|
|
11255
|
+
"disableBoardApprovalOnNewCompanies"
|
|
11256
|
+
);
|
|
11257
|
+
const enableIsolatedWorktrees = await resolveEnableIsolatedWorkspacesFromInstance(cfg, log);
|
|
10925
11258
|
const companyName = typeof params.companyName === "string" ? params.companyName.trim() : "";
|
|
10926
11259
|
const existingCompanyId = typeof params.existingCompanyId === "string" && params.existingCompanyId.trim() ? params.existingCompanyId.trim() : "";
|
|
10927
11260
|
if (!companyName) return { error: "companyName is required", logs };
|
|
@@ -10935,25 +11268,33 @@ var plugin = definePlugin({
|
|
|
10935
11268
|
(Array.isArray(roleTemplates) ? roleTemplates : []).filter((role) => role && typeof role.name === "string").map((role) => [role.name, role])
|
|
10936
11269
|
);
|
|
10937
11270
|
const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
|
|
10938
|
-
const
|
|
11271
|
+
const effectiveModules = resolveEffectiveModules(
|
|
10939
11272
|
selectedPreset,
|
|
10940
11273
|
allModules,
|
|
10941
|
-
|
|
11274
|
+
params.selectedModules ?? []
|
|
10942
11275
|
);
|
|
11276
|
+
const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
|
|
11277
|
+
const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
|
|
10943
11278
|
const outputDir = resolveCompaniesDir(cfg);
|
|
10944
11279
|
fs2.mkdirSync(outputDir, { recursive: true });
|
|
10945
11280
|
log("Assembling company workspace...");
|
|
10946
11281
|
const companyDescription = typeof params.companyDescription === "string" ? params.companyDescription.trim() : "";
|
|
10947
11282
|
const userGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
|
|
10948
11283
|
const userProjects = Array.isArray(params.projects) ? params.projects : [];
|
|
11284
|
+
const userIssues = Array.isArray(params.issues) ? params.issues : [];
|
|
10949
11285
|
const assembleResult = await assembleCompany({
|
|
10950
11286
|
companyName,
|
|
10951
11287
|
companyDescription,
|
|
10952
11288
|
userGoals,
|
|
10953
11289
|
userProjects,
|
|
10954
|
-
moduleNames:
|
|
11290
|
+
moduleNames: effectiveModules,
|
|
10955
11291
|
extraRoleNames: params.selectedRoles ?? [],
|
|
10956
11292
|
inlineGoals: goals,
|
|
11293
|
+
userIssues,
|
|
11294
|
+
presetIssues: presetBootstrapData.issues,
|
|
11295
|
+
presetRoutines: presetBootstrapData.routines,
|
|
11296
|
+
presetLabels: presetBootstrapData.labels,
|
|
11297
|
+
enableIsolatedWorktrees,
|
|
10957
11298
|
outputDir,
|
|
10958
11299
|
templatesDir,
|
|
10959
11300
|
onProgress: log
|
|
@@ -11018,6 +11359,7 @@ var plugin = definePlugin({
|
|
|
11018
11359
|
}
|
|
11019
11360
|
}
|
|
11020
11361
|
let ceoAgentId;
|
|
11362
|
+
const teamAgentIds = {};
|
|
11021
11363
|
let bootstrapIssue;
|
|
11022
11364
|
try {
|
|
11023
11365
|
const userCeoAdapter = params.ceoAdapter || {};
|
|
@@ -11125,18 +11467,125 @@ var plugin = definePlugin({
|
|
|
11125
11467
|
fallbackEntryContent: ceoPromptTemplate,
|
|
11126
11468
|
log
|
|
11127
11469
|
});
|
|
11470
|
+
const teamRoles = [...assembleResult.allRoles ?? []].filter(
|
|
11471
|
+
(r) => r && r !== "ceo"
|
|
11472
|
+
);
|
|
11473
|
+
let existingByTemplateRole = /* @__PURE__ */ new Map();
|
|
11474
|
+
if (existingCompanyId && teamRoles.length > 0) {
|
|
11475
|
+
const agents = await client.listAgents(companyId);
|
|
11476
|
+
if (Array.isArray(agents)) {
|
|
11477
|
+
for (const a of agents) {
|
|
11478
|
+
const tr = a?.metadata?.templateRole;
|
|
11479
|
+
if (tr && a?.status !== "terminated" && a?.role !== "ceo") {
|
|
11480
|
+
existingByTemplateRole.set(tr, a);
|
|
11481
|
+
}
|
|
11482
|
+
}
|
|
11483
|
+
}
|
|
11484
|
+
}
|
|
11485
|
+
for (const roleName of teamRoles) {
|
|
11486
|
+
const roleTemplate = roleTemplateByName.get(roleName) || {};
|
|
11487
|
+
const paperclipRole = typeof roleTemplate.paperclipRole === "string" && roleTemplate.paperclipRole.trim() ? roleTemplate.paperclipRole.trim() : "general";
|
|
11488
|
+
const roleTitle = typeof roleTemplate.title === "string" && roleTemplate.title.trim() ? roleTemplate.title.trim() : formatRoleName(roleName);
|
|
11489
|
+
const roleDescription = typeof roleTemplate.description === "string" && roleTemplate.description.trim() ? roleTemplate.description.trim() : void 0;
|
|
11490
|
+
const roleMetadata = {
|
|
11491
|
+
templateRole: roleName,
|
|
11492
|
+
...roleDescription ? { description: roleDescription } : {}
|
|
11493
|
+
};
|
|
11494
|
+
const roleRuntimeConfig = buildWorkerAgentRuntimeConfig();
|
|
11495
|
+
const roleAdapterConfig = buildCeoAdapterConfig({
|
|
11496
|
+
userCeoAdapter,
|
|
11497
|
+
companyDir,
|
|
11498
|
+
roleAdapterOverrides: assembleResult.roleAdapterOverrides?.get(roleName) ?? {}
|
|
11499
|
+
});
|
|
11500
|
+
const roleInstructionsDir = path2.join(companyDir, "agents", roleName);
|
|
11501
|
+
const roleInstructionFiles = collectInstructionFiles(roleInstructionsDir);
|
|
11502
|
+
const roleInstructionsBundle = Object.keys(roleInstructionFiles).length > 0 ? { entryFile: "AGENTS.md", files: roleInstructionFiles } : void 0;
|
|
11503
|
+
const existingAgent = existingByTemplateRole.get(roleName);
|
|
11504
|
+
if (existingAgent?.id) {
|
|
11505
|
+
try {
|
|
11506
|
+
await client.updateAgent(existingAgent.id, {
|
|
11507
|
+
adapterType,
|
|
11508
|
+
adapterConfig: roleAdapterConfig,
|
|
11509
|
+
runtimeConfig: roleRuntimeConfig,
|
|
11510
|
+
metadata: { ...existingAgent.metadata ?? {}, ...roleMetadata },
|
|
11511
|
+
...!existingAgent.title && roleTitle ? { title: roleTitle } : {},
|
|
11512
|
+
...!existingAgent.capabilities && roleDescription ? { capabilities: roleDescription } : {}
|
|
11513
|
+
});
|
|
11514
|
+
log(`\u2713 Reusing ${roleTitle} (${existingAgent.id})`);
|
|
11515
|
+
} catch (err) {
|
|
11516
|
+
log(
|
|
11517
|
+
`\u26A0 Could not update ${roleTitle}: ${err instanceof Error ? err.message : String(err)}`
|
|
11518
|
+
);
|
|
11519
|
+
}
|
|
11520
|
+
teamAgentIds[roleName] = existingAgent.id;
|
|
11521
|
+
continue;
|
|
11522
|
+
}
|
|
11523
|
+
const roleAgent = await client.createAgent(companyId, {
|
|
11524
|
+
name: roleTitle,
|
|
11525
|
+
role: paperclipRole,
|
|
11526
|
+
title: roleTitle,
|
|
11527
|
+
...roleDescription ? { capabilities: roleDescription } : {},
|
|
11528
|
+
metadata: roleMetadata,
|
|
11529
|
+
reportsTo: ceoAgentId,
|
|
11530
|
+
adapterType,
|
|
11531
|
+
adapterConfig: roleAdapterConfig,
|
|
11532
|
+
instructionsBundle: roleInstructionsBundle,
|
|
11533
|
+
runtimeConfig: roleRuntimeConfig
|
|
11534
|
+
});
|
|
11535
|
+
teamAgentIds[roleName] = roleAgent.id;
|
|
11536
|
+
log(`\u2713 ${roleTitle} created (${roleAgent.id})`);
|
|
11537
|
+
if (roleAgent?._pendingApprovalId) {
|
|
11538
|
+
log(
|
|
11539
|
+
`\u26A0 ${roleTitle} hire pending approval: ${roleAgent._pendingApprovalId}. Approve it in the board.`
|
|
11540
|
+
);
|
|
11541
|
+
if (roleAgent._approvalAutoApproveError) {
|
|
11542
|
+
log(` Auto-approve failed: ${roleAgent._approvalAutoApproveError}`);
|
|
11543
|
+
}
|
|
11544
|
+
}
|
|
11545
|
+
}
|
|
11546
|
+
if (!existingCompanyId) {
|
|
11547
|
+
const routines = Array.isArray(assembleResult.initialRoutines) ? assembleResult.initialRoutines : [];
|
|
11548
|
+
for (const routine of routines) {
|
|
11549
|
+
const title = typeof routine.title === "string" && routine.title.trim() ? routine.title.trim() : typeof routine.name === "string" ? routine.name.trim() : "";
|
|
11550
|
+
if (!title) continue;
|
|
11551
|
+
const role = routine.assignTo;
|
|
11552
|
+
const assigneeAgentId = !role || role === "ceo" ? ceoAgentId : teamAgentIds[role] ?? ceoAgentId;
|
|
11553
|
+
try {
|
|
11554
|
+
const createdRoutine = await client.createRoutine(companyId, {
|
|
11555
|
+
title,
|
|
11556
|
+
description: routine.description,
|
|
11557
|
+
assigneeAgentId,
|
|
11558
|
+
priority: routine.priority || "medium",
|
|
11559
|
+
concurrencyPolicy: routine.concurrencyPolicy || "skip_if_active"
|
|
11560
|
+
});
|
|
11561
|
+
if (routine.schedule && createdRoutine?.id) {
|
|
11562
|
+
await client.createRoutineTrigger(createdRoutine.id, {
|
|
11563
|
+
kind: "schedule",
|
|
11564
|
+
cronExpression: routine.schedule,
|
|
11565
|
+
timezone: "UTC"
|
|
11566
|
+
});
|
|
11567
|
+
}
|
|
11568
|
+
log(
|
|
11569
|
+
`\u2713 Routine "${title}" created${routine.schedule ? ` (${routine.schedule})` : ""}`
|
|
11570
|
+
);
|
|
11571
|
+
} catch (err) {
|
|
11572
|
+
log(
|
|
11573
|
+
`\u26A0 Could not create routine "${title}": ${err instanceof Error ? err.message : String(err)}`
|
|
11574
|
+
);
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
}
|
|
11128
11578
|
const bootstrapDescription = fs2.readFileSync(
|
|
11129
11579
|
path2.join(companyDir, "BOOTSTRAP.md"),
|
|
11130
11580
|
"utf-8"
|
|
11131
11581
|
);
|
|
11132
11582
|
log("Creating bootstrap task for CEO...");
|
|
11133
|
-
const issue = await
|
|
11134
|
-
companyId,
|
|
11583
|
+
const issue = await client.createIssue(companyId, {
|
|
11135
11584
|
title: `Bootstrap ${company.name || companyName}`,
|
|
11136
11585
|
description: bootstrapDescription,
|
|
11137
|
-
assigneeAgentId: ceoAgentId
|
|
11586
|
+
assigneeAgentId: ceoAgentId,
|
|
11587
|
+
status: "todo"
|
|
11138
11588
|
});
|
|
11139
|
-
await ctx.issues.update(issue.id, { status: "todo" }, companyId);
|
|
11140
11589
|
bootstrapIssue = issue;
|
|
11141
11590
|
log(`\u2713 Bootstrap task created: ${bootstrapIssue.identifier || bootstrapIssue.id}`);
|
|
11142
11591
|
} catch (err) {
|
|
@@ -11166,7 +11615,7 @@ var plugin = definePlugin({
|
|
|
11166
11615
|
companyId,
|
|
11167
11616
|
issuePrefix: company.issuePrefix,
|
|
11168
11617
|
paperclipUrl,
|
|
11169
|
-
agentIds: { ceo: ceoAgentId },
|
|
11618
|
+
agentIds: { ceo: ceoAgentId, ...teamAgentIds },
|
|
11170
11619
|
issueIds: [bootstrapIssue.id],
|
|
11171
11620
|
logs
|
|
11172
11621
|
};
|