@desplega.ai/agent-swarm 1.74.4 → 1.76.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.
Files changed (88) hide show
  1. package/README.md +1 -1
  2. package/openapi.json +1264 -46
  3. package/package.json +2 -2
  4. package/src/be/db.ts +563 -9
  5. package/src/be/memory/edges-store.ts +69 -0
  6. package/src/be/memory/providers/sqlite-store.ts +4 -0
  7. package/src/be/memory/raters/explicit-self.ts +22 -0
  8. package/src/be/memory/raters/implicit-citation.ts +44 -0
  9. package/src/be/memory/raters/llm-client.ts +172 -0
  10. package/src/be/memory/raters/llm-summarizer.ts +218 -0
  11. package/src/be/memory/raters/llm.ts +375 -0
  12. package/src/be/memory/raters/noop.ts +14 -0
  13. package/src/be/memory/raters/registry.ts +86 -0
  14. package/src/be/memory/raters/retrieval.ts +88 -0
  15. package/src/be/memory/raters/run-server-raters.ts +97 -0
  16. package/src/be/memory/raters/store.ts +228 -0
  17. package/src/be/memory/raters/types.ts +101 -0
  18. package/src/be/memory/reranker.ts +32 -2
  19. package/src/be/memory/retrieval-store.ts +116 -0
  20. package/src/be/memory/types.ts +3 -0
  21. package/src/be/migrations/051_memory_posteriors_and_retrieval.sql +67 -0
  22. package/src/be/migrations/052_memory_edges.sql +36 -0
  23. package/src/be/migrations/053_agent_waiting_for_credentials_status.sql +61 -0
  24. package/src/be/migrations/054_agent_harness_provider.sql +21 -0
  25. package/src/be/migrations/055_agent_cred_status.sql +15 -0
  26. package/src/be/migrations/056_drop_agent_tasks_source_check.sql +139 -0
  27. package/src/be/migrations/057_inbox_item_state.sql +27 -0
  28. package/src/be/migrations/058_task_templates.sql +31 -0
  29. package/src/be/swarm-config-guard.ts +24 -0
  30. package/src/commands/credential-wait.ts +186 -0
  31. package/src/commands/provider-credentials.ts +434 -0
  32. package/src/commands/runner.ts +253 -21
  33. package/src/hooks/hook.ts +143 -66
  34. package/src/http/agents.ts +191 -1
  35. package/src/http/config.ts +11 -1
  36. package/src/http/core.ts +5 -0
  37. package/src/http/inbox-state.ts +89 -0
  38. package/src/http/index.ts +10 -0
  39. package/src/http/memory.ts +230 -1
  40. package/src/http/sessions.ts +86 -0
  41. package/src/http/status.ts +665 -0
  42. package/src/http/task-templates.ts +51 -0
  43. package/src/http/tasks.ts +85 -5
  44. package/src/http/users.ts +134 -0
  45. package/src/prompts/memories.ts +62 -0
  46. package/src/providers/claude-adapter.ts +22 -0
  47. package/src/providers/claude-managed-adapter.ts +24 -0
  48. package/src/providers/codex-adapter.ts +43 -1
  49. package/src/providers/devin-adapter.ts +18 -0
  50. package/src/providers/index.ts +7 -0
  51. package/src/providers/opencode-adapter.ts +60 -0
  52. package/src/providers/pi-mono-adapter.ts +71 -0
  53. package/src/providers/types.ts +34 -0
  54. package/src/server.ts +2 -0
  55. package/src/slack/handlers.ts +0 -1
  56. package/src/tests/agents-harness-provider.test.ts +333 -0
  57. package/src/tests/credential-check.test.ts +367 -0
  58. package/src/tests/credential-status-api.test.ts +223 -0
  59. package/src/tests/credential-status-routing.test.ts +150 -0
  60. package/src/tests/credential-wait.test.ts +282 -0
  61. package/src/tests/harness-provider-resolution.test.ts +242 -0
  62. package/src/tests/jira-sync.test.ts +1 -1
  63. package/src/tests/memory-edges.test.ts +722 -0
  64. package/src/tests/memory-rate-endpoint.test.ts +330 -0
  65. package/src/tests/memory-rate-tool.test.ts +252 -0
  66. package/src/tests/memory-rater-e2e.test.ts +578 -0
  67. package/src/tests/memory-rater-implicit-citation.test.ts +304 -0
  68. package/src/tests/memory-rater-llm-summarizer.test.ts +317 -0
  69. package/src/tests/memory-rater-llm.test.ts +964 -0
  70. package/src/tests/memory-rater-store.test.ts +249 -0
  71. package/src/tests/memory-reranker.test.ts +161 -2
  72. package/src/tests/migration-runner-regressions.test.ts +17 -2
  73. package/src/tests/mocks/mock-llm-rater-client.ts +35 -0
  74. package/src/tests/run-server-raters.test.ts +291 -0
  75. package/src/tests/sessions.test.ts +141 -0
  76. package/src/tests/status.test.ts +843 -0
  77. package/src/tests/stop-hook-task-resolution.test.ts +98 -0
  78. package/src/tests/template-recommendations.test.ts +148 -0
  79. package/src/tests/tool-annotations.test.ts +2 -2
  80. package/src/tests/use-dismissible-card.test.ts +140 -0
  81. package/src/tools/memory-rate.ts +166 -0
  82. package/src/tools/memory-search.ts +18 -0
  83. package/src/tools/store-progress.ts +37 -0
  84. package/src/tools/swarm-config/set-config.ts +17 -1
  85. package/src/tools/tool-config.ts +1 -0
  86. package/src/types.ts +122 -1
  87. package/src/utils/harness-provider.ts +32 -0
  88. package/tsconfig.json +0 -2
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Swarm API",
5
- "version": "1.74.4",
5
+ "version": "1.76.0",
6
6
  "description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
