@tdk-landscape/tdk-cli-core 1.3.170 → 1.3.172

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.
@@ -1,2 +1,2 @@
1
1
  import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{Nb as a,Ob as b,Pb as c,Qb as d,Rb as e}from"./chunk-MZBDLTO2.js";import"./chunk-42IVF3YT.js";import"./chunk-6EA4DGCY.js";export{e as assertMachineReadyOrExit,d as formatColdPreflight,a as nodeTooOld,b as requireVerifiedDockerVersions,c as runColdPreflight};
2
+ import{Qb as a,Rb as b,Sb as c,Tb as d,Ub as e}from"./chunk-JF2COU6K.js";import"./chunk-42IVF3YT.js";import"./chunk-6EA4DGCY.js";export{e as assertMachineReadyOrExit,d as formatColdPreflight,a as nodeTooOld,b as requireVerifiedDockerVersions,c as runColdPreflight};
package/cli/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tdk-cli-internal",
3
3
  "private": true,
4
- "version": "1.3.170",
4
+ "version": "1.3.172",
5
5
  "description": "TDK CLI — start services on your machine.",
6
6
  "keywords": [
7
7
  "tdk",
@@ -118,7 +118,7 @@
118
118
  "type": "string"
119
119
  },
120
120
  "appType": {
121
- "description": "Resource type determining build strategy:\n• backend - Hono/Express API server\n• frontend - Vite single-page application (React, Vue, Svelte, Preact, Lit, Solid, Qwik or Vanilla TypeScript, see framework)\n• sdk - Shared library package\n• worker - Background job processor\n• migrator - Database migration runner\n• library - Shared code library\n• mcp - Model Context Protocol server (an HTTP service on Bun, run like a backend)\n• bring-your-own - Wrap an existing service. No app scaffold. Needs Dockerfile or --image.",
121
+ "description": "Resource type determining build strategy:\n• backend - Hono/Express API server\n• frontend - Vite single-page application (React, Vue, Svelte, Preact, Lit, Solid, Qwik or Vanilla TypeScript, see framework)\n• sdk - Shared library package\n• worker - Background job processor\n• migrator - Database migration runner\n• library - Shared code library\n• mcp - Model Context Protocol server (an HTTP service on Bun, run like a backend)\n• agent - Long-running AI agent (a Bun HTTP service with /health and /ready, run like a backend; see agent)\n• bring-your-own - Wrap an existing service. No app scaffold. Needs Dockerfile or --image.",
122
122
  "enum": [
123
123
  "backend",
124
124
  "frontend",
@@ -127,6 +127,7 @@
127
127
  "migrator",
128
128
  "library",
129
129
  "mcp",
130
+ "agent",
130
131
  "bring-your-own"
131
132
  ],
132
133
  "type": "string"
@@ -476,6 +477,7 @@
476
477
  "migrator",
477
478
  "library",
478
479
  "mcp",
480
+ "agent",
479
481
  "bring-your-own"
480
482
  ],
481
483
  "type": "string"
@@ -487,6 +489,29 @@
487
489
  "apiPath": {
488
490
  "description": "API path exposed by this resource, when applicable.",
489
491
  "type": "string"
492
+ },
493
+ "agent": {
494
+ "description": "Agent settings, used when appType is 'agent'. The agent runtime checkpoints its sessions; TDK provides the volume or database.",
495
+ "type": "object",
496
+ "additionalProperties": false,
497
+ "properties": {
498
+ "runtime": {
499
+ "description": "Agent runtime scaffold. 'custom' is the default and has no vendor dependency.",
500
+ "type": "string",
501
+ "enum": [
502
+ "custom"
503
+ ]
504
+ },
505
+ "durability": {
506
+ "description": "files: sessions live in a named volume that tdk down keeps. postgres: sessions live in Postgres via DATABASE_URL.",
507
+ "type": "string",
508
+ "enum": [
509
+ "files",
510
+ "postgres"
511
+ ],
512
+ "default": "files"
513
+ }
514
+ }
490
515
  }
491
516
  },
