Skip to content

Commit 8a812d1

Browse files
committed
cp
1 parent bcdf8c5 commit 8a812d1

5 files changed

Lines changed: 291 additions & 5 deletions

File tree

action.yml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ inputs:
1212
required: true
1313

1414
source-type:
15-
description: 'Agent source type: git, tar, or file'
15+
description: 'Agent source type: git, tar, file, npm, or pip'
1616
required: true
1717

1818
# Optional inputs
@@ -33,6 +33,33 @@ inputs:
3333
description: 'Git ref (branch/tag/commit SHA). Defaults to current commit or release tag'
3434
required: false
3535

36+
# NPM source inputs
37+
npm-package:
38+
description: 'NPM package name (required when source-type=npm, e.g., "@anthropic-ai/claude-code")'
39+
required: false
40+
41+
npm-registry-url:
42+
description: 'NPM registry URL (optional, defaults to public npm registry)'
43+
required: false
44+
45+
# Pip source inputs
46+
pip-package:
47+
description: 'PyPI package name (required when source-type=pip, e.g., "deepagents-cli")'
48+
required: false
49+
50+
pip-index-url:
51+
description: 'PyPI index URL (optional, defaults to public PyPI)'
52+
required: false
53+
54+
# Agent runtime inputs
55+
binary:
56+
description: 'Agent binary path (e.g., "claude", "codex")'
57+
required: false
58+
59+
axon-attach-protocol:
60+
description: 'Axon attach protocol: acp, claude, or codex'
61+
required: false
62+
3663
# File/tar source inputs
3764
path:
3865
description: 'Path to file or tar archive (required if source-type=tar/file)'

dist/index.js

Lines changed: 114 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/agent-deployer.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ interface AgentResponse {
1616
name: string;
1717
}
1818

19+
/**
20+
* Build optional top-level fields (binary, axon_attach_config) from inputs.
21+
*/
22+
function buildOptionalFields(inputs: ActionInputs): Record<string, unknown> {
23+
const fields: Record<string, unknown> = {};
24+
if (inputs.binary) {
25+
fields.binary = inputs.binary;
26+
}
27+
if (inputs.axonAttachProtocol) {
28+
fields.axon_attach_config = { protocol: inputs.axonAttachProtocol };
29+
}
30+
return fields;
31+
}
32+
1933
/**
2034
* Deploy an agent to Runloop based on the source type.
2135
*/
@@ -46,6 +60,14 @@ export async function deployAgent(inputs: ActionInputs): Promise<DeploymentResul
4660
result = await deployFileAgent(client, agentName, inputs);
4761
break;
4862

63+
case 'npm':
64+
result = await deployNpmAgent(client, agentName, inputs);
65+
break;
66+
67+
case 'pip':
68+
result = await deployPipAgent(client, agentName, inputs);
69+
break;
70+
4971
default: {
5072
// Exhaustiveness check - this should never happen
5173
const exhaustiveCheck: never = inputs.sourceType;
@@ -84,6 +106,7 @@ async function deployGitAgent(
84106
name: agentName,
85107
version: inputs.agentVersion,
86108
is_public: inputs.isPublic,
109+
...buildOptionalFields(inputs),
87110
source: {
88111
type: 'git',
89112
git: {
@@ -127,6 +150,7 @@ async function deployTarAgent(
127150
name: agentName,
128151
version: inputs.agentVersion,
129152
is_public: inputs.isPublic,
153+
...buildOptionalFields(inputs),
130154
source: {
131155
type: 'object',
132156
object: {
@@ -170,6 +194,7 @@ async function deployFileAgent(
170194
name: agentName,
171195
version: inputs.agentVersion,
172196
is_public: inputs.isPublic,
197+
...buildOptionalFields(inputs),
173198
source: {
174199
type: 'object',
175200
object: {
@@ -186,3 +211,89 @@ async function deployFileAgent(
186211
objectId: uploadResult.objectId,
187212
};
188213
}
214+
215+
/**
216+
* Deploy an agent from an NPM package.
217+
*/
218+
async function deployNpmAgent(
219+
client: RunloopSDK,
220+
agentName: string,
221+
inputs: ActionInputs
222+
): Promise<DeploymentResult> {
223+
core.info('Deploying NPM agent...');
224+
225+
if (!inputs.npmPackage) {
226+
throw new Error('npm-package is required for npm agent deployment');
227+
}
228+
229+
const npmSource: Record<string, unknown> = {
230+
package_name: inputs.npmPackage,
231+
};
232+
if (inputs.npmRegistryUrl) {
233+
npmSource.registry_url = inputs.npmRegistryUrl;
234+
}
235+
if (inputs.setupCommands && inputs.setupCommands.length > 0) {
236+
npmSource.agent_setup = inputs.setupCommands;
237+
}
238+
239+
const agent = await client.api.post<unknown, AgentResponse>('/v1/agents', {
240+
body: {
241+
name: agentName,
242+
version: inputs.agentVersion,
243+
is_public: inputs.isPublic,
244+
...buildOptionalFields(inputs),
245+
source: {
246+
type: 'npm',
247+
npm: npmSource,
248+
},
249+
},
250+
});
251+
252+
return {
253+
agentId: agent.id,
254+
agentName: agent.name,
255+
};
256+
}
257+
258+
/**
259+
* Deploy an agent from a PyPI package.
260+
*/
261+
async function deployPipAgent(
262+
client: RunloopSDK,
263+
agentName: string,
264+
inputs: ActionInputs
265+
): Promise<DeploymentResult> {
266+
core.info('Deploying pip agent...');
267+
268+
if (!inputs.pipPackage) {
269+
throw new Error('pip-package is required for pip agent deployment');
270+
}
271+
272+
const pipSource: Record<string, unknown> = {
273+
package_name: inputs.pipPackage,
274+
};
275+
if (inputs.pipIndexUrl) {
276+
pipSource.index_url = inputs.pipIndexUrl;
277+
}
278+
if (inputs.setupCommands && inputs.setupCommands.length > 0) {
279+
pipSource.agent_setup = inputs.setupCommands;
280+
}
281+
282+
const agent = await client.api.post<unknown, AgentResponse>('/v1/agents', {
283+
body: {
284+
name: agentName,
285+
version: inputs.agentVersion,
286+
is_public: inputs.isPublic,
287+
...buildOptionalFields(inputs),
288+
source: {
289+
type: 'pip',
290+
pip: pipSource,
291+
},
292+
},
293+
});
294+
295+
return {
296+
agentId: agent.id,
297+
agentName: agent.name,
298+
};
299+
}

0 commit comments

Comments
 (0)