7
7
  },
8
8
  "servers": [
@@ -326,6 +326,17 @@
326
326
  "claude-managed",
327
327
  "opencode"
328
328
  ]
329
+ },
330
+ "harness_provider": {
331
+ "type": "string",
332
+ "enum": [
333
+ "claude",
334
+ "codex",
335
+ "pi",
336
+ "devin",
337
+ "claude-managed",
338
+ "opencode"
339
+ ]
329
340
  }
330
341
  },
331
342
  "required": [
@@ -377,6 +388,66 @@
377
388
  }
378
389
  }
379
390
  },
391
+ "/api/agents/{id}/harness-provider": {
392
+ "patch": {
393
+ "summary": "Re-assign an agent's harness_provider (live)",
394
+ "description": "Updates `agents.harness_provider` and upserts `swarm_config` (scope=agent, key=HARNESS_PROVIDER) so the worker's poll-loop reconciliation picks up the new provider within ~10s. No restart required. The swarm_config row is what actually drives the worker; the column mirrors the latest set value for dashboards.",
395
+ "tags": [
396
+ "Agents"
397
+ ],
398
+ "security": [
399
+ {
400
+ "bearerAuth": []
401
+ }
402
+ ],
403
+ "parameters": [
404
+ {
405
+ "schema": {
406
+ "type": "string"
407
+ },
408
+ "required": true,
409
+ "name": "id",
410
+ "in": "path"
411
+ }
412
+ ],
413
+ "requestBody": {
414
+ "content": {
415
+ "application/json": {
416
+ "schema": {
417
+ "type": "object",
418
+ "properties": {
419
+ "harness_provider": {
420
+ "type": "string",
421
+ "enum": [
422
+ "claude",
423
+ "codex",
424
+ "pi",
425
+ "devin",
426
+ "claude-managed",
427
+ "opencode"
428
+ ]
429
+ }
430
+ },
431
+ "required": [
432
+ "harness_provider"
433
+ ]
434
+ }
435
+ }
436
+ }
437
+ },
438
+ "responses": {
439
+ "200": {
440
+ "description": "Updated agent row"
441
+ },
442
+ "400": {
443
+ "description": "Validation error (unknown provider)"
444
+ },
445
+ "404": {
446
+ "description": "Agent not found"
447
+ }
448
+ }
449
+ }
450
+ },
380
451
  "/api/agents/{id}/name": {
381
452
  "put": {
382
453
  "summary": "Update agent name",
@@ -621,6 +692,209 @@
621
692
  }
622
693
  }
623
694
  },
695
+ "/api/agents/{id}/credential-status": {
696
+ "put": {
697
+ "summary": "Worker self-report of credential readiness (Phase 3 boot loop)",
698
+ "tags": [
699
+ "Agents"
700
+ ],
701
+ "security": [
702
+ {
703
+ "bearerAuth": []
704
+ }
705
+ ],
706
+ "parameters": [
707
+ {
708
+ "schema": {
709
+ "type": "string"
710
+ },
711
+ "required": true,
712
+ "name": "id",
713
+ "in": "path"
714
+ }
715
+ ],
716
+ "requestBody": {
717
+ "content": {
718
+ "application/json": {
719
+ "schema": {
720
+ "type": "object",
721
+ "properties": {
722
+ "ready": {
723
+ "type": "boolean"
724
+ },
725
+ "missing": {
726
+ "type": [
727
+ "array",
728
+ "null"
729
+ ],
730
+ "items": {
731
+ "type": "string"
732
+ }
733
+ },
734
+ "cred_status": {
735
+ "type": [
736
+ "object",
737
+ "null"
738
+ ],
739
+ "properties": {
740
+ "ready": {
741
+ "type": "boolean"
742
+ },
743
+ "missing": {
744
+ "type": "array",
745
+ "items": {
746
+ "type": "string"
747
+ },
748
+ "default": []
749
+ },
750
+ "satisfiedBy": {
751
+ "type": [
752
+ "string",
753
+ "null"
754
+ ],
755
+ "enum": [
756
+ "env",
757
+ "file",
758
+ "side-effect-pending",
759
+ null
760
+ ],
761
+ "default": null
762
+ },
763
+ "hint": {
764
+ "type": [
765
+ "string",
766
+ "null"
767
+ ],
768
+ "default": null
769
+ },
770
+ "liveTest": {
771
+ "type": [
772
+ "object",
773
+ "null"
774
+ ],
775
+ "properties": {
776
+ "ok": {
777
+ "type": "boolean"
778
+ },
779
+ "error": {
780
+ "type": [
781
+ "string",
782
+ "null"
783
+ ],
784
+ "default": null
785
+ },
786
+ "latency_ms": {
787
+ "type": "number"
788
+ },
789
+ "testedAt": {
790
+ "type": "number"
791
+ }
792
+ },
793
+ "default": null,
794
+ "required": [
795
+ "ok",
796
+ "latency_ms",
797
+ "testedAt"
798
+ ]
799
+ },
800
+ "reportedAt": {
801
+ "type": "number"
802
+ },
803
+ "reportKind": {
804
+ "type": "string",
805
+ "enum": [
806
+ "boot",
807
+ "post_task"
808
+ ],
809
+ "default": "boot"
810
+ }
811
+ },
812
+ "required": [
813
+ "ready",
814
+ "reportedAt"
815
+ ]
816
+ }
817
+ },
818
+ "required": [
819
+ "ready"
820
+ ]
821
+ }
822
+ }
823
+ }
824
+ },
825
+ "responses": {
826
+ "200": {
827
+ "description": "State updated; returns the agent row."
828
+ },
829
+ "404": {
830
+ "description": "Agent not found"
831
+ }
832
+ }
833
+ },
834
+ "get": {
835
+ "summary": "Single-agent credential-status snapshot for the dashboard",
836
+ "tags": [
837
+ "Agents"
838
+ ],
839
+ "security": [
840
+ {
841
+ "bearerAuth": []
842
+ }
843
+ ],
844
+ "parameters": [
845
+ {
846
+ "schema": {
847
+ "type": "string"
848
+ },
849
+ "required": true,
850
+ "name": "id",
851
+ "in": "path"
852
+ }
853
+ ],
854
+ "responses": {
855
+ "200": {
856
+ "description": "Credential status payload"
857
+ },
858
+ "404": {
859
+ "description": "Agent not found"
860
+ }
861
+ }
862
+ }
863
+ },
864
+ "/api/agents/credential-status": {
865
+ "get": {
866
+ "summary": "Bulk credential-status across all agents (powers the dashboard)",
867
+ "tags": [
868
+ "Agents"
869
+ ],
870
+ "security": [
871
+ {
872
+ "bearerAuth": []
873
+ }
874
+ ],
875
+ "parameters": [
876
+ {
877
+ "schema": {
878
+ "type": "string",
879
+ "enum": [
880
+ "idle",
881
+ "busy",
882
+ "offline",
883
+ "waiting_for_credentials"
884
+ ]
885
+ },
886
+ "required": false,
887
+ "name": "status",
888
+ "in": "query"
889
+ }
890
+ ],
891
+ "responses": {
892
+ "200": {
893
+ "description": "List of {agentId, status, missing[], lastCheckedAt}"
894
+ }
895
+ }
896
+ }
897
+ },
624
898
  "/api/approval-requests": {
625
899
  "post": {
626
900
  "summary": "Create a new approval request",
@@ -2732,34 +3006,166 @@
2732
3006
  }
2733
3007
  }
