tryassay 0.6.0 → 0.11.1

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 (109) hide show
  1. package/dist/api/pricing-enforcer.d.ts +45 -0
  2. package/dist/api/pricing-enforcer.js +144 -0
  3. package/dist/api/pricing-enforcer.js.map +1 -0
  4. package/dist/api/server.d.ts +28 -0
  5. package/dist/api/server.js +265 -0
  6. package/dist/api/server.js.map +1 -0
  7. package/dist/api/team-session.d.ts +59 -0
  8. package/dist/api/team-session.js +240 -0
  9. package/dist/api/team-session.js.map +1 -0
  10. package/dist/cli.js +123 -2
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/api.d.ts +4 -0
  13. package/dist/commands/api.js +50 -0
  14. package/dist/commands/api.js.map +1 -0
  15. package/dist/commands/runtime.d.ts +61 -0
  16. package/dist/commands/runtime.js +554 -0
  17. package/dist/commands/runtime.js.map +1 -1
  18. package/dist/runtime/agent-spawner.d.ts +56 -0
  19. package/dist/runtime/agent-spawner.js +217 -0
  20. package/dist/runtime/agent-spawner.js.map +1 -0
  21. package/dist/runtime/agents/coordinator-agent.d.ts +20 -0
  22. package/dist/runtime/agents/coordinator-agent.js +182 -0
  23. package/dist/runtime/agents/coordinator-agent.js.map +1 -0
  24. package/dist/runtime/agents/ops-agent.d.ts +11 -0
  25. package/dist/runtime/agents/ops-agent.js +113 -0
  26. package/dist/runtime/agents/ops-agent.js.map +1 -0
  27. package/dist/runtime/agents/research-agent.d.ts +11 -0
  28. package/dist/runtime/agents/research-agent.js +114 -0
  29. package/dist/runtime/agents/research-agent.js.map +1 -0
  30. package/dist/runtime/agents/test-agent.d.ts +11 -0
  31. package/dist/runtime/agents/test-agent.js +114 -0
  32. package/dist/runtime/agents/test-agent.js.map +1 -0
  33. package/dist/runtime/audit-log.js +2 -2
  34. package/dist/runtime/audit-log.js.map +1 -1
  35. package/dist/runtime/capability-registry.d.ts +62 -0
  36. package/dist/runtime/capability-registry.js +191 -0
  37. package/dist/runtime/capability-registry.js.map +1 -0
  38. package/dist/runtime/collusion-detector.d.ts +35 -0
  39. package/dist/runtime/collusion-detector.js +97 -0
  40. package/dist/runtime/collusion-detector.js.map +1 -0
  41. package/dist/runtime/control-server.js +8 -4
  42. package/dist/runtime/control-server.js.map +1 -1
  43. package/dist/runtime/domain-coverage-analyzer.d.ts +24 -0
  44. package/dist/runtime/domain-coverage-analyzer.js +178 -0
  45. package/dist/runtime/domain-coverage-analyzer.js.map +1 -0
  46. package/dist/runtime/executor.js +27 -12
  47. package/dist/runtime/executor.js.map +1 -1
  48. package/dist/runtime/human-escalation.d.ts +41 -0
  49. package/dist/runtime/human-escalation.js +122 -0
  50. package/dist/runtime/human-escalation.js.map +1 -0
  51. package/dist/runtime/kill-switch.d.ts +51 -0
  52. package/dist/runtime/kill-switch.js +185 -0
  53. package/dist/runtime/kill-switch.js.map +1 -0
  54. package/dist/runtime/layer2-guardian.d.ts +81 -0
  55. package/dist/runtime/layer2-guardian.js +263 -0
  56. package/dist/runtime/layer2-guardian.js.map +1 -0
  57. package/dist/runtime/multi-agent-loop.d.ts +37 -0
  58. package/dist/runtime/multi-agent-loop.js +411 -0
  59. package/dist/runtime/multi-agent-loop.js.map +1 -0
  60. package/dist/runtime/prompt-safety-analyzer.d.ts +17 -0
  61. package/dist/runtime/prompt-safety-analyzer.js +230 -0
  62. package/dist/runtime/prompt-safety-analyzer.js.map +1 -0
  63. package/dist/runtime/rollback-manager.d.ts +50 -0
  64. package/dist/runtime/rollback-manager.js +157 -0
  65. package/dist/runtime/rollback-manager.js.map +1 -0
  66. package/dist/runtime/rule-canary-deployer.d.ts +69 -0
  67. package/dist/runtime/rule-canary-deployer.js +289 -0
  68. package/dist/runtime/rule-canary-deployer.js.map +1 -0
  69. package/dist/runtime/rule-conflict-detector.d.ts +48 -0
  70. package/dist/runtime/rule-conflict-detector.js +214 -0
  71. package/dist/runtime/rule-conflict-detector.js.map +1 -0
  72. package/dist/runtime/rule-meta-verifier.d.ts +18 -0
  73. package/dist/runtime/rule-meta-verifier.js +275 -0
  74. package/dist/runtime/rule-meta-verifier.js.map +1 -0
  75. package/dist/runtime/rule-proposal-manager.d.ts +95 -0
  76. package/dist/runtime/rule-proposal-manager.js +190 -0
  77. package/dist/runtime/rule-proposal-manager.js.map +1 -0
  78. package/dist/runtime/safety-enforcer.d.ts +35 -0
  79. package/dist/runtime/safety-enforcer.js +165 -0
  80. package/dist/runtime/safety-enforcer.js.map +1 -0
  81. package/dist/runtime/safety-status.d.ts +48 -0
  82. package/dist/runtime/safety-status.js +119 -0
  83. package/dist/runtime/safety-status.js.map +1 -0
  84. package/dist/runtime/shared-memory.d.ts +47 -0
  85. package/dist/runtime/shared-memory.js +151 -0
  86. package/dist/runtime/shared-memory.js.map +1 -0
  87. package/dist/runtime/specialized-agent.d.ts +5 -0
  88. package/dist/runtime/specialized-agent.js +37 -0
  89. package/dist/runtime/specialized-agent.js.map +1 -1
  90. package/dist/runtime/stall-detector.d.ts +13 -0
  91. package/dist/runtime/stall-detector.js +121 -0
  92. package/dist/runtime/stall-detector.js.map +1 -0
  93. package/dist/runtime/tool-approval.d.ts +51 -0
  94. package/dist/runtime/tool-approval.js +148 -0
  95. package/dist/runtime/tool-approval.js.map +1 -0
  96. package/dist/runtime/tool-sandbox.d.ts +43 -0
  97. package/dist/runtime/tool-sandbox.js +394 -0
  98. package/dist/runtime/tool-sandbox.js.map +1 -0
  99. package/dist/runtime/tool-verifier.d.ts +18 -0
  100. package/dist/runtime/tool-verifier.js +323 -0
  101. package/dist/runtime/tool-verifier.js.map +1 -0
  102. package/dist/runtime/trust-manager.d.ts +33 -3
  103. package/dist/runtime/trust-manager.js +128 -26
  104. package/dist/runtime/trust-manager.js.map +1 -1
  105. package/dist/runtime/types.d.ts +652 -0
  106. package/dist/runtime/verification-intensity.d.ts +34 -0
  107. package/dist/runtime/verification-intensity.js +104 -0
  108. package/dist/runtime/verification-intensity.js.map +1 -0
  109. package/package.json +1 -1