492
517
  "required": [
@@ -271,6 +271,17 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
271
271
  no_http_healthcheck_section = NO_HTTP_HEALTHCHECK if (is_worker or health_path == None) else ""
272
272
  # Backends with a health path get it in the env, so the shared golden image's HEALTHCHECK can probe it.
273
273
  health_env = " - TDK_HEALTH_PATH={}\n".format(health_path) if health_path else ""
274
+ # An agent with files durability keeps its session checkpoints in a named volume. The volume is declared at the top of the
275
+ # generated file (generate_app_compose_from_entries reads the marker line below), so tdk down keeps it.
276
+ agent_env = ""
277
+ agent_volume_section = ""
278
+ if manifest and type(manifest.get('agent')) == 'dict':
279
+ agent_durability = manifest['agent'].get('durability', 'files')
280
+ agent_env = " - AGENT_DURABILITY={}\n".format(agent_durability)
281
+ if agent_durability == 'files':
282
+ agent_volume = res_name + '-agent-state'
283
+ agent_env += " - AGENT_STATE_DIR=/var/lib/tdk-agent\n"
284
+ agent_volume_section = " # tdk-agent-volume: {vol}\n volumes:\n - {vol}:/var/lib/tdk-agent\n".format(vol=agent_volume)
274
285
 
275
286
  if is_worker or is_proxy_disabled_byo:
276
287
  traefik_labels = ' - "traefik.enable=false"'
@@ -311,7 +322,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
311
322
  {infisical_env}
312
323
  - RESOURCE_NAME={stack}
313
324
  - PORT={port_anchor}
314
- {health_env} - INSTANCE_ID={instance_label}
325
+ {health_env}{agent_env} - INSTANCE_ID={instance_label}
315
326
  - NATS_QUEUE_GROUP={nats_queue}
316
327
  - TILT_DATABASE_URL={db_url_for_tilt}
317
328
  - TILT_NATS_URL={nats_url}
@@ -322,7 +333,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
322
333
  # migration/CLI issue) without touching the generator or any service code.
323
334
  - AUTO_MIGRATE=${{AUTO_MIGRATE:-true}}
324
335
  {auth_env}{secrets_env}
325
- labels:
336
+ {agent_volume_section} labels:
326
337
  {traefik_labels}
327
338
  networks:
328
339
  - {network_traefik_public}
@@ -368,6 +379,8 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
368
379
  traefik_labels=traefik_labels,
369
380
  healthcheck_section=healthcheck_section,
370
381
  health_env=health_env,
382
+ agent_env=agent_env,
383
+ agent_volume_section=agent_volume_section,
371
384
  infisical_env=infisical_env,
372
385
  auth_env=auth_env,
373
386
  secrets_env=secrets_env,
@@ -510,6 +523,20 @@ x-frontend-memory-limit: &frontend-memory-limit
510
523
  services:
511
524
  """.format(port_anchors=port_anchors)
512
525
 
526
+ # Named volumes used by services (agent session state) must be declared at the top level. Services mark them with a
527
+ # "# tdk-agent-volume: <name>" line, so the declaration follows the services without a separate registry.
528
+ volume_names = []
529
+ for entry in resource_entries:
530
+ for line in entry.split("\n"):
531
+ if line.strip().startswith("# tdk-agent-volume: "):
532
+ name = line.strip()[len("# tdk-agent-volume: "):]
533
+ # Replicas of one agent repeat the marker; Compose rejects a duplicate key under volumes:.
534
+ if name not in volume_names:
535
+ volume_names.append(name)
536
+ volumes_section = ""
537
+ if volume_names:
538
+ volumes_section = "\nvolumes:\n" + "".join([" {}:\n".format(name) for name in volume_names])
539
+
513
540
  footer = """
514
541
  networks:
515
542
  {network_traefik_public}:
@@ -520,11 +547,12 @@ networks:
520
547
  external: true
521
548
  {network_infisical}:
522
549
  external: true
523
- """.format(
550
+ {volumes_section}""".format(
524
551
  network_traefik_public=PlatformDockerConstants.NETWORK_TRAEFIK_PUBLIC,
525
552
  network_backend=PlatformDockerConstants.NETWORK_BACKEND,
526
553
  network_database=PlatformDockerConstants.NETWORK_DATABASE,
527
554
  network_infisical=PlatformDockerConstants.NETWORK_INFISICAL,
555
+ volumes_section=volumes_section,
528
556
  )
529
557
 
530
558
  content = header + "\n".join(resource_entries) + footer
@@ -173,6 +173,14 @@ def L4_generate_backend_runtime(res_path, port = BASE_PORT_BACKEND, cmd = 'bun r
173
173
  parts.append("RUN apk add --no-cache hugo\n")
174
174
  parts.append("USER bun\n")
175
175
 
176
+ # A files-durability agent keeps its checkpoints in /var/lib/tdk-agent, a named volume. Docker seeds a new volume with the
177
+ # image directory's owner, so create the directory owned by bun, or the agent cannot write its first checkpoint (EACCES).
178
+ agent_cfg = manifest.get('agent') if manifest else None
179
+ if type(agent_cfg) == 'dict' and agent_cfg.get('durability', 'files') == 'files':
180
+ parts.append("USER root\n")
181
+ parts.append("RUN mkdir -p /var/lib/tdk-agent && chown bun:bun /var/lib/tdk-agent\n")
182
+ parts.append("USER bun\n")
183
+
176
184
  if has_prisma_config:
177
185
  # Prisma v7 migrate deploy reads datasource.url from prisma.config.ts in CWD
178
186
  parts.append(prisma_config_copy(res_path))
@@ -79,6 +79,15 @@ def load_from_file(path):
79
79
  if type(manifest) == "dict" and manifest.get("appType") == "mcp":
80
80
  manifest["appType"] = "backend"
81
81
  manifest["mcp"] = True
82
+
83
+ # An `agent` resource is a long-running AI agent: a Bun HTTP service (/health, /ready, SIGTERM drain) that is built, routed
84
+ # and health-checked as a backend, so it reuses the backend code paths and boots health-gated. Its settings are kept under
85
+ # manifest["agent"] for the generators (state volume, AGENT_* environment), with durability defaulting to files.
86
+ if type(manifest) == "dict" and manifest.get("appType") == "agent":
87
+ agent = dict(manifest.get("agent") or {})
88
+ agent["durability"] = agent.get("durability") or "files"
89
+ manifest["appType"] = "backend"
90
+ manifest["agent"] = agent
82
91
 
83
92
  return struct(manifest=manifest, error=None)
84
93
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tdk-landscape/tdk-cli-core",
3
- "version": "1.3.170",
3
+ "version": "1.3.172",
4
4
  "description": "TDK CLI — start services on your machine.",
5
5
  "homepage": "https://tdk-landscape.github.io/tdk-website",
6
6
  "repository": {