2734
3008
  },
2735
- "/api/integrations/claude-managed/test": {
2736
- "post": {
2737
- "summary": "Test the claude-managed integration: resolves ANTHROPIC_API_KEY + MANAGED_AGENT_ID from swarm_config and calls beta.agents.retrieve.",
3009
+ "/api/inbox-state": {
3010
+ "get": {
3011
+ "summary": "List inbox-item state rows for a user",
2738
3012
  "tags": [
2739
- "Integrations"
3013
+ "Inbox State"
2740
3014
  ],
2741
3015
  "security": [
2742
3016
  {
2743
3017
  "bearerAuth": []
2744
3018
  }
2745
3019
  ],
2746
- "requestBody": {
2747
- "content": {
2748
- "application/json": {
2749
- "schema": {
2750
- "type": "object",
2751
- "properties": {}
2752
- }
2753
- }
3020
+ "parameters": [
3021
+ {
3022
+ "schema": {
3023
+ "type": "string"
3024
+ },
3025
+ "required": true,
3026
+ "name": "userId",
3027
+ "in": "query"
3028
+ },
3029
+ {
3030
+ "schema": {
3031
+ "type": "string",
3032
+ "enum": [
3033
+ "open",
3034
+ "snoozed",
3035
+ "dismissed",
3036
+ "done"
3037
+ ]
3038
+ },
3039
+ "required": false,
3040
+ "name": "status",
3041
+ "in": "query"
3042
+ },
3043
+ {
3044
+ "schema": {
3045
+ "type": "string",
3046
+ "enum": [
3047
+ "approval",
3048
+ "credential_missing",
3049
+ "broken_task",
3050
+ "to_read",
3051
+ "to_start_template"
3052
+ ]
3053
+ },
3054
+ "required": false,
3055
+ "name": "itemType",
3056
+ "in": "query"
2754
3057
  }
2755
- },
3058
+ ],
2756
3059
  "responses": {
2757
3060
  "200": {
2758
- "description": "Connection result — `{ ok: true, agentName, model }` on success or `{ ok: false, error }` on any failure (missing config, Anthropic API error). Always 200 OK."
2759
- }
2760
- }
2761
- }
2762
- },
3061
+ "description": "Inbox state rows"
3062
+ },
3063
+ "400": {
3064
+ "description": "Validation error"
3065
+ },
3066
+ "401": {
3067
+ "description": "Unauthorized"
3068
+ }
3069
+ }
3070
+ },
3071
+ "patch": {
3072
+ "summary": "Upsert per-user dismiss/snooze/done state for an inbox item",
3073
+ "tags": [
3074
+ "Inbox State"
3075
+ ],
3076
+ "security": [
3077
+ {
3078
+ "bearerAuth": []
3079
+ }
3080
+ ],
3081
+ "requestBody": {
3082
+ "content": {
3083
+ "application/json": {
3084
+ "schema": {
3085
+ "type": "object",
3086
+ "properties": {
3087
+ "userId": {
3088
+ "type": "string"
3089
+ },
3090
+ "itemType": {
3091
+ "type": "string",
3092
+ "enum": [
3093
+ "approval",
3094
+ "credential_missing",
3095
+ "broken_task",
3096
+ "to_read",
3097
+ "to_start_template"
3098
+ ]
3099
+ },
3100
+ "itemId": {
3101
+ "type": "string",
3102
+ "minLength": 1
3103
+ },
3104
+ "status": {
3105
+ "type": "string",
3106
+ "enum": [
3107
+ "open",
3108
+ "snoozed",
3109
+ "dismissed",
3110
+ "done"
3111
+ ]
3112
+ },
3113
+ "snoozeUntil": {
3114
+ "type": "string",
3115
+ "format": "date-time"
3116
+ }
3117
+ },
3118
+ "required": [
3119
+ "userId",
3120
+ "itemType",
3121
+ "itemId",
3122
+ "status"
3123
+ ]
3124
+ }
3125
+ }
3126
+ }
3127
+ },
3128
+ "responses": {
3129
+ "200": {
3130
+ "description": "Upserted inbox state row"
3131
+ },
3132
+ "400": {
3133
+ "description": "Validation error"
3134
+ },
3135
+ "401": {
3136
+ "description": "Unauthorized"
3137
+ }
3138
+ }
3139
+ }
3140
+ },
3141
+ "/api/integrations/claude-managed/test": {
3142
+ "post": {
3143
+ "summary": "Test the claude-managed integration: resolves ANTHROPIC_API_KEY + MANAGED_AGENT_ID from swarm_config and calls beta.agents.retrieve.",
3144
+ "tags": [
3145
+ "Integrations"
3146
+ ],
3147
+ "security": [
3148
+ {
3149
+ "bearerAuth": []
3150
+ }
3151
+ ],
3152
+ "requestBody": {
3153
+ "content": {
3154
+ "application/json": {
3155
+ "schema": {
3156
+ "type": "object",
3157
+ "properties": {}
3158
+ }
3159
+ }
3160
+ }
3161
+ },
3162
+ "responses": {
3163
+ "200": {
3164
+ "description": "Connection result — `{ ok: true, agentName, model }` on success or `{ ok: false, error }` on any failure (missing config, Anthropic API error). Always 200 OK."
3165
+ }
3166
+ }
3167
+ }
3168
+ },
2763
3169
  "/api/memory/index": {
2764
3170
  "post": {
2765
3171
  "summary": "Ingest content into memory system (async embedding)",
@@ -3031,6 +3437,167 @@
3031
3437
  }
3032
3438
  }