@@ -0,0 +1,121 @@
1
+ // ============================================================
2
+ // Assay Verified Agent Runtime — Stall Detector
3
+ // Monitors task graph for timeouts, reject loops,
4
+ // dependency deadlocks, and resource contention.
5
+ // ============================================================
6
+ // ── Stall Detector ─────────────────────────────────────────
7
+ export class StallDetector {
8
+ /**
9
+ * Detect stalls in a task graph.
10
+ * Returns stall reports for any problematic tasks.
11
+ */
12
+ detectStalls(graph, thresholdMs) {
13
+ const reports = [];
14
+ const now = Date.now();
15
+ for (const task of graph.tasks) {
16
+ // Skip completed or failed tasks
17
+ if (task.status === 'completed' || task.status === 'failed')
18
+ continue;
19
+ // Check for timeout: task in progress for too long
20
+ if (task.status === 'in_progress' || task.status === 'assigned') {
21
+ const taskStart = new Date(task.createdAt).getTime();
22
+ const elapsed = now - taskStart;
23
+ if (elapsed > thresholdMs) {
24
+ reports.push({
25
+ taskId: task.id,
26
+ type: 'timeout',
27
+ duration: elapsed,
28
+ attempts: task.attempts,
29
+ suggestedAction: task.attempts >= task.maxAttempts ? 'escalate' : 'reassign',
30
+ });
31
+ }
32
+ }
33
+ // Check for reject loop: task rejected too many times
34
+ if (task.status === 'rejected' && task.attempts >= task.maxAttempts) {
35
+ reports.push({
36
+ taskId: task.id,
37
+ type: 'reject_loop',
38
+ duration: now - new Date(task.createdAt).getTime(),
39
+ attempts: task.attempts,
40
+ suggestedAction: task.attempts >= task.maxAttempts ? 'escalate' : 'simplify',
41
+ });
42
+ }
43
+ // Check for resource contention: multiple tasks waiting for the same specialization
44
+ if (task.status === 'ready' || task.status === 'pending') {
45
+ const waitingForSameSpec = graph.tasks.filter(t => t.id !== task.id &&
46
+ t.specialization === task.specialization &&
47
+ (t.status === 'in_progress' || t.status === 'assigned'));
48
+ if (waitingForSameSpec.length >= 2) {
49
+ reports.push({
50
+ taskId: task.id,
51
+ type: 'resource_contention',
52
+ duration: now - new Date(task.createdAt).getTime(),
53
+ attempts: task.attempts,
54
+ suggestedAction: 'reassign',
55
+ });
56
+ }
57
+ }
58
+ }
59
+ // Check for dependency deadlocks: circular dependencies
60
+ const deadlockTasks = this.detectDeadlocks(graph);
61
+ for (const taskId of deadlockTasks) {
62
+ const task = graph.tasks.find(t => t.id === taskId);
63
+ if (task) {
64
+ reports.push({
65
+ taskId: task.id,
66
+ type: 'dependency_deadlock',
67
+ duration: now - new Date(task.createdAt).getTime(),
68
+ attempts: task.attempts,
69
+ suggestedAction: 'abort',
70
+ });
71
+ }
72
+ }
73
+ return reports;
74
+ }
75
+ /**
76
+ * Detect circular dependencies in the task graph.
77
+ * Returns task IDs involved in deadlock cycles.
78
+ */
79
+ detectDeadlocks(graph) {
80
+ const deadlocked = new Set();
81
+ // Build adjacency list from blocking edges
82
+ const blockingEdges = graph.edges.filter(e => e.type === 'blocks');
83
+ const adjacency = new Map();
84
+ for (const edge of blockingEdges) {
85
+ const existing = adjacency.get(edge.from) ?? [];
86
+ existing.push(edge.to);
87
+ adjacency.set(edge.from, existing);
88
+ }
89
+ // DFS-based cycle detection
90
+ const visited = new Set();
91
+ const inStack = new Set();
92
+ const dfs = (taskId) => {
93
+ if (inStack.has(taskId)) {
94
+ // Found a cycle — collect all tasks in the cycle
95
+ deadlocked.add(taskId);
96
+ return true;
97
+ }
98
+ if (visited.has(taskId))
99
+ return false;
100
+ visited.add(taskId);
101
+ inStack.add(taskId);
102
+ const neighbors = adjacency.get(taskId) ?? [];
103
+ for (const neighbor of neighbors) {
104
+ if (dfs(neighbor)) {
105
+ deadlocked.add(taskId);
106
+ }
107
+ }
108
+ inStack.delete(taskId);
109
+ return false;
110
+ };
111
+ // Only check tasks that are not yet completed
112
+ const activeTasks = graph.tasks
113
+ .filter(t => t.status !== 'completed' && t.status !== 'failed')
114
+ .map(t => t.id);
115
+ for (const taskId of activeTasks) {
116
+ dfs(taskId);
117
+ }
118
+ return Array.from(deadlocked);
119
+ }
120
+ }
121
+ //# sourceMappingURL=stall-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stall-detector.js","sourceRoot":"","sources":["../../src/runtime/stall-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { ToolDefinition, ToolVerification, ModificationProposal, ModificationApproval, ProposalStatus } from './types.js';
2
+ import { ToolVerifier } from './tool-verifier.js';
3
+ import { CapabilityRegistryManager } from './capability-registry.js';
4
+ export interface PendingApproval {
5
+ readonly proposal: ModificationProposal;
6
+ readonly verification: ToolVerification;
7
+ readonly toolDefinition: ToolDefinition;
8
+ readonly toolSourceDir: string;
9
+ }
10
+ export declare class ToolApprovalManager {
11
+ private verifier;
12
+ private registry;
13
+ private pendingApprovals;
14
+ private approvalHistoryPath;
15
+ constructor(registry: CapabilityRegistryManager, verifier?: ToolVerifier, approvalHistoryPath?: string);
16
+ /**
17
+ * Propose a new tool. Runs verification and queues for human approval.
18
+ * Returns the proposal ID and verification result.
19
+ */
20
+ propose(tool: ToolDefinition, toolSourceDir: string, justification: {
21
+ capability_gap: string;
22
+ evidence: string[];
23
+ expected_impact: string;
24
+ risk_assessment: string;
25
+ }): Promise<{
26
+ proposalId: string;
27
+ verification: ToolVerification;
28
+ status: ProposalStatus;
29
+ }>;
30
+ /**
31
+ * List all pending approvals.
32
+ */
33
+ listPending(): PendingApproval[];
34
+ /**
35
+ * Get a specific pending approval.
36
+ */
37
+ getPending(proposalId: string): PendingApproval | undefined;
38
+ /**
39
+ * Approve a pending tool proposal. Activates the tool in the registry.
40
+ */
41
+ approve(proposalId: string, approvedBy: string, reasoning: string, conditions?: string[]): Promise<ModificationApproval>;
42
+ /**
43
+ * Reject a pending tool proposal.
44
+ */
45
+ reject(proposalId: string, rejectedBy: string, reasoning: string): Promise<ModificationApproval>;
46
+ /**
47
+ * Rollback the last registry change.
48
+ */
49
+ rollback(rolledBackBy: string): Promise<boolean>;
50
+ private logApproval;
51
+ }
@@ -0,0 +1,148 @@
1
+ // ============================================================
2
+ // Assay Verified Agent Runtime — Tool Approval Flow
3
+ // Orchestrates: propose → verify → approve → activate
4
+ // Human approval is required before any tool goes active.
5
+ // ============================================================
6
+ import { randomUUID } from 'node:crypto';
7
+ import { mkdir, appendFile } from 'node:fs/promises';
8
+ import { dirname } from 'node:path';
9
+ import { ToolVerifier } from './tool-verifier.js';
10
+ // ── Tool Approval Manager ──────────────────────────────────
11
+ export class ToolApprovalManager {
12
+ verifier;
13
+ registry;
14
+ pendingApprovals = new Map();
15
+ approvalHistoryPath;
16
+ constructor(registry, verifier, approvalHistoryPath) {
17
+ this.registry = registry;
18
+ this.verifier = verifier ?? new ToolVerifier();
19
+ this.approvalHistoryPath = approvalHistoryPath ?? '.assay/tool-approvals.ndjson';
20
+ }
21
+ /**
22
+ * Propose a new tool. Runs verification and queues for human approval.
23
+ * Returns the proposal ID and verification result.
24
+ */
25
+ async propose(tool, toolSourceDir, justification) {
26
+ const proposalId = `mod_${Date.now()}_${randomUUID().slice(0, 8)}`;
27
+ // Create the proposal
28
+ const proposal = {
29
+ id: proposalId,
30
+ type: 'tool',
31
+ timestamp: new Date().toISOString(),
32
+ title: `New tool: ${tool.name}`,
33
+ description: tool.description,
34
+ payload: tool,
35
+ justification,
36
+ safety: {
37
+ modifies_layer2: false,
38
+ modifies_approval_framework: false,
39
+ trust_level_required: 'provisional',
40
+ rollback_plan: `Deprecate tool ${tool.id} and rollback registry`,
41
+ },
42
+ proposed_by: tool.created_by,
43
+ status: 'verifying',
44
+ };
45
+ // Run verification
46
+ const verification = await this.verifier.verify(tool, toolSourceDir);
47
+ // Update proposal status based on verification
48
+ let status;
49
+ if (verification.verdict === 'reject') {
50
+ status = 'rejected';
51
+ }
52
+ else {
53
+ status = 'pending_approval';
54
+ // Queue for human approval
55
+ this.pendingApprovals.set(proposalId, {
56
+ proposal: { ...proposal, status, verification_id: verification.verification_id },
57
+ verification,
58
+ toolDefinition: tool,
59
+ toolSourceDir,
60
+ });
61
+ }
62
+ return { proposalId, verification, status };
63
+ }
64
+ /**
65
+ * List all pending approvals.
66
+ */
67
+ listPending() {
68
+ return Array.from(this.pendingApprovals.values());
69
+ }
70
+ /**
71
+ * Get a specific pending approval.
72
+ */
73
+ getPending(proposalId) {
74
+ return this.pendingApprovals.get(proposalId);
75
+ }
76
+ /**
77
+ * Approve a pending tool proposal. Activates the tool in the registry.
78
+ */
79
+ async approve(proposalId, approvedBy, reasoning, conditions) {
80
+ const pending = this.pendingApprovals.get(proposalId);
81
+ if (!pending) {
82
+ throw new Error(`No pending approval found for proposal "${proposalId}"`);
83
+ }
84
+ const approval = {
85
+ proposal_id: proposalId,
86
+ decision: 'approved',
87
+ decided_by: approvedBy,
88
+ decided_at: new Date().toISOString(),
89
+ reasoning,
90
+ conditions,
91
+ };
92
+ // Activate the tool in the registry
93
+ const approvedTool = {
94
+ ...pending.toolDefinition,
95
+ status: 'approved',
96
+ };
97
+ this.registry.addTool(approvedTool, approvedBy, proposalId);
98
+ await this.registry.save();
99
+ // Remove from pending
100
+ this.pendingApprovals.delete(proposalId);
101
+ // Log the approval
102
+ await this.logApproval(approval);
103
+ return approval;
104
+ }
105
+ /**
106
+ * Reject a pending tool proposal.
107
+ */
108
+ async reject(proposalId, rejectedBy, reasoning) {
109
+ const pending = this.pendingApprovals.get(proposalId);
110
+ if (!pending) {
111
+ throw new Error(`No pending approval found for proposal "${proposalId}"`);
112
+ }
113
+ const approval = {
114
+ proposal_id: proposalId,
115
+ decision: 'rejected',
116
+ decided_by: rejectedBy,
117
+ decided_at: new Date().toISOString(),
118
+ reasoning,
119
+ };
120
+ // Remove from pending
121
+ this.pendingApprovals.delete(proposalId);
122
+ // Log the rejection
123
+ await this.logApproval(approval);
124
+ return approval;
125
+ }
126
+ /**
127
+ * Rollback the last registry change.
128
+ */
129
+ async rollback(rolledBackBy) {
130
+ const success = this.registry.rollback(rolledBackBy);
131
+ if (success) {
132
+ await this.registry.save();
133
+ }
134
+ return success;
135
+ }
136
+ // ── Private ──────────────────────────────────────────────
137
+ async logApproval(approval) {
138
+ try {
139
+ await mkdir(dirname(this.approvalHistoryPath), { recursive: true });
140
+ const line = JSON.stringify(approval) + '\n';
141
+ await appendFile(this.approvalHistoryPath, line, 'utf-8');
142
+ }
143
+ catch {
144
+ // Non-critical: approval history logging failure doesn't block the flow
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=tool-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-approval.js","sourceRoot":"","sources":["../../src/runtime/tool-approval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { ToolDefinition, ToolConstraints, ToolTestResult } from './types.js';
2
+ export interface SandboxRequest {
3
+ readonly toolId: string;
4
+ readonly entryPoint: string;
5
+ readonly functionName: string;
6
+ readonly input: unknown;
7
+ readonly constraints: ToolConstraints;
8
+ }
9
+ export interface SandboxResponse {
10
+ readonly status: 'success' | 'error' | 'timeout' | 'constraint_violation';
11
+ readonly output?: unknown;
12
+ readonly error?: string;
13
+ readonly durationMs: number;
14
+ readonly memoryUsageMb?: number;
15
+ readonly networkAttempts?: readonly string[];
16
+ readonly filesystemWrites?: readonly string[];
17
+ }
18
+ export declare class ToolSandbox {
19
+ private sandboxDir;
20
+ constructor(sandboxBaseDir?: string);
21
+ /**
22
+ * Execute a tool in a sandboxed child process.
23
+ * Enforces all constraints from the ToolDefinition.
24
+ */
25
+ execute(request: SandboxRequest): Promise<SandboxResponse>;
26
+ /**
27
+ * Run a full test suite against a tool: happy path, malformed input,
28
+ * timeout behavior, and constraint compliance.
29
+ */
30
+ runTestSuite(tool: ToolDefinition, toolSourceDir: string): Promise<{
31
+ happy_path: ToolTestResult;
32
+ malformed_input: ToolTestResult;
33
+ timeout_behavior: ToolTestResult;
34
+ constraint_compliance: ToolTestResult;
35
+ }>;
36
+ private forkAndRun;
37
+ private generateRunnerScript;
38
+ private runSingleTest;
39
+ private runTimeoutTest;
40
+ private runConstraintComplianceTest;
41
+ private generateHappyPathInput;
42
+ private generateMalformedInput;
43
+ }