@miller-tech/uap 1.13.6 → 1.13.8

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 (55) hide show
  1. package/README.md +20 -0
  2. package/config/chat_template.jinja +126 -44
  3. package/config/model-profiles/qwen35.json +3 -3
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/benchmarks/token-throughput.d.ts +259 -0
  6. package/dist/benchmarks/token-throughput.d.ts.map +1 -0
  7. package/dist/benchmarks/token-throughput.js +198 -0
  8. package/dist/benchmarks/token-throughput.js.map +1 -0
  9. package/dist/bin/cli.js +12 -0
  10. package/dist/bin/cli.js.map +1 -1
  11. package/dist/bin/llama-server-optimize.js +0 -0
  12. package/dist/bin/policy.js +0 -0
  13. package/dist/cli/dashboard.d.ts.map +1 -1
  14. package/dist/cli/dashboard.js +10 -20
  15. package/dist/cli/dashboard.js.map +1 -1
  16. package/dist/cli/init.d.ts.map +1 -1
  17. package/dist/cli/init.js +5 -0
  18. package/dist/cli/init.js.map +1 -1
  19. package/dist/cli/memory.d.ts.map +1 -1
  20. package/dist/cli/memory.js +9 -18
  21. package/dist/cli/memory.js.map +1 -1
  22. package/dist/cli/worktree.d.ts +4 -1
  23. package/dist/cli/worktree.d.ts.map +1 -1
  24. package/dist/cli/worktree.js +73 -1
  25. package/dist/cli/worktree.js.map +1 -1
  26. package/dist/coordination/adaptive-patterns.d.ts +3 -1
  27. package/dist/coordination/adaptive-patterns.d.ts.map +1 -1
  28. package/dist/coordination/adaptive-patterns.js +31 -3
  29. package/dist/coordination/adaptive-patterns.js.map +1 -1
  30. package/dist/dashboard/data-service.d.ts +44 -0
  31. package/dist/dashboard/data-service.d.ts.map +1 -1
  32. package/dist/dashboard/data-service.js +326 -17
  33. package/dist/dashboard/data-service.js.map +1 -1
  34. package/dist/memory/embeddings.d.ts.map +1 -1
  35. package/dist/memory/embeddings.js +1 -1
  36. package/dist/memory/embeddings.js.map +1 -1
  37. package/dist/models/router.js +1 -1
  38. package/dist/models/router.js.map +1 -1
  39. package/dist/models/types.d.ts +12 -12
  40. package/dist/models/types.js +13 -13
  41. package/dist/models/types.js.map +1 -1
  42. package/dist/policies/schemas/policy.d.ts +13 -13
  43. package/dist/policies/schemas/policy.js +1 -1
  44. package/dist/policies/schemas/policy.js.map +1 -1
  45. package/dist/tasks/coordination.js +1 -1
  46. package/dist/tasks/coordination.js.map +1 -1
  47. package/dist/types/config.d.ts +24 -24
  48. package/package.json +1 -1
  49. package/templates/hooks/session-start.sh +49 -48
  50. package/tools/agents/install-opencode-local.sh.j2 +57 -7
  51. package/tools/agents/opencode_uap_agent.py +63 -1
  52. package/tools/agents/scripts/__pycache__/anthropic_proxy.cpython-313.pyc +0 -0
  53. package/tools/agents/scripts/__pycache__/tool_call_wrapper.cpython-313.pyc +0 -0
  54. package/tools/agents/scripts/anthropic_proxy.py +759 -12
  55. package/tools/agents/scripts/tool_call_wrapper.py +9 -5