3033
3439
  },
3440
+ "/api/memory/rate": {
3441
+ "post": {
3442
+ "summary": "Submit RatingEvents to update memory usefulness posteriors",
3443
+ "tags": [
3444
+ "Memory"
3445
+ ],
3446
+ "security": [
3447
+ {
3448
+ "bearerAuth": []
3449
+ }
3450
+ ],
3451
+ "requestBody": {
3452
+ "content": {
3453
+ "application/json": {
3454
+ "schema": {
3455
+ "type": "object",
3456
+ "properties": {
3457
+ "events": {
3458
+ "type": "array",
3459
+ "items": {
3460
+ "type": "object",
3461
+ "properties": {
3462
+ "memoryId": {
3463
+ "type": "string",
3464
+ "minLength": 1
3465
+ },
3466
+ "signal": {
3467
+ "type": "number",
3468
+ "minimum": -1,
3469
+ "maximum": 1
3470
+ },
3471
+ "weight": {
3472
+ "type": "number",
3473
+ "minimum": 0,
3474
+ "maximum": 1
3475
+ },
3476
+ "source": {
3477
+ "type": "string",
3478
+ "enum": [
3479
+ "llm",
3480
+ "explicit-self"
3481
+ ]
3482
+ },
3483
+ "reasoning": {
3484
+ "type": "string",
3485
+ "maxLength": 500
3486
+ },
3487
+ "taskId": {
3488
+ "type": "string",
3489
+ "format": "uuid"
3490
+ },
3491
+ "referencesSource": {
3492
+ "type": "string",
3493
+ "minLength": 1,
3494
+ "maxLength": 512,
3495
+ "description": "Optional external source ID this memory references. Free-form string, convention \"<source>:<identifier>\" (e.g. \"github:owner/repo#N\", \"linear:KEY-N\", \"customer:<slug>\", \"slack:<channel>:<ts>\", \"agentmail:<thread-id>\"). Pick any prefix that fits — no closed enum. When present, an edge from this memory to the external source is created/updated."
3496
+ }
3497
+ },
3498
+ "required": [
3499
+ "memoryId",
3500
+ "signal",
3501
+ "weight",
3502
+ "source"
3503
+ ]
3504
+ },
3505
+ "minItems": 1,
3506
+ "maxItems": 50
3507
+ }
3508
+ },
3509
+ "required": [
3510
+ "events"
3511
+ ]
3512
+ }
3513
+ }
3514
+ }
3515
+ },
3516
+ "responses": {
3517
+ "200": {
3518
+ "description": "Ratings applied; per-event rejections returned in body"
3519
+ },
3520
+ "400": {
3521
+ "description": "Validation error or explicit-self R6 spam-guard rejection"
3522
+ },
3523
+ "409": {
3524
+ "description": "Duplicate explicit-self rating for (taskId, memoryId)"
3525
+ }
3526
+ }
3527
+ }
3528
+ },
3529
+ "/api/memory/retrievals": {
3530
+ "get": {
3531
+ "summary": "List memories retrieved for a task or session (rater input)",
3532
+ "tags": [
3533
+ "Memory"
3534
+ ],
3535
+ "security": [
3536
+ {
3537
+ "bearerAuth": []
3538
+ }
3539
+ ],
3540
+ "parameters": [
3541
+ {
3542
+ "schema": {
3543
+ "type": "string",
3544
+ "format": "uuid"
3545
+ },
3546
+ "required": false,
3547
+ "name": "taskId",
3548
+ "in": "query"
3549
+ },
3550
+ {
3551
+ "schema": {
3552
+ "type": "string"
3553
+ },
3554
+ "required": false,
3555
+ "name": "sessionId",
3556
+ "in": "query"
3557
+ }
3558
+ ],
3559
+ "responses": {
3560
+ "200": {
3561
+ "description": "Retrieval rows joined with agent_memory"
3562
+ },
3563
+ "400": {
3564
+ "description": "Missing taskId/sessionId or X-Agent-ID"
3565
+ }
3566
+ }
3567
+ }
3568
+ },
3569
+ "/api/memory/edges": {
3570
+ "get": {
3571
+ "summary": "List references-source edges for a memory",
3572
+ "tags": [
3573
+ "Memory"
3574
+ ],
3575
+ "security": [
3576
+ {
3577
+ "bearerAuth": []
3578
+ }
3579
+ ],
3580
+ "parameters": [
3581
+ {
3582
+ "schema": {
3583
+ "type": "string",
3584
+ "minLength": 1
3585
+ },
3586
+ "required": true,
3587
+ "name": "memoryId",
3588
+ "in": "query"
3589
+ }
3590
+ ],
3591
+ "responses": {
3592
+ "200": {
3593
+ "description": "Edges with computed usefulness scores"
3594
+ },
3595
+ "400": {
3596
+ "description": "Missing memoryId or X-Agent-ID"
3597
+ }
3598
+ }
3599
+ }
3600
+ },
3034
3601
  "/api/prompt-templates/resolved": {
3035
3602
  "get": {
3036
3603
  "summary": "Resolve a prompt template for a given event type and scope chain",
@@ -5303,11 +5870,11 @@
5303
5870
  }
5304
5871
  }
