stable-harness 0.0.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 (131) hide show
  1. package/README.md +32 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +2 -0
  4. package/dist/compat/agent-harness.d.ts +24 -0
  5. package/dist/compat/agent-harness.js +1 -0
  6. package/dist/index.d.ts +13 -0
  7. package/dist/index.js +1 -0
  8. package/dist/runtime/compat/agent-harness-compat-runner.d.ts +2 -0
  9. package/dist/runtime/compat/agent-harness-compat-runner.js +1 -0
  10. package/dist/runtime/compat/json.d.ts +3 -0
  11. package/dist/runtime/compat/json.js +1 -0
  12. package/dist/runtime/compat/presentation.d.ts +1 -0
  13. package/dist/runtime/compat/presentation.js +1 -0
  14. package/dist/runtime/compat/prompts.d.ts +24 -0
  15. package/dist/runtime/compat/prompts.js +1 -0
  16. package/dist/runtime/compat/tool-registry.d.ts +3 -0
  17. package/dist/runtime/compat/tool-registry.js +1 -0
  18. package/dist/runtime/compat/types.d.ts +38 -0
  19. package/dist/runtime/compat/types.js +1 -0
  20. package/dist/runtime/model/ollama.d.ts +2 -0
  21. package/dist/runtime/model/ollama.js +1 -0
  22. package/dist/runtime/skills/skill-metadata.d.ts +7 -0
  23. package/dist/runtime/skills/skill-metadata.js +1 -0
  24. package/dist/runtime/workspace/types.d.ts +38 -0
  25. package/dist/runtime/workspace/types.js +1 -0
  26. package/dist/tools.d.ts +12 -0
  27. package/dist/tools.js +1 -0
  28. package/dist/workspace/compile.d.ts +2 -0
  29. package/dist/workspace/compile.js +1 -0
  30. package/package.json +94 -0
  31. package/packages/adapter-deepagents/dist/src/adapter.d.ts +8 -0
  32. package/packages/adapter-deepagents/dist/src/adapter.js +1 -0
  33. package/packages/adapter-deepagents/dist/src/builtin-tool-policy.d.ts +18 -0
  34. package/packages/adapter-deepagents/dist/src/builtin-tool-policy.js +1 -0
  35. package/packages/adapter-deepagents/dist/src/index.d.ts +2 -0
  36. package/packages/adapter-deepagents/dist/src/index.js +1 -0
  37. package/packages/adapter-deepagents/dist/src/messages.d.ts +9 -0
  38. package/packages/adapter-deepagents/dist/src/messages.js +1 -0
  39. package/packages/adapter-deepagents/dist/src/retry-policy.d.ts +2 -0
  40. package/packages/adapter-deepagents/dist/src/retry-policy.js +1 -0
  41. package/packages/adapter-deepagents/dist/src/stream-events.d.ts +2 -0
  42. package/packages/adapter-deepagents/dist/src/stream-events.js +1 -0
  43. package/packages/adapter-deepagents/dist/src/types.d.ts +6 -0
  44. package/packages/adapter-deepagents/dist/src/types.js +1 -0
  45. package/packages/adapter-deepagents/package.json +26 -0
  46. package/packages/cli/dist/src/cli.d.ts +2 -0
  47. package/packages/cli/dist/src/cli.js +2 -0
  48. package/packages/cli/dist/src/index.d.ts +1 -0
  49. package/packages/cli/dist/src/index.js +1 -0
  50. package/packages/cli/package.json +22 -0
  51. package/packages/core/dist/artifacts.d.ts +8 -0
  52. package/packages/core/dist/artifacts.js +1 -0
  53. package/packages/core/dist/execution-contract.d.ts +8 -0
  54. package/packages/core/dist/execution-contract.js +1 -0
  55. package/packages/core/dist/index.d.ts +9 -0
  56. package/packages/core/dist/index.js +1 -0
  57. package/packages/core/dist/inspection.d.ts +4 -0
  58. package/packages/core/dist/inspection.js +1 -0
  59. package/packages/core/dist/memory-plugins.d.ts +68 -0
  60. package/packages/core/dist/memory-plugins.js +1 -0
  61. package/packages/core/dist/queue.d.ts +2 -0
  62. package/packages/core/dist/queue.js +1 -0
  63. package/packages/core/dist/runtime.d.ts +12 -0
  64. package/packages/core/dist/runtime.js +1 -0
  65. package/packages/core/dist/stores.d.ts +3 -0
  66. package/packages/core/dist/stores.js +1 -0
  67. package/packages/core/dist/trace.d.ts +15 -0
  68. package/packages/core/dist/trace.js +1 -0
  69. package/packages/core/dist/types.d.ts +526 -0
  70. package/packages/core/dist/types.js +1 -0
  71. package/packages/core/package.json +17 -0
  72. package/packages/evaluation/dist/src/index.d.ts +2 -0
  73. package/packages/evaluation/dist/src/index.js +1 -0
  74. package/packages/evaluation/dist/src/trace.d.ts +16 -0
  75. package/packages/evaluation/dist/src/trace.js +1 -0
  76. package/packages/evaluation/dist/src/types.d.ts +11 -0
  77. package/packages/evaluation/dist/src/types.js +1 -0
  78. package/packages/evaluation/package.json +15 -0
  79. package/packages/governance/dist/src/approval-queue.d.ts +2 -0
  80. package/packages/governance/dist/src/approval-queue.js +1 -0
  81. package/packages/governance/dist/src/index.d.ts +4 -0
  82. package/packages/governance/dist/src/index.js +1 -0
  83. package/packages/governance/dist/src/policy-engine.d.ts +2 -0
  84. package/packages/governance/dist/src/policy-engine.js +1 -0
  85. package/packages/governance/dist/src/skill-candidates.d.ts +2 -0
  86. package/packages/governance/dist/src/skill-candidates.js +1 -0
  87. package/packages/governance/dist/src/types.d.ts +100 -0
  88. package/packages/governance/dist/src/types.js +1 -0
  89. package/packages/governance/package.json +12 -0
  90. package/packages/memory/dist/src/index.d.ts +9 -0
  91. package/packages/memory/dist/src/index.js +1 -0
  92. package/packages/memory/dist/src/langmem-service.d.ts +8 -0
  93. package/packages/memory/dist/src/langmem-service.js +1 -0
  94. package/packages/memory/dist/src/maintenance.d.ts +2 -0
  95. package/packages/memory/dist/src/maintenance.js +1 -0
  96. package/packages/memory/dist/src/persistence.d.ts +4 -0
  97. package/packages/memory/dist/src/persistence.js +1 -0
  98. package/packages/memory/dist/src/policy.d.ts +2 -0
  99. package/packages/memory/dist/src/policy.js +1 -0
  100. package/packages/memory/dist/src/provider.d.ts +50 -0
  101. package/packages/memory/dist/src/provider.js +1 -0
  102. package/packages/memory/dist/src/store.d.ts +5 -0
  103. package/packages/memory/dist/src/store.js +1 -0
  104. package/packages/memory/dist/src/types.d.ts +138 -0
  105. package/packages/memory/dist/src/types.js +1 -0
  106. package/packages/memory/package.json +12 -0
  107. package/packages/protocols/dist/src/http-server.d.ts +3 -0
  108. package/packages/protocols/dist/src/http-server.js +1 -0
  109. package/packages/protocols/dist/src/in-process-client.d.ts +2 -0
  110. package/packages/protocols/dist/src/in-process-client.js +1 -0
  111. package/packages/protocols/dist/src/index.d.ts +4 -0
  112. package/packages/protocols/dist/src/index.js +1 -0
  113. package/packages/protocols/dist/src/openai-compatible.d.ts +9 -0
  114. package/packages/protocols/dist/src/openai-compatible.js +1 -0
  115. package/packages/protocols/package.json +15 -0
  116. package/packages/tool-gateway/dist/src/argument-guard.d.ts +32 -0
  117. package/packages/tool-gateway/dist/src/argument-guard.js +1 -0
  118. package/packages/tool-gateway/dist/src/in-memory.d.ts +4 -0
  119. package/packages/tool-gateway/dist/src/in-memory.js +1 -0
  120. package/packages/tool-gateway/dist/src/index.d.ts +7 -0
  121. package/packages/tool-gateway/dist/src/index.js +1 -0
  122. package/packages/tool-gateway/dist/src/module-loader.d.ts +13 -0
  123. package/packages/tool-gateway/dist/src/module-loader.js +1 -0
  124. package/packages/tool-gateway/dist/src/types.d.ts +65 -0
  125. package/packages/tool-gateway/dist/src/types.js +1 -0
  126. package/packages/tool-gateway/package.json +15 -0
  127. package/packages/workspace-yaml/dist/index.d.ts +1 -0
  128. package/packages/workspace-yaml/dist/index.js +1 -0
  129. package/packages/workspace-yaml/dist/loader.d.ts +2 -0
  130. package/packages/workspace-yaml/dist/loader.js +1 -0
  131. package/packages/workspace-yaml/package.json +16 -0