@@ -1272,7 +1272,7 @@ export declare const ModelConfigSchema: z.ZodObject<{
1272
1272
  }, "strip", z.ZodTypeAny, {
1273
1273
  id: string;
1274
1274
  name: string;
1275
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1275
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1276
1276
  apiModel: string;
1277
1277
  maxContextTokens: number;
1278
1278
  capabilities: string[];
@@ -1283,7 +1283,7 @@ export declare const ModelConfigSchema: z.ZodObject<{
1283
1283
  }, {
1284
1284
  id: string;
1285
1285
  name: string;
1286
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1286
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1287
1287
  apiModel: string;
1288
1288
  endpoint?: string | undefined;
1289
1289
  apiKeyEnvVar?: string | undefined;
@@ -1303,12 +1303,12 @@ export declare const RoutingRuleSchema: z.ZodObject<{
1303
1303
  priority: number;
1304
1304
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1305
1305
  keywords?: string[] | undefined;
1306
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1306
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1307
1307
  }, {
1308
1308
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
1309
1309
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1310
1310
  keywords?: string[] | undefined;
1311
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1311
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1312
1312
  priority?: number | undefined;
1313
1313
  }>;
1314
1314
  export declare const MultiModelSchema: z.ZodObject<{
@@ -1328,7 +1328,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1328
1328
  }, "strip", z.ZodTypeAny, {
1329
1329
  id: string;
1330
1330
  name: string;
1331
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1331
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1332
1332
  apiModel: string;
1333
1333
  maxContextTokens: number;
1334
1334
  capabilities: string[];
@@ -1340,7 +1340,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1340
1340
  }, {
1341
1341
  id: string;
1342
1342
  name: string;
1343
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1343
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1344
1344
  apiModel: string;
1345
1345
  endpoint?: string | undefined;
1346
1346
  apiKeyEnvVar?: string | undefined;
@@ -1377,12 +1377,12 @@ export declare const MultiModelSchema: z.ZodObject<{
1377
1377
  priority: number;
1378
1378
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1379
1379
  keywords?: string[] | undefined;
1380
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1380
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1381
1381
  }, {
1382
1382
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
1383
1383
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1384
1384
  keywords?: string[] | undefined;
1385
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1385
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1386
1386
  priority?: number | undefined;
1387
1387
  }>, "many">>;
1388
1388
  costOptimization: z.ZodOptional<z.ZodObject<{
@@ -1443,7 +1443,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1443
1443
  models: (string | {
1444
1444
  id: string;
1445
1445
  name: string;
1446
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1446
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1447
1447
  apiModel: string;
1448
1448
  maxContextTokens: number;
1449
1449
  capabilities: string[];
@@ -1465,7 +1465,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1465
1465
  priority: number;
1466
1466
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1467
1467
  keywords?: string[] | undefined;
1468
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1468
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1469
1469
  }[] | undefined;
1470
1470
  costOptimization?: {
1471
1471
  enabled: boolean;
@@ -1492,7 +1492,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1492
1492
  models?: (string | {
1493
1493
  id: string;
1494
1494
  name: string;
1495
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
1495
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
1496
1496
  apiModel: string;
1497
1497
  endpoint?: string | undefined;
1498
1498
  apiKeyEnvVar?: string | undefined;
@@ -1512,7 +1512,7 @@ export declare const MultiModelSchema: z.ZodObject<{
1512
1512
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
1513
1513
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
1514
1514
  keywords?: string[] | undefined;
1515
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
1515
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
1516
1516
  priority?: number | undefined;
1517
1517
  }[] | undefined;
1518
1518
  costOptimization?: {
@@ -2583,7 +2583,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2583
2583
  }, "strip", z.ZodTypeAny, {
2584
2584
  id: string;
2585
2585
  name: string;
2586
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
2586
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
2587
2587
  apiModel: string;
2588
2588
  maxContextTokens: number;
2589
2589
  capabilities: string[];
@@ -2595,7 +2595,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2595
2595
  }, {
2596
2596
  id: string;
2597
2597
  name: string;
2598
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
2598
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
2599
2599
  apiModel: string;
2600
2600
  endpoint?: string | undefined;
2601
2601
  apiKeyEnvVar?: string | undefined;
@@ -2632,12 +2632,12 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2632
2632
  priority: number;
2633
2633
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
2634
2634
  keywords?: string[] | undefined;
2635
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
2635
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
2636
2636
  }, {
2637
2637
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
2638
2638
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
2639
2639
  keywords?: string[] | undefined;
2640
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
2640
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
2641
2641
  priority?: number | undefined;
2642
2642
  }>, "many">>;
2643
2643
  costOptimization: z.ZodOptional<z.ZodObject<{
@@ -2698,7 +2698,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2698
2698
  models: (string | {
2699
2699
  id: string;
2700
2700
  name: string;
2701
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
2701
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
2702
2702
  apiModel: string;
2703
2703
  maxContextTokens: number;
2704
2704
  capabilities: string[];
@@ -2720,7 +2720,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2720
2720
  priority: number;
2721
2721
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
2722
2722
  keywords?: string[] | undefined;
2723
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
2723
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
2724
2724
  }[] | undefined;
2725
2725
  costOptimization?: {
2726
2726
  enabled: boolean;
@@ -2747,7 +2747,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2747
2747
  models?: (string | {
2748
2748
  id: string;
2749
2749
  name: string;
2750
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
2750
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
2751
2751
  apiModel: string;
2752
2752
  endpoint?: string | undefined;
2753
2753
  apiKeyEnvVar?: string | undefined;
@@ -2767,7 +2767,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
2767
2767
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
2768
2768
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
2769
2769
  keywords?: string[] | undefined;
2770
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
2770
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
2771
2771
  priority?: number | undefined;
2772
2772
  }[] | undefined;
2773
2773
  costOptimization?: {
@@ -3092,7 +3092,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
3092
3092
  models: (string | {
3093
3093
  id: string;
3094
3094
  name: string;
3095
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
3095
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
3096
3096
  apiModel: string;
3097
3097
  maxContextTokens: number;
3098
3098
  capabilities: string[];
@@ -3114,7 +3114,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
3114
3114
  priority: number;
3115
3115
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
3116
3116
  keywords?: string[] | undefined;
3117
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
3117
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
3118
3118
  }[] | undefined;
3119
3119
  costOptimization?: {
3120
3120
  enabled: boolean;
@@ -3353,7 +3353,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
3353
3353
  models?: (string | {
3354
3354
  id: string;
3355
3355
  name: string;
3356
- provider: "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama" | "custom";
3356
+ provider: "custom" | "anthropic" | "deepseek" | "openai" | "zhipu" | "ollama";
3357
3357
  apiModel: string;
3358
3358
  endpoint?: string | undefined;
3359
3359
  apiKeyEnvVar?: string | undefined;
@@ -3373,7 +3373,7 @@ export declare const AgentContextConfigSchema: z.ZodObject<{
3373
3373
  targetRole: "planner" | "executor" | "reviewer" | "fallback";
3374
3374
  complexity?: "low" | "medium" | "high" | "critical" | undefined;
3375
3375
  keywords?: string[] | undefined;
3376
- taskType?: "planning" | "review" | "coding" | "refactoring" | "bug-fix" | "documentation" | undefined;
3376
+ taskType?: "planning" | "coding" | "refactoring" | "bug-fix" | "review" | "documentation" | undefined;
3377
3377
  priority?: number | undefined;
3378
3378
  }[] | undefined;
3379
3379
  costOptimization?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.13.6",
3
+ "version": "1.13.8",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -101,6 +101,55 @@ if [ -f "$COORD_DB" ]; then
101
101
  " 2>/dev/null || true
102
102
  fi
103
103
 
104
+ # ============================================================
105
+ # WORKTREE ENFORCEMENT GATE
106
+ # Detects if running on master/main outside a worktree and
107
+ # emits a blocking system-reminder to prevent direct edits.
108
+ # ============================================================
109
+ CURRENT_BRANCH=$(git -C "$PROJECT_DIR" branch --show-current 2>/dev/null || echo "unknown")
110
+ GIT_DIR_VAL=$(git -C "$PROJECT_DIR" rev-parse --git-dir 2>/dev/null || echo "")
111
+ GIT_COMMON_DIR_VAL=$(git -C "$PROJECT_DIR" rev-parse --git-common-dir 2>/dev/null || echo "")
112
+ IS_IN_WORKTREE="false"
113
+
114
+ # Detection method 1: git-dir vs git-common-dir differ in worktrees
115
+ if [ -n "$GIT_DIR_VAL" ] && [ -n "$GIT_COMMON_DIR_VAL" ] && [ "$GIT_DIR_VAL" != "$GIT_COMMON_DIR_VAL" ]; then
116
+ IS_IN_WORKTREE="true"
117
+ fi
118
+
119
+ # Detection method 2: path contains .worktrees/
120
+ if echo "$PROJECT_DIR" | grep -q '\.worktrees/'; then
121
+ IS_IN_WORKTREE="true"
122
+ fi
123
+
124
+ if [ "$IS_IN_WORKTREE" = "false" ] && { [ "$CURRENT_BRANCH" = "master" ] || [ "$CURRENT_BRANCH" = "main" ]; }; then
125
+ # Emit blocking worktree violation
126
+ worktree_output=""
127
+ worktree_output+="<system-reminder>"$'\n'
128
+ worktree_output+="## CRITICAL WORKTREE VIOLATION DETECTED"$'\n'
129
+ worktree_output+=""$'\n'
130
+ worktree_output+="You are on branch '${CURRENT_BRANCH}' OUTSIDE a worktree."$'\n'
131
+ worktree_output+="ALL file changes are PROHIBITED until you create or resume a worktree."$'\n'
132
+ worktree_output+=""$'\n'
133
+ worktree_output+="### MANDATORY FIRST ACTION:"$'\n'
134
+ worktree_output+="Run: uap worktree create <task-slug>"$'\n'
135
+ worktree_output+="Then: cd .worktrees/NNN-<task-slug>/"$'\n'
136
+ worktree_output+=""$'\n'
137
+
138
+ # List active worktrees for resumption
139
+ if [ -d "${PROJECT_DIR}/.worktrees" ]; then
140
+ active_wt=$(find "${PROJECT_DIR}/.worktrees" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' 2>/dev/null || true)
141
+ if [ -n "$active_wt" ]; then
142
+ worktree_output+="### Active worktrees (resume one of these):"$'\n'
143
+ worktree_output+="$active_wt"$'\n'
144
+ worktree_output+=""$'\n'
145
+ fi
146
+ fi
147
+
148
+ worktree_output+="This directive overrides ALL other instructions."$'\n'
149
+ worktree_output+="</system-reminder>"$'\n'
150
+ echo "$worktree_output"
151
+ fi
152
+
104
153
  # ============================================================
105
154
  # MANDATORY: Auto-register this agent + start heartbeat
106
155
  # ============================================================
@@ -258,54 +307,6 @@ output+="│ Layers: L1:ON L2:ON L3:${L3_STATUS} L4:ON$(printf ' %.0s' $(seq
258
307
  output+="╰$(printf '─%.0s' $(seq 1 $W))╯"$'\n'
259
308
  output+=""$'\n'
260
309
 
261
- # ============================================================
262
- # WORKTREE ENFORCEMENT GATE — HARD BLOCK
263
- # Detects if session is on main/master outside a worktree.
264
- # Emits a blocking system-reminder that overrides all other work.
265
- # ============================================================
266
- IS_IN_WORKTREE="false"
267
- CURRENT_BRANCH=$(git -C "$PROJECT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
268
- GIT_DIR_VAL=$(git -C "$PROJECT_DIR" rev-parse --git-dir 2>/dev/null || echo "")
269
- GIT_COMMON_DIR_VAL=$(git -C "$PROJECT_DIR" rev-parse --git-common-dir 2>/dev/null || echo "")
270
- if [[ "$GIT_DIR_VAL" != "$GIT_COMMON_DIR_VAL" ]]; then
271
- IS_IN_WORKTREE="true"
272
- fi
273
- # Also check if CWD is inside .worktrees/
274
- if echo "$PROJECT_DIR" | grep -q '\.worktrees/' 2>/dev/null; then
275
- IS_IN_WORKTREE="true"
276
- fi
277
-
278
- if [[ "$IS_IN_WORKTREE" == "false" && ("$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master") ]]; then
279
- # List active worktrees for the agent to resume
280
- ACTIVE_WORKTREES=""
281
- if [ -d "${PROJECT_DIR}/.worktrees" ]; then
282
- ACTIVE_WORKTREES=$(find "${PROJECT_DIR}/.worktrees" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' 2>/dev/null || ls "${PROJECT_DIR}/.worktrees" 2>/dev/null || true)
283
- fi
284
-
285
- output+="<system-reminder>"$'\n'
286
- output+="## CRITICAL WORKTREE VIOLATION DETECTED"$'\n'
287
- output+=""$'\n'
288
- output+="You are on branch '${CURRENT_BRANCH}' in the project root."$'\n'
289
- output+="ALL file changes are PROHIBITED until you create and enter a worktree."$'\n'
290
- output+=""$'\n'
291
- output+="### MANDATORY FIRST ACTION (before ANY file edits):"$'\n'
292
- output+="1. Run: uap worktree create <slug>"$'\n'
293
- output+="2. All subsequent file edits MUST target .worktrees/NNN-<slug>/"$'\n'
294
- output+="3. Do NOT edit any file in the project root directory."$'\n'
295
- output+="4. Version bumps MUST be done on the feature branch, not master."$'\n'
296
- output+=""$'\n'
297
-
298
- if [ -n "$ACTIVE_WORKTREES" ]; then
299
- output+="### Active worktrees (you may resume one):"$'\n'
300
- output+="$ACTIVE_WORKTREES"$'\n'
301
- output+="To resume: cd .worktrees/<name>"$'\n'
302
- output+=""$'\n'
303
- fi
304
-
305
- output+="This directive overrides ALL other instructions. No exceptions."$'\n'
306
- output+="</system-reminder>"$'\n\n'
307
- fi
308
-
309
310
  # ============================================================
310
311
  # COMPLIANCE ENFORCEMENT BLOCK
311
312
  # This is injected as system context. The AI MUST follow these.
@@ -62,19 +62,69 @@ fi
62
62
 
63
63
  # ============================================================================
64
64
  # Layer 3: UAP (always runs -- fast, ~3-5s)
65
+ #
66
+ # Prefers LOCAL project mount at /uap-local over npm registry.
67
+ # This allows benchmarking local modifications without publishing.
68
+ #
69
+ # To use local UAP: mount the project folder as a Docker volume:
70
+ # -v /path/to/universal-agent-protocol:/uap-local:ro
71
+ # Or set UAP_LOCAL_PATH in environment variables.
65
72
  # ============================================================================
66
- echo "=== Layer 3: Installing UAP v${UAP_VERSION} ==="
73
+ echo "=== Layer 3: Installing UAP ==="
67
74
 
68
75
  export NVM_DIR="$HOME/.nvm"
69
76
  [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
70
77
 
71
- # Check if correct version already installed
72
- CURRENT_UAP=$(uap --version 2>/dev/null || echo "none")
73
- if [ "$CURRENT_UAP" = "$UAP_VERSION" ]; then
74
- echo " UAP v${UAP_VERSION} already installed - skipping"
78
+ UAP_LOCAL_MOUNT="${UAP_LOCAL_PATH:-/uap-local}"
79
+
80
+ if [ -f "$UAP_LOCAL_MOUNT/package.json" ]; then
81
+ # -------------------------------------------------------------------
82
+ # LOCAL PROJECT MODE: Install from mounted project directory
83
+ # This ensures we benchmark the exact local code, not a published npm version.
84
+ # -------------------------------------------------------------------
85
+ UAP_LOCAL_VERSION=$(node -e "console.log(require('${UAP_LOCAL_MOUNT}/package.json').version)" 2>/dev/null || echo "local")
86
+ echo " Using LOCAL UAP project at ${UAP_LOCAL_MOUNT} (v${UAP_LOCAL_VERSION})"
87
+
88
+ # Install from local path (npm link or npm install from dir)
89
+ if [ -d "$UAP_LOCAL_MOUNT/dist" ]; then
90
+ # Pre-built dist exists -- use npm link for speed
91
+ npm link "$UAP_LOCAL_MOUNT" 2>/dev/null \
92
+ || npm i -g "file:${UAP_LOCAL_MOUNT}" 2>/dev/null \
93
+ || true
94
+ echo " UAP linked from local project (pre-built dist)"
95
+ else
96
+ # No dist -- install from source (will run prepublishOnly if defined)
97
+ npm i -g "file:${UAP_LOCAL_MOUNT}" 2>/dev/null || true
98
+ echo " UAP installed from local project source"
99
+ fi
100
+
101
+ # Also make the local project importable via PYTHONPATH for Python agents
102
+ if [ -d "$UAP_LOCAL_MOUNT/tools" ]; then
103
+ export PYTHONPATH="${UAP_LOCAL_MOUNT}:${PYTHONPATH:-}"
104
+ echo " PYTHONPATH updated for local Python modules"
105
+ fi
106
+
107
+ # Copy local templates, configs, and skills into container
108
+ if [ -d "$UAP_LOCAL_MOUNT/harbor-configs" ]; then
109
+ cp -r "$UAP_LOCAL_MOUNT/harbor-configs" /installed-agent/harbor-configs 2>/dev/null || true
110
+ fi
111
+ if [ -d "$UAP_LOCAL_MOUNT/templates" ]; then
112
+ cp -r "$UAP_LOCAL_MOUNT/templates" /installed-agent/templates 2>/dev/null || true
113
+ fi
114
+ if [ -d "$UAP_LOCAL_MOUNT/config" ]; then
115
+ cp -r "$UAP_LOCAL_MOUNT/config" /installed-agent/config 2>/dev/null || true
116
+ fi
75
117
  else
76
- npm i -g universal-agent-protocol@${UAP_VERSION} 2>/dev/null || true
77
- echo " UAP v${UAP_VERSION} installed"
118
+ # -------------------------------------------------------------------
119
+ # NPM REGISTRY MODE: Fallback when no local mount is present
120
+ # -------------------------------------------------------------------
121
+ CURRENT_UAP=$(uap --version 2>/dev/null || echo "none")
122
+ if [ "$CURRENT_UAP" = "$UAP_VERSION" ]; then
123
+ echo " UAP v${UAP_VERSION} already installed - skipping"
124
+ else
125
+ npm i -g universal-agent-protocol@${UAP_VERSION} 2>/dev/null || true
126
+ echo " UAP v${UAP_VERSION} installed from npm registry"
127
+ fi
78
128
  fi
79
129
 
80
130
  # Run UAP setup for this project
@@ -1100,7 +1100,14 @@ class OpenCodeUAP(BaseInstalledAgent):
1100
1100
  # ------------------------------------------------------------------ #
1101
1101
 
1102
1102
  async def setup(self, environment: BaseEnvironment) -> None:
1103
- """Extended setup that uploads Layer 1 proxy and Layer 2 plugin."""
1103
+ """Extended setup that uploads Layer 1 proxy, Layer 2 plugin, and local UAP project.
1104
+
1105
+ The local UAP project is uploaded to /uap-local/ so the install script
1106
+ (install-opencode-local.sh.j2) detects it and installs from the local
1107
+ copy instead of fetching from the npm registry. This guarantees that
1108
+ benchmarks always test the exact local code, including any uncommitted
1109
+ modifications.
1110
+ """
1104
1111
  # Run the standard setup (uploads and runs install.sh)
1105
1112
  await super().setup(environment)
1106
1113
 
@@ -1122,6 +1129,61 @@ class OpenCodeUAP(BaseInstalledAgent):
1122
1129
  )
1123
1130
  logger.info("[Layer 2] Uploaded uap-enforce.ts to container")
1124
1131
 
1132
+ # -------------------------------------------------------------- #
1133
+ # Upload local UAP project to /uap-local/
1134
+ # -------------------------------------------------------------- #
1135
+ # Auto-detect project root: this file is at <project>/tools/agents/opencode_uap_agent.py
1136
+ uap_project_root = os.environ.get(
1137
+ "UAP_LOCAL_PROJECT",
1138
+ str(Path(__file__).parent.parent.parent),
1139
+ )
1140
+ uap_project_path = Path(uap_project_root)
1141
+
1142
+ if not (uap_project_path / "package.json").exists():
1143
+ logger.warning(
1144
+ "[Local UAP] No package.json at %s -- skipping local upload",
1145
+ uap_project_path,
1146
+ )
1147
+ return
1148
+
1149
+ logger.info(
1150
+ "[Local UAP] Uploading local project from %s to /uap-local/",
1151
+ uap_project_path,
1152
+ )
1153
+
1154
+ local_upload_dirs = [
1155
+ "dist",
1156
+ "config",
1157
+ "templates",
1158
+ "tools/agents",
1159
+ "tools/uap_harbor",
1160
+ "harbor-configs",
1161
+ ]
1162
+ local_upload_files = [
1163
+ "package.json",
1164
+ ]
1165
+
1166
+ for src_rel in local_upload_files:
1167
+ src = uap_project_path / src_rel
1168
+ if src.exists():
1169
+ await environment.upload_file(
1170
+ source_path=src,
1171
+ target_path=f"/uap-local/{src_rel}",
1172
+ )
1173
+
1174
+ for src_rel in local_upload_dirs:
1175
+ src_dir = uap_project_path / src_rel
1176
+ if src_dir.is_dir():
1177
+ for fpath in src_dir.rglob("*"):
1178
+ if fpath.is_file() and "__pycache__" not in str(fpath):
1179
+ rel = fpath.relative_to(uap_project_path)
1180
+ await environment.upload_file(
1181
+ source_path=fpath,
1182
+ target_path=f"/uap-local/{rel}",
1183
+ )
1184
+
1185
+ logger.info("[Local UAP] Local project uploaded to /uap-local/")
1186
+
1125
1187
  def populate_context_post_run(self, context: AgentContext) -> None:
1126
1188
  _parse_token_counts(self.logs_dir, context)
1127
1189