@app-vitals/agent-runtime 0.13.0 → 0.13.2

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.
@@ -42,6 +42,7 @@ function makeCron(id: string): AgentCronJob {
42
42
 
43
43
  function makeConfig(env: Record<string, string>): AgentConfigResponse {
44
44
  return {
45
+ specialty: "coding",
45
46
  env,
46
47
  allowedTools: [],
47
48
  plugins: [],
@@ -18,6 +18,7 @@ import { RecordedShipwrightConfigClient } from "./shipwright-config-client.ts";
18
18
  // ─── Test fixtures ─────────────────────────────────────────────────────────────
19
19
 
20
20
  const SAMPLE_CONFIG: AgentConfigResponse = {
21
+ specialty: "coding",
21
22
  env: {
22
23
  ANTHROPIC_MODEL: "claude-sonnet-4-6",
23
24
  CUSTOM_VAR: "custom-value",
@@ -139,18 +140,18 @@ describe("runEntrypoint — happy path", () => {
139
140
  it("exports the specialty to the server process when the config carries one (ARD-6.1)", async () => {
140
141
  const configClient = new RecordedShipwrightConfigClient({
141
142
  ...SAMPLE_CONFIG,
142
- typeName: "specialist",
143
+ specialty: "specialist",
143
144
  });
144
145
  const { deps, appliedEnv } = makeDeps(configClient);
145
146
  await runEntrypoint(deps);
146
147
  expect(appliedEnv.SHIPWRIGHT_AGENT_TYPE).toBe("specialist");
147
148
  });
148
149
 
149
- it("does not set SHIPWRIGHT_AGENT_TYPE when the config has no typeName (ARD-6.1)", async () => {
150
+ it("exports the default specialty from the config bundle (AGR-6.3: specialty is required)", async () => {
150
151
  const configClient = new RecordedShipwrightConfigClient(SAMPLE_CONFIG);
151
152
  const { deps, appliedEnv } = makeDeps(configClient);
152
153
  await runEntrypoint(deps);
153
- expect(appliedEnv.SHIPWRIGHT_AGENT_TYPE).toBeUndefined();
154
+ expect(appliedEnv.SHIPWRIGHT_AGENT_TYPE).toBe("coding");
154
155
  });
155
156
 
156
157
  it("fetches config and applies env vars from the bundle", async () => {
@@ -272,6 +273,7 @@ describe("runEntrypoint — missing required vars", () => {
272
273
  describe("runEntrypoint — config with empty env", () => {
273
274
  it("handles config with no env vars gracefully", async () => {
274
275
  const emptyConfig: AgentConfigResponse = {
276
+ specialty: "coding",
275
277
  env: {},
276
278
  allowedTools: [],
277
279
  plugins: [],
package/entrypoint.ts CHANGED
@@ -116,9 +116,7 @@ export async function runEntrypoint(deps: EntrypointDeps): Promise<void> {
116
116
  applyEnv(config.env);
117
117
  // ARD-6.1: hand the specialty to the server process (inherits our env) so
118
118
  // ensureAgentHome() can pick type-specific workspace templates.
119
- if (config.typeName) {
120
- applyEnv({ SHIPWRIGHT_AGENT_TYPE: config.typeName });
121
- }
119
+ applyEnv({ SHIPWRIGHT_AGENT_TYPE: config.specialty });
122
120
 
123
121
  // Step 4: Symlink ~/.claude → $AGENT_HOME/dot-claude
124
122
  const dotClaudeTarget = join(agentHome, "dot-claude");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@app-vitals/agent-runtime",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/app-vitals/agent.git",
@@ -40,8 +40,8 @@
40
40
  "./workspace-paths": "./workspace-paths.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@app-vitals/agent-admin": "0.13.0",
44
- "@app-vitals/agent-lib": "0.13.0",
43
+ "@app-vitals/agent-admin": "0.13.2",
44
+ "@app-vitals/agent-lib": "0.13.2",
45
45
  "@octokit/auth-app": "^8.2.0",
46
46
  "@sentry/bun": "^10.63.0",
47
47
  "@slack/bolt": "^5.0.0",
package/setup.ts CHANGED
@@ -75,7 +75,7 @@ const REQUIRED_TEMPLATES: readonly string[] = [
75
75
  /**
76
76
  * Resolves the workspace template directory for a specialty (ARD-6.1).
77
77
  *
78
- * Reads `identity.templatesDir` from `<repoRoot>/specialties/<typeName>/manifest.yaml`
78
+ * Reads `identity.templatesDir` from `<repoRoot>/specialties/<specialty>/manifest.yaml`
79
79
  * (relative paths resolve against the repo root, matching how the manifests
80
80
  * spell them). Returns the built-in workspace/ dir for `coding`, an absent
81
81
  * type, and any type that does not resolve (no manifest, unparseable, or the
@@ -89,17 +89,17 @@ export function resolveTemplatesDir(
89
89
  env: Record<string, string | undefined> = process.env,
90
90
  ): string {
91
91
  const repoRoot = repoRootOverride ?? resolveShipwrightRepoRoot(env);
92
- const typeName =
92
+ const specialty =
93
93
  requestedType ||
94
94
  env.SHIPWRIGHT_DEFAULT_AGENT_TYPE ||
95
95
  DEFAULT_SPECIALTY_NAME;
96
- if (typeName === DEFAULT_SPECIALTY_NAME) {
96
+ if (specialty === DEFAULT_SPECIALTY_NAME) {
97
97
  return WORKSPACE_TEMPLATE_DIR;
98
98
  }
99
99
  try {
100
100
  const manifestPath = join(
101
101
  env.SHIPWRIGHT_SPECIALTIES_DIR || join(repoRoot, "specialties"),
102
- typeName,
102
+ specialty,
103
103
  "manifest.yaml",
104
104
  );
105
105
  const manifest = Bun.YAML.parse(readFileSync(manifestPath, "utf8")) as {
@@ -128,7 +128,7 @@ export function resolveTemplatesDir(
128
128
  return dir;
129
129
  } catch (err) {
130
130
  warn(
131
- `[setup] could not resolve workspace templates for specialty "${typeName}" ` +
131
+ `[setup] could not resolve workspace templates for specialty "${specialty}" ` +
132
132
  `(${(err as Error).message}) — falling back to "${DEFAULT_SPECIALTY_NAME}" templates`,
133
133
  );
134
134
  return WORKSPACE_TEMPLATE_DIR;
@@ -648,8 +648,8 @@ export function ensureAgentHome(
648
648
  home: string,
649
649
  // ARD-6.1: the entrypoint exports the agent's type (from the config
650
650
  // response) as SHIPWRIGHT_AGENT_TYPE before spawning this process.
651
- typeName: string | undefined = process.env.SHIPWRIGHT_AGENT_TYPE,
652
- templatesDir: string = resolveTemplatesDir(typeName),
651
+ specialty: string | undefined = process.env.SHIPWRIGHT_AGENT_TYPE,
652
+ templatesDir: string = resolveTemplatesDir(specialty),
653
653
  ): void {
654
654
  const workspaceDir = join(home, "workspace");
655
655
  const stateDir = join(workspaceDir, "state");
@@ -267,6 +267,20 @@ describe("discoverBakedMarketplaces", () => {
267
267
  });
268
268
 
269
269
  describe("resolveTemplatesDir option resolution (AEP-1.2)", () => {
270
+ it("resolves the shipped specialist manifest to agent-types/specialist/templates/ with no warning (SAI-1.2)", async () => {
271
+ const { resolveTemplatesDir } = await import("./setup.ts");
272
+ const repoRoot = join(import.meta.dir, "..");
273
+ const warnings: string[] = [];
274
+ const dir = resolveTemplatesDir(
275
+ "specialist",
276
+ repoRoot,
277
+ (m) => warnings.push(m),
278
+ { SHIPWRIGHT_SPECIALTIES_DIR: join(repoRoot, "agent-types") },
279
+ );
280
+ expect(dir).toBe(join(repoRoot, "agent-types", "specialist", "templates"));
281
+ expect(warnings).toEqual([]);
282
+ });
283
+
270
284
  it("resolves an absent type to the built-in templates with no env set", async () => {
271
285
  const { resolveTemplatesDir } = await import("./setup.ts");
272
286
  const dir = resolveTemplatesDir(undefined, "/nonexistent", () => {}, {});
@@ -22,6 +22,7 @@ const API_KEY = "test-bearer-key";
22
22
  const AGENT_ID = "agent-abc-123";
23
23
 
24
24
  const SAMPLE_CONFIG: AgentConfigResponse = {
25
+ specialty: "coding",
25
26
  env: { ANTHROPIC_MODEL: "claude-sonnet-4-6" },
26
27
  allowedTools: ["Read", "Bash"],
27
28
  plugins: [{ marketplace: "shipwright", plugin: "my-plugin" }],