@@ -0,0 +1,100 @@
1
+ export type PolicyDecision = {
2
+ action: "allow";
3
+ reason: string;
4
+ } | {
5
+ action: "require_approval";
6
+ reason: string;
7
+ };
8
+ export type ToolPolicy = {
9
+ approvalRequiredToolIds?: string[];
10
+ sandboxByToolId?: Record<string, string>;
11
+ };
12
+ export type RuntimePolicyEngine = {
13
+ evaluateTool(input: {
14
+ toolId: string;
15
+ metadata?: Record<string, unknown>;
16
+ }): PolicyDecision;
17
+ resolveSandbox(input: {
18
+ toolId: string;
19
+ defaultSandbox?: string;
20
+ }): string;
21
+ };
22
+ export type ApprovalRequestKind = "tool_invocation" | "memory_write" | "skill_candidate";
23
+ export type ApprovalRequestStatus = "pending" | "approved" | "rejected";
24
+ export type ApprovalRequest = {
25
+ id: string;
26
+ kind: ApprovalRequestKind;
27
+ reason: string;
28
+ status: ApprovalRequestStatus;
29
+ requestId?: string;
30
+ sessionId?: string;
31
+ agentId?: string;
32
+ subject: Record<string, unknown>;
33
+ createdAt: string;
34
+ resolvedAt?: string;
35
+ };
36
+ export type ApprovalQueue = {
37
+ create(input: {
38
+ kind: ApprovalRequestKind;
39
+ reason: string;
40
+ requestId?: string;
41
+ sessionId?: string;
42
+ agentId?: string;
43
+ subject: Record<string, unknown>;
44
+ }): Promise<ApprovalRequest>;
45
+ list(status?: ApprovalRequestStatus): Promise<ApprovalRequest[]>;
46
+ resolve(id: string, status: Exclude<ApprovalRequestStatus, "pending">): Promise<ApprovalRequest | undefined>;
47
+ };
48
+ export type SkillCandidateStatus = "observed" | "candidate" | "review_required" | "approved" | "rejected" | "drafted" | "enabled" | "deprecated";
49
+ export type SkillCandidate = {
50
+ id: string;
51
+ workspaceId: string;
52
+ name: string;
53
+ status: SkillCandidateStatus;
54
+ confidence: number;
55
+ evidenceCount: number;
56
+ proposedPath?: string;
57
+ title: string;
58
+ summary: string;
59
+ draftMarkdown: string;
60
+ createdAt: string;
61
+ updatedAt: string;
62
+ reviewedAt?: string;
63
+ reviewedBy?: string;
64
+ rejectionReason?: string;
65
+ };
66
+ export type SkillCandidateEvidence = {
67
+ id: string;
68
+ candidateId: string;
69
+ evidenceType: "memory_record" | "run" | "tool_event" | "validation" | "user_correction" | "deepagents_memory_file";
70
+ evidenceRef: string;
71
+ summary?: string;
72
+ weight?: number;
73
+ createdAt: string;
74
+ };
75
+ export type SkillCandidateInput = {
76
+ workspaceId: string;
77
+ name: string;
78
+ status?: SkillCandidateStatus;
79
+ confidence: number;
80
+ proposedPath?: string;
81
+ title: string;
82
+ summary: string;
83
+ draftMarkdown: string;
84
+ evidence: Array<Omit<SkillCandidateEvidence, "id" | "candidateId" | "createdAt">>;
85
+ };
86
+ export type SkillCandidateStore = {
87
+ upsert(input: SkillCandidateInput): Promise<SkillCandidate>;
88
+ list(filter?: {
89
+ workspaceId?: string;
90
+ status?: SkillCandidateStatus;
91
+ }): Promise<SkillCandidate[]>;
92
+ get(id: string): Promise<SkillCandidate | undefined>;
93
+ listEvidence(candidateId: string): Promise<SkillCandidateEvidence[]>;
94
+ updateStatus(input: {
95
+ id: string;
96
+ status: SkillCandidateStatus;
97
+ reviewedBy?: string;
98
+ rejectionReason?: string;
99
+ }): Promise<SkillCandidate | undefined>;
100
+ };
@@ -0,0 +1 @@
1
+ export{};
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@stable-harness/governance",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist/**/*.js",
7
+ "dist/**/*.d.ts",
8
+ "package.json"
9
+ ],
10
+ "main": "dist/src/index.js",
11
+ "types": "dist/src/index.d.ts"
12
+ }
@@ -0,0 +1,9 @@
1
+ export { applyMemoryMaintenance } from "./maintenance.js";
2
+ export { createEmbeddedMemoryProvider, } from "./provider.js";
3
+ export { createLangMemServiceProvider, } from "./langmem-service.js";
4
+ export type { LangMemServiceProviderOptions, } from "./langmem-service.js";
5
+ export type { MemoryProvider, MemoryProviderApprovalConfig, MemoryProviderConfig, MemoryProviderConsolidateInput, MemoryProviderDefaults, MemoryProviderMode, MemoryProviderProposeInput, MemoryProviderSearchInput, MemoryProviderTypeConfig, } from "./provider.js";
6
+ export { cloneRecords, createInMemoryMemoryPersistenceAdapter, createMemorySnapshot, } from "./persistence.js";
7
+ export { createDefaultMemoryPolicy } from "./policy.js";
8
+ export { createInMemoryRuntimeMemoryStore } from "./store.js";
9
+ export type { ListMemoriesInput, MemorizeInput, MemoryCandidate, MemoryDecision, MemoryDecisionAction, MemoryKind, MemoryMaintenanceAction, MemoryMaintenanceOperation, MemoryMaintenanceResult, MemoryPolicy, MemoryPersistenceAdapter, MemoryRecallResult, MemoryRecord, MemoryRecordStatus, MemoryScope, MemorySensitivity, MemoryStoreSnapshot, MemorySubmitResult, RecallInput, RuntimeMemoryStore, UpdateMemoryInput, } from "./types.js";
@@ -0,0 +1 @@
1
+ export{applyMemoryMaintenance}from"./maintenance.js";export{createEmbeddedMemoryProvider}from"./provider.js";export{createLangMemServiceProvider}from"./langmem-service.js";export{cloneRecords,createInMemoryMemoryPersistenceAdapter,createMemorySnapshot}from"./persistence.js";export{createDefaultMemoryPolicy}from"./policy.js";export{createInMemoryRuntimeMemoryStore}from"./store.js";
@@ -0,0 +1,8 @@
1
+ import type { MemoryProvider, MemoryProviderConfig } from "./provider.js";
2
+ export type LangMemServiceProviderOptions = {
3
+ baseUrl: string;
4
+ config?: MemoryProviderConfig;
5
+ headers?: Record<string, string>;
6
+ timeoutMs?: number;
7
+ };
8
+ export declare function createLangMemServiceProvider(options: LangMemServiceProviderOptions): MemoryProvider;
@@ -0,0 +1 @@
1
+ export function createLangMemServiceProvider(r){const t=function(e){return e.replace(/\/+$/u,"")}(r.baseUrl),a={...r.config,provider:"langmem-service"};return{name:"langmem-service",config:a,propose:async n=>(await e(t,"/memory/propose",{...n,config:a},r)).candidates??[],async search(o){const i=await(o.store?.list({namespace:o.namespace,kinds:o.kinds}))??[];return(await e(t,"/memory/search",{...n(o),records:i,config:a},r)).records??[]},consolidate:async n=>(await e(t,"/memory/consolidate",{...n,config:a},r)).operations??[]}}async function e(e,n,r,t){const a=new AbortController,o=setTimeout(()=>a.abort(),t.timeoutMs??3e4);try{const o=await fetch(`${e}${n}`,{method:"POST",headers:{"content-type":"application/json",...t.headers},body:JSON.stringify(r),signal:a.signal});return await async function(e,n){const r=await e.text();if(!e.ok)throw new Error(`LangMem service ${n} failed with ${e.status}: ${r}`);return r?JSON.parse(r):{}}(o,n)}finally{clearTimeout(o)}}function n(e){return{namespace:e.namespace,query:e.query,limit:e.limit,kinds:e.kinds,records:[]}}
@@ -0,0 +1,2 @@
1
+ import type { MemoryMaintenanceOperation, MemoryMaintenanceResult, RuntimeMemoryStore } from "./types.js";
2
+ export declare function applyMemoryMaintenance(store: RuntimeMemoryStore, operations: MemoryMaintenanceOperation[]): Promise<MemoryMaintenanceResult[]>;
@@ -0,0 +1 @@
1
+ export async function applyMemoryMaintenance(e,n){const t=[];for(const r of n)t.push(await a(e,r));return t}async function a(a,n){return"archive"===n.action?e(n,await a.archive(n.recordId,n.reason)):"mark_stale"===n.action?e(n,await a.update({id:n.recordId,status:"stale",metadata:{maintenanceReason:n.reason}})):"refresh"===n.action?e(n,await a.update({id:n.recordId,status:"active",metadata:{maintenanceReason:n.reason}})):e(n,await a.update({id:n.recordId,status:"archived",metadata:{maintenanceReason:n.reason,supersededBy:n.replacementRecordId}}))}function e(a,e){return{operation:a,record:e,applied:Boolean(e),reason:e?a.reason:"record not found"}}
@@ -0,0 +1,4 @@
1
+ import type { ListMemoriesInput, MemoryPersistenceAdapter, MemoryRecord, MemoryStoreSnapshot, RuntimeMemoryStore } from "./types.js";
2
+ export declare function createMemorySnapshot(store: RuntimeMemoryStore, input: ListMemoriesInput): Promise<MemoryStoreSnapshot>;
3
+ export declare function createInMemoryMemoryPersistenceAdapter(): MemoryPersistenceAdapter;
4
+ export declare function cloneRecords(records: MemoryRecord[]): MemoryRecord[];
@@ -0,0 +1 @@
1
+ export async function createMemorySnapshot(e,t){return{namespace:t.namespace,records:await e.list(t),exportedAt:(new Date).toISOString()}}export function createInMemoryMemoryPersistenceAdapter(){const e=new Map;return{load:async t=>cloneRecords(e.get(t)??[]),async save(t){e.set(t.namespace,cloneRecords(t.records))}}}export function cloneRecords(e){return e.map(e=>({...e,sourceRefs:[...e.sourceRefs],tags:[...e.tags],metadata:{...e.metadata},provenance:{...e.provenance},supersedes:[...e.supersedes],conflictsWith:[...e.conflictsWith]}))}
@@ -0,0 +1,2 @@
1
+ import type { MemoryPolicy } from "./types.js";
2
+ export declare function createDefaultMemoryPolicy(): MemoryPolicy;
@@ -0,0 +1 @@
1
+ export function createDefaultMemoryPolicy(){return{decide:i=>i.noStore?{action:"reject",reason:"candidate marked noStore",reviewRequired:!1}:i.content.trim()?"sensitive"===i.sensitivity||"restricted"===i.sensitivity?{action:"review",reason:"sensitive memory requires operator approval",kind:i.kindHint??"semantic",scope:i.scopeHint??"workspace",confidence:e(i.confidenceHint),reviewRequired:!0}:{action:"store",reason:"candidate accepted by default runtime policy",kind:i.kindHint??"semantic",scope:i.scopeHint??"workspace",confidence:e(i.confidenceHint),retrievalPriority:0,reviewRequired:!1}:{action:"reject",reason:"candidate content is empty",reviewRequired:!1}}}function e(e){return void 0===e||Number.isNaN(e)?.6:Math.min(1,Math.max(0,e))}
@@ -0,0 +1,50 @@
1
+ import type { MemoryCandidate, MemoryKind, MemoryMaintenanceOperation, MemoryRecord, MemoryScope, MemorySensitivity, RuntimeMemoryStore } from "./types.js";
2
+ export type MemoryProviderMode = {
3
+ hotPathTools?: boolean;
4
+ backgroundManager?: boolean;
5
+ };
6
+ export type MemoryProviderTypeConfig = Partial<Record<MemoryKind, boolean>>;
7
+ export type MemoryProviderApprovalConfig = {
8
+ procedural?: boolean;
9
+ sensitive?: boolean;
10
+ restricted?: boolean;
11
+ };
12
+ export type MemoryProviderDefaults = {
13
+ scope?: MemoryScope;
14
+ sensitivity?: MemorySensitivity;
15
+ };
16
+ export type MemoryProviderConfig = {
17
+ provider?: "embedded" | "langmem-service" | "custom";
18
+ mode?: MemoryProviderMode;
19
+ types?: MemoryProviderTypeConfig;
20
+ approval?: MemoryProviderApprovalConfig;
21
+ defaults?: MemoryProviderDefaults;
22
+ };
23
+ export type MemoryProviderProposeInput = {
24
+ namespace: string;
25
+ content: string;
26
+ sourceType?: string;
27
+ sourceRef?: string;
28
+ kindHint?: MemoryKind;
29
+ scopeHint?: MemoryScope;
30
+ sensitivity?: MemorySensitivity;
31
+ metadata?: Record<string, unknown>;
32
+ };
33
+ export type MemoryProviderSearchInput = {
34
+ store?: RuntimeMemoryStore;
35
+ namespace: string;
36
+ query: string;
37
+ limit?: number;
38
+ kinds?: MemoryKind[];
39
+ };
40
+ export type MemoryProviderConsolidateInput = {
41
+ records: MemoryRecord[];
42
+ };
43
+ export type MemoryProvider = {
44
+ name: string;
45
+ config: MemoryProviderConfig;
46
+ propose(input: MemoryProviderProposeInput): Promise<MemoryCandidate[]>;
47
+ search(input: MemoryProviderSearchInput): Promise<MemoryRecord[]>;
48
+ consolidate(input: MemoryProviderConsolidateInput): Promise<MemoryMaintenanceOperation[]>;
49
+ };
50
+ export declare function createEmbeddedMemoryProvider(config?: MemoryProviderConfig): MemoryProvider;
@@ -0,0 +1 @@
1
+ export function createEmbeddedMemoryProvider(e={}){return{name:"embedded",config:e,async propose(n){const s=n.kindHint??function(e){const n=e.toLowerCase();return n.includes("must ")||n.includes("should ")?"procedural":n.includes("run ")||n.includes("failed ")?"episodic":"semantic"}(n.content);return function(e,n){return!1!==e.types?.[n]}(e,s)?[{namespace:n.namespace,content:n.content,sourceType:n.sourceType,sourceRef:n.sourceRef,kindHint:s,scopeHint:n.scopeHint??e.defaults?.scope??"workspace",sensitivity:n.sensitivity??e.defaults?.sensitivity??"internal",confidenceHint:.6,metadata:n.metadata}]:[]},search:async e=>e.store?(await e.store.recall({namespace:e.namespace,query:e.query,limit:e.limit,kinds:e.kinds})).records:[],consolidate:async e=>e.records.filter(e=>"stale"===e.status).map(e=>({action:"archive",recordId:e.id,reason:"embedded provider archives stale records during consolidation"}))}}
@@ -0,0 +1,5 @@
1
+ import type { MemoryPolicy, MemoryRecord, RuntimeMemoryStore } from "./types.js";
2
+ export declare function createInMemoryRuntimeMemoryStore(options?: {
3
+ policy?: MemoryPolicy;
4
+ records?: MemoryRecord[];
5
+ }): RuntimeMemoryStore;
@@ -0,0 +1 @@
1
+ import{randomUUID as e}from"node:crypto";import{createDefaultMemoryPolicy as t}from"./policy.js";import{cloneRecords as n}from"./persistence.js";export function createInMemoryRuntimeMemoryStore(e={}){const d=e.policy??t(),m=n(e.records??[]);return{async submitCandidate(e){const t=d.decide(e);if("store"!==t.action)return{candidate:e,decision:t};const n=a({namespace:e.namespace,content:e.content,kind:t.kind,scope:t.scope,summary:e.summary,confidence:t.confidence,tags:e.tags,sensitivity:e.sensitivity,sourceType:e.sourceType,sourceRef:e.sourceRef,metadata:e.metadata,provenance:e.provenance,observedAt:e.observedAt,retrievalPriority:t.retrievalPriority});return m.push(n),{candidate:e,decision:{...t,recordId:n.id},record:r(n)}},async memorize(e){const t=a(e);return m.push(t),r(t)},async recall(e){const t=e.query.toLowerCase(),n=s(m,e).filter(e=>function(e,t){return[e.canonicalKey,e.content,e.summary??"",...e.tags].join("\n").toLowerCase().includes(t)}(e,t)).sort(i).slice(0,e.limit??10);return{records:n,context:c(n)}},list:async e=>n(s(m,e)),async update(e){const t=m.find(t=>t.id===e.id);if(t)return function(e,t){e.content=t.content??e.content,e.summary=t.summary??e.summary,e.status=t.status??e.status,e.confidence=o(t.confidence??e.confidence),e.tags=t.tags??e.tags,e.metadata=t.metadata?{...e.metadata,...t.metadata}:e.metadata,e.lastConfirmedAt=(new Date).toISOString(),e.revision+=1}(t,e),r(t)},async archive(e,t){const n=m.find(t=>t.id===e);if(n)return n.status="archived",n.metadata={...n.metadata,archiveReason:t},n.revision+=1,r(n)}}}function r(e){return n([e])[0]}function a(t){const n=(new Date).toISOString();return{id:e(),namespace:t.namespace,canonicalKey:(r=t.namespace,a=t.content,`${r}:${a.trim().toLowerCase().replace(/\s+/gu," ").slice(0,120)}`),kind:t.kind??"semantic",scope:t.scope??"workspace",status:"active",content:t.content,summary:t.summary,confidence:o(t.confidence),sourceType:t.sourceType,sourceRefs:t.sourceRef?[t.sourceRef]:[],tags:t.tags??[],sensitivity:t.sensitivity??"internal",metadata:t.metadata??{},createdAt:n,observedAt:t.observedAt??n,lastConfirmedAt:n,provenance:t.provenance??{},revision:1,supersedes:[],conflictsWith:[],retrievalPriority:t.retrievalPriority??0};var r,a}function s(e,t){return e.filter(e=>e.namespace===t.namespace).filter(e=>!t.kinds||t.kinds.includes(e.kind)).filter(e=>!t.scopes||t.scopes.includes(e.scope)).filter(e=>(t.statuses??["active"]).includes(e.status))}function i(e,t){return t.retrievalPriority-e.retrievalPriority||t.confidence-e.confidence||t.lastConfirmedAt.localeCompare(e.lastConfirmedAt)}function c(e){return e.map(e=>`- [${e.kind}/${e.scope}] ${e.summary??e.content}`).join("\n")}function o(e){return void 0===e||Number.isNaN(e)?.6:Math.min(1,Math.max(0,e))}
@@ -0,0 +1,138 @@
1
+ export type MemoryKind = "semantic" | "episodic" | "procedural";
2
+ export type MemoryScope = "session" | "agent" | "workspace" | "user" | "project";
3
+ export type MemoryRecordStatus = "active" | "stale" | "conflicted" | "archived" | "pending_review";
4
+ export type MemorySensitivity = "public" | "internal" | "sensitive" | "restricted";
5
+ export type MemoryDecisionAction = "reject" | "store" | "merge" | "refresh" | "supersede" | "archive" | "review";
6
+ export type MemoryCandidate = {
7
+ namespace: string;
8
+ content: string;
9
+ sourceType?: string;
10
+ sourceRef?: string;
11
+ kindHint?: MemoryKind;
12
+ summary?: string;
13
+ scopeHint?: MemoryScope;
14
+ confidenceHint?: number;
15
+ tags?: string[];
16
+ sensitivity?: MemorySensitivity;
17
+ noStore?: boolean;
18
+ provenance?: Record<string, unknown>;
19
+ metadata?: Record<string, unknown>;
20
+ observedAt?: string;
21
+ };
22
+ export type MemoryDecision = {
23
+ action: MemoryDecisionAction;
24
+ reason: string;
25
+ recordId?: string;
26
+ kind?: MemoryKind;
27
+ scope?: MemoryScope;
28
+ confidence?: number;
29
+ ttlDays?: number;
30
+ retrievalPriority?: number;
31
+ reviewRequired?: boolean;
32
+ };
33
+ export type MemoryRecord = {
34
+ id: string;
35
+ namespace: string;
36
+ canonicalKey: string;
37
+ kind: MemoryKind;
38
+ scope: MemoryScope;
39
+ status: MemoryRecordStatus;
40
+ content: string;
41
+ summary?: string;
42
+ confidence: number;
43
+ sourceType?: string;
44
+ sourceRefs: string[];
45
+ tags: string[];
46
+ sensitivity: MemorySensitivity;
47
+ metadata: Record<string, unknown>;
48
+ createdAt: string;
49
+ observedAt: string;
50
+ lastConfirmedAt: string;
51
+ expiresAt?: string;
52
+ provenance: Record<string, unknown>;
53
+ revision: number;
54
+ supersedes: string[];
55
+ conflictsWith: string[];
56
+ retrievalPriority: number;
57
+ };
58
+ export type MemorizeInput = {
59
+ namespace: string;
60
+ content: string;
61
+ kind?: MemoryKind;
62
+ scope?: MemoryScope;
63
+ summary?: string;
64
+ confidence?: number;
65
+ tags?: string[];
66
+ sensitivity?: MemorySensitivity;
67
+ sourceType?: string;
68
+ sourceRef?: string;
69
+ metadata?: Record<string, unknown>;
70
+ provenance?: Record<string, unknown>;
71
+ observedAt?: string;
72
+ retrievalPriority?: number;
73
+ };
74
+ export type MemorySubmitResult = {
75
+ candidate: MemoryCandidate;
76
+ decision: MemoryDecision;
77
+ record?: MemoryRecord;
78
+ };
79
+ export type RecallInput = {
80
+ namespace: string;
81
+ query: string;
82
+ limit?: number;
83
+ kinds?: MemoryKind[];
84
+ scopes?: MemoryScope[];
85
+ statuses?: MemoryRecordStatus[];
86
+ };
87
+ export type MemoryRecallResult = {
88
+ records: MemoryRecord[];
89
+ context: string;
90
+ };
91
+ export type MemoryStoreSnapshot = {
92
+ namespace: string;
93
+ records: MemoryRecord[];
94
+ exportedAt: string;
95
+ };
96
+ export type MemoryPersistenceAdapter = {
97
+ load(namespace: string): Promise<MemoryRecord[]>;
98
+ save(snapshot: MemoryStoreSnapshot): Promise<void>;
99
+ };
100
+ export type MemoryMaintenanceAction = "mark_stale" | "archive" | "refresh" | "supersede";
101
+ export type MemoryMaintenanceOperation = {
102
+ action: MemoryMaintenanceAction;
103
+ recordId: string;
104
+ reason: string;
105
+ replacementRecordId?: string;
106
+ };
107
+ export type MemoryMaintenanceResult = {
108
+ operation: MemoryMaintenanceOperation;
109
+ record?: MemoryRecord;
110
+ applied: boolean;
111
+ reason: string;
112
+ };
113
+ export type ListMemoriesInput = {
114
+ namespace: string;
115
+ kinds?: MemoryKind[];
116
+ scopes?: MemoryScope[];
117
+ statuses?: MemoryRecordStatus[];
118
+ };
119
+ export type UpdateMemoryInput = {
120
+ id: string;
121
+ content?: string;
122
+ summary?: string;
123
+ status?: MemoryRecordStatus;
124
+ confidence?: number;
125
+ tags?: string[];
126
+ metadata?: Record<string, unknown>;
127
+ };
128
+ export type MemoryPolicy = {
129
+ decide(candidate: MemoryCandidate): MemoryDecision;
130
+ };
131
+ export type RuntimeMemoryStore = {
132
+ submitCandidate(candidate: MemoryCandidate): Promise<MemorySubmitResult>;
133
+ memorize(input: MemorizeInput): Promise<MemoryRecord>;
134
+ recall(input: RecallInput): Promise<MemoryRecallResult>;
135
+ list(input: ListMemoriesInput): Promise<MemoryRecord[]>;
136
+ update(input: UpdateMemoryInput): Promise<MemoryRecord | undefined>;
137
+ archive(id: string, reason?: string): Promise<MemoryRecord | undefined>;
138
+ };
@@ -0,0 +1 @@
1
+ export{};
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@stable-harness/memory",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist/**/*.js",
7
+ "dist/**/*.d.ts",
8
+ "package.json"
9
+ ],
10
+ "main": "dist/src/index.js",
11
+ "types": "dist/src/index.d.ts"
12
+ }
@@ -0,0 +1,3 @@
1
+ import { type IncomingMessage, type ServerResponse } from "node:http";
2
+ import { type StableHarnessRuntime } from "@stable-harness/core";
3
+ export declare function createHttpServer(runtime: StableHarnessRuntime): import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
@@ -0,0 +1 @@
1
+ import{createServer as t}from"node:http";import{projectRuntimeTrace as e}from"@stable-harness/core";export function createHttpServer(o){return t(async(t,n)=>{try{if("GET"===t.method&&"/health"===t.url)return void r(n,200,{ok:!0});if("GET"===t.method&&"/inspect"===t.url)return void r(n,200,o.inspect());if("GET"===t.method&&"/requests"===t.url)return void r(n,200,o.listRequests());if("GET"===t.method&&"/sessions"===t.url)return void r(n,200,o.listSessions());const s=function(t){const e=(t??"").match(/^\/requests\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(t.url);if("GET"===t.method&&s){const t=o.inspectRequest(s);return void r(n,t?200:404,t??{error:"request_not_found"})}const i=function(t){const e=(t??"").match(/^\/runs\/([^/]+)\/trace$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(t.url);if("GET"===t.method&&i){const t=o.getRun(i);return void r(n,t?200:404,t?e(t):{error:"run_not_found"})}if("POST"===t.method&&"/requests"===t.url){const e=await async function(t){const e=[];for await(const r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(r));return 0===e.length?{}:JSON.parse(Buffer.concat(e).toString("utf8"))}(t),s="string"==typeof e.input?e.input:"",i="string"==typeof e.agentId?e.agentId:void 0,u=function(t){if("object"!=typeof t||null===t)return;const e=t;return"string"==typeof e.toolId?{toolId:e.toolId,args:e.args}:void 0}(e.toolCall);return void r(n,200,await o.request({input:s,agentId:i,toolCall:u}))}r(n,404,{error:"not_found"})}catch(t){r(n,500,{error:t instanceof Error?t.message:String(t)})}})}function r(t,e,r){t.writeHead(e,{"content-type":"application/json"}),t.end(JSON.stringify(r))}
@@ -0,0 +1,2 @@
1
+ import type { StableHarnessRuntime } from "@stable-harness/core";
2
+ export declare function createInProcessClient(runtime: StableHarnessRuntime): StableHarnessRuntime;
@@ -0,0 +1 @@
1
+ export function createInProcessClient(e){return{request:s=>e.request(s),subscribe:s=>e.subscribe(s),inspect:()=>e.inspect(),getRun:s=>e.getRun(s),listRequests:s=>e.listRequests(s),listSessions:()=>e.listSessions(),inspectRequest:s=>e.inspectRequest(s),cancel:(s,t)=>e.cancel(s,t),stop:()=>e.stop()}}
@@ -0,0 +1,4 @@
1
+ export { createInProcessClient } from "./in-process-client.js";
2
+ export { createHttpServer } from "./http-server.js";
3
+ export { createOpenAiCompatibleHttpServer } from "./openai-compatible.js";
4
+ export type { OpenAiCompatibleServerOptions } from "./openai-compatible.js";
@@ -0,0 +1 @@
1
+ export{createInProcessClient}from"./in-process-client.js";export{createHttpServer}from"./http-server.js";export{createOpenAiCompatibleHttpServer}from"./openai-compatible.js";
@@ -0,0 +1,9 @@
1
+ import { type IncomingMessage, type ServerResponse } from "node:http";
2
+ import type { StableHarnessRuntime } from "@stable-harness/core";
3
+ export type OpenAiCompatibleServerOptions = {
4
+ bearerToken?: string;
5
+ corsOrigins?: string[];
6
+ modelAgentMap?: Record<string, string>;
7
+ defaultModel?: string;
8
+ };
9
+ export declare function createOpenAiCompatibleHttpServer(runtime: StableHarnessRuntime, options?: OpenAiCompatibleServerOptions): import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
@@ -0,0 +1 @@
1
+ import{createServer as e}from"node:http";import{randomUUID as t}from"node:crypto";export function createOpenAiCompatibleHttpServer(o,c={}){return e(async(e,p)=>{try{if(function(e,t,n){return"OPTIONS"===e.method&&(t.writeHead(204,l(n)),t.end(),!0)}(e,p,c))return;if(!function(e,t){return!t.bearerToken||e.headers.authorization===`Bearer ${t.bearerToken}`}(e,c))return void u(p,401,{error:{message:"unauthorized",type:"invalid_request_error"}},c);if("GET"===e.method&&"/v1/models"===e.url)return void u(p,200,function(e,t){const n=Object.keys(t.modelAgentMap??{});return{object:"list",data:[...new Set([...e.inspect().agents,...n])].sort().map(e=>({id:e,object:"model",created:0,owned_by:"stable-harness"}))}}(o,c),c);if("GET"===e.method&&"/v1/capabilities"===e.url)return void u(p,200,{object:"stable_harness.capabilities",endpoints:["/v1/models","/v1/chat/completions","/v1/capabilities"],streaming:!0,toolProgressEvents:!0},c);if("POST"===e.method&&"/v1/chat/completions"===e.url)return void await async function(e,o,c,p){const f=await async function(e){const t=[];for await(const n of e)t.push(Buffer.isBuffer(n)?n:Buffer.from(n));return 0===t.length?{}:JSON.parse(Buffer.concat(t).toString("utf8"))}(o);if(f.model&&!r(f.model,e,p))return void u(c,404,{error:{message:`model_not_found: ${f.model}`,type:"invalid_request_error"}},p);const m=function(e,o,s){const a=function(e){if(!Array.isArray(e)||0===e.length)throw new Error("messages must be a non-empty array");return e.map(e=>`${e.role??"user"}: ${n(e.content)}`).join("\n\n")}(e.messages);return{input:a,requestId:`chatcmpl-${t()}`,agentId:r(e.model,o,s),metadata:{protocol:"openai-compatible",openaiStream:!0===e.stream,openaiMessages:(i=e.messages,Array.isArray(i)?i.map(e=>({role:e.role??"user",content:n(e.content)})):[]),model:e.model,user:e.user,clientMetadata:e.metadata}};var i}(f,e,p);f.stream?await async function(e,t,n,o,r){(function(e,t){e.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive",...l(t)})})(t,r),d(t,a(o.requestId,n.model,{role:"assistant"},null));let i=!1;const c=e.subscribe(e=>{e.requestId===o.requestId&&(i=function(e,t,n,o){const r=function(e){if("adapter.event"!==e.type||"object"!=typeof e.event||null===e.event)return;const t=e.event;return"output.delta"===t.phase&&"string"==typeof t.text?t.text:void 0}(t);return r?(d(e,s(n,o,r)),!0):(function(e,t){const n=function(e){if("tool.started"===e.type||"tool.completed"===e.type)return{request_id:e.requestId,session_id:e.sessionId,agent_id:e.agentId,type:e.type,tool_id:e.toolId};if("adapter.event"!==e.type||"object"!=typeof e.event||null===e.event)return;const t=e.event,n="tool.start"===t.phase?"tool.started":"tool.result"===t.phase?"tool.completed":void 0,o="string"==typeof t.toolId?t.toolId:void 0;return n&&o?{request_id:e.requestId,session_id:e.sessionId,agent_id:e.agentId,type:n,tool_id:o,adapter:t.adapter}:void 0}(t);n&&function(e,t,n){e.write("event: stable_harness.tool.progress\n"),e.write(`data: ${JSON.stringify(n)}\n\n`)}(e,0,n)}(e,t),!1)}(t,e,o.requestId,n.model)||i)});try{const r=await e.request(o);i||d(t,s(o.requestId,n.model,r.output)),d(t,function(e,t){return a(e,t,{},"stop")}(o.requestId,n.model)),t.write("data: [DONE]\n\n"),t.end()}finally{c()}}(e,c,f,m,p):u(c,200,function(e,t){return{id:t.requestId,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:e.model??t.agentId,choices:[{index:0,message:{role:"assistant",content:t.output},finish_reason:"stop"}],usage:i(e.messages,t.output),metadata:{sessionId:t.sessionId,agentId:t.agentId,state:t.state}}}(f,await e.request(m)),p)}(o,e,p,c);u(p,404,{error:{message:"not_found",type:"invalid_request_error"}},c)}catch(e){u(p,400,{error:{message:e instanceof Error?e.message:String(e),type:"invalid_request_error"}},c)}})}function n(e){if("string"==typeof e)return e;if(!Array.isArray(e))throw new Error("message content must be a string or content part array");return e.map(o).join("\n")}function o(e){if("object"!=typeof e||null===e)throw new Error("message content parts must be objects");const t=e;if("text"===t.type&&"string"==typeof t.text)return t.text;const n=t.image_url;if("image_url"===t.type&&"string"==typeof n?.url)return`[image:${n.url}]`;throw new Error("unsupported_content_type")}function r(e,t,n){if(!e)return;const o=n.modelAgentMap?.[e];return o||(t.inspect().agents.includes(e)?e:void 0)}function s(e,t,n){return a(e,t,{content:n},null)}function a(e,t,n,o){return{id:e,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:t??"stable-harness",choices:[{index:0,delta:n,finish_reason:o}]}}function i(e,t){const o=c(Array.isArray(e)?e.map(e=>n(e.content)).join("\n"):""),r=c(t);return{prompt_tokens:o,completion_tokens:r,total_tokens:o+r}}function c(e){return e.trim()?Math.ceil(1.3*e.trim().split(/\s+/u).length):0}function u(e,t,n,o){e.writeHead(t,{"content-type":"application/json",...l(o)}),e.end(JSON.stringify(n))}function d(e,t){e.write(`data: ${JSON.stringify(t)}\n\n`)}function l(e){return e.corsOrigins?.length?{"access-control-allow-origin":e.corsOrigins.join(", "),"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}:{}}
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@stable-harness/protocols",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist/**/*.js",
7
+ "dist/**/*.d.ts",
8
+ "package.json"
9
+ ],
10
+ "main": "dist/src/index.js",
11
+ "types": "dist/src/index.d.ts",
12
+ "dependencies": {
13
+ "@stable-harness/core": "0.0.1"
14
+ }
15
+ }
@@ -0,0 +1,32 @@
1
+ import type { BetterToolLike, RepairFunction, RepairModelLike } from "@botbotgo/better-call";
2
+ import type { ToolArgumentGuard, ToolArgumentIssue, ToolGatewayContext, ToolGatewayTool } from "./types.js";
3
+ type ToolGatewayRuntimeTool = ToolGatewayTool & {
4
+ validationTool?: BetterToolLike;
5
+ };
6
+ export type BetterCallArgumentRepairOptions = {
7
+ mode?: "guard" | "repair" | "review";
8
+ repair?: RepairFunction;
9
+ repairModel?: RepairModelLike;
10
+ };
11
+ export type ToolArgumentGuardOptions = {
12
+ betterCall?: BetterCallArgumentRepairOptions;
13
+ };
14
+ export type BetterCallToolSelectionRepair = {
15
+ toolId: string;
16
+ args: unknown;
17
+ };
18
+ export declare class ToolArgumentValidationError extends Error {
19
+ readonly toolId: string;
20
+ readonly issues: ToolArgumentIssue[];
21
+ constructor(toolId: string, issues: ToolArgumentIssue[]);
22
+ }
23
+ export declare function createDefaultArgumentGuard(options?: ToolArgumentGuardOptions): ToolArgumentGuard;
24
+ export declare function assertToolArguments(tool: ToolGatewayTool, args: unknown, context: ToolGatewayContext, guard: ToolArgumentGuard): Promise<unknown>;
25
+ export declare function prepareBetterCallTools(tools: ToolGatewayTool[], options: BetterCallArgumentRepairOptions | undefined): ToolGatewayRuntimeTool[];
26
+ export declare function repairBetterCallToolSelection(input: {
27
+ toolId: string;
28
+ args: unknown;
29
+ tools: ToolGatewayTool[];
30
+ options: BetterCallArgumentRepairOptions | undefined;
31
+ }): Promise<BetterCallToolSelectionRepair | undefined>;
32
+ export {};
@@ -0,0 +1 @@
1
+ import{BetterToolValidationError as e,betterTools as t,defaultRepair as r,reliableToolCalls as o}from"@botbotgo/better-call";export class ToolArgumentValidationError extends Error{toolId;issues;constructor(e,t){super(`Tool argument validation failed for ${e}: ${t.map(e=>`${e.path} ${e.message}`).join("; ")}`),this.toolId=e,this.issues=t,this.name="ToolArgumentValidationError"}}export function createDefaultArgumentGuard(t={}){return{async validate(r){const o=r.tool.validateArgs?await r.tool.validateArgs({args:r.args,context:r.context}):{action:"allow",args:r.args};if("reject"===o.action)return o;const n=await async function(t,r,o){const n=function(e,t){return d(e.schema)?a(e.schema.safeParse(t??{})):u(r=e.schema)&&Object.values(r).length>0&&Object.values(r).every(d)?function(e,t){const r=u(t)?t:{},o={},s=[];for(const[t,a]of Object.entries(e)){const e=a.safeParse(r[t]);e.success?void 0!==e.data&&(o[t]=e.data):s.push(...e.error.issues.map(e=>({...e,path:[t,...e.path]})))}return s.length>0?a({success:!1,error:{issues:s}}):{action:"allow",args:o}}(e.schema,t):void 0;var r}(t,r);return n||(u(t.schema)?async function(t,r,o){try{return{action:"allow",args:await s(t,o).invoke(r)}}catch(t){if(t instanceof e)return{action:"reject",reason:"BetterCall validation failed",issues:t.issues.map(c)};throw t}}(t,r,o):{action:"allow",args:r})}(r.tool,o.args,t.betterCall);return"reject"===n.action?n:"repair"===o.action?{...o,args:n.args}:n}}}export function assertToolArguments(e,t,r,o){return Promise.resolve(o.validate({tool:e,args:t,context:r})).then(t=>{if("reject"===t.action)throw new ToolArgumentValidationError(e.id,t.issues);return t.args})}function a(e){return e.success?{action:"allow",args:e.data}:{action:"reject",reason:"Zod schema validation failed",issues:e.error.issues.map(e=>{return{path:(t=e.path,t.length>0?`$.${t.map(String).join(".")}`:"$"),message:e.message,expected:"schema"};var t})}}export function prepareBetterCallTools(e,r){const o=t(e.map(n),l(r));return e.map((e,t)=>({...e,validationTool:o[t]}))}export async function repairBetterCallToolSelection(e){const t=(a=e.options,a?.repair??(a?.repairModel?r(a.repairModel):void 0));var a;if(!t||0===e.tools.length)return;const s=await o({userInput:JSON.stringify({tool:e.toolId,args:e.args}),tools:e.tools.map(i),calls:[{tool:e.toolId,args:(n=e.args,u(n)?n:{input:n})}],repair:t,mode:e.options?.mode??"repair"});var n;const c=s.ok?s.calls.find(t=>e.tools.some(e=>e.id===t.tool)):void 0;return c?{toolId:c.tool,args:c.args}:void 0}function s(e,r){return e.validationTool??t([n(e)],l(r))[0]}function n(e){return{name:e.id,description:e.description,schema:e.schema,invoke:e=>e}}function i(e){return{name:e.id,description:e.description,schema:u(e.schema)?e.schema:void 0}}function c(e){return{path:e.path.replace(/^\$\.calls\[\d+\]\.args/u,"$"),message:e.message,expected:void 0===e.expected?void 0:String(e.expected),actual:e.actual}}function l(e){return{mode:e?.mode??"repair",repair:e?.repair,repairModel:e?.repairModel}}function u(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function d(e){return u(e)&&"function"==typeof e.safeParse}
@@ -0,0 +1,4 @@
1
+ import type { ToolGateway, ToolGatewayTool } from "./types.js";
2
+ import type { ToolArgumentGuardOptions } from "./argument-guard.js";
3
+ export type ToolGatewayOptions = ToolArgumentGuardOptions;
4
+ export declare function createInMemoryToolGateway(tools: ToolGatewayTool[], options?: ToolGatewayOptions): ToolGateway;
@@ -0,0 +1 @@
1
+ import{assertToolArguments as o,createDefaultArgumentGuard as t,prepareBetterCallTools as e,repairBetterCallToolSelection as a}from"./argument-guard.js";export function createInMemoryToolGateway(r,l={}){const s=new Map(e(r,l.betterCall).map(o=>[o.id,o])),n=t(l),i=async o=>{const t=o.allowedToolIds?new Set(o.allowedToolIds):void 0,e=[...s.values()].filter(o=>!t||t.has(o.id));return a({toolId:o.toolId,args:o.args,tools:e,options:l.betterCall})};return{list:()=>[...s.values()],get:o=>s.get(o),repairToolCall:i,async invoke(t){const e=s.has(t.toolId)?void 0:await i(t),a=e?.toolId??t.toolId,r=s.get(a);if(!r)throw new Error(`Tool is not registered: ${t.toolId}`);const l=await o(r,e?.args??t.args,t.context,n);return{toolId:r.id,output:await r.invoke(l,t.context)}}}}
@@ -0,0 +1,7 @@
1
+ export { createDefaultArgumentGuard, ToolArgumentValidationError } from "./argument-guard.js";
2
+ export { createInMemoryToolGateway } from "./in-memory.js";
3
+ export { createModuleToolGateway } from "./module-loader.js";
4
+ export type { BetterCallArgumentRepairOptions, ToolArgumentGuardOptions } from "./argument-guard.js";
5
+ export type { ToolGatewayOptions } from "./in-memory.js";
6
+ export type { ModuleToolDescriptor } from "./module-loader.js";
7
+ export type { ToolArgumentGuard, ToolArgumentGuardResult, ToolArgumentIssue, ToolArgumentValidator, ToolGateway, ToolGatewayContext, ToolGatewayInvokeRequest, ToolGatewayInvokeResult, ToolGatewayRepairRequest, ToolGatewayRepairResult, ToolGatewayTool, } from "./types.js";
@@ -0,0 +1 @@
1
+ export{createDefaultArgumentGuard,ToolArgumentValidationError}from"./argument-guard.js";export{createInMemoryToolGateway}from"./in-memory.js";export{createModuleToolGateway}from"./module-loader.js";
@@ -0,0 +1,13 @@
1
+ import type { ToolGatewayOptions } from "./in-memory.js";
2
+ import type { ToolGateway } from "./types.js";
3
+ export type ModuleToolDescriptor = {
4
+ id: string;
5
+ name?: string;
6
+ description?: string;
7
+ schema?: unknown;
8
+ sourcePath?: string;
9
+ };
10
+ export declare function createModuleToolGateway(input: {
11
+ tools: Iterable<ModuleToolDescriptor>;
12
+ options?: ToolGatewayOptions;
13
+ }): Promise<ToolGateway>;
@@ -0,0 +1 @@
1
+ import o from"node:path";import{pathToFileURL as e}from"node:url";import{createInMemoryToolGateway as t}from"./in-memory.js";export async function createModuleToolGateway(o){const e=[];for(const t of o.tools){const o=await r(t);o&&e.push(o)}return t(e,o.options)}async function r(t){if(!t.sourcePath)return;const r=await import(e(o.resolve(t.sourcePath)).href),n=r[t.name??t.id]??r.default;var i;return"object"==typeof(i=n)&&null!==i&&"invoke"in i&&"function"==typeof i.invoke?{id:t.id,description:t.description??n.description,schema:t.schema??n.schema,validateArgs:n.validateArgs,invoke:(o,e)=>async function(o,e,t){const r=process.cwd();try{return process.chdir(t.workspaceRoot),await o(e)}finally{process.chdir(r)}}(n.invoke,o,e)}:void 0}
@@ -0,0 +1,65 @@
1
+ export type ToolGatewayContext = {
2
+ workspaceRoot: string;
3
+ requestId: string;
4
+ sessionId: string;
5
+ agentId: string;
6
+ };
7
+ export type ToolGatewayTool = {
8
+ id: string;
9
+ description?: string;
10
+ schema?: unknown;
11
+ validateArgs?: ToolArgumentValidator;
12
+ invoke(args: unknown, context: ToolGatewayContext): Promise<unknown>;
13
+ };
14
+ export type ToolArgumentIssue = {
15
+ path: string;
16
+ message: string;
17
+ expected?: string;
18
+ actual?: unknown;
19
+ };
20
+ export type ToolArgumentGuardResult = {
21
+ action: "allow";
22
+ args: unknown;
23
+ } | {
24
+ action: "repair";
25
+ args: unknown;
26
+ reason: string;
27
+ issues: ToolArgumentIssue[];
28
+ } | {
29
+ action: "reject";
30
+ reason: string;
31
+ issues: ToolArgumentIssue[];
32
+ };
33
+ export type ToolArgumentGuard = {
34
+ validate(input: {
35
+ tool: ToolGatewayTool;
36
+ args: unknown;
37
+ context: ToolGatewayContext;
38
+ }): Promise<ToolArgumentGuardResult> | ToolArgumentGuardResult;
39
+ };
40
+ export type ToolArgumentValidator = (input: {
41
+ args: unknown;
42
+ context: ToolGatewayContext;
43
+ }) => Promise<ToolArgumentGuardResult> | ToolArgumentGuardResult;
44
+ export type ToolGatewayInvokeRequest = {
45
+ toolId: string;
46
+ args?: unknown;
47
+ context: ToolGatewayContext;
48
+ };
49
+ export type ToolGatewayRepairRequest = ToolGatewayInvokeRequest & {
50
+ allowedToolIds?: string[];
51
+ };
52
+ export type ToolGatewayInvokeResult = {
53
+ toolId: string;
54
+ output: unknown;
55
+ };
56
+ export type ToolGatewayRepairResult = {
57
+ toolId: string;
58
+ args: unknown;
59
+ };
60
+ export type ToolGateway = {
61
+ list(): ToolGatewayTool[];
62
+ get(toolId: string): ToolGatewayTool | undefined;
63
+ repairToolCall?(request: ToolGatewayRepairRequest): Promise<ToolGatewayRepairResult | undefined>;
64
+ invoke(request: ToolGatewayInvokeRequest): Promise<ToolGatewayInvokeResult>;
65
+ };
@@ -0,0 +1 @@
1
+ export{};
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@stable-harness/tool-gateway",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist/**/*.js",
7
+ "dist/**/*.d.ts",
8
+ "package.json"
9
+ ],
10
+ "main": "dist/src/index.js",
11
+ "types": "dist/src/index.d.ts",
12
+ "dependencies": {
13
+ "@botbotgo/better-call": "^0.1.1"
14
+ }
15
+ }