@starlein/paperclip-plugin-company-wizard 0.2.4 → 0.3.15
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 +60 -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 +1143 -559
- package/dist/ui/index.js.map +4 -4
- package/dist/worker.js +679 -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 +4 -1
- 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) {
|
|
@@ -9444,6 +9381,11 @@ async function assembleCompany({
|
|
|
9444
9381
|
moduleNames,
|
|
9445
9382
|
extraRoleNames,
|
|
9446
9383
|
inlineGoals = [],
|
|
9384
|
+
userIssues = [],
|
|
9385
|
+
presetIssues = [],
|
|
9386
|
+
presetRoutines = [],
|
|
9387
|
+
presetLabels = [],
|
|
9388
|
+
enableIsolatedWorktrees = false,
|
|
9447
9389
|
outputDir,
|
|
9448
9390
|
templatesDir,
|
|
9449
9391
|
onProgress = () => {
|
|
@@ -9548,9 +9490,20 @@ async function assembleCompany({
|
|
|
9548
9490
|
}
|
|
9549
9491
|
onProgress(`+ agents/${roleName}/ (role)`);
|
|
9550
9492
|
}
|
|
9551
|
-
const initialIssues = [];
|
|
9552
|
-
const initialRoutines = [];
|
|
9493
|
+
const initialIssues = Array.isArray(presetIssues) ? presetIssues.map((issue) => ({ ...issue, source: issue.source || "preset" })) : [];
|
|
9494
|
+
const initialRoutines = Array.isArray(presetRoutines) ? presetRoutines.map((routine) => ({ ...routine, source: routine.source || "preset" })) : [];
|
|
9495
|
+
const explicitBootstrapLabels = Array.isArray(presetLabels) ? [...presetLabels] : [];
|
|
9553
9496
|
const roleAdapterOverrides = /* @__PURE__ */ new Map();
|
|
9497
|
+
const docRoleMap = /* @__PURE__ */ new Map();
|
|
9498
|
+
const addDocRoles = (docName, roles) => {
|
|
9499
|
+
const set = docRoleMap.get(docName) ?? /* @__PURE__ */ new Set();
|
|
9500
|
+
for (const r of roles) set.add(r);
|
|
9501
|
+
docRoleMap.set(docName, set);
|
|
9502
|
+
};
|
|
9503
|
+
const normalizeIssueTitle = (title) => String(title || "").trim().toLowerCase();
|
|
9504
|
+
const seenIssueTitles = new Set(
|
|
9505
|
+
initialIssues.map((issue) => normalizeIssueTitle(issue.title)).filter(Boolean)
|
|
9506
|
+
);
|
|
9554
9507
|
const resolveAssignee = (assignee, moduleJson) => {
|
|
9555
9508
|
if (assignee?.startsWith("capability:")) {
|
|
9556
9509
|
const capName = assignee.slice("capability:".length);
|
|
@@ -9561,6 +9514,55 @@ async function assembleCompany({
|
|
|
9561
9514
|
}
|
|
9562
9515
|
return assignee;
|
|
9563
9516
|
};
|
|
9517
|
+
const resolveReviewGate = (reviewGate) => {
|
|
9518
|
+
if (!reviewGate || typeof reviewGate !== "object") return null;
|
|
9519
|
+
const reviewersRaw = Array.isArray(reviewGate.reviewers) ? reviewGate.reviewers : [];
|
|
9520
|
+
const reviewers = [];
|
|
9521
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9522
|
+
for (const role of reviewersRaw) {
|
|
9523
|
+
if (typeof role !== "string") continue;
|
|
9524
|
+
if (!allRoles.has(role)) continue;
|
|
9525
|
+
if (seen.has(role)) continue;
|
|
9526
|
+
seen.add(role);
|
|
9527
|
+
reviewers.push(role);
|
|
9528
|
+
}
|
|
9529
|
+
const approver = typeof reviewGate.approver === "string" && allRoles.has(reviewGate.approver) ? reviewGate.approver : void 0;
|
|
9530
|
+
if (approver) {
|
|
9531
|
+
const idx = reviewers.indexOf(approver);
|
|
9532
|
+
if (idx !== -1) reviewers.splice(idx, 1);
|
|
9533
|
+
}
|
|
9534
|
+
if (reviewers.length === 0 && !approver) return null;
|
|
9535
|
+
return { reviewers, approver };
|
|
9536
|
+
};
|
|
9537
|
+
const renderReviewGate = (gate) => {
|
|
9538
|
+
const stages = [];
|
|
9539
|
+
for (const role of gate.reviewers) {
|
|
9540
|
+
stages.push(` - stage ${stages.length + 1} (review) \u2192 assign ${JSON.stringify(role)}`);
|
|
9541
|
+
}
|
|
9542
|
+
if (gate.approver) {
|
|
9543
|
+
stages.push(
|
|
9544
|
+
` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
|
|
9545
|
+
);
|
|
9546
|
+
}
|
|
9547
|
+
return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
|
|
9548
|
+
${stages.join("\n")}
|
|
9549
|
+
|
|
9550
|
+
`;
|
|
9551
|
+
};
|
|
9552
|
+
const isFoundationIssue = (issue) => issue?.bootstrapPhase === "foundation" || issue?.phase === "foundation" || issue?.bootstrapOrder === "foundation" || issue?.foundation === true;
|
|
9553
|
+
const resolvedUserIssues = [];
|
|
9554
|
+
for (const issue of Array.isArray(userIssues) ? userIssues : []) {
|
|
9555
|
+
if (!issue || !issue.title) continue;
|
|
9556
|
+
const titleKey = normalizeIssueTitle(issue.title);
|
|
9557
|
+
if (titleKey && seenIssueTitles.has(titleKey)) continue;
|
|
9558
|
+
if (titleKey) seenIssueTitles.add(titleKey);
|
|
9559
|
+
resolvedUserIssues.push({
|
|
9560
|
+
...issue,
|
|
9561
|
+
assignTo: resolveAssignee(issue.assignTo, null),
|
|
9562
|
+
source: "user"
|
|
9563
|
+
});
|
|
9564
|
+
}
|
|
9565
|
+
initialIssues.unshift(...resolvedUserIssues);
|
|
9564
9566
|
for (const moduleName of moduleNames) {
|
|
9565
9567
|
const moduleDir = join(templatesDir, "modules", moduleName);
|
|
9566
9568
|
if (!await exists(moduleDir)) {
|
|
@@ -9575,8 +9577,17 @@ async function assembleCompany({
|
|
|
9575
9577
|
continue;
|
|
9576
9578
|
}
|
|
9577
9579
|
}
|
|
9580
|
+
if (Array.isArray(moduleJson?.labels)) {
|
|
9581
|
+
explicitBootstrapLabels.push(...moduleJson.labels);
|
|
9582
|
+
}
|
|
9578
9583
|
const moduleIssues = moduleJson?.issues || moduleJson?.tasks || [];
|
|
9579
9584
|
for (const issue of moduleIssues) {
|
|
9585
|
+
const titleKey = normalizeIssueTitle(issue.title);
|
|
9586
|
+
if (titleKey && seenIssueTitles.has(titleKey)) {
|
|
9587
|
+
onProgress(`\u25CB issue "${issue.title}" (already provided by preset or earlier module)`);
|
|
9588
|
+
continue;
|
|
9589
|
+
}
|
|
9590
|
+
if (titleKey) seenIssueTitles.add(titleKey);
|
|
9580
9591
|
initialIssues.push({
|
|
9581
9592
|
...issue,
|
|
9582
9593
|
assignTo: resolveAssignee(issue.assignTo, moduleJson),
|
|
@@ -9595,8 +9606,21 @@ async function assembleCompany({
|
|
|
9595
9606
|
const docsDir = join(moduleDir, "docs");
|
|
9596
9607
|
if (await exists(docsDir)) {
|
|
9597
9608
|
await copyDir(docsDir, join(companyDir, "docs"));
|
|
9609
|
+
const moduleRoles = /* @__PURE__ */ new Set();
|
|
9610
|
+
for (const cap of moduleJson?.capabilities ?? []) {
|
|
9611
|
+
for (const owner of cap.owners ?? []) if (allRoles.has(owner)) moduleRoles.add(owner);
|
|
9612
|
+
}
|
|
9613
|
+
for (const issue of moduleIssues) {
|
|
9614
|
+
if (issue.assignTo && allRoles.has(issue.assignTo)) moduleRoles.add(issue.assignTo);
|
|
9615
|
+
}
|
|
9616
|
+
for (const routine of moduleJson?.routines ?? []) {
|
|
9617
|
+
if (routine.assignTo && allRoles.has(routine.assignTo)) moduleRoles.add(routine.assignTo);
|
|
9618
|
+
}
|
|
9619
|
+
for (const r of moduleJson?.activatesWithRoles ?? []) if (allRoles.has(r)) moduleRoles.add(r);
|
|
9620
|
+
const rolesForDocs = moduleRoles.size > 0 ? moduleRoles : /* @__PURE__ */ new Set(["*"]);
|
|
9598
9621
|
const docs = await readdir(docsDir);
|
|
9599
9622
|
for (const doc of docs) {
|
|
9623
|
+
addDocRoles(doc, rolesForDocs);
|
|
9600
9624
|
onProgress(`+ docs/${doc} (${moduleName})`);
|
|
9601
9625
|
}
|
|
9602
9626
|
}
|
|
@@ -9711,25 +9735,53 @@ Read and follow: \`$AGENT_HOME/skills/${skillFile}\`
|
|
|
9711
9735
|
}
|
|
9712
9736
|
const finalDocsDir = join(companyDir, "docs");
|
|
9713
9737
|
if (await exists(finalDocsDir)) {
|
|
9714
|
-
const docs = await readdir(finalDocsDir);
|
|
9738
|
+
const docs = (await readdir(finalDocsDir)).sort();
|
|
9715
9739
|
if (docs.length > 0) {
|
|
9716
9740
|
const agentsBaseDir = join(companyDir, "agents");
|
|
9717
9741
|
const agentRoles = await readdir(agentsBaseDir, { withFileTypes: true });
|
|
9718
9742
|
for (const role of agentRoles) {
|
|
9719
9743
|
if (!role.isDirectory()) continue;
|
|
9720
9744
|
const agentsMd = join(agentsBaseDir, role.name, "AGENTS.md");
|
|
9721
|
-
if (await exists(agentsMd))
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9745
|
+
if (!await exists(agentsMd)) continue;
|
|
9746
|
+
const relevantDocs = docs.filter((doc) => {
|
|
9747
|
+
if (role.name === "ceo") return true;
|
|
9748
|
+
const roles = docRoleMap.get(doc);
|
|
9749
|
+
return !roles || roles.has("*") || roles.has(role.name);
|
|
9750
|
+
});
|
|
9751
|
+
if (relevantDocs.length === 0) continue;
|
|
9752
|
+
let docRefs = "\n## Shared Documentation\n\nReference docs relevant to your role (paths are relative to your workspace home):\n";
|
|
9753
|
+
for (const doc of relevantDocs) {
|
|
9754
|
+
docRefs += `
|
|
9725
9755
|
Read: \`docs/${doc}\`
|
|
9726
9756
|
`;
|
|
9727
|
-
}
|
|
9728
|
-
await appendToFile(agentsMd, docRefs);
|
|
9729
9757
|
}
|
|
9758
|
+
await appendToFile(agentsMd, docRefs);
|
|
9730
9759
|
}
|
|
9731
9760
|
}
|
|
9732
9761
|
}
|
|
9762
|
+
const agentsBaseDirForSubst = join(companyDir, "agents");
|
|
9763
|
+
if (await exists(agentsBaseDirForSubst)) {
|
|
9764
|
+
const agentRoleDirs = await readdir(agentsBaseDirForSubst, { withFileTypes: true });
|
|
9765
|
+
for (const roleDir of agentRoleDirs) {
|
|
9766
|
+
if (!roleDir.isDirectory()) continue;
|
|
9767
|
+
const absoluteAgentHome = join(agentsBaseDirForSubst, roleDir.name);
|
|
9768
|
+
const subst = async (dir) => {
|
|
9769
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
9770
|
+
for (const entry of entries) {
|
|
9771
|
+
const full = join(dir, entry.name);
|
|
9772
|
+
if (entry.isDirectory()) {
|
|
9773
|
+
await subst(full);
|
|
9774
|
+
} else if (entry.name.endsWith(".md")) {
|
|
9775
|
+
const content = await readFile(full, "utf-8");
|
|
9776
|
+
if (content.includes("$AGENT_HOME")) {
|
|
9777
|
+
await writeFile(full, content.split("$AGENT_HOME").join(absoluteAgentHome));
|
|
9778
|
+
}
|
|
9779
|
+
}
|
|
9780
|
+
}
|
|
9781
|
+
};
|
|
9782
|
+
await subst(join(agentsBaseDirForSubst, roleDir.name));
|
|
9783
|
+
}
|
|
9784
|
+
}
|
|
9733
9785
|
const rolesList = [...allRoles];
|
|
9734
9786
|
const DEFAULT_BOOTSTRAP_LABELS = [
|
|
9735
9787
|
{ name: "feature", color: "#0075ca", useFor: "New user-facing capability" },
|
|
@@ -9824,16 +9876,23 @@ Read: \`docs/${doc}\`
|
|
|
9824
9876
|
}
|
|
9825
9877
|
return "feature";
|
|
9826
9878
|
};
|
|
9827
|
-
const buildBootstrapLabels = (issues) => {
|
|
9828
|
-
if (issues.length === 0) return [];
|
|
9879
|
+
const buildBootstrapLabels = (issues, explicitLabels = []) => {
|
|
9880
|
+
if (issues.length === 0 && explicitLabels.length === 0) return [];
|
|
9829
9881
|
const labelsByName2 = new Map(
|
|
9830
9882
|
DEFAULT_BOOTSTRAP_LABELS.map((label) => [label.name, { ...label }])
|
|
9831
9883
|
);
|
|
9884
|
+
for (const label of explicitLabels) {
|
|
9885
|
+
for (const parsedLabel of parseIssueLabels({ labels: [label] })) {
|
|
9886
|
+
labelsByName2.set(parsedLabel.name, parsedLabel);
|
|
9887
|
+
}
|
|
9888
|
+
}
|
|
9832
9889
|
for (const issue of issues) {
|
|
9833
|
-
const
|
|
9834
|
-
if (
|
|
9835
|
-
for (const label of
|
|
9836
|
-
labelsByName2.
|
|
9890
|
+
const explicitLabels2 = parseIssueLabels(issue);
|
|
9891
|
+
if (explicitLabels2.length > 0) {
|
|
9892
|
+
for (const label of explicitLabels2) {
|
|
9893
|
+
if (!labelsByName2.has(label.name)) {
|
|
9894
|
+
labelsByName2.set(label.name, label);
|
|
9895
|
+
}
|
|
9837
9896
|
}
|
|
9838
9897
|
continue;
|
|
9839
9898
|
}
|
|
@@ -9848,7 +9907,17 @@ Read: \`docs/${doc}\`
|
|
|
9848
9907
|
}
|
|
9849
9908
|
return [...labelsByName2.values()];
|
|
9850
9909
|
};
|
|
9851
|
-
const
|
|
9910
|
+
const orderInitialIssuesForBootstrap = () => {
|
|
9911
|
+
const originalOrder = new Map(initialIssues.map((issue, index) => [issue, index]));
|
|
9912
|
+
const rank = (issue) => {
|
|
9913
|
+
if (isFoundationIssue(issue)) return 0;
|
|
9914
|
+
if (issue?.source === "user") return 1;
|
|
9915
|
+
return 2;
|
|
9916
|
+
};
|
|
9917
|
+
initialIssues.sort((a, b) => rank(a) - rank(b) || originalOrder.get(a) - originalOrder.get(b));
|
|
9918
|
+
};
|
|
9919
|
+
orderInitialIssuesForBootstrap();
|
|
9920
|
+
const bootstrapLabels = buildBootstrapLabels(initialIssues, explicitBootstrapLabels);
|
|
9852
9921
|
const labelsByName = new Map(bootstrapLabels.map((label) => [label.name, label]));
|
|
9853
9922
|
const getIssueLabelNames = (issue) => {
|
|
9854
9923
|
const explicit = parseIssueLabels(issue).map((label) => label.name);
|
|
@@ -9860,7 +9929,11 @@ Read: \`docs/${doc}\`
|
|
|
9860
9929
|
if (lines.length === 0) return "";
|
|
9861
9930
|
return lines.map(([k, v]) => `- **${k}**: ${v}`).join("\n") + "\n\n";
|
|
9862
9931
|
};
|
|
9863
|
-
const
|
|
9932
|
+
const redactSecrets = (text) => String(text || "").replace(
|
|
9933
|
+
/\b(GH_TOKEN|GITHUB_TOKEN|API_KEY|SECRET|TOKEN|PASSWORD|PASS|PRIVATE_KEY)\s*=\s*[^\s`'"<>]+/gi,
|
|
9934
|
+
"$1=[REDACTED]"
|
|
9935
|
+
).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]");
|
|
9936
|
+
const escapeBody = (text) => redactSecrets(text).split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
|
|
9864
9937
|
let bootstrap = `# Bootstrap: ${companyName}
|
|
9865
9938
|
|
|
9866
9939
|
`;
|
|
@@ -9875,7 +9948,7 @@ Read: \`docs/${doc}\`
|
|
|
9875
9948
|
bootstrap += `## Company
|
|
9876
9949
|
|
|
9877
9950
|
`;
|
|
9878
|
-
bootstrap += `${companyDescription}
|
|
9951
|
+
bootstrap += `${escapeBody(companyDescription)}
|
|
9879
9952
|
|
|
9880
9953
|
`;
|
|
9881
9954
|
}
|
|
@@ -9899,6 +9972,75 @@ Read: \`docs/${doc}\`
|
|
|
9899
9972
|
}
|
|
9900
9973
|
}
|
|
9901
9974
|
}
|
|
9975
|
+
const normalizeProjectWorkspace = (proj) => {
|
|
9976
|
+
const explicitWorkspace = proj && typeof proj.workspace === "object" && proj.workspace !== null ? proj.workspace : {};
|
|
9977
|
+
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";
|
|
9978
|
+
const localCwd = join(companyDir, "projects", toPascalCase(proj.name));
|
|
9979
|
+
const workspace = {
|
|
9980
|
+
sourceType,
|
|
9981
|
+
...explicitWorkspace,
|
|
9982
|
+
isPrimary: explicitWorkspace.isPrimary ?? proj?.isPrimary ?? true
|
|
9983
|
+
};
|
|
9984
|
+
if (sourceType === "git_repo") {
|
|
9985
|
+
const repoUrl = explicitWorkspace.repoUrl || proj?.repoUrl;
|
|
9986
|
+
const repoRef = explicitWorkspace.repoRef || proj?.repoRef || proj?.defaultRef;
|
|
9987
|
+
const defaultRef = explicitWorkspace.defaultRef || proj?.defaultRef || repoRef;
|
|
9988
|
+
if (repoUrl) workspace.repoUrl = repoUrl;
|
|
9989
|
+
if (repoRef) workspace.repoRef = repoRef;
|
|
9990
|
+
if (defaultRef) workspace.defaultRef = defaultRef;
|
|
9991
|
+
delete workspace.cwd;
|
|
9992
|
+
} else {
|
|
9993
|
+
if (!workspace.cwd) workspace.cwd = localCwd;
|
|
9994
|
+
const trimmedSetup = typeof workspace.setupCommand === "string" ? workspace.setupCommand.trim() : "";
|
|
9995
|
+
if (!trimmedSetup || trimmedSetup === "git init -b main" || trimmedSetup === "git init") {
|
|
9996
|
+
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'";
|
|
9997
|
+
}
|
|
9998
|
+
}
|
|
9999
|
+
return workspace;
|
|
10000
|
+
};
|
|
10001
|
+
const renderWorkspaceMetaFields = (workspace) => {
|
|
10002
|
+
const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
|
|
10003
|
+
const keys = [
|
|
10004
|
+
...orderedKeys.filter((key) => workspace[key] !== void 0),
|
|
10005
|
+
...Object.keys(workspace).filter((key) => !orderedKeys.includes(key))
|
|
10006
|
+
];
|
|
10007
|
+
return keys.map((key) => [`workspace.${key}`, String(workspace[key])]);
|
|
10008
|
+
};
|
|
10009
|
+
const formatWorkspaceObject = (workspace) => {
|
|
10010
|
+
const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
|
|
10011
|
+
const entries = [
|
|
10012
|
+
...orderedKeys.filter((key) => workspace[key] !== void 0).map((key) => [key, workspace[key]]),
|
|
10013
|
+
...Object.entries(workspace).filter(([key]) => !orderedKeys.includes(key))
|
|
10014
|
+
];
|
|
10015
|
+
const fields = entries.filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([key, value]) => {
|
|
10016
|
+
if (typeof value === "boolean") return `${key}: ${value}`;
|
|
10017
|
+
return `${key}: "${String(value)}"`;
|
|
10018
|
+
});
|
|
10019
|
+
return `{ ${fields.join(", ")} }`;
|
|
10020
|
+
};
|
|
10021
|
+
const isFreshLocalRepo = (workspace) => workspace?.sourceType !== "git_repo";
|
|
10022
|
+
const effectiveExecutionPolicy = (proj, workspace) => {
|
|
10023
|
+
const policy = proj?.executionWorkspacePolicy;
|
|
10024
|
+
if (!policy || typeof policy !== "object") return null;
|
|
10025
|
+
if (policy.defaultMode === "isolated_workspace") {
|
|
10026
|
+
if (!enableIsolatedWorktrees || isFreshLocalRepo(workspace)) return null;
|
|
10027
|
+
}
|
|
10028
|
+
return policy;
|
|
10029
|
+
};
|
|
10030
|
+
const renderExecutionPolicyMetaFields = (proj, workspace) => {
|
|
10031
|
+
const policy = effectiveExecutionPolicy(proj, workspace);
|
|
10032
|
+
if (!policy) return [];
|
|
10033
|
+
const rows = [];
|
|
10034
|
+
if (policy.defaultMode) rows.push(["executionWorkspacePolicy.defaultMode", policy.defaultMode]);
|
|
10035
|
+
const strategy = policy.workspaceStrategy;
|
|
10036
|
+
if (strategy && typeof strategy === "object") {
|
|
10037
|
+
if (strategy.type)
|
|
10038
|
+
rows.push(["executionWorkspacePolicy.workspaceStrategy.type", strategy.type]);
|
|
10039
|
+
if (strategy.baseRef)
|
|
10040
|
+
rows.push(["executionWorkspacePolicy.workspaceStrategy.baseRef", strategy.baseRef]);
|
|
10041
|
+
}
|
|
10042
|
+
return rows;
|
|
10043
|
+
};
|
|
9902
10044
|
const mainProject = resolvedProjects[0];
|
|
9903
10045
|
const mainProjectName = mainProject?.name || companyName;
|
|
9904
10046
|
if (resolvedProjects.length > 0) {
|
|
@@ -9906,14 +10048,13 @@ Read: \`docs/${doc}\`
|
|
|
9906
10048
|
|
|
9907
10049
|
`;
|
|
9908
10050
|
for (const proj of resolvedProjects) {
|
|
9909
|
-
const
|
|
10051
|
+
const workspace = normalizeProjectWorkspace(proj);
|
|
9910
10052
|
bootstrap += `### ${proj.name}
|
|
9911
10053
|
|
|
9912
10054
|
`;
|
|
9913
10055
|
bootstrap += renderMeta([
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
["workspace.isPrimary", "true"],
|
|
10056
|
+
...renderWorkspaceMetaFields(workspace),
|
|
10057
|
+
...renderExecutionPolicyMetaFields(proj, workspace),
|
|
9917
10058
|
[
|
|
9918
10059
|
"goalIds",
|
|
9919
10060
|
proj.goals?.length > 0 ? proj.goals.map((g) => `"${g}"`).join(", ") : void 0
|
|
@@ -9947,6 +10088,9 @@ Read: \`docs/${doc}\`
|
|
|
9947
10088
|
}
|
|
9948
10089
|
bootstrap += `## Agents
|
|
9949
10090
|
|
|
10091
|
+
`;
|
|
10092
|
+
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.
|
|
10093
|
+
|
|
9950
10094
|
`;
|
|
9951
10095
|
for (const role of rolesList) {
|
|
9952
10096
|
const roleMeta = roleMetaByName.get(role) || {};
|
|
@@ -9998,6 +10142,8 @@ Read: \`docs/${doc}\`
|
|
|
9998
10142
|
const explicitProjectRef = typeof issue.projectIdRef === "string" ? issue.projectIdRef : typeof issue.projectName === "string" ? issue.projectName : typeof issue.project === "string" ? issue.project : void 0;
|
|
9999
10143
|
const resolvedProjectRef = explicitProjectRef || mainProjectName;
|
|
10000
10144
|
const issueLabelNames = getIssueLabelNames(issue);
|
|
10145
|
+
const goalRefRaw = issue.goalId || issue.goalIdRef || issue.goal || issue.goalTitle;
|
|
10146
|
+
const goalRef = typeof goalRefRaw === "string" && goalRefRaw.trim().length > 0 ? goalRefRaw.trim() : void 0;
|
|
10001
10147
|
for (const labelName of issueLabelNames) {
|
|
10002
10148
|
if (!labelsByName.has(labelName)) {
|
|
10003
10149
|
labelsByName.set(labelName, {
|
|
@@ -10016,8 +10162,13 @@ Read: \`docs/${doc}\`
|
|
|
10016
10162
|
["priority", issue.priority || "medium"],
|
|
10017
10163
|
["parentId", parentRef ? `\u2192 "${parentRef}"` : void 0],
|
|
10018
10164
|
["projectId", `\u2192 "${resolvedProjectRef}"`],
|
|
10165
|
+
["goalId", goalRef ? `\u2192 "${goalRef}"` : void 0],
|
|
10019
10166
|
["labelIds", `\u2192 [${issueLabelNames.map((name) => `"${name}"`).join(", ")}]`]
|
|
10020
10167
|
]);
|
|
10168
|
+
const issueReviewGate = resolveReviewGate(issue.reviewGate);
|
|
10169
|
+
if (issueReviewGate) {
|
|
10170
|
+
bootstrap += renderReviewGate(issueReviewGate);
|
|
10171
|
+
}
|
|
10021
10172
|
if (issue.description) {
|
|
10022
10173
|
bootstrap += `${escapeBody(issue.description)}
|
|
10023
10174
|
|
|
@@ -10036,12 +10187,20 @@ Read: \`docs/${doc}\`
|
|
|
10036
10187
|
bootstrap += `- Do not reopen \`done\` parent/subissues without an explicit reason in a comment.
|
|
10037
10188
|
`;
|
|
10038
10189
|
bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
|
|
10039
|
-
|
|
10190
|
+
`;
|
|
10191
|
+
if (moduleNames.includes("pr-review")) {
|
|
10192
|
+
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.
|
|
10193
|
+
`;
|
|
10194
|
+
}
|
|
10195
|
+
bootstrap += `
|
|
10040
10196
|
`;
|
|
10041
10197
|
}
|
|
10042
10198
|
if (initialRoutines.length > 0) {
|
|
10043
10199
|
bootstrap += `## Routines
|
|
10044
10200
|
|
|
10201
|
+
`;
|
|
10202
|
+
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.
|
|
10203
|
+
|
|
10045
10204
|
`;
|
|
10046
10205
|
for (const routine of initialRoutines) {
|
|
10047
10206
|
bootstrap += `### ${routine.title}
|
|
@@ -10080,23 +10239,25 @@ Read: \`docs/${doc}\`
|
|
|
10080
10239
|
`;
|
|
10081
10240
|
}
|
|
10082
10241
|
for (const proj of resolvedProjects) {
|
|
10083
|
-
const
|
|
10242
|
+
const workspace = normalizeProjectWorkspace(proj);
|
|
10084
10243
|
const goalLinks = proj.goals?.length > 0 ? `, goalIds \u2192 [${proj.goals.map((g) => `"${g}"`).join(", ")}]` : "";
|
|
10085
|
-
|
|
10244
|
+
const activePolicy = effectiveExecutionPolicy(proj, workspace);
|
|
10245
|
+
const policy = activePolicy?.defaultMode ? `, executionWorkspacePolicy.defaultMode: "${activePolicy.defaultMode}"` : "";
|
|
10246
|
+
bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: ${formatWorkspaceObject(workspace)}${policy}${goalLinks})
|
|
10086
10247
|
`;
|
|
10087
10248
|
}
|
|
10088
10249
|
if (bootstrapLabels.length > 0) {
|
|
10089
10250
|
bootstrap += `${stepN++}. **Create labels** \u2014 create each label exactly as listed in the Labels section before creating issues
|
|
10090
10251
|
`;
|
|
10091
10252
|
}
|
|
10092
|
-
bootstrap += `${stepN++}. **
|
|
10253
|
+
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
10254
|
`;
|
|
10094
10255
|
if (initialIssues.length > 0) {
|
|
10095
10256
|
bootstrap += `${stepN++}. **Create issues** \u2014 every issue, including subtasks, must carry explicit projectId; subtasks also require parentId
|
|
10096
10257
|
`;
|
|
10097
10258
|
}
|
|
10098
10259
|
if (initialRoutines.length > 0) {
|
|
10099
|
-
bootstrap += `${stepN++}. **
|
|
10260
|
+
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
10261
|
`;
|
|
10101
10262
|
}
|
|
10102
10263
|
bootstrap += `${stepN}. **Start CEO heartbeat** (one-time initial wakeup)
|
|
@@ -10220,6 +10381,12 @@ var PaperclipClient = class {
|
|
|
10220
10381
|
return false;
|
|
10221
10382
|
}
|
|
10222
10383
|
}
|
|
10384
|
+
/**
|
|
10385
|
+
* Read instance-wide experimental settings (including enableIsolatedWorkspaces).
|
|
10386
|
+
*/
|
|
10387
|
+
async getInstanceExperimentalSettings() {
|
|
10388
|
+
return this._fetch("/api/instance/settings/experimental");
|
|
10389
|
+
}
|
|
10223
10390
|
async createCompany({ name, description }) {
|
|
10224
10391
|
return this._fetch("/api/companies", {
|
|
10225
10392
|
method: "POST",
|
|
@@ -10406,6 +10573,12 @@ var PaperclipClient = class {
|
|
|
10406
10573
|
})
|
|
10407
10574
|
});
|
|
10408
10575
|
}
|
|
10576
|
+
async updateIssue(issueId, updates = {}) {
|
|
10577
|
+
return this._fetch(`/api/issues/${issueId}`, {
|
|
10578
|
+
method: "PATCH",
|
|
10579
|
+
body: JSON.stringify(updates || {})
|
|
10580
|
+
});
|
|
10581
|
+
}
|
|
10409
10582
|
async createRoutine(companyId, {
|
|
10410
10583
|
title,
|
|
10411
10584
|
description,
|
|
@@ -10504,14 +10677,16 @@ async function loadModules(templatesDir) {
|
|
|
10504
10677
|
for (const dir of dirs) {
|
|
10505
10678
|
if (!dir.isDirectory()) continue;
|
|
10506
10679
|
const moduleJson = await readJson2(join2(modulesDir, dir.name, "module.meta.json"));
|
|
10507
|
-
const
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10680
|
+
const mod = { name: dir.name, ...moduleJson || {} };
|
|
10681
|
+
if (!mod.description) {
|
|
10682
|
+
const readmePath = join2(modulesDir, dir.name, "README.md");
|
|
10683
|
+
if (await exists2(readmePath)) {
|
|
10684
|
+
const content = await readFile2(readmePath, "utf-8");
|
|
10685
|
+
const descLine = content.split("\n").find((l) => l.length > 0 && !l.startsWith("#"));
|
|
10686
|
+
mod.description = descLine?.trim() || "";
|
|
10687
|
+
}
|
|
10688
|
+
}
|
|
10689
|
+
if (mod.description === void 0) mod.description = "";
|
|
10515
10690
|
if (mod.tasks && !mod.issues) {
|
|
10516
10691
|
mod.issues = mod.tasks;
|
|
10517
10692
|
delete mod.tasks;
|
|
@@ -10586,6 +10761,39 @@ function collectGoals(preset, modules, selectedModules) {
|
|
|
10586
10761
|
}
|
|
10587
10762
|
return goals;
|
|
10588
10763
|
}
|
|
10764
|
+
function resolveEffectiveModules(preset, modules, selectedModules) {
|
|
10765
|
+
const known = new Set(modules.map((m) => m.name));
|
|
10766
|
+
const requiresByName = new Map(
|
|
10767
|
+
modules.map((m) => [m.name, Array.isArray(m.requires) ? m.requires : []])
|
|
10768
|
+
);
|
|
10769
|
+
const effective = /* @__PURE__ */ new Set();
|
|
10770
|
+
const queue = [];
|
|
10771
|
+
const add = (name) => {
|
|
10772
|
+
if (typeof name !== "string" || !known.has(name) || effective.has(name)) return;
|
|
10773
|
+
effective.add(name);
|
|
10774
|
+
queue.push(name);
|
|
10775
|
+
};
|
|
10776
|
+
for (const moduleName of Array.isArray(preset?.modules) ? preset.modules : []) {
|
|
10777
|
+
add(moduleName);
|
|
10778
|
+
}
|
|
10779
|
+
for (const moduleName of selectedModules ?? []) {
|
|
10780
|
+
add(moduleName);
|
|
10781
|
+
}
|
|
10782
|
+
while (queue.length > 0) {
|
|
10783
|
+
const moduleName = queue.shift();
|
|
10784
|
+
for (const dep of requiresByName.get(moduleName) ?? []) {
|
|
10785
|
+
add(dep);
|
|
10786
|
+
}
|
|
10787
|
+
}
|
|
10788
|
+
return [...effective];
|
|
10789
|
+
}
|
|
10790
|
+
function collectPresetBootstrapData(preset) {
|
|
10791
|
+
return {
|
|
10792
|
+
labels: Array.isArray(preset?.labels) ? preset.labels.map((label) => ({ ...label })) : [],
|
|
10793
|
+
issues: Array.isArray(preset?.issues) ? preset.issues.map((issue) => ({ ...issue })) : [],
|
|
10794
|
+
routines: Array.isArray(preset?.routines) ? preset.routines.map((routine) => ({ ...routine })) : []
|
|
10795
|
+
};
|
|
10796
|
+
}
|
|
10589
10797
|
|
|
10590
10798
|
// src/worker.ts
|
|
10591
10799
|
var __dirname = path2.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -10656,6 +10864,61 @@ async function ensureTemplatesDir(cfg) {
|
|
|
10656
10864
|
);
|
|
10657
10865
|
}
|
|
10658
10866
|
}
|
|
10867
|
+
function isLikelyAnthropicApiKey(value) {
|
|
10868
|
+
return value.startsWith("sk-ant-");
|
|
10869
|
+
}
|
|
10870
|
+
async function resolveAnthropicApiKey(ctx, configuredValue) {
|
|
10871
|
+
if (typeof configuredValue !== "string") return "";
|
|
10872
|
+
const value = configuredValue.trim();
|
|
10873
|
+
if (!value) return "";
|
|
10874
|
+
if (isLikelyAnthropicApiKey(value)) return value;
|
|
10875
|
+
try {
|
|
10876
|
+
const resolved = await ctx.secrets.resolve(value);
|
|
10877
|
+
return resolved.trim();
|
|
10878
|
+
} catch (err) {
|
|
10879
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
10880
|
+
throw new Error(
|
|
10881
|
+
`Anthropic API key could not be resolved. Re-save the plugin setting with a valid Anthropic API key (sk-ant-...). ${detail}`
|
|
10882
|
+
);
|
|
10883
|
+
}
|
|
10884
|
+
}
|
|
10885
|
+
async function callAnthropic(apiKey, system, messages) {
|
|
10886
|
+
try {
|
|
10887
|
+
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
10888
|
+
method: "POST",
|
|
10889
|
+
headers: {
|
|
10890
|
+
"Content-Type": "application/json",
|
|
10891
|
+
"x-api-key": apiKey,
|
|
10892
|
+
"anthropic-version": "2023-06-01"
|
|
10893
|
+
},
|
|
10894
|
+
body: JSON.stringify({
|
|
10895
|
+
model: "claude-opus-4-8",
|
|
10896
|
+
// High ceiling so the wizard's final config — which reproduces the user's
|
|
10897
|
+
// full spec in the first goal — is never truncated mid-JSON. This is only
|
|
10898
|
+
// an upper bound; generation time tracks the tokens actually produced.
|
|
10899
|
+
max_tokens: 32768,
|
|
10900
|
+
...system ? { system } : {},
|
|
10901
|
+
messages
|
|
10902
|
+
})
|
|
10903
|
+
});
|
|
10904
|
+
if (!response.ok) {
|
|
10905
|
+
const body = await response.text();
|
|
10906
|
+
return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
|
|
10907
|
+
}
|
|
10908
|
+
const data = await response.json();
|
|
10909
|
+
return { text: data.content?.[0]?.text || "" };
|
|
10910
|
+
} catch (err) {
|
|
10911
|
+
return { text: "", error: err instanceof Error ? err.message : String(err) };
|
|
10912
|
+
}
|
|
10913
|
+
}
|
|
10914
|
+
var aiChatJobs = /* @__PURE__ */ new Map();
|
|
10915
|
+
var AI_CHAT_JOB_TTL_MS = 10 * 60 * 1e3;
|
|
10916
|
+
function sweepAiChatJobs() {
|
|
10917
|
+
const now = Date.now();
|
|
10918
|
+
for (const [id, job] of aiChatJobs) {
|
|
10919
|
+
if (now - job.createdAt > AI_CHAT_JOB_TTL_MS) aiChatJobs.delete(id);
|
|
10920
|
+
}
|
|
10921
|
+
}
|
|
10659
10922
|
function loadJsonFiles(dir, filename) {
|
|
10660
10923
|
const items = [];
|
|
10661
10924
|
const errors = [];
|
|
@@ -10701,10 +10964,37 @@ function loadTemplates(templatesDir) {
|
|
|
10701
10964
|
loadErrors: [...presetLoad.errors, ...moduleLoad.errors, ...roleLoad.errors]
|
|
10702
10965
|
};
|
|
10703
10966
|
}
|
|
10967
|
+
function cfgBool(cfg, key) {
|
|
10968
|
+
const raw = cfg[key];
|
|
10969
|
+
return raw === true || typeof raw === "string" && raw.toLowerCase() === "true";
|
|
10970
|
+
}
|
|
10971
|
+
async function resolveEnableIsolatedWorkspacesFromInstance(cfg, log) {
|
|
10972
|
+
const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
|
|
10973
|
+
const paperclipEmail = cfg.paperclipEmail || "";
|
|
10974
|
+
const paperclipPassword = cfg.paperclipPassword || "";
|
|
10975
|
+
const instanceClient = new PaperclipClient(paperclipUrl, {
|
|
10976
|
+
email: paperclipEmail,
|
|
10977
|
+
password: paperclipPassword
|
|
10978
|
+
});
|
|
10979
|
+
try {
|
|
10980
|
+
await instanceClient.connect();
|
|
10981
|
+
const experimentalSettings = await instanceClient.getInstanceExperimentalSettings();
|
|
10982
|
+
return experimentalSettings?.enableIsolatedWorkspaces === true;
|
|
10983
|
+
} catch (err) {
|
|
10984
|
+
if (log) {
|
|
10985
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
10986
|
+
log(`\u26A0 Could not read instance experimental settings: ${detail}. Using fallback false.`);
|
|
10987
|
+
}
|
|
10988
|
+
return false;
|
|
10989
|
+
}
|
|
10990
|
+
}
|
|
10704
10991
|
function resolveCompaniesDir(cfg) {
|
|
10705
10992
|
if (cfg.companiesDir) return cfg.companiesDir;
|
|
10706
10993
|
return path2.join(os.homedir(), ".paperclip", "instances", "default", "companies");
|
|
10707
10994
|
}
|
|
10995
|
+
function formatRoleName(role) {
|
|
10996
|
+
return role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
10997
|
+
}
|
|
10708
10998
|
function collectInstructionFiles(rootDir) {
|
|
10709
10999
|
const out = {};
|
|
10710
11000
|
if (!fs2.existsSync(rootDir)) return out;
|
|
@@ -10815,20 +11105,28 @@ var plugin = definePlugin({
|
|
|
10815
11105
|
loadModules(templatesDir)
|
|
10816
11106
|
]);
|
|
10817
11107
|
const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
|
|
10818
|
-
const
|
|
11108
|
+
const effectiveModules = resolveEffectiveModules(
|
|
10819
11109
|
selectedPreset,
|
|
10820
11110
|
allModules,
|
|
10821
|
-
|
|
11111
|
+
params.selectedModules ?? []
|
|
10822
11112
|
);
|
|
11113
|
+
const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
|
|
11114
|
+
const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
|
|
10823
11115
|
const previewGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
|
|
10824
11116
|
const previewProjects = Array.isArray(params.projects) ? params.projects : [];
|
|
11117
|
+
const previewIssues = Array.isArray(params.issues) ? params.issues : [];
|
|
10825
11118
|
const result = await assembleCompany({
|
|
10826
11119
|
companyName,
|
|
10827
11120
|
userGoals: previewGoals,
|
|
10828
11121
|
userProjects: previewProjects,
|
|
10829
|
-
moduleNames:
|
|
11122
|
+
moduleNames: effectiveModules,
|
|
10830
11123
|
extraRoleNames: params.selectedRoles ?? [],
|
|
10831
11124
|
inlineGoals: goals,
|
|
11125
|
+
userIssues: previewIssues,
|
|
11126
|
+
presetIssues: presetBootstrapData.issues,
|
|
11127
|
+
presetRoutines: presetBootstrapData.routines,
|
|
11128
|
+
presetLabels: presetBootstrapData.labels,
|
|
11129
|
+
enableIsolatedWorktrees: await resolveEnableIsolatedWorkspacesFromInstance(cfg),
|
|
10832
11130
|
outputDir: tmpDir,
|
|
10833
11131
|
templatesDir
|
|
10834
11132
|
});
|
|
@@ -10863,34 +11161,42 @@ var plugin = definePlugin({
|
|
|
10863
11161
|
});
|
|
10864
11162
|
ctx.actions.register("ai-chat", async (params) => {
|
|
10865
11163
|
try {
|
|
11164
|
+
if (params.mode === "poll") {
|
|
11165
|
+
const jobId = typeof params.jobId === "string" ? params.jobId : "";
|
|
11166
|
+
const job = jobId ? aiChatJobs.get(jobId) : void 0;
|
|
11167
|
+
if (!job) {
|
|
11168
|
+
return {
|
|
11169
|
+
text: "",
|
|
11170
|
+
status: "error",
|
|
11171
|
+
error: "Unknown or expired generation job. Please retry."
|
|
11172
|
+
};
|
|
11173
|
+
}
|
|
11174
|
+
if (job.status === "pending") return { status: "pending" };
|
|
11175
|
+
aiChatJobs.delete(jobId);
|
|
11176
|
+
if (job.status === "error") return { text: "", status: "error", error: job.error };
|
|
11177
|
+
return { text: job.text, status: "done" };
|
|
11178
|
+
}
|
|
10866
11179
|
const cfg = await ctx.config.get() ?? {};
|
|
10867
|
-
const apiKey = cfg.anthropicApiKey
|
|
11180
|
+
const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
|
|
10868
11181
|
if (!apiKey) {
|
|
10869
11182
|
return {
|
|
10870
11183
|
text: "",
|
|
10871
11184
|
error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
|
|
10872
11185
|
};
|
|
10873
11186
|
}
|
|
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}` };
|
|
11187
|
+
if (params.mode === "start") {
|
|
11188
|
+
sweepAiChatJobs();
|
|
11189
|
+
const jobId = `aichat-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
11190
|
+
aiChatJobs.set(jobId, { status: "pending", createdAt: Date.now() });
|
|
11191
|
+
void callAnthropic(apiKey, params.system, params.messages).then((result) => {
|
|
11192
|
+
aiChatJobs.set(
|
|
11193
|
+
jobId,
|
|
11194
|
+
result.error ? { status: "error", error: result.error, createdAt: Date.now() } : { status: "done", text: result.text, createdAt: Date.now() }
|
|
11195
|
+
);
|
|
11196
|
+
});
|
|
11197
|
+
return { jobId, status: "pending" };
|
|
10891
11198
|
}
|
|
10892
|
-
|
|
10893
|
-
return { text: data.content?.[0]?.text || "" };
|
|
11199
|
+
return await callAnthropic(apiKey, params.system, params.messages);
|
|
10894
11200
|
} catch (err) {
|
|
10895
11201
|
return { text: "", error: err instanceof Error ? err.message : String(err) };
|
|
10896
11202
|
}
|
|
@@ -10898,7 +11204,8 @@ var plugin = definePlugin({
|
|
|
10898
11204
|
ctx.actions.register("check-ai-config", async () => {
|
|
10899
11205
|
try {
|
|
10900
11206
|
const cfg = await ctx.config.get() ?? {};
|
|
10901
|
-
|
|
11207
|
+
const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
|
|
11208
|
+
if (!apiKey) {
|
|
10902
11209
|
return {
|
|
10903
11210
|
ok: false,
|
|
10904
11211
|
error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
|
|
@@ -10920,8 +11227,11 @@ var plugin = definePlugin({
|
|
|
10920
11227
|
const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
|
|
10921
11228
|
const paperclipEmail = cfg.paperclipEmail || "";
|
|
10922
11229
|
const paperclipPassword = cfg.paperclipPassword || "";
|
|
10923
|
-
const
|
|
10924
|
-
|
|
11230
|
+
const disableBoardApprovalOnNewCompanies = cfgBool(
|
|
11231
|
+
cfg,
|
|
11232
|
+
"disableBoardApprovalOnNewCompanies"
|
|
11233
|
+
);
|
|
11234
|
+
const enableIsolatedWorktrees = await resolveEnableIsolatedWorkspacesFromInstance(cfg, log);
|
|
10925
11235
|
const companyName = typeof params.companyName === "string" ? params.companyName.trim() : "";
|
|
10926
11236
|
const existingCompanyId = typeof params.existingCompanyId === "string" && params.existingCompanyId.trim() ? params.existingCompanyId.trim() : "";
|
|
10927
11237
|
if (!companyName) return { error: "companyName is required", logs };
|
|
@@ -10935,25 +11245,33 @@ var plugin = definePlugin({
|
|
|
10935
11245
|
(Array.isArray(roleTemplates) ? roleTemplates : []).filter((role) => role && typeof role.name === "string").map((role) => [role.name, role])
|
|
10936
11246
|
);
|
|
10937
11247
|
const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
|
|
10938
|
-
const
|
|
11248
|
+
const effectiveModules = resolveEffectiveModules(
|
|
10939
11249
|
selectedPreset,
|
|
10940
11250
|
allModules,
|
|
10941
|
-
|
|
11251
|
+
params.selectedModules ?? []
|
|
10942
11252
|
);
|
|
11253
|
+
const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
|
|
11254
|
+
const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
|
|
10943
11255
|
const outputDir = resolveCompaniesDir(cfg);
|
|
10944
11256
|
fs2.mkdirSync(outputDir, { recursive: true });
|
|
10945
11257
|
log("Assembling company workspace...");
|
|
10946
11258
|
const companyDescription = typeof params.companyDescription === "string" ? params.companyDescription.trim() : "";
|
|
10947
11259
|
const userGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
|
|
10948
11260
|
const userProjects = Array.isArray(params.projects) ? params.projects : [];
|
|
11261
|
+
const userIssues = Array.isArray(params.issues) ? params.issues : [];
|
|
10949
11262
|
const assembleResult = await assembleCompany({
|
|
10950
11263
|
companyName,
|
|
10951
11264
|
companyDescription,
|
|
10952
11265
|
userGoals,
|
|
10953
11266
|
userProjects,
|
|
10954
|
-
moduleNames:
|
|
11267
|
+
moduleNames: effectiveModules,
|
|
10955
11268
|
extraRoleNames: params.selectedRoles ?? [],
|
|
10956
11269
|
inlineGoals: goals,
|
|
11270
|
+
userIssues,
|
|
11271
|
+
presetIssues: presetBootstrapData.issues,
|
|
11272
|
+
presetRoutines: presetBootstrapData.routines,
|
|
11273
|
+
presetLabels: presetBootstrapData.labels,
|
|
11274
|
+
enableIsolatedWorktrees,
|
|
10957
11275
|
outputDir,
|
|
10958
11276
|
templatesDir,
|
|
10959
11277
|
onProgress: log
|
|
@@ -11018,6 +11336,7 @@ var plugin = definePlugin({
|
|
|
11018
11336
|
}
|
|
11019
11337
|
}
|
|
11020
11338
|
let ceoAgentId;
|
|
11339
|
+
const teamAgentIds = {};
|
|
11021
11340
|
let bootstrapIssue;
|
|
11022
11341
|
try {
|
|
11023
11342
|
const userCeoAdapter = params.ceoAdapter || {};
|
|
@@ -11125,18 +11444,125 @@ var plugin = definePlugin({
|
|
|
11125
11444
|
fallbackEntryContent: ceoPromptTemplate,
|
|
11126
11445
|
log
|
|
11127
11446
|
});
|
|
11447
|
+
const teamRoles = [...assembleResult.allRoles ?? []].filter(
|
|
11448
|
+
(r) => r && r !== "ceo"
|
|
11449
|
+
);
|
|
11450
|
+
let existingByTemplateRole = /* @__PURE__ */ new Map();
|
|
11451
|
+
if (existingCompanyId && teamRoles.length > 0) {
|
|
11452
|
+
const agents = await client.listAgents(companyId);
|
|
11453
|
+
if (Array.isArray(agents)) {
|
|
11454
|
+
for (const a of agents) {
|
|
11455
|
+
const tr = a?.metadata?.templateRole;
|
|
11456
|
+
if (tr && a?.status !== "terminated" && a?.role !== "ceo") {
|
|
11457
|
+
existingByTemplateRole.set(tr, a);
|
|
11458
|
+
}
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
}
|
|
11462
|
+
for (const roleName of teamRoles) {
|
|
11463
|
+
const roleTemplate = roleTemplateByName.get(roleName) || {};
|
|
11464
|
+
const paperclipRole = typeof roleTemplate.paperclipRole === "string" && roleTemplate.paperclipRole.trim() ? roleTemplate.paperclipRole.trim() : "general";
|
|
11465
|
+
const roleTitle = typeof roleTemplate.title === "string" && roleTemplate.title.trim() ? roleTemplate.title.trim() : formatRoleName(roleName);
|
|
11466
|
+
const roleDescription = typeof roleTemplate.description === "string" && roleTemplate.description.trim() ? roleTemplate.description.trim() : void 0;
|
|
11467
|
+
const roleMetadata = {
|
|
11468
|
+
templateRole: roleName,
|
|
11469
|
+
...roleDescription ? { description: roleDescription } : {}
|
|
11470
|
+
};
|
|
11471
|
+
const roleRuntimeConfig = buildWorkerAgentRuntimeConfig();
|
|
11472
|
+
const roleAdapterConfig = buildCeoAdapterConfig({
|
|
11473
|
+
userCeoAdapter,
|
|
11474
|
+
companyDir,
|
|
11475
|
+
roleAdapterOverrides: assembleResult.roleAdapterOverrides?.get(roleName) ?? {}
|
|
11476
|
+
});
|
|
11477
|
+
const roleInstructionsDir = path2.join(companyDir, "agents", roleName);
|
|
11478
|
+
const roleInstructionFiles = collectInstructionFiles(roleInstructionsDir);
|
|
11479
|
+
const roleInstructionsBundle = Object.keys(roleInstructionFiles).length > 0 ? { entryFile: "AGENTS.md", files: roleInstructionFiles } : void 0;
|
|
11480
|
+
const existingAgent = existingByTemplateRole.get(roleName);
|
|
11481
|
+
if (existingAgent?.id) {
|
|
11482
|
+
try {
|
|
11483
|
+
await client.updateAgent(existingAgent.id, {
|
|
11484
|
+
adapterType,
|
|
11485
|
+
adapterConfig: roleAdapterConfig,
|
|
11486
|
+
runtimeConfig: roleRuntimeConfig,
|
|
11487
|
+
metadata: { ...existingAgent.metadata ?? {}, ...roleMetadata },
|
|
11488
|
+
...!existingAgent.title && roleTitle ? { title: roleTitle } : {},
|
|
11489
|
+
...!existingAgent.capabilities && roleDescription ? { capabilities: roleDescription } : {}
|
|
11490
|
+
});
|
|
11491
|
+
log(`\u2713 Reusing ${roleTitle} (${existingAgent.id})`);
|
|
11492
|
+
} catch (err) {
|
|
11493
|
+
log(
|
|
11494
|
+
`\u26A0 Could not update ${roleTitle}: ${err instanceof Error ? err.message : String(err)}`
|
|
11495
|
+
);
|
|
11496
|
+
}
|
|
11497
|
+
teamAgentIds[roleName] = existingAgent.id;
|
|
11498
|
+
continue;
|
|
11499
|
+
}
|
|
11500
|
+
const roleAgent = await client.createAgent(companyId, {
|
|
11501
|
+
name: roleTitle,
|
|
11502
|
+
role: paperclipRole,
|
|
11503
|
+
title: roleTitle,
|
|
11504
|
+
...roleDescription ? { capabilities: roleDescription } : {},
|
|
11505
|
+
metadata: roleMetadata,
|
|
11506
|
+
reportsTo: ceoAgentId,
|
|
11507
|
+
adapterType,
|
|
11508
|
+
adapterConfig: roleAdapterConfig,
|
|
11509
|
+
instructionsBundle: roleInstructionsBundle,
|
|
11510
|
+
runtimeConfig: roleRuntimeConfig
|
|
11511
|
+
});
|
|
11512
|
+
teamAgentIds[roleName] = roleAgent.id;
|
|
11513
|
+
log(`\u2713 ${roleTitle} created (${roleAgent.id})`);
|
|
11514
|
+
if (roleAgent?._pendingApprovalId) {
|
|
11515
|
+
log(
|
|
11516
|
+
`\u26A0 ${roleTitle} hire pending approval: ${roleAgent._pendingApprovalId}. Approve it in the board.`
|
|
11517
|
+
);
|
|
11518
|
+
if (roleAgent._approvalAutoApproveError) {
|
|
11519
|
+
log(` Auto-approve failed: ${roleAgent._approvalAutoApproveError}`);
|
|
11520
|
+
}
|
|
11521
|
+
}
|
|
11522
|
+
}
|
|
11523
|
+
if (!existingCompanyId) {
|
|
11524
|
+
const routines = Array.isArray(assembleResult.initialRoutines) ? assembleResult.initialRoutines : [];
|
|
11525
|
+
for (const routine of routines) {
|
|
11526
|
+
const title = typeof routine.title === "string" && routine.title.trim() ? routine.title.trim() : typeof routine.name === "string" ? routine.name.trim() : "";
|
|
11527
|
+
if (!title) continue;
|
|
11528
|
+
const role = routine.assignTo;
|
|
11529
|
+
const assigneeAgentId = !role || role === "ceo" ? ceoAgentId : teamAgentIds[role] ?? ceoAgentId;
|
|
11530
|
+
try {
|
|
11531
|
+
const createdRoutine = await client.createRoutine(companyId, {
|
|
11532
|
+
title,
|
|
11533
|
+
description: routine.description,
|
|
11534
|
+
assigneeAgentId,
|
|
11535
|
+
priority: routine.priority || "medium",
|
|
11536
|
+
concurrencyPolicy: routine.concurrencyPolicy || "skip_if_active"
|
|
11537
|
+
});
|
|
11538
|
+
if (routine.schedule && createdRoutine?.id) {
|
|
11539
|
+
await client.createRoutineTrigger(createdRoutine.id, {
|
|
11540
|
+
kind: "schedule",
|
|
11541
|
+
cronExpression: routine.schedule,
|
|
11542
|
+
timezone: "UTC"
|
|
11543
|
+
});
|
|
11544
|
+
}
|
|
11545
|
+
log(
|
|
11546
|
+
`\u2713 Routine "${title}" created${routine.schedule ? ` (${routine.schedule})` : ""}`
|
|
11547
|
+
);
|
|
11548
|
+
} catch (err) {
|
|
11549
|
+
log(
|
|
11550
|
+
`\u26A0 Could not create routine "${title}": ${err instanceof Error ? err.message : String(err)}`
|
|
11551
|
+
);
|
|
11552
|
+
}
|
|
11553
|
+
}
|
|
11554
|
+
}
|
|
11128
11555
|
const bootstrapDescription = fs2.readFileSync(
|
|
11129
11556
|
path2.join(companyDir, "BOOTSTRAP.md"),
|
|
11130
11557
|
"utf-8"
|
|
11131
11558
|
);
|
|
11132
11559
|
log("Creating bootstrap task for CEO...");
|
|
11133
|
-
const issue = await
|
|
11134
|
-
companyId,
|
|
11560
|
+
const issue = await client.createIssue(companyId, {
|
|
11135
11561
|
title: `Bootstrap ${company.name || companyName}`,
|
|
11136
11562
|
description: bootstrapDescription,
|
|
11137
|
-
assigneeAgentId: ceoAgentId
|
|
11563
|
+
assigneeAgentId: ceoAgentId,
|
|
11564
|
+
status: "todo"
|
|
11138
11565
|
});
|
|
11139
|
-
await ctx.issues.update(issue.id, { status: "todo" }, companyId);
|
|
11140
11566
|
bootstrapIssue = issue;
|
|
11141
11567
|
log(`\u2713 Bootstrap task created: ${bootstrapIssue.identifier || bootstrapIssue.id}`);
|
|
11142
11568
|
} catch (err) {
|
|
@@ -11166,7 +11592,7 @@ var plugin = definePlugin({
|
|
|
11166
11592
|
companyId,
|
|
11167
11593
|
issuePrefix: company.issuePrefix,
|
|
11168
11594
|
paperclipUrl,
|
|
11169
|
-
agentIds: { ceo: ceoAgentId },
|
|
11595
|
+
agentIds: { ceo: ceoAgentId, ...teamAgentIds },
|
|
11170
11596
|
issueIds: [bootstrapIssue.id],
|
|
11171
11597
|
logs
|
|
11172
11598
|
};
|