@agentworkforce/deploy 0.0.0
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/bundle.d.ts +22 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +132 -0
- package/dist/bundle.js.map +1 -0
- package/dist/bundle.test.d.ts +2 -0
- package/dist/bundle.test.d.ts.map +1 -0
- package/dist/bundle.test.js +92 -0
- package/dist/bundle.test.js.map +1 -0
- package/dist/connect.d.ts +81 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +127 -0
- package/dist/connect.js.map +1 -0
- package/dist/deploy.d.ts +50 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +172 -0
- package/dist/deploy.js.map +1 -0
- package/dist/deploy.test.d.ts +2 -0
- package/dist/deploy.test.d.ts.map +1 -0
- package/dist/deploy.test.js +293 -0
- package/dist/deploy.test.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +22 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +76 -0
- package/dist/io.js.map +1 -0
- package/dist/login.d.ts +24 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +27 -0
- package/dist/login.js.map +1 -0
- package/dist/modes/cloud.d.ts +18 -0
- package/dist/modes/cloud.d.ts.map +1 -0
- package/dist/modes/cloud.js +21 -0
- package/dist/modes/cloud.js.map +1 -0
- package/dist/modes/dev.d.ts +12 -0
- package/dist/modes/dev.d.ts.map +1 -0
- package/dist/modes/dev.js +153 -0
- package/dist/modes/dev.js.map +1 -0
- package/dist/modes/sandbox-client.d.ts +63 -0
- package/dist/modes/sandbox-client.d.ts.map +1 -0
- package/dist/modes/sandbox-client.js +177 -0
- package/dist/modes/sandbox-client.js.map +1 -0
- package/dist/modes/sandbox-client.test.d.ts +2 -0
- package/dist/modes/sandbox-client.test.d.ts.map +1 -0
- package/dist/modes/sandbox-client.test.js +177 -0
- package/dist/modes/sandbox-client.test.js.map +1 -0
- package/dist/modes/sandbox.d.ts +50 -0
- package/dist/modes/sandbox.d.ts.map +1 -0
- package/dist/modes/sandbox.js +131 -0
- package/dist/modes/sandbox.js.map +1 -0
- package/dist/modes/sandbox.test.d.ts +2 -0
- package/dist/modes/sandbox.test.d.ts.map +1 -0
- package/dist/modes/sandbox.test.js +95 -0
- package/dist/modes/sandbox.test.js.map +1 -0
- package/dist/preflight.d.ts +14 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +78 -0
- package/dist/preflight.js.map +1 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -0
package/dist/bundle.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BundleStager } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stage a deploy-ready bundle to `input.outDir`. Output layout:
|
|
4
|
+
*
|
|
5
|
+
* <outDir>/
|
|
6
|
+
* agent.bundle.mjs — esbuilt user `onEvent` (default-exported handler)
|
|
7
|
+
* runner.mjs — entry that imports the runtime + bundle + persona
|
|
8
|
+
* persona.json — verbatim copy of the input persona spec
|
|
9
|
+
* package.json — minimal manifest pinning the runtime dep
|
|
10
|
+
*
|
|
11
|
+
* The bundle is idempotent: re-running with the same `outDir` overwrites
|
|
12
|
+
* the four files cleanly. Auxiliary files left behind from earlier runs
|
|
13
|
+
* are not touched (callers control the directory lifecycle).
|
|
14
|
+
*
|
|
15
|
+
* Externals: every `node:*` builtin and `@agentworkforce/runtime` itself
|
|
16
|
+
* are left external so the runner can resolve them at execution time.
|
|
17
|
+
* Bundling the runtime in would require shipping the runtime sources into
|
|
18
|
+
* every sandbox; the chosen split keeps the bundle small and lets ops
|
|
19
|
+
* patch the runtime without rebuilding every persona.
|
|
20
|
+
*/
|
|
21
|
+
export declare const bundleStager: BundleStager;
|
|
22
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkC,YAAY,EAAE,MAAM,YAAY,CAAC;AAS/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,EAAE,YAyD1B,CAAC"}
|
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { mkdir, writeFile, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { build } from 'esbuild';
|
|
4
|
+
/**
|
|
5
|
+
* Versioned identifier embedded in the generated runner so a future
|
|
6
|
+
* bundle reader can detect format drift. Bumped whenever the runner
|
|
7
|
+
* shape changes incompatibly.
|
|
8
|
+
*/
|
|
9
|
+
const RUNNER_FORMAT_VERSION = 1;
|
|
10
|
+
/**
|
|
11
|
+
* Stage a deploy-ready bundle to `input.outDir`. Output layout:
|
|
12
|
+
*
|
|
13
|
+
* <outDir>/
|
|
14
|
+
* agent.bundle.mjs — esbuilt user `onEvent` (default-exported handler)
|
|
15
|
+
* runner.mjs — entry that imports the runtime + bundle + persona
|
|
16
|
+
* persona.json — verbatim copy of the input persona spec
|
|
17
|
+
* package.json — minimal manifest pinning the runtime dep
|
|
18
|
+
*
|
|
19
|
+
* The bundle is idempotent: re-running with the same `outDir` overwrites
|
|
20
|
+
* the four files cleanly. Auxiliary files left behind from earlier runs
|
|
21
|
+
* are not touched (callers control the directory lifecycle).
|
|
22
|
+
*
|
|
23
|
+
* Externals: every `node:*` builtin and `@agentworkforce/runtime` itself
|
|
24
|
+
* are left external so the runner can resolve them at execution time.
|
|
25
|
+
* Bundling the runtime in would require shipping the runtime sources into
|
|
26
|
+
* every sandbox; the chosen split keeps the bundle small and lets ops
|
|
27
|
+
* patch the runtime without rebuilding every persona.
|
|
28
|
+
*/
|
|
29
|
+
export const bundleStager = {
|
|
30
|
+
async stage(input) {
|
|
31
|
+
await mkdir(input.outDir, { recursive: true });
|
|
32
|
+
const onEventAbs = path.resolve(path.dirname(input.personaPath), input.persona.onEvent ?? '');
|
|
33
|
+
if (!input.persona.onEvent) {
|
|
34
|
+
throw new Error(`bundle: persona "${input.persona.id}" is missing onEvent (cannot stage a bundle without a handler)`);
|
|
35
|
+
}
|
|
36
|
+
await assertReadableFile(onEventAbs, `persona "${input.persona.id}" onEvent`);
|
|
37
|
+
const bundlePath = path.join(input.outDir, 'agent.bundle.mjs');
|
|
38
|
+
const runnerPath = path.join(input.outDir, 'runner.mjs');
|
|
39
|
+
const personaCopyPath = path.join(input.outDir, 'persona.json');
|
|
40
|
+
const packageJsonPath = path.join(input.outDir, 'package.json');
|
|
41
|
+
await build({
|
|
42
|
+
entryPoints: [onEventAbs],
|
|
43
|
+
outfile: bundlePath,
|
|
44
|
+
bundle: true,
|
|
45
|
+
format: 'esm',
|
|
46
|
+
platform: 'node',
|
|
47
|
+
target: 'node20',
|
|
48
|
+
sourcemap: 'inline',
|
|
49
|
+
logLevel: 'silent',
|
|
50
|
+
minify: input.bundlerOptions?.minify ?? false,
|
|
51
|
+
// Resolve TypeScript / JS extensions without forcing the user to
|
|
52
|
+
// write `.ts`-suffixed imports in their handler file.
|
|
53
|
+
resolveExtensions: ['.ts', '.mts', '.cts', '.tsx', '.js', '.mjs', '.cjs', '.jsx', '.json'],
|
|
54
|
+
external: [
|
|
55
|
+
// Runtime stays external — see file header comment.
|
|
56
|
+
'@agentworkforce/runtime',
|
|
57
|
+
'@agentworkforce/runtime/raw',
|
|
58
|
+
// Node builtins must never be bundled.
|
|
59
|
+
'node:*'
|
|
60
|
+
]
|
|
61
|
+
});
|
|
62
|
+
await writeFile(personaCopyPath, JSON.stringify(input.persona, null, 2) + '\n', 'utf8');
|
|
63
|
+
await writeFile(packageJsonPath, buildPackageJson(input.persona.id), 'utf8');
|
|
64
|
+
await writeFile(runnerPath, renderRunner(), 'utf8');
|
|
65
|
+
const bundleStat = await stat(bundlePath);
|
|
66
|
+
const runnerStat = await stat(runnerPath);
|
|
67
|
+
const sizeBytes = bundleStat.size + runnerStat.size;
|
|
68
|
+
return {
|
|
69
|
+
personaCopyPath,
|
|
70
|
+
runnerPath,
|
|
71
|
+
bundlePath,
|
|
72
|
+
packageJsonPath,
|
|
73
|
+
sizeBytes
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
function buildPackageJson(personaId) {
|
|
78
|
+
return (JSON.stringify({
|
|
79
|
+
name: `@agentworkforce/deployed-${personaId}`,
|
|
80
|
+
private: true,
|
|
81
|
+
version: '0.0.0',
|
|
82
|
+
type: 'module',
|
|
83
|
+
main: './runner.mjs',
|
|
84
|
+
dependencies: {
|
|
85
|
+
'@agentworkforce/runtime': '*'
|
|
86
|
+
},
|
|
87
|
+
comment: 'Generated by workforce deploy. The runtime dep is pinned to "*" because deploys resolve the runtime version from the active workspace.'
|
|
88
|
+
}, null, 2) + '\n');
|
|
89
|
+
}
|
|
90
|
+
function renderRunner() {
|
|
91
|
+
return `// Generated by @agentworkforce/deploy. Format version ${RUNNER_FORMAT_VERSION}.
|
|
92
|
+
// Do not edit by hand — \`workforce deploy\` overwrites this file on every stage.
|
|
93
|
+
//
|
|
94
|
+
// The runner imports the user's handler from the esbuilt bundle, the
|
|
95
|
+
// parsed persona spec from the verbatim JSON copy, and the runtime's
|
|
96
|
+
// \`startRunner\` to drive the dispatch loop. Envelopes arrive on stdin
|
|
97
|
+
// as NDJSON; structured logs go to stdout.
|
|
98
|
+
|
|
99
|
+
import { createRequire } from 'node:module';
|
|
100
|
+
import { startRunner } from '@agentworkforce/runtime/runner';
|
|
101
|
+
import { handler as wrapHandler } from '@agentworkforce/runtime';
|
|
102
|
+
import * as userModule from './agent.bundle.mjs';
|
|
103
|
+
|
|
104
|
+
const require = createRequire(import.meta.url);
|
|
105
|
+
const persona = require('./persona.json');
|
|
106
|
+
|
|
107
|
+
const candidate = userModule.default ?? userModule.handler;
|
|
108
|
+
if (typeof candidate !== 'function') {
|
|
109
|
+
throw new TypeError(
|
|
110
|
+
\`workforce deploy bundle: \${persona.id} did not default-export a function. Did you forget \\\`export default handler(...)\\\`?\`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const handler = candidate.__workforceHandler ? candidate : wrapHandler(candidate);
|
|
114
|
+
|
|
115
|
+
await startRunner({ persona, handler });
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
async function assertReadableFile(abs, label) {
|
|
119
|
+
try {
|
|
120
|
+
const st = await stat(abs);
|
|
121
|
+
if (!st.isFile()) {
|
|
122
|
+
throw new Error(`${label}: ${abs} is not a regular file`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
if (err.code === 'ENOENT') {
|
|
127
|
+
throw new Error(`${label}: file not found at ${abs}`);
|
|
128
|
+
}
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.test.d.ts","sourceRoot":"","sources":["../src/bundle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { bundleStager } from './bundle.js';
|
|
7
|
+
function persona(overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'bundle-fixture',
|
|
10
|
+
intent: 'documentation',
|
|
11
|
+
tags: ['documentation'],
|
|
12
|
+
description: 'fixture for bundle tests',
|
|
13
|
+
skills: [],
|
|
14
|
+
harness: 'claude',
|
|
15
|
+
model: 'anthropic/claude-3-5-sonnet',
|
|
16
|
+
systemPrompt: 'be helpful',
|
|
17
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 },
|
|
18
|
+
cloud: true,
|
|
19
|
+
schedules: [{ name: 'weekly', cron: '0 9 * * 6' }],
|
|
20
|
+
onEvent: './agent.ts',
|
|
21
|
+
...overrides
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
test('bundleStager produces an executable, importable bundle from a real onEvent file', async () => {
|
|
25
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), 'wf-bundle-'));
|
|
26
|
+
try {
|
|
27
|
+
const personaPath = path.join(dir, 'persona.json');
|
|
28
|
+
const personaSpec = persona();
|
|
29
|
+
await writeFile(personaPath, JSON.stringify(personaSpec, null, 2), 'utf8');
|
|
30
|
+
await writeFile(path.join(dir, 'agent.ts'), [
|
|
31
|
+
"import { handler } from '@agentworkforce/runtime';",
|
|
32
|
+
'',
|
|
33
|
+
'export default handler(async (ctx, event) => {',
|
|
34
|
+
" ctx.log('info', 'fixture.handler.fired', { eventId: event.id });",
|
|
35
|
+
'});',
|
|
36
|
+
''
|
|
37
|
+
].join('\n'), 'utf8');
|
|
38
|
+
const outDir = path.join(dir, 'build');
|
|
39
|
+
const result = await bundleStager.stage({
|
|
40
|
+
personaPath,
|
|
41
|
+
persona: personaSpec,
|
|
42
|
+
outDir
|
|
43
|
+
});
|
|
44
|
+
assert.equal(result.personaCopyPath, path.join(outDir, 'persona.json'));
|
|
45
|
+
assert.equal(result.runnerPath, path.join(outDir, 'runner.mjs'));
|
|
46
|
+
assert.equal(result.bundlePath, path.join(outDir, 'agent.bundle.mjs'));
|
|
47
|
+
assert.equal(result.packageJsonPath, path.join(outDir, 'package.json'));
|
|
48
|
+
assert.ok(result.sizeBytes > 0);
|
|
49
|
+
// persona.json round-trips verbatim
|
|
50
|
+
const personaCopy = JSON.parse(await readFile(result.personaCopyPath, 'utf8'));
|
|
51
|
+
assert.equal(personaCopy.id, personaSpec.id);
|
|
52
|
+
assert.equal(personaCopy.onEvent, './agent.ts');
|
|
53
|
+
// runner imports the expected entry points
|
|
54
|
+
const runnerSource = await readFile(result.runnerPath, 'utf8');
|
|
55
|
+
assert.match(runnerSource, /from '@agentworkforce\/runtime\/runner'/);
|
|
56
|
+
assert.match(runnerSource, /from '@agentworkforce\/runtime'/);
|
|
57
|
+
assert.match(runnerSource, /import \* as userModule from '\.\/agent\.bundle\.mjs'/);
|
|
58
|
+
// bundle output is ES module shape and references the runtime as external
|
|
59
|
+
const bundleSource = await readFile(result.bundlePath, 'utf8');
|
|
60
|
+
assert.match(bundleSource, /^import /m);
|
|
61
|
+
assert.match(bundleSource, /from\s+['"]@agentworkforce\/runtime['"]/);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
await rm(dir, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
test('bundleStager throws when onEvent file is missing', async () => {
|
|
68
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), 'wf-bundle-'));
|
|
69
|
+
try {
|
|
70
|
+
const personaPath = path.join(dir, 'persona.json');
|
|
71
|
+
const personaSpec = persona({ onEvent: './missing.ts' });
|
|
72
|
+
await writeFile(personaPath, JSON.stringify(personaSpec, null, 2), 'utf8');
|
|
73
|
+
await assert.rejects(() => bundleStager.stage({ personaPath, persona: personaSpec, outDir: path.join(dir, 'build') }), /file not found/);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await rm(dir, { recursive: true, force: true });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
test('bundleStager throws when persona has no onEvent', async () => {
|
|
80
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), 'wf-bundle-'));
|
|
81
|
+
try {
|
|
82
|
+
const personaPath = path.join(dir, 'persona.json');
|
|
83
|
+
const personaSpec = persona();
|
|
84
|
+
delete personaSpec.onEvent;
|
|
85
|
+
await writeFile(personaPath, JSON.stringify(personaSpec, null, 2), 'utf8');
|
|
86
|
+
await assert.rejects(() => bundleStager.stage({ personaPath, persona: personaSpec, outDir: path.join(dir, 'build') }), /missing onEvent/);
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
await rm(dir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=bundle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.test.js","sourceRoot":"","sources":["../src/bundle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { PersonaSpec } from '@agentworkforce/persona-kit';
|
|
2
|
+
import type { DeployIO, IntegrationConnectOutcome } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolver the orchestrator uses to check + connect a Relayfile-backed
|
|
5
|
+
* provider for the active workspace. The deploy package does not depend
|
|
6
|
+
* on `@relayfile/sdk` directly; the CLI dispatches the real implementation
|
|
7
|
+
* (which imports the SDK) into this contract.
|
|
8
|
+
*
|
|
9
|
+
* Decoupling this keeps the orchestrator unit-testable without spinning
|
|
10
|
+
* up Relayfile and keeps the SDK out of the deploy package's transitive
|
|
11
|
+
* dep tree (smaller bin, faster install).
|
|
12
|
+
*/
|
|
13
|
+
export interface IntegrationConnectResolver {
|
|
14
|
+
/** Is the provider already linked to the workspace? */
|
|
15
|
+
isConnected(args: {
|
|
16
|
+
workspace: string;
|
|
17
|
+
provider: string;
|
|
18
|
+
}): Promise<boolean>;
|
|
19
|
+
/** Run the browser-based OAuth flow and resolve when the user finishes. */
|
|
20
|
+
connect(args: {
|
|
21
|
+
workspace: string;
|
|
22
|
+
provider: string;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
connectionId: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Provider linker for `useSubscription: true` personas — connects the
|
|
29
|
+
* user's chosen LLM provider so cloud inference is billed against their
|
|
30
|
+
* subscription rather than workforce.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProviderSubscriptionResolver {
|
|
33
|
+
isConnected(args: {
|
|
34
|
+
workspace: string;
|
|
35
|
+
providerHint?: string;
|
|
36
|
+
}): Promise<boolean>;
|
|
37
|
+
connect(args: {
|
|
38
|
+
workspace: string;
|
|
39
|
+
providerHint?: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
provider: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolver backed by env vars. Used as the default when no higher-level
|
|
46
|
+
* implementation is plugged in. `isConnected` returns true exactly when
|
|
47
|
+
* one of the two recognized env vars is set for the provider; `connect`
|
|
48
|
+
* is a no-op that records the env-resolved nature of the connection so
|
|
49
|
+
* the orchestrator's flow stays uniform across resolvers.
|
|
50
|
+
*/
|
|
51
|
+
export declare function envIntegrationResolver(): IntegrationConnectResolver;
|
|
52
|
+
export interface ConnectAllInput {
|
|
53
|
+
persona: PersonaSpec;
|
|
54
|
+
workspace: string;
|
|
55
|
+
noConnect: boolean;
|
|
56
|
+
io: DeployIO;
|
|
57
|
+
integrations: IntegrationConnectResolver;
|
|
58
|
+
/** Required only when persona.useSubscription is true. */
|
|
59
|
+
subscription?: ProviderSubscriptionResolver;
|
|
60
|
+
}
|
|
61
|
+
export interface ConnectAllResult {
|
|
62
|
+
outcomes: IntegrationConnectOutcome[];
|
|
63
|
+
/** Provider the subscription was bound to, when applicable. */
|
|
64
|
+
subscriptionProvider?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Walk the persona's declared integrations and ensure each is connected.
|
|
68
|
+
* Per the deploy-v1 spec, the orchestrator prompts before each provider's
|
|
69
|
+
* connect flow ("Connect github now? (Y/n)") so users running on a shared
|
|
70
|
+
* machine don't have surprise browser pops.
|
|
71
|
+
*
|
|
72
|
+
* Behavior summary:
|
|
73
|
+
* - integrations: {} or undefined → returns immediately, no prompts
|
|
74
|
+
* - already-connected provider → no prompt; emits `already-connected`
|
|
75
|
+
* - not connected + noConnect=true → fails the deploy with a clear message
|
|
76
|
+
* - not connected + noConnect=false → prompts; on yes runs `connect`,
|
|
77
|
+
* on no marks `skipped`. The orchestrator decides what to do with
|
|
78
|
+
* `skipped` outcomes (today: fails the deploy at the call site).
|
|
79
|
+
*/
|
|
80
|
+
export declare function connectIntegrations(input: ConnectAllInput): Promise<ConnectAllResult>;
|
|
81
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAkBtE;;;;;;;;;GASG;AACH,MAAM,WAAW,0BAA0B;IACzC,uDAAuD;IACvD,WAAW,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,2EAA2E;IAC3E,OAAO,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3F;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClF,OAAO,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5F;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,0BAA0B,CAcnE;AAUD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,EAAE,QAAQ,CAAC;IACb,YAAY,EAAE,0BAA0B,CAAC;IACzC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,4BAA4B,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,yBAAyB,EAAE,CAAC;IACtC,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0F3F"}
|
package/dist/connect.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider env-var conventions the deploy CLI checks when no higher-level
|
|
3
|
+
* integration resolver is supplied. The convention is:
|
|
4
|
+
*
|
|
5
|
+
* - `WORKFORCE_INTEGRATION_<PROVIDER>_TOKEN` — direct provider token
|
|
6
|
+
* (e.g. `WORKFORCE_INTEGRATION_GITHUB_TOKEN`). Treated as "connected"
|
|
7
|
+
* when present and non-empty.
|
|
8
|
+
* - or `WORKFORCE_INTEGRATION_<PROVIDER>_CONNECTION_ID` — Relayfile
|
|
9
|
+
* connection id, resolved to a scoped token at runtime by the agent.
|
|
10
|
+
*
|
|
11
|
+
* The connect side is a no-op for the env path: there is nothing to
|
|
12
|
+
* authenticate interactively. Authors plug a higher-level resolver into
|
|
13
|
+
* `DeployResolvers.integrations` once Relayfile's OAuth surface is wired.
|
|
14
|
+
*/
|
|
15
|
+
const PROVIDER_ENV_PREFIX = 'WORKFORCE_INTEGRATION_';
|
|
16
|
+
/**
|
|
17
|
+
* Resolver backed by env vars. Used as the default when no higher-level
|
|
18
|
+
* implementation is plugged in. `isConnected` returns true exactly when
|
|
19
|
+
* one of the two recognized env vars is set for the provider; `connect`
|
|
20
|
+
* is a no-op that records the env-resolved nature of the connection so
|
|
21
|
+
* the orchestrator's flow stays uniform across resolvers.
|
|
22
|
+
*/
|
|
23
|
+
export function envIntegrationResolver() {
|
|
24
|
+
return {
|
|
25
|
+
async isConnected({ provider }) {
|
|
26
|
+
return providerHasEnvCredentials(provider);
|
|
27
|
+
},
|
|
28
|
+
async connect({ provider }) {
|
|
29
|
+
if (!providerHasEnvCredentials(provider)) {
|
|
30
|
+
throw new Error(`env resolver: ${provider} is not connected. Set ${PROVIDER_ENV_PREFIX}${provider.toUpperCase()}_TOKEN or ${PROVIDER_ENV_PREFIX}${provider.toUpperCase()}_CONNECTION_ID, then re-run deploy. (Higher-level resolvers — e.g. a Relayfile OAuth flow — plug in via DeployResolvers.integrations.)`);
|
|
31
|
+
}
|
|
32
|
+
return { connectionId: `env:${provider}` };
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function providerHasEnvCredentials(provider) {
|
|
37
|
+
const upper = provider.toUpperCase();
|
|
38
|
+
return Boolean(process.env[`${PROVIDER_ENV_PREFIX}${upper}_TOKEN`] ||
|
|
39
|
+
process.env[`${PROVIDER_ENV_PREFIX}${upper}_CONNECTION_ID`]);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Walk the persona's declared integrations and ensure each is connected.
|
|
43
|
+
* Per the deploy-v1 spec, the orchestrator prompts before each provider's
|
|
44
|
+
* connect flow ("Connect github now? (Y/n)") so users running on a shared
|
|
45
|
+
* machine don't have surprise browser pops.
|
|
46
|
+
*
|
|
47
|
+
* Behavior summary:
|
|
48
|
+
* - integrations: {} or undefined → returns immediately, no prompts
|
|
49
|
+
* - already-connected provider → no prompt; emits `already-connected`
|
|
50
|
+
* - not connected + noConnect=true → fails the deploy with a clear message
|
|
51
|
+
* - not connected + noConnect=false → prompts; on yes runs `connect`,
|
|
52
|
+
* on no marks `skipped`. The orchestrator decides what to do with
|
|
53
|
+
* `skipped` outcomes (today: fails the deploy at the call site).
|
|
54
|
+
*/
|
|
55
|
+
export async function connectIntegrations(input) {
|
|
56
|
+
const integrations = input.persona.integrations ?? {};
|
|
57
|
+
const outcomes = [];
|
|
58
|
+
for (const provider of Object.keys(integrations)) {
|
|
59
|
+
const connected = await input.integrations
|
|
60
|
+
.isConnected({ workspace: input.workspace, provider })
|
|
61
|
+
.catch((err) => {
|
|
62
|
+
input.io.warn(`failed to check connection status for ${provider}: ${err instanceof Error ? err.message : String(err)}`);
|
|
63
|
+
return false;
|
|
64
|
+
});
|
|
65
|
+
if (connected) {
|
|
66
|
+
input.io.info(`integrations.${provider}: already connected`);
|
|
67
|
+
outcomes.push({ provider, status: 'already-connected' });
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (input.noConnect) {
|
|
71
|
+
input.io.error(`integrations.${provider}: not connected, and --no-connect was passed`);
|
|
72
|
+
outcomes.push({
|
|
73
|
+
provider,
|
|
74
|
+
status: 'failed',
|
|
75
|
+
message: 'not connected (--no-connect was set)'
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const shouldConnect = await input.io.confirm(`Connect ${provider} now? (opens browser)`, { defaultValue: true });
|
|
80
|
+
if (!shouldConnect) {
|
|
81
|
+
outcomes.push({ provider, status: 'skipped', message: 'user declined to connect' });
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const result = await input.integrations.connect({ workspace: input.workspace, provider });
|
|
86
|
+
input.io.info(`integrations.${provider}: connected (${result.connectionId})`);
|
|
87
|
+
outcomes.push({ provider, status: 'connected-now' });
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
input.io.error(`integrations.${provider}: connect failed: ${message}`);
|
|
92
|
+
outcomes.push({ provider, status: 'failed', message });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Track the subscription provider only when this deploy actually
|
|
96
|
+
// connected one — already-connected cases stay logged but do not
|
|
97
|
+
// leak a sentinel string up to callers reading `subscriptionProvider`.
|
|
98
|
+
let subscriptionProvider;
|
|
99
|
+
if (input.persona.useSubscription) {
|
|
100
|
+
if (!input.subscription) {
|
|
101
|
+
throw new Error('persona has useSubscription:true but no subscription resolver was supplied to the deploy orchestrator');
|
|
102
|
+
}
|
|
103
|
+
const isConn = await input.subscription
|
|
104
|
+
.isConnected({ workspace: input.workspace })
|
|
105
|
+
.catch(() => false);
|
|
106
|
+
if (!isConn) {
|
|
107
|
+
if (input.noConnect) {
|
|
108
|
+
throw new Error('persona requires a subscription provider connection, but --no-connect was passed');
|
|
109
|
+
}
|
|
110
|
+
const ok = await input.io.confirm('persona has useSubscription:true — connect your LLM provider now?', { defaultValue: true });
|
|
111
|
+
if (!ok) {
|
|
112
|
+
throw new Error('user declined the subscription provider connect; deploy aborted');
|
|
113
|
+
}
|
|
114
|
+
const result = await input.subscription.connect({ workspace: input.workspace });
|
|
115
|
+
subscriptionProvider = result.provider;
|
|
116
|
+
input.io.info(`subscription: connected (${result.provider})`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
input.io.info('subscription: already connected');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
outcomes,
|
|
124
|
+
...(subscriptionProvider ? { subscriptionProvider } : {})
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/deploy.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type IntegrationConnectResolver, type ProviderSubscriptionResolver } from './connect.js';
|
|
2
|
+
import { type WorkspaceAuth } from './login.js';
|
|
3
|
+
import type { BundleStager, DeployMode, DeployOptions, DeployResult, ModeLauncher } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* External-resolver bundle the orchestrator depends on. Each field has a
|
|
6
|
+
* real default backed by env (or, for `bundle`/`modes`, the real
|
|
7
|
+
* launchers). Callers override individual fields to plug in higher-level
|
|
8
|
+
* implementations: a CLI dispatch case may pass an `IntegrationResolver`
|
|
9
|
+
* backed by `@relayfile/sdk`'s OAuth flow once it is available, tests
|
|
10
|
+
* pass deterministic in-memory fakes.
|
|
11
|
+
*/
|
|
12
|
+
export interface DeployResolvers {
|
|
13
|
+
workspaceAuth?: WorkspaceAuth;
|
|
14
|
+
integrations?: IntegrationConnectResolver;
|
|
15
|
+
subscription?: ProviderSubscriptionResolver;
|
|
16
|
+
bundle?: BundleStager;
|
|
17
|
+
modes?: Partial<Record<DeployMode, ModeLauncher>>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Pick the run mode for this deploy. Per the deploy-v1 spec:
|
|
21
|
+
* - Explicit `--mode` always wins.
|
|
22
|
+
* - Otherwise `--mode sandbox` is the default when Daytona creds resolve
|
|
23
|
+
* (BYO env or workforce-managed both count as "resolved" here; the
|
|
24
|
+
* sandbox launcher itself decides which auth path to use).
|
|
25
|
+
* - Otherwise fall back to `--mode dev`.
|
|
26
|
+
*
|
|
27
|
+
* The orchestrator doesn't probe the cloud endpoint here — `--mode cloud`
|
|
28
|
+
* stays opt-in until the M4 endpoint is live.
|
|
29
|
+
*/
|
|
30
|
+
export declare function pickMode(opts: DeployOptions): DeployMode;
|
|
31
|
+
/**
|
|
32
|
+
* Top-level entry. The CLI dispatch case calls this with parsed options
|
|
33
|
+
* and resolvers. Returns a `DeployResult` summarizing the deploy; on
|
|
34
|
+
* failure, throws with an actionable message (no half-deploys).
|
|
35
|
+
*
|
|
36
|
+
* Step ordering — see `docs/plans/deploy-v1.md` §5:
|
|
37
|
+
* 1. Preflight persona (parse, lint, onEvent on disk).
|
|
38
|
+
* 2. Resolve workspace + token.
|
|
39
|
+
* 3. Connect integrations (prompt per provider).
|
|
40
|
+
* 4. Stage bundle to `.workforce/build/<id>/`.
|
|
41
|
+
* 5. Launch in the resolved mode.
|
|
42
|
+
* 6. Return the handle + summary.
|
|
43
|
+
*
|
|
44
|
+
* `dryRun: true` exits cleanly after step 1, returning a minimal result
|
|
45
|
+
* with the warnings collected so far.
|
|
46
|
+
*
|
|
47
|
+
* `bundleOut: <dir>` runs steps 1-4 then exits, skipping launch.
|
|
48
|
+
*/
|
|
49
|
+
export declare function deploy(opts: DeployOptions, resolvers?: DeployResolvers): Promise<DeployResult>;
|
|
50
|
+
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAKlE,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;CACnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAQxD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,GAAE,eAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAsHxG"}
|