crewly 1.20.133 → 1.20.134
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/dist/backend/backend/src/constants.d.ts +82 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +87 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/bundle/bundle.controller.d.ts +44 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.controller.js +122 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.routes.d.ts +25 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.routes.js +33 -0
- package/dist/backend/backend/src/controllers/bundle/bundle.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +14 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +4 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/bundle/bundle-apply.factory.d.ts +62 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.factory.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.factory.js +173 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.factory.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.service.d.ts +359 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.service.js +888 -0
- package/dist/backend/backend/src/services/bundle/bundle-apply.service.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-catalog.d.ts +167 -0
- package/dist/backend/backend/src/services/bundle/bundle-catalog.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-catalog.js +248 -0
- package/dist/backend/backend/src/services/bundle/bundle-catalog.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-connectors.d.ts +43 -0
- package/dist/backend/backend/src/services/bundle/bundle-connectors.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-connectors.js +57 -0
- package/dist/backend/backend/src/services/bundle/bundle-connectors.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-deps.d.ts +37 -0
- package/dist/backend/backend/src/services/bundle/bundle-deps.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-deps.js +60 -0
- package/dist/backend/backend/src/services/bundle/bundle-deps.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-manifest.d.ts +93 -0
- package/dist/backend/backend/src/services/bundle/bundle-manifest.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-manifest.js +532 -0
- package/dist/backend/backend/src/services/bundle/bundle-manifest.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-placeholders.d.ts +100 -0
- package/dist/backend/backend/src/services/bundle/bundle-placeholders.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-placeholders.js +183 -0
- package/dist/backend/backend/src/services/bundle/bundle-placeholders.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-runtime.d.ts +36 -0
- package/dist/backend/backend/src/services/bundle/bundle-runtime.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-runtime.js +38 -0
- package/dist/backend/backend/src/services/bundle/bundle-runtime.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-skill-installer.d.ts +105 -0
- package/dist/backend/backend/src/services/bundle/bundle-skill-installer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-skill-installer.js +144 -0
- package/dist/backend/backend/src/services/bundle/bundle-skill-installer.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-state.store.d.ts +48 -0
- package/dist/backend/backend/src/services/bundle/bundle-state.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-state.store.js +90 -0
- package/dist/backend/backend/src/services/bundle/bundle-state.store.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-team.builder.d.ts +81 -0
- package/dist/backend/backend/src/services/bundle/bundle-team.builder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-team.builder.js +172 -0
- package/dist/backend/backend/src/services/bundle/bundle-team.builder.js.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-time.d.ts +59 -0
- package/dist/backend/backend/src/services/bundle/bundle-time.d.ts.map +1 -0
- package/dist/backend/backend/src/services/bundle/bundle-time.js +98 -0
- package/dist/backend/backend/src/services/bundle/bundle-time.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +5 -0
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/teams-backup.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/teams-backup.service.js +4 -2
- package/dist/backend/backend/src/services/core/teams-backup.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.d.ts.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.js +2 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.d.ts +14 -2
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js +37 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +21 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +85 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/template/template.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/template/template.service.js +5 -2
- package/dist/backend/backend/src/services/template/template.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.js +4 -2
- package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/backend/backend/src/types/solution-bundle.types.d.ts +367 -0
- package/dist/backend/backend/src/types/solution-bundle.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/solution-bundle.types.js +17 -0
- package/dist/backend/backend/src/types/solution-bundle.types.js.map +1 -0
- package/dist/backend/backend/src/types/team-template.types.d.ts +8 -0
- package/dist/backend/backend/src/types/team-template.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/team-template.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +82 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +87 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/bundle/bundle-apply.service.d.ts +359 -0
- package/dist/cli/backend/src/services/bundle/bundle-apply.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-apply.service.js +888 -0
- package/dist/cli/backend/src/services/bundle/bundle-apply.service.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-catalog.d.ts +167 -0
- package/dist/cli/backend/src/services/bundle/bundle-catalog.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-catalog.js +248 -0
- package/dist/cli/backend/src/services/bundle/bundle-catalog.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-deps.d.ts +37 -0
- package/dist/cli/backend/src/services/bundle/bundle-deps.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-deps.js +60 -0
- package/dist/cli/backend/src/services/bundle/bundle-deps.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-manifest.d.ts +93 -0
- package/dist/cli/backend/src/services/bundle/bundle-manifest.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-manifest.js +532 -0
- package/dist/cli/backend/src/services/bundle/bundle-manifest.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-placeholders.d.ts +100 -0
- package/dist/cli/backend/src/services/bundle/bundle-placeholders.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-placeholders.js +183 -0
- package/dist/cli/backend/src/services/bundle/bundle-placeholders.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-runtime.d.ts +36 -0
- package/dist/cli/backend/src/services/bundle/bundle-runtime.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-runtime.js +38 -0
- package/dist/cli/backend/src/services/bundle/bundle-runtime.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-skill-installer.d.ts +105 -0
- package/dist/cli/backend/src/services/bundle/bundle-skill-installer.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-skill-installer.js +144 -0
- package/dist/cli/backend/src/services/bundle/bundle-skill-installer.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-state.store.d.ts +48 -0
- package/dist/cli/backend/src/services/bundle/bundle-state.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-state.store.js +90 -0
- package/dist/cli/backend/src/services/bundle/bundle-state.store.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-team.builder.d.ts +81 -0
- package/dist/cli/backend/src/services/bundle/bundle-team.builder.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-team.builder.js +172 -0
- package/dist/cli/backend/src/services/bundle/bundle-team.builder.js.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-time.d.ts +59 -0
- package/dist/cli/backend/src/services/bundle/bundle-time.d.ts.map +1 -0
- package/dist/cli/backend/src/services/bundle/bundle-time.js +98 -0
- package/dist/cli/backend/src/services/bundle/bundle-time.js.map +1 -0
- package/dist/cli/backend/src/services/core/storage.service.js +1 -1
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/teams-backup.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/teams-backup.service.js +4 -2
- package/dist/cli/backend/src/services/core/teams-backup.service.js.map +1 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts +72 -0
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js +389 -0
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/index.d.ts +15 -0
- package/dist/cli/backend/src/services/messaging/index.d.ts.map +1 -0
- package/dist/cli/backend/src/services/messaging/index.js +20 -0
- package/dist/cli/backend/src/services/messaging/index.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts +224 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +969 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/response-router.service.d.ts +110 -0
- package/dist/cli/backend/src/services/messaging/response-router.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/messaging/response-router.service.js +268 -0
- package/dist/cli/backend/src/services/messaging/response-router.service.js.map +1 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.d.ts +14 -2
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js +37 -1
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -1
- package/dist/cli/backend/src/services/orchestrator/commitment-approval-guard.d.ts +133 -0
- package/dist/cli/backend/src/services/orchestrator/commitment-approval-guard.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/commitment-approval-guard.js +232 -0
- package/dist/cli/backend/src/services/orchestrator/commitment-approval-guard.js.map +1 -0
- package/dist/cli/backend/src/services/skill/skill-catalog.service.d.ts +277 -0
- package/dist/cli/backend/src/services/skill/skill-catalog.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/skill/skill-catalog.service.js +708 -0
- package/dist/cli/backend/src/services/skill/skill-catalog.service.js.map +1 -0
- package/dist/cli/backend/src/services/skill-setup/skill-install-job.service.d.ts +243 -0
- package/dist/cli/backend/src/services/skill-setup/skill-install-job.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/skill-setup/skill-install-job.service.js +439 -0
- package/dist/cli/backend/src/services/skill-setup/skill-install-job.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +21 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +85 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/template/template.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/template/template.service.js +5 -2
- package/dist/cli/backend/src/services/template/template.service.js.map +1 -1
- package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts +316 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.js +1043 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.js.map +1 -0
- package/dist/cli/backend/src/types/cron-task.types.d.ts +95 -0
- package/dist/cli/backend/src/types/cron-task.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/cron-task.types.js +10 -0
- package/dist/cli/backend/src/types/cron-task.types.js.map +1 -0
- package/dist/cli/backend/src/types/solution-bundle.types.d.ts +367 -0
- package/dist/cli/backend/src/types/solution-bundle.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/solution-bundle.types.js +17 -0
- package/dist/cli/backend/src/types/solution-bundle.types.js.map +1 -0
- package/dist/cli/backend/src/types/team-template.types.d.ts +8 -0
- package/dist/cli/backend/src/types/team-template.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/team-template.types.js.map +1 -1
- package/dist/cli/cli/src/commands/deploy-bundle.d.ts +160 -0
- package/dist/cli/cli/src/commands/deploy-bundle.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/deploy-bundle.js +386 -0
- package/dist/cli/cli/src/commands/deploy-bundle.js.map +1 -0
- package/dist/cli/cli/src/commands/onboard.d.ts +32 -1
- package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/onboard.js +80 -3
- package/dist/cli/cli/src/commands/onboard.js.map +1 -1
- package/dist/cli/cli/src/constants.d.ts +5 -0
- package/dist/cli/cli/src/constants.d.ts.map +1 -1
- package/dist/cli/cli/src/constants.js +5 -0
- package/dist/cli/cli/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +15 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/frontend/dist/assets/{index-e6c403b6.js → index-97bb17d4.js} +274 -274
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill installation for bundles, through the existing marketplace install.
|
|
3
|
+
*
|
|
4
|
+
* Kept behind {@link BundleSkillInstaller} so the apply engine can switch to
|
|
5
|
+
* the skill-autoinstall runner (`feat/skill-autoinstall`: skill discovery
|
|
6
|
+
* over bundled / installed / registry skills + install jobs with setup
|
|
7
|
+
* recipes) when it lands, without touching the engine.
|
|
8
|
+
*
|
|
9
|
+
* A skill counts as available when it is bundled with Crewly
|
|
10
|
+
* (`config/skills/{agent,team-leader,orchestrator}/**`) or already installed
|
|
11
|
+
* from the marketplace. Missing ones are installed with the marketplace
|
|
12
|
+
* installer (`POST /api/marketplace/:id/install` / `crewly install <id>`).
|
|
13
|
+
*
|
|
14
|
+
* @module services/bundle/bundle-skill-installer
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readdirSync, statSync } from 'fs';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
/** Skill roots under `config/skills/` that ship with Crewly. */
|
|
19
|
+
const BUNDLED_SKILL_ROOTS = ['agent', 'team-leader', 'orchestrator'];
|
|
20
|
+
/** How deep a skill folder may sit under a root (e.g. agent/core/<id>). */
|
|
21
|
+
const MAX_SKILL_DEPTH = 3;
|
|
22
|
+
/** Files that make a folder a skill. */
|
|
23
|
+
const SKILL_MARKERS = ['SKILL.md', 'skill.json', 'execute.sh'];
|
|
24
|
+
/**
|
|
25
|
+
* Find a skill folder by id under the bundled skill roots.
|
|
26
|
+
*
|
|
27
|
+
* @param packageRoot - Crewly package root (contains `config/skills`)
|
|
28
|
+
* @param skillId - Skill id (folder name)
|
|
29
|
+
* @returns The folder, or null
|
|
30
|
+
*/
|
|
31
|
+
export function findBundledSkill(packageRoot, skillId) {
|
|
32
|
+
const walk = (dir, depth) => {
|
|
33
|
+
let entries;
|
|
34
|
+
try {
|
|
35
|
+
entries = readdirSync(dir);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (entry.startsWith('.') || entry.startsWith('_'))
|
|
42
|
+
continue;
|
|
43
|
+
const full = path.join(dir, entry);
|
|
44
|
+
try {
|
|
45
|
+
if (!statSync(full).isDirectory())
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (entry === skillId && SKILL_MARKERS.some((m) => existsSync(path.join(full, m))))
|
|
52
|
+
return full;
|
|
53
|
+
if (depth < MAX_SKILL_DEPTH) {
|
|
54
|
+
const found = walk(full, depth + 1);
|
|
55
|
+
if (found)
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
for (const root of BUNDLED_SKILL_ROOTS) {
|
|
62
|
+
const found = walk(path.join(packageRoot, 'config', 'skills', root), 1);
|
|
63
|
+
if (found)
|
|
64
|
+
return found;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A {@link BundleSkillInstaller} over the marketplace.
|
|
70
|
+
*
|
|
71
|
+
* @param deps - Package root, homes and marketplace functions
|
|
72
|
+
* @returns Installer
|
|
73
|
+
*/
|
|
74
|
+
export function createMarketplaceSkillInstaller(deps) {
|
|
75
|
+
return {
|
|
76
|
+
async isAvailable(skillId) {
|
|
77
|
+
if (findBundledSkill(deps.packageRoot, skillId))
|
|
78
|
+
return true;
|
|
79
|
+
try {
|
|
80
|
+
return existsSync(deps.installPath(skillId));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
async install(skillId) {
|
|
87
|
+
if (path.resolve(deps.crewlyHome) !== path.resolve(deps.marketplaceHome)) {
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
message: `Not installed: the marketplace installs into ${deps.marketplaceHome}, not this CREWLY_HOME (${deps.crewlyHome})`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const registry = await deps.fetchRegistry();
|
|
94
|
+
const item = registry.items.find((i) => i.id === skillId && i.type === 'skill');
|
|
95
|
+
if (!item)
|
|
96
|
+
return { ok: false, message: `"${skillId}" is not in the marketplace` };
|
|
97
|
+
const result = await deps.installItem(item);
|
|
98
|
+
return { ok: result.success, message: result.message };
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Bundle skill installer on the skill-setup services (specs/skill-auto-install.md):
|
|
104
|
+
* a skill counts as available only when its declared dependencies are set up,
|
|
105
|
+
* and installing runs that setup too (brew/apt/model downloads). Deploying a
|
|
106
|
+
* bundle is the owner's own action, so third-party skills in it install as
|
|
107
|
+
* the owner (`ownerDashboard`).
|
|
108
|
+
*
|
|
109
|
+
* @param deps - Discovery and install-job services
|
|
110
|
+
* @returns Installer for the apply engine
|
|
111
|
+
*/
|
|
112
|
+
export function createSkillSetupInstaller(deps) {
|
|
113
|
+
return {
|
|
114
|
+
async isAvailable(skillId) {
|
|
115
|
+
const skill = await deps.discovery.resolve(skillId);
|
|
116
|
+
if (!skill || !skill.installed)
|
|
117
|
+
return false;
|
|
118
|
+
const probed = await deps.discovery.probe(skill);
|
|
119
|
+
return probed.ready !== false;
|
|
120
|
+
},
|
|
121
|
+
async install(skillId) {
|
|
122
|
+
const skill = await deps.discovery.resolve(skillId);
|
|
123
|
+
if (!skill)
|
|
124
|
+
return { ok: false, message: `"${skillId}" is not bundled with Crewly or listed in the marketplace` };
|
|
125
|
+
// A download from the marketplace lands in ~/.crewly whatever CREWLY_HOME
|
|
126
|
+
// says — refuse rather than write into the real home from a test deploy.
|
|
127
|
+
if (!skill.installed && path.resolve(deps.crewlyHome) !== path.resolve(deps.marketplaceHome)) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
message: `Not installed: the marketplace installs into ${deps.marketplaceHome}, not this CREWLY_HOME (${deps.crewlyHome})`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const started = await deps.jobs.startInstall({ skillId, ownerDashboard: true, resumeNote: 'solution bundle deploy' });
|
|
134
|
+
if (started.kind === 'already-ready')
|
|
135
|
+
return { ok: true, message: `${skillId} already set up` };
|
|
136
|
+
const job = await deps.jobs.waitForJob(started.job.jobId);
|
|
137
|
+
const tail = job.log.trim().split('\n').slice(-3).join(' | ');
|
|
138
|
+
return job.state === 'succeeded'
|
|
139
|
+
? { ok: true, message: `${skillId} installed and set up` }
|
|
140
|
+
: { ok: false, message: `${skillId} install failed${tail ? `: ${tail}` : ''}` };
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=bundle-skill-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-skill-installer.js","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-skill-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle deployment store — `<crewlyHome>/bundles/<templateId>.json`.
|
|
3
|
+
*
|
|
4
|
+
* One file per deployed template. The apply engine writes it after every
|
|
5
|
+
* step, so a crash or a failed step leaves an accurate record and a re-run
|
|
6
|
+
* resumes from it. Writes are atomic (temp file + rename).
|
|
7
|
+
*
|
|
8
|
+
* @module services/bundle/bundle-state.store
|
|
9
|
+
*/
|
|
10
|
+
import type { BundleDeployment } from '../../types/solution-bundle.types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Persists bundle deployments.
|
|
13
|
+
*/
|
|
14
|
+
export declare class BundleDeploymentStore {
|
|
15
|
+
private readonly dir;
|
|
16
|
+
/**
|
|
17
|
+
* @param crewlyHome - Crewly home directory
|
|
18
|
+
*/
|
|
19
|
+
constructor(crewlyHome: string);
|
|
20
|
+
/**
|
|
21
|
+
* File of a template's deployment.
|
|
22
|
+
*
|
|
23
|
+
* @param templateId - Template id (kebab case)
|
|
24
|
+
* @returns Absolute path
|
|
25
|
+
* @throws Error for an id that is not a safe file name
|
|
26
|
+
*/
|
|
27
|
+
fileFor(templateId: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Read a deployment.
|
|
30
|
+
*
|
|
31
|
+
* @param templateId - Template id
|
|
32
|
+
* @returns The deployment, or null when the template was never deployed (or the file is unreadable)
|
|
33
|
+
*/
|
|
34
|
+
read(templateId: string): Promise<BundleDeployment | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Write a deployment atomically.
|
|
37
|
+
*
|
|
38
|
+
* @param deployment - Deployment
|
|
39
|
+
*/
|
|
40
|
+
write(deployment: BundleDeployment): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Every stored deployment.
|
|
43
|
+
*
|
|
44
|
+
* @returns Deployments (unreadable files are skipped)
|
|
45
|
+
*/
|
|
46
|
+
list(): Promise<BundleDeployment[]>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=bundle-state.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-state.store.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-state.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAM7E;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B;;OAEG;gBACS,UAAU,EAAE,MAAM;IAI9B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAKnC;;;;;OAKG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAShE;;;;OAIG;IACG,KAAK,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxD;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAiB1C"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle deployment store — `<crewlyHome>/bundles/<templateId>.json`.
|
|
3
|
+
*
|
|
4
|
+
* One file per deployed template. The apply engine writes it after every
|
|
5
|
+
* step, so a crash or a failed step leaves an accurate record and a re-run
|
|
6
|
+
* resumes from it. Writes are atomic (temp file + rename).
|
|
7
|
+
*
|
|
8
|
+
* @module services/bundle/bundle-state.store
|
|
9
|
+
*/
|
|
10
|
+
import { promises as fs } from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { BUNDLE_CONSTANTS } from '../../constants.js';
|
|
13
|
+
import { atomicWriteFile } from '../../utils/file-io.utils.js';
|
|
14
|
+
/** Template ids become file names; keep them to safe characters. */
|
|
15
|
+
const SAFE_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Persists bundle deployments.
|
|
18
|
+
*/
|
|
19
|
+
export class BundleDeploymentStore {
|
|
20
|
+
dir;
|
|
21
|
+
/**
|
|
22
|
+
* @param crewlyHome - Crewly home directory
|
|
23
|
+
*/
|
|
24
|
+
constructor(crewlyHome) {
|
|
25
|
+
this.dir = path.join(crewlyHome, BUNDLE_CONSTANTS.STATE_DIR);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* File of a template's deployment.
|
|
29
|
+
*
|
|
30
|
+
* @param templateId - Template id (kebab case)
|
|
31
|
+
* @returns Absolute path
|
|
32
|
+
* @throws Error for an id that is not a safe file name
|
|
33
|
+
*/
|
|
34
|
+
fileFor(templateId) {
|
|
35
|
+
if (!SAFE_ID_PATTERN.test(templateId))
|
|
36
|
+
throw new Error(`Invalid template id: ${templateId}`);
|
|
37
|
+
return path.join(this.dir, `${templateId}.json`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read a deployment.
|
|
41
|
+
*
|
|
42
|
+
* @param templateId - Template id
|
|
43
|
+
* @returns The deployment, or null when the template was never deployed (or the file is unreadable)
|
|
44
|
+
*/
|
|
45
|
+
async read(templateId) {
|
|
46
|
+
try {
|
|
47
|
+
const parsed = JSON.parse(await fs.readFile(this.fileFor(templateId), 'utf-8'));
|
|
48
|
+
return parsed && parsed.templateId === templateId && Array.isArray(parsed.steps) ? parsed : null;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Write a deployment atomically.
|
|
56
|
+
*
|
|
57
|
+
* @param deployment - Deployment
|
|
58
|
+
*/
|
|
59
|
+
async write(deployment) {
|
|
60
|
+
await fs.mkdir(this.dir, { recursive: true });
|
|
61
|
+
await atomicWriteFile(this.fileFor(deployment.templateId), JSON.stringify(deployment, null, 2));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Every stored deployment.
|
|
65
|
+
*
|
|
66
|
+
* @returns Deployments (unreadable files are skipped)
|
|
67
|
+
*/
|
|
68
|
+
async list() {
|
|
69
|
+
let entries;
|
|
70
|
+
try {
|
|
71
|
+
entries = await fs.readdir(this.dir);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const entry of entries.sort()) {
|
|
78
|
+
if (!entry.endsWith('.json'))
|
|
79
|
+
continue;
|
|
80
|
+
const id = entry.slice(0, -'.json'.length);
|
|
81
|
+
if (!SAFE_ID_PATTERN.test(id))
|
|
82
|
+
continue;
|
|
83
|
+
const deployment = await this.read(id);
|
|
84
|
+
if (deployment)
|
|
85
|
+
out.push(deployment);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=bundle-state.store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-state.store.js","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-state.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,oEAAoE;AACpE,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C;;GAEG;AACH,MAAM,OAAO,qBAAqB;IACf,GAAG,CAAS;IAE7B;;OAEG;IACH,YAAY,UAAkB;QAC5B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,UAAkB;QACxB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAC7F,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,OAAO,CAAC,CAAC;IACnD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,UAAkB;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAqB,CAAC;YACpG,OAAO,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACnG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,UAA4B;QACtC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAuB,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACvC,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YACxC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvC,IAAI,UAAU;gBAAE,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the Crewly teams of a solution bundle.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `TemplateService.createTeamFromTemplate` (members per role,
|
|
5
|
+
* hierarchy wiring) with what bundles need on top: placeholder filling,
|
|
6
|
+
* deterministic team ids (so every re-run and the CLI find the same team),
|
|
7
|
+
* ASCII session names like the onboarding starters, and one runtime for
|
|
8
|
+
* every member.
|
|
9
|
+
*
|
|
10
|
+
* @module services/bundle/bundle-team.builder
|
|
11
|
+
*/
|
|
12
|
+
import type { Team, TeamMember } from '../../types/index.js';
|
|
13
|
+
import type { BundleTemplate } from '../../types/solution-bundle.types.js';
|
|
14
|
+
import type { NormalizedBundleTeam } from './bundle-manifest.js';
|
|
15
|
+
import { type BundleAnswers } from './bundle-placeholders.js';
|
|
16
|
+
/**
|
|
17
|
+
* Lower-case ASCII slug.
|
|
18
|
+
*
|
|
19
|
+
* @param value - Any text
|
|
20
|
+
* @returns Slug (may be empty for non-ASCII text)
|
|
21
|
+
*/
|
|
22
|
+
export declare function toSlug(value: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* The deterministic id of a bundle team: the template id for the main
|
|
25
|
+
* team, `<templateId>--<key>` for extra teams.
|
|
26
|
+
*
|
|
27
|
+
* @param templateId - Template id
|
|
28
|
+
* @param teamKey - Team key
|
|
29
|
+
* @returns Team id
|
|
30
|
+
*/
|
|
31
|
+
export declare function bundleTeamId(templateId: string, teamKey: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* The member name of the n-th member of a role.
|
|
34
|
+
*
|
|
35
|
+
* @param defaultName - Role default name
|
|
36
|
+
* @param count - Members in the role
|
|
37
|
+
* @param index - 0-based index
|
|
38
|
+
* @returns Name (`Writer`, or `Writer1`, `Writer2` …)
|
|
39
|
+
*/
|
|
40
|
+
export declare function memberNameFor(defaultName: string, count: number, index: number): string;
|
|
41
|
+
/**
|
|
42
|
+
* Values for a team's placeholders: the answers plus the built-ins.
|
|
43
|
+
*
|
|
44
|
+
* @param answers - Owner answers
|
|
45
|
+
* @param teamName - Filled team name
|
|
46
|
+
* @param leadName - The lead member's name
|
|
47
|
+
* @returns Placeholder values
|
|
48
|
+
*/
|
|
49
|
+
export declare function teamPlaceholderValues(answers: BundleAnswers, teamName: string, leadName: string): BundleAnswers;
|
|
50
|
+
/** Input of {@link buildBundleTeam}. */
|
|
51
|
+
export interface BuildBundleTeamInput {
|
|
52
|
+
template: BundleTemplate;
|
|
53
|
+
team: NormalizedBundleTeam;
|
|
54
|
+
answers: BundleAnswers;
|
|
55
|
+
runtime: string;
|
|
56
|
+
now: Date;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build one bundle team (not saved).
|
|
60
|
+
*
|
|
61
|
+
* @param input - Template, normalized team, answers, runtime, clock
|
|
62
|
+
* @returns The team, ready for `StorageService.saveTeam`
|
|
63
|
+
* @throws BundlePlaceholderError when a text keeps an unfilled placeholder
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildBundleTeam(input: BuildBundleTeamInput): Team;
|
|
66
|
+
/**
|
|
67
|
+
* Find the member a ref names in a built team.
|
|
68
|
+
*
|
|
69
|
+
* @param team - Saved team
|
|
70
|
+
* @param role - Role id (the first member of the role is returned)
|
|
71
|
+
* @returns The member, or undefined
|
|
72
|
+
*/
|
|
73
|
+
export declare function memberForRole(team: Team, role: string): TeamMember | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* The session name a member runs under (its permanent agent id).
|
|
76
|
+
*
|
|
77
|
+
* @param member - Member
|
|
78
|
+
* @returns Session name
|
|
79
|
+
*/
|
|
80
|
+
export declare function memberSession(member: TeamMember): string;
|
|
81
|
+
//# sourceMappingURL=bundle-team.builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-team.builder.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-team.builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEhF;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAE/G;AAED,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,IAAI,CAAC;CACX;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAmFjE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the Crewly teams of a solution bundle.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `TemplateService.createTeamFromTemplate` (members per role,
|
|
5
|
+
* hierarchy wiring) with what bundles need on top: placeholder filling,
|
|
6
|
+
* deterministic team ids (so every re-run and the CLI find the same team),
|
|
7
|
+
* ASCII session names like the onboarding starters, and one runtime for
|
|
8
|
+
* every member.
|
|
9
|
+
*
|
|
10
|
+
* @module services/bundle/bundle-team.builder
|
|
11
|
+
*/
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
import { BUNDLE_CONSTANTS } from '../../constants.js';
|
|
14
|
+
import { fillPlaceholders } from './bundle-placeholders.js';
|
|
15
|
+
/**
|
|
16
|
+
* Lower-case ASCII slug.
|
|
17
|
+
*
|
|
18
|
+
* @param value - Any text
|
|
19
|
+
* @returns Slug (may be empty for non-ASCII text)
|
|
20
|
+
*/
|
|
21
|
+
export function toSlug(value) {
|
|
22
|
+
return value
|
|
23
|
+
.toLowerCase()
|
|
24
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
25
|
+
.replace(/^-+|-+$/g, '');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The deterministic id of a bundle team: the template id for the main
|
|
29
|
+
* team, `<templateId>--<key>` for extra teams.
|
|
30
|
+
*
|
|
31
|
+
* @param templateId - Template id
|
|
32
|
+
* @param teamKey - Team key
|
|
33
|
+
* @returns Team id
|
|
34
|
+
*/
|
|
35
|
+
export function bundleTeamId(templateId, teamKey) {
|
|
36
|
+
return teamKey === BUNDLE_CONSTANTS.MAIN_TEAM_KEY
|
|
37
|
+
? templateId
|
|
38
|
+
: `${templateId}${BUNDLE_CONSTANTS.TEAM_ID_SEPARATOR}${teamKey}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The member name of the n-th member of a role.
|
|
42
|
+
*
|
|
43
|
+
* @param defaultName - Role default name
|
|
44
|
+
* @param count - Members in the role
|
|
45
|
+
* @param index - 0-based index
|
|
46
|
+
* @returns Name (`Writer`, or `Writer1`, `Writer2` …)
|
|
47
|
+
*/
|
|
48
|
+
export function memberNameFor(defaultName, count, index) {
|
|
49
|
+
return count > 1 ? `${defaultName}${index + 1}` : defaultName;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Values for a team's placeholders: the answers plus the built-ins.
|
|
53
|
+
*
|
|
54
|
+
* @param answers - Owner answers
|
|
55
|
+
* @param teamName - Filled team name
|
|
56
|
+
* @param leadName - The lead member's name
|
|
57
|
+
* @returns Placeholder values
|
|
58
|
+
*/
|
|
59
|
+
export function teamPlaceholderValues(answers, teamName, leadName) {
|
|
60
|
+
return { ...answers, team_name: teamName, lead_name: leadName };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build one bundle team (not saved).
|
|
64
|
+
*
|
|
65
|
+
* @param input - Template, normalized team, answers, runtime, clock
|
|
66
|
+
* @returns The team, ready for `StorageService.saveTeam`
|
|
67
|
+
* @throws BundlePlaceholderError when a text keeps an unfilled placeholder
|
|
68
|
+
*/
|
|
69
|
+
export function buildBundleTeam(input) {
|
|
70
|
+
const { template, team, answers, runtime, now } = input;
|
|
71
|
+
const iso = now.toISOString();
|
|
72
|
+
const teamId = bundleTeamId(template.id, team.key);
|
|
73
|
+
const teamSlug = toSlug(teamId) || 'team';
|
|
74
|
+
const leadRole = team.roles.find((r) => r.role === team.leadRole);
|
|
75
|
+
const leadName = leadRole ? memberNameFor(leadRole.defaultName, leadRole.count, 0) : '';
|
|
76
|
+
const nameValues = { ...answers, lead_name: leadName, team_name: '' };
|
|
77
|
+
const teamName = fillPlaceholders(team.name, nameValues, `team ${team.key} name`);
|
|
78
|
+
const values = teamPlaceholderValues(answers, teamName, leadName);
|
|
79
|
+
const members = [];
|
|
80
|
+
const idsByRole = new Map();
|
|
81
|
+
for (const role of team.roles) {
|
|
82
|
+
const ids = [];
|
|
83
|
+
for (let i = 0; i < role.count; i++) {
|
|
84
|
+
const id = randomUUID();
|
|
85
|
+
const name = memberNameFor(role.defaultName, role.count, i);
|
|
86
|
+
const sessionName = `${teamSlug}-${toSlug(name) || 'member'}-${id.slice(0, 8)}`;
|
|
87
|
+
const where = `${team.key}/${role.role}`;
|
|
88
|
+
members.push({
|
|
89
|
+
id,
|
|
90
|
+
name,
|
|
91
|
+
sessionName,
|
|
92
|
+
agentId: sessionName,
|
|
93
|
+
role: role.role,
|
|
94
|
+
systemPrompt: fillPlaceholders(role.promptAdditions ?? '', values, `${where} promptAdditions`),
|
|
95
|
+
agentStatus: 'inactive',
|
|
96
|
+
workingStatus: 'idle',
|
|
97
|
+
runtimeType: runtime,
|
|
98
|
+
hierarchyLevel: role.hierarchyLevel,
|
|
99
|
+
canDelegate: role.canDelegate,
|
|
100
|
+
skillOverrides: role.defaultSkills.length > 0 ? [...role.defaultSkills] : undefined,
|
|
101
|
+
excludedRoleSkills: role.excludedSkills,
|
|
102
|
+
createdAt: iso,
|
|
103
|
+
updatedAt: iso,
|
|
104
|
+
jobTitle: role.jobTitle ?? role.label,
|
|
105
|
+
jobDescription: role.jobDescription ? fillPlaceholders(role.jobDescription, values, `${where} jobDescription`) : undefined,
|
|
106
|
+
ownershipScope: role.ownershipScope,
|
|
107
|
+
responsibilityType: role.responsibilityType,
|
|
108
|
+
autonomyLevel: role.autonomyLevel,
|
|
109
|
+
expertId: role.expertId,
|
|
110
|
+
domainSOP: role.domainSOP,
|
|
111
|
+
riskPolicy: role.riskPolicy,
|
|
112
|
+
});
|
|
113
|
+
ids.push(id);
|
|
114
|
+
}
|
|
115
|
+
idsByRole.set(role.role, ids);
|
|
116
|
+
}
|
|
117
|
+
// Hierarchy: every member of a role reports to the first member of its parent role.
|
|
118
|
+
for (const role of team.roles) {
|
|
119
|
+
if (!role.reportsTo)
|
|
120
|
+
continue;
|
|
121
|
+
const parentId = idsByRole.get(role.reportsTo)?.[0];
|
|
122
|
+
if (!parentId)
|
|
123
|
+
continue;
|
|
124
|
+
const childIds = idsByRole.get(role.role) ?? [];
|
|
125
|
+
for (const childId of childIds) {
|
|
126
|
+
const child = members.find((m) => m.id === childId);
|
|
127
|
+
if (child)
|
|
128
|
+
child.parentMemberId = parentId;
|
|
129
|
+
}
|
|
130
|
+
const parent = members.find((m) => m.id === parentId);
|
|
131
|
+
if (parent)
|
|
132
|
+
parent.subordinateIds = [...(parent.subordinateIds ?? []), ...childIds];
|
|
133
|
+
}
|
|
134
|
+
const leaderId = idsByRole.get(team.leadRole)?.[0];
|
|
135
|
+
const description = team.description ? fillPlaceholders(team.description, values, `team ${team.key} description`) : undefined;
|
|
136
|
+
const mission = team.key === BUNDLE_CONSTANTS.MAIN_TEAM_KEY && template.mission
|
|
137
|
+
? fillPlaceholders(template.mission, values, 'mission')
|
|
138
|
+
: undefined;
|
|
139
|
+
return {
|
|
140
|
+
id: teamId,
|
|
141
|
+
name: teamName,
|
|
142
|
+
...(description ? { description } : {}),
|
|
143
|
+
members,
|
|
144
|
+
projectIds: [],
|
|
145
|
+
hierarchical: template.hierarchical ?? true,
|
|
146
|
+
...(leaderId ? { leaderId, leaderIds: [leaderId] } : {}),
|
|
147
|
+
templateId: template.id,
|
|
148
|
+
...(mission ? { mission } : {}),
|
|
149
|
+
createdAt: iso,
|
|
150
|
+
updatedAt: iso,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Find the member a ref names in a built team.
|
|
155
|
+
*
|
|
156
|
+
* @param team - Saved team
|
|
157
|
+
* @param role - Role id (the first member of the role is returned)
|
|
158
|
+
* @returns The member, or undefined
|
|
159
|
+
*/
|
|
160
|
+
export function memberForRole(team, role) {
|
|
161
|
+
return team.members.find((m) => m.role === role);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The session name a member runs under (its permanent agent id).
|
|
165
|
+
*
|
|
166
|
+
* @param member - Member
|
|
167
|
+
* @returns Session name
|
|
168
|
+
*/
|
|
169
|
+
export function memberSession(member) {
|
|
170
|
+
return member.agentId || member.sessionName;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=bundle-team.builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-team.builder.js","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-team.builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,EAAE,gBAAgB,EAAsB,MAAM,0BAA0B,CAAC;AAEhF;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,KAAK;SACT,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,OAAe;IAC9D,OAAO,OAAO,KAAK,gBAAgB,CAAC,aAAa;QAC/C,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,GAAG,UAAU,GAAG,gBAAgB,CAAC,iBAAiB,GAAG,OAAO,EAAE,CAAC;AACrE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,KAAa,EAAE,KAAa;IAC7E,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAsB,EAAE,QAAgB,EAAE,QAAgB;IAC9F,OAAO,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AAClE,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,MAAM,UAAU,GAAG,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IACtE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAElE,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5D,MAAM,WAAW,GAAG,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,QAAQ,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAChF,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE;gBACF,IAAI;gBACJ,WAAW;gBACX,OAAO,EAAE,WAAW;gBACpB,IAAI,EAAE,IAAI,CAAC,IAAsB;gBACjC,YAAY,EAAE,gBAAgB,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,kBAAkB,CAAC;gBAC9F,WAAW,EAAE,UAAU;gBACvB,aAAa,EAAE,MAAM;gBACrB,WAAW,EAAE,OAAoC;gBACjD,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,cAAc,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;gBACnF,kBAAkB,EAAE,IAAI,CAAC,cAAc;gBACvC,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE,GAAG;gBACd,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK;gBACrC,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,KAAK,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC1H,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;gBAC3C,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B,CAAC,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,oFAAoF;IACpF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QAC9B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAChD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;YACpD,IAAI,KAAK;gBAAE,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC7C,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACtD,IAAI,MAAM;YAAE,MAAM,CAAC,cAAc,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9H,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,KAAK,gBAAgB,CAAC,aAAa,IAAI,QAAQ,CAAC,OAAO;QAC7E,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC;QACvD,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO;QACL,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,QAAQ;QACd,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO;QACP,UAAU,EAAE,EAAE;QACd,YAAY,EAAE,QAAQ,CAAC,YAAY,IAAI,IAAI;QAC3C,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU,EAAE,IAAY;IACpD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAkB;IAC9C,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,WAAW,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time helpers for bundle first-week tasks: "day 2 at 09:00 in the
|
|
3
|
+
* bundle's timezone" as a UTC instant, independent of the server's own
|
|
4
|
+
* timezone (hosted servers run in UTC; owners mostly do not).
|
|
5
|
+
*
|
|
6
|
+
* @module services/bundle/bundle-time
|
|
7
|
+
*/
|
|
8
|
+
/** Calendar date and time in some timezone. */
|
|
9
|
+
interface ZonedParts {
|
|
10
|
+
year: number;
|
|
11
|
+
month: number;
|
|
12
|
+
day: number;
|
|
13
|
+
hour: number;
|
|
14
|
+
minute: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether a string is a valid IANA timezone.
|
|
18
|
+
*
|
|
19
|
+
* @param tz - Candidate
|
|
20
|
+
* @returns True when Intl accepts it
|
|
21
|
+
*/
|
|
22
|
+
export declare function isValidTimezone(tz: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Calendar parts of an instant in a timezone.
|
|
25
|
+
*
|
|
26
|
+
* @param date - Instant
|
|
27
|
+
* @param tz - IANA timezone
|
|
28
|
+
* @returns Year, month (1-12), day, hour, minute
|
|
29
|
+
*/
|
|
30
|
+
export declare function zonedParts(date: Date, tz: string): ZonedParts;
|
|
31
|
+
/**
|
|
32
|
+
* The UTC instant of a wall-clock time in a timezone.
|
|
33
|
+
*
|
|
34
|
+
* Starts from the wall time read as UTC, then corrects by the zone's offset
|
|
35
|
+
* at that instant (twice, which settles DST edges).
|
|
36
|
+
*
|
|
37
|
+
* @param wall - Calendar date and time in `tz`
|
|
38
|
+
* @param tz - IANA timezone
|
|
39
|
+
* @returns The instant
|
|
40
|
+
*/
|
|
41
|
+
export declare function zonedTimeToUtc(wall: ZonedParts, tz: string): Date;
|
|
42
|
+
/**
|
|
43
|
+
* When a first-week task is due.
|
|
44
|
+
*
|
|
45
|
+
* Day 0 is due at `deployedAt`. Day n is due at `time` (default 09:00) on
|
|
46
|
+
* the n-th calendar day after the deploy day, in `tz`.
|
|
47
|
+
*
|
|
48
|
+
* @param deployedAt - When the bundle was applied
|
|
49
|
+
* @param day - 0-based day
|
|
50
|
+
* @param time - `HH:MM` (optional)
|
|
51
|
+
* @param tz - IANA timezone
|
|
52
|
+
* @returns ISO timestamp
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* firstWeekDueAt(new Date('2026-09-25T02:00:00Z'), 1, '09:00', 'Asia/Shanghai') // '2026-09-26T01:00:00.000Z'
|
|
56
|
+
*/
|
|
57
|
+
export declare function firstWeekDueAt(deployedAt: Date, day: number, time: string | undefined, tz: string): string;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=bundle-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-time.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/bundle/bundle-time.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,+CAA+C;AAC/C,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAmB7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CASjE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAU1G"}
|