5305
5872
  },
5306
- "/api/skills": {
5873
+ "/api/sessions": {
5307
5874
  "get": {
5308
- "summary": "List skills with optional filters",
5875
+ "summary": "List recent task sessions (root tasks + chain summary)",
5309
5876
  "tags": [
5310
- "Skills"
5877
+ "Sessions"
5311
5878
  ],
5312
5879
  "security": [
5313
5880
  {
@@ -5317,26 +5884,24 @@
5317
5884
  "parameters": [
5318
5885
  {
5319
5886
  "schema": {
5320
- "type": "string"
5321
- },
5322
- "required": false,
5323
- "name": "type",
5324
- "in": "query"
5325
- },
5326
- {
5327
- "schema": {
5328
- "type": "string"
5887
+ "type": [
5888
+ "integer",
5889
+ "null"
5890
+ ]
5329
5891
  },
5330
5892
  "required": false,
5331
- "name": "scope",
5893
+ "name": "limit",
5332
5894
  "in": "query"
5333
5895
  },
5334
5896
  {
5335
5897
  "schema": {
5336
- "type": "string"
5898
+ "type": [
5899
+ "integer",
5900
+ "null"
5901
+ ]
5337
5902
  },
5338
5903
  "required": false,
5339
- "name": "agentId",
5904
+ "name": "offset",
5340
5905
  "in": "query"
5341
5906
  },
5342
5907
  {
@@ -5344,7 +5909,7 @@
5344
5909
  "type": "string"
5345
5910
  },
5346
5911
  "required": false,
5347
- "name": "enabled",
5912
+ "name": "source",
5348
5913
  "in": "query"
5349
5914
  },
5350
5915
  {
@@ -5352,30 +5917,127 @@
5352
5917
  "type": "string"
5353
5918
  },
5354
5919
  "required": false,
5355
- "name": "search",
5920
+ "name": "q",
5356
5921
  "in": "query"
5357
5922
  }
5358
5923
  ],
5359
5924
  "responses": {
5360
5925
  "200": {
5361
- "description": "Skill list"
5926
+ "description": "Recent sessions ordered by chain-wide last activity"
5927
+ },
5928
+ "401": {
5929
+ "description": "Unauthorized"
5362
5930
  }
5363
5931
  }
5364
- },
5365
- "post": {
5366
- "summary": "Create a new skill",
5932
+ }
5933
+ },
5934
+ "/api/sessions/{rootTaskId}": {
5935
+ "get": {
5936
+ "summary": "Get a session — root task + the entire descendant chain",
5367
5937
  "tags": [
5368
- "Skills"
5938
+ "Sessions"
5369
5939
  ],
5370
5940
  "security": [
5371
5941
  {
5372
5942
  "bearerAuth": []
5373
5943
  }
5374
5944
  ],
5375
- "requestBody": {
5376
- "content": {
5377
- "application/json": {
5378
- "schema": {
5945
+ "parameters": [
5946
+ {
5947
+ "schema": {
5948
+ "type": "string"
5949
+ },
5950
+ "required": true,
5951
+ "name": "rootTaskId",
5952
+ "in": "path"
5953
+ }
5954
+ ],
5955
+ "responses": {
5956
+ "200": {
5957
+ "description": "Root task + chain (ordered by createdAt)"
5958
+ },
5959
+ "401": {
5960
+ "description": "Unauthorized"
5961
+ },
5962
+ "404": {
5963
+ "description": "Root task not found"
5964
+ }
5965
+ }
5966
+ }
5967
+ },
5968
+ "/api/skills": {
5969
+ "get": {
5970
+ "summary": "List skills with optional filters",
5971
+ "tags": [
5972
+ "Skills"
5973
+ ],
5974
+ "security": [
5975
+ {
5976
+ "bearerAuth": []
5977
+ }
5978
+ ],
5979
+ "parameters": [
5980
+ {
5981
+ "schema": {
5982
+ "type": "string"
5983
+ },
5984
+ "required": false,
5985
+ "name": "type",
5986
+ "in": "query"
5987
+ },
5988
+ {
5989
+ "schema": {
5990
+ "type": "string"
5991
+ },
5992
+ "required": false,
5993
+ "name": "scope",
5994
+ "in": "query"
5995
+ },
5996
+ {
5997
+ "schema": {
5998
+ "type": "string"
5999
+ },
6000
+ "required": false,
6001
+ "name": "agentId",
6002
+ "in": "query"
6003
+ },
6004
+ {
6005
+ "schema": {
6006
+ "type": "string"
6007
+ },
6008
+ "required": false,
6009
+ "name": "enabled",
6010
+ "in": "query"
6011
+ },
6012
+ {
6013
+ "schema": {
6014
+ "type": "string"
6015
+ },
6016
+ "required": false,
6017
+ "name": "search",
6018
+ "in": "query"
6019
+ }
6020
+ ],
6021
+ "responses": {
6022
+ "200": {
6023
+ "description": "Skill list"
6024
+ }
6025
+ }
6026
+ },
6027
+ "post": {
6028
+ "summary": "Create a new skill",
6029
+ "tags": [
6030
+ "Skills"
6031
+ ],
6032
+ "security": [
6033
+ {
6034
+ "bearerAuth": []
6035
+ }
6036
+ ],
6037
+ "requestBody": {
6038
+ "content": {
6039
+ "application/json": {
6040
+ "schema": {
5379
6041
  "type": "object",
5380
6042
  "properties": {
5381
6043
  "content": {
@@ -6657,6 +7319,294 @@
6657
7319
  }
6658
7320
  }
6659
7321
  },
7322
+ "/status": {
7323
+ "get": {
7324
+ "summary": "Identity + setup readiness + live activity for the swarm dashboard",
7325
+ "description": "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; the 7 setup milestones each emit `unverified | configured | verified`; activity counts agents alive in the last 5 min and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set.",
7326
+ "tags": [
7327
+ "Status"
7328
+ ],
7329
+ "security": [
7330
+ {
7331
+ "bearerAuth": []
7332
+ }
7333
+ ],
7334
+ "responses": {
7335
+ "200": {
7336
+ "description": "Status payload",
7337
+ "content": {
7338
+ "application/json": {
7339
+ "schema": {
7340
+ "type": "object",
7341
+ "properties": {
7342
+ "identity": {
7343
+ "type": "object",
7344
+ "properties": {
7345
+ "name": {
7346
+ "type": "string"
7347
+ },
7348
+ "logo_url": {
7349
+ "type": [
7350
+ "string",
7351
+ "null"
7352
+ ]
7353
+ },
7354
+ "brand_color": {
7355
+ "type": [
7356
+ "string",
7357
+ "null"
7358
+ ]
7359
+ },
7360
+ "is_cloud": {
7361
+ "type": "boolean"
7362
+ },
7363
+ "marketing_url": {
7364
+ "type": [
7365
+ "string",
7366
+ "null"
7367
+ ]
7368
+ },
7369
+ "hide_cloud_promo": {
7370
+ "type": "boolean"
7371
+ }
7372
+ },
7373
+ "required": [
7374
+ "name",
7375
+ "logo_url",
7376
+ "brand_color",
7377
+ "is_cloud",
7378
+ "marketing_url",
7379
+ "hide_cloud_promo"
7380
+ ]
7381
+ },
7382
+ "setup": {
7383
+ "type": "array",
7384
+ "items": {
7385
+ "type": "object",
7386
+ "properties": {
7387
+ "id": {
7388
+ "type": "string",
7389
+ "enum": [
7390
+ "harness",
7391
+ "slack",
7392
+ "github",
7393
+ "linear",
7394
+ "jira",
7395
+ "workers",
7396
+ "first_task"
7397
+ ]
7398
+ },
7399
+ "label": {
7400
+ "type": "string"
7401
+ },
7402
+ "state": {
7403
+ "type": "string",
7404
+ "enum": [
7405
+ "unverified",
7406
+ "configured",
7407
+ "verified"
7408
+ ]
7409
+ },
7410
+ "hint": {
7411
+ "type": "string"
7412
+ },
7413
+ "action_url": {
7414
+ "type": "string"
7415
+ },
7416
+ "provider": {
7417
+ "type": "string",
7418
+ "enum": [
7419
+ "claude",
7420
+ "codex",
7421
+ "pi",
7422
+ "devin",
7423
+ "claude-managed",
7424
+ "opencode"
7425
+ ]
7426
+ },
7427
+ "providers": {
7428
+ "type": "array",
7429
+ "items": {
7430
+ "type": "object",
7431
+ "properties": {
7432
+ "provider": {
7433
+ "type": "string",
7434
+ "enum": [
7435
+ "claude",
7436
+ "codex",
7437
+ "pi",
7438
+ "devin",
7439
+ "claude-managed",
7440
+ "opencode"
7441
+ ]
7442
+ },
7443
+ "state": {
7444
+ "type": "string",
7445
+ "enum": [
7446
+ "unverified",
7447
+ "configured",
7448
+ "verified"
7449
+ ]
7450
+ },
7451
+ "workers": {
7452
+ "type": "integer",
7453
+ "minimum": 0
7454
+ }
7455
+ },
7456
+ "required": [
7457
+ "provider",
7458
+ "state",
7459
+ "workers"
7460
+ ]
7461
+ }
7462
+ }
7463
+ },
7464
+ "required": [
7465
+ "id",
7466
+ "label",
7467
+ "state"
7468
+ ]
7469
+ }
7470
+ },
7471
+ "activity": {
7472
+ "type": "object",
7473
+ "properties": {
7474
+ "agents_online": {
7475
+ "type": "integer",
7476
+ "minimum": 0
7477
+ },
7478
+ "leads_online": {
7479
+ "type": "integer",
7480
+ "minimum": 0
7481
+ },
7482
+ "recent_tasks_count": {
7483
+ "type": "integer",
7484
+ "minimum": 0
7485
+ }
7486
+ },
7487
+ "required": [
7488
+ "agents_online",
7489
+ "leads_online",
7490
+ "recent_tasks_count"
7491
+ ]
7492
+ },
7493
+ "agent_fs": {
7494
+ "type": "object",
7495
+ "properties": {
7496
+ "configured": {
7497
+ "type": "boolean"
7498
+ },
7499
+ "base_url": {
7500
+ "type": [
7501
+ "string",
7502
+ "null"
7503
+ ]
7504
+ }
7505
+ },
7506
+ "required": [
7507
+ "configured",
7508
+ "base_url"
7509
+ ]
7510
+ },
7511
+ "health": {
7512
+ "type": "string",
7513
+ "enum": [
7514
+ "ok",
7515
+ "degraded",
7516
+ "broken"
7517
+ ]
7518
+ }
7519
+ },
7520
+ "required": [
7521
+ "identity",
7522
+ "setup",
7523
+ "activity",
7524
+ "agent_fs",
7525
+ "health"
7526
+ ]
7527
+ }
7528
+ }
7529
+ }
7530
+ },
7531
+ "401": {
7532
+ "description": "Unauthorized"
7533
+ }
7534
+ }
7535
+ }
7536
+ },
7537
+ "/status/test-connection": {
7538
+ "post": {
7539
+ "summary": "Live-test the harness provider's credentials",
7540
+ "description": "Issues a real upstream call (Anthropic /v1/models, OpenAI /v1/models, etc.) for the given provider. Updates an in-memory cache so the next GET /status reports `harness.state = 'verified'` for SWARM_VERIFY_TTL_MS (default 1h).",
7541
+ "tags": [
7542
+ "Status"
7543
+ ],
7544
+ "security": [
7545
+ {
7546
+ "bearerAuth": []
7547
+ }
7548
+ ],
7549
+ "requestBody": {
7550
+ "content": {
7551
+ "application/json": {
7552
+ "schema": {
7553
+ "type": "object",
7554
+ "properties": {
7555
+ "provider": {
7556
+ "type": "string",
7557
+ "enum": [
7558
+ "claude",
7559
+ "codex",
7560
+ "pi",
7561
+ "devin",
7562
+ "claude-managed",
7563
+ "opencode"
7564
+ ]
7565
+ }
7566
+ },
7567
+ "required": [
7568
+ "provider"
7569
+ ]
7570
+ }
7571
+ }
7572
+ }
7573
+ },
7574
+ "responses": {
7575
+ "200": {
7576
+ "description": "Live-test result",
7577
+ "content": {
7578
+ "application/json": {
7579
+ "schema": {
7580
+ "type": "object",
7581
+ "properties": {
7582
+ "ok": {
7583
+ "type": "boolean"
7584
+ },
7585
+ "error": {
7586
+ "type": "string"
7587
+ },
7588
+ "latency_ms": {
7589
+ "type": "integer",
7590
+ "minimum": 0
7591
+ }
7592
+ },
7593
+ "required": [
7594
+ "ok",
7595
+ "latency_ms"
7596
+ ]
7597
+ }
7598
+ }
7599
+ }
7600
+ },
7601
+ "400": {
7602
+ "description": "Validation error"
7603
+ },
7604
+ "401": {
7605
+ "description": "Unauthorized"
7606
+ }
7607
+ }
7608
+ }
7609
+ },
6660
7610
  "/api/tasks": {
6661
7611
  "get": {
6662
7612
  "summary": "List tasks with filters",
@@ -6713,6 +7663,23 @@
6713
7663
  "name": "includeHeartbeat",
6714
7664
  "in": "query"
6715
7665
  },
7666
+ {
7667
+ "schema": {
7668
+ "type": "string",
7669
+ "format": "date-time"
7670
+ },
7671
+ "required": false,
7672
+ "name": "createdAfter",
7673
+ "in": "query"
7674
+ },
7675
+ {
7676
+ "schema": {
7677
+ "type": "string"
7678
+ },
7679
+ "required": false,
7680
+ "name": "source",
7681
+ "in": "query"
7682
+ },
6716
7683
  {
6717
7684
  "schema": {
6718
7685
  "type": [
@@ -6739,6 +7706,9 @@
6739
7706
  "responses": {
6740
7707
  "200": {
6741
7708
  "description": "Paginated task list"
7709
+ },
7710
+ "400": {
7711
+ "description": "Validation error (e.g. unknown status token)"
6742
7712
  }
6743
7713
  }
6744
7714
  },
@@ -6793,7 +7763,21 @@
6793
7763
  "type": "string"
6794
7764
  },
6795
7765
  "source": {
6796
- "type": "string"
7766
+ "type": "string",
7767
+ "enum": [
7768
+ "mcp",
7769
+ "slack",
7770
+ "api",
7771
+ "ui",
7772
+ "github",
7773
+ "gitlab",
7774
+ "agentmail",
7775
+ "system",
7776
+ "schedule",
7777
+ "workflow",
7778
+ "linear",
7779
+ "jira"
7780
+ ]
6797
7781
  },
6798
7782
  "outputSchema": {
6799
7783
  "type": "object",
@@ -6801,6 +7785,9 @@
6801
7785
  },
6802
7786
  "contextKey": {
6803
7787
  "type": "string"
7788
+ },
7789
+ "requestedByUserId": {
7790
+ "type": "string"
6804
7791
  }
6805
7792
  },
6806
7793
  "required": [
@@ -7266,6 +8253,58 @@
7266
8253
  }
7267
8254
  }
7268
8255
  },
8256
+ "/api/task-templates": {
8257
+ "get": {
8258
+ "summary": "List task templates ('To start' bucket)",
8259
+ "tags": [
8260
+ "Task Templates"
8261
+ ],
8262
+ "security": [
8263
+ {
8264
+ "bearerAuth": []
8265
+ }
8266
+ ],
8267
+ "parameters": [
8268
+ {
8269
+ "schema": {
8270
+ "type": "string"
8271
+ },
8272
+ "required": false,
8273
+ "name": "category",
8274
+ "in": "query"
8275
+ },
8276
+ {
8277
+ "schema": {
8278
+ "type": "string",
8279
+ "enum": [
8280
+ "task",
8281
+ "workflow",
8282
+ "schedule"
8283
+ ]
8284
+ },
8285
+ "required": false,
8286
+ "name": "kind",
8287
+ "in": "query"
8288
+ },
8289
+ {
8290
+ "schema": {
8291
+ "type": "string"
8292
+ },
8293
+ "required": false,
8294
+ "name": "query",
8295
+ "in": "query"
8296
+ }
8297
+ ],
8298
+ "responses": {
8299
+ "200": {
8300
+ "description": "Task template list"
8301
+ },
8302
+ "401": {
8303
+ "description": "Unauthorized"
8304
+ }
8305
+ }
8306
+ }
8307
+ },
7269
8308
  "/api/trackers/jira/authorize": {
7270
8309
  "get": {
7271
8310
  "summary": "Redirect to Atlassian OAuth consent screen",
@@ -7641,6 +8680,185 @@
7641
8680
  }
7642
8681
  }
7643
8682
  },
8683
+ "/api/users": {
8684
+ "get": {
8685
+ "summary": "List all users",
8686
+ "tags": [
8687
+ "Users"
8688
+ ],
8689
+ "security": [
8690
+ {
8691
+ "bearerAuth": []
8692
+ }
8693
+ ],
8694
+ "responses": {
8695
+ "200": {
8696
+ "description": "List of users"
8697
+ },
8698
+ "401": {
8699
+ "description": "Unauthorized"
8700
+ }
8701
+ }
8702
+ },
8703
+ "post": {
8704
+ "summary": "Create a new user",
8705
+ "tags": [
8706
+ "Users"
8707
+ ],
8708
+ "security": [
8709
+ {
8710
+ "bearerAuth": []
8711
+ }
8712
+ ],
8713
+ "requestBody": {
8714
+ "content": {
8715
+ "application/json": {
8716
+ "schema": {
8717
+ "type": "object",
8718
+ "properties": {
8719
+ "name": {
8720
+ "type": "string",
8721
+ "minLength": 1
8722
+ },
8723
+ "email": {
8724
+ "type": "string"
8725
+ },
8726
+ "role": {
8727
+ "type": "string"
8728
+ },
8729
+ "notes": {
8730
+ "type": "string"
8731
+ },
8732
+ "slackUserId": {
8733
+ "type": "string"
8734
+ },
8735
+ "linearUserId": {
8736
+ "type": "string"
8737
+ },
8738
+ "githubUsername": {
8739
+ "type": "string"
8740
+ },
8741
+ "gitlabUsername": {
8742
+ "type": "string"
8743
+ },
8744
+ "emailAliases": {
8745
+ "type": "array",
8746
+ "items": {
8747
+ "type": "string"
8748
+ }
8749
+ },
8750
+ "preferredChannel": {
8751
+ "type": "string"
8752
+ },
8753
+ "timezone": {
8754
+ "type": "string"
8755
+ }
8756
+ },
8757
+ "required": [
8758
+ "name"
8759
+ ]
8760
+ }
8761
+ }
8762
+ }
8763
+ },
8764
+ "responses": {
8765
+ "200": {
8766
+ "description": "User created"
8767
+ },
8768
+ "400": {
8769
+ "description": "Validation error"
8770
+ },
8771
+ "401": {
8772
+ "description": "Unauthorized"
8773
+ }
8774
+ }
8775
+ }
8776
+ },
8777
+ "/api/users/{id}": {
8778
+ "put": {
8779
+ "summary": "Update an existing user (partial — at least one field required)",
8780
+ "tags": [
8781
+ "Users"
8782
+ ],
8783
+ "security": [
8784
+ {
8785
+ "bearerAuth": []
8786
+ }
8787
+ ],
8788
+ "parameters": [
8789
+ {
8790
+ "schema": {
8791
+ "type": "string"
8792
+ },
8793
+ "required": true,
8794
+ "name": "id",
8795
+ "in": "path"
8796
+ }
8797
+ ],
8798
+ "requestBody": {
8799
+ "content": {
8800
+ "application/json": {
8801
+ "schema": {
8802
+ "type": "object",
8803
+ "properties": {
8804
+ "name": {
8805
+ "type": "string",
8806
+ "minLength": 1
8807
+ },
8808
+ "email": {
8809
+ "type": "string"
8810
+ },
8811
+ "role": {
8812
+ "type": "string"
8813
+ },
8814
+ "notes": {
8815
+ "type": "string"
8816
+ },
8817
+ "slackUserId": {
8818
+ "type": "string"
8819
+ },
8820
+ "linearUserId": {
8821
+ "type": "string"
8822
+ },
8823
+ "githubUsername": {
8824
+ "type": "string"
8825
+ },
8826
+ "gitlabUsername": {
8827
+ "type": "string"
8828
+ },
8829
+ "emailAliases": {
8830
+ "type": "array",
8831
+ "items": {
8832
+ "type": "string"
8833
+ }
8834
+ },
8835
+ "preferredChannel": {
8836
+ "type": "string"
8837
+ },
8838
+ "timezone": {
8839
+ "type": "string"
8840
+ }
8841
+ }
8842
+ }
8843
+ }
8844
+ }
8845
+ },
8846
+ "responses": {
8847
+ "200": {
8848
+ "description": "User updated"
8849
+ },
8850
+ "400": {
8851
+ "description": "Validation error or empty body"
8852
+ },
8853
+ "401": {
8854
+ "description": "Unauthorized"
8855
+ },
8856
+ "404": {
8857
+ "description": "User not found"
8858
+ }
8859
+ }
8860
+ }
8861
+ },
7644
8862
  "/api/github/webhook": {
7645
8863
  "post": {
7646
8864
  "summary": "Handle GitHub webhook events",