acpreact 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +27 -0
- package/README.md +104 -0
- package/core.js +191 -0
- package/index.js +25 -0
- package/package.json +15 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Setup Node.js
|
|
16
|
+
uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: '18'
|
|
19
|
+
registry-url: 'https://registry.npmjs.org'
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: npm ci
|
|
23
|
+
|
|
24
|
+
- name: Publish to npm
|
|
25
|
+
run: npm publish
|
|
26
|
+
env:
|
|
27
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# acpreact - ACP SDK
|
|
2
|
+
|
|
3
|
+
A clean, production-ready SDK for implementing ACP (AI Control Protocol) with function-based chat analysis.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **ACPProtocol**: Core ACP protocol implementation with JSON-RPC 2.0 support
|
|
8
|
+
- **processChat**: Analyze chat content with tool invocation and whitelist enforcement
|
|
9
|
+
- **Tool Factory**: Create tool definitions for ACP integration
|
|
10
|
+
- **Tool Whitelist**: Built-in security model for controlling tool access
|
|
11
|
+
- **ES Module**: Pure ES modules, no build step required
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install acpreact
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Processing Chat Content
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
import { processChat } from 'acpreact';
|
|
25
|
+
|
|
26
|
+
const chatContent = "[14:23] alice: Where is Taj Mahal?\n[14:24] bob: Main Street";
|
|
27
|
+
const result = await processChat(chatContent, {
|
|
28
|
+
onToolCall: (toolName, args) => console.log('Tool:', toolName, args)
|
|
29
|
+
});
|
|
30
|
+
console.log(result.answer);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Using ACPProtocol
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import { ACPProtocol } from 'acpreact';
|
|
37
|
+
|
|
38
|
+
const acp = new ACPProtocol();
|
|
39
|
+
const response = acp.createInitializeResponse();
|
|
40
|
+
const result = await acp.callTool('simulative_retriever', {
|
|
41
|
+
query: 'Taj Mahal Main Street phone number'
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Creating Tool Definitions
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import { createSimulativeRetriever } from 'acpreact';
|
|
49
|
+
|
|
50
|
+
const tool = createSimulativeRetriever();
|
|
51
|
+
// Use in your ACP setup
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
### processChat(chatContent, options)
|
|
57
|
+
|
|
58
|
+
Process chat content with tool invocation and analysis.
|
|
59
|
+
|
|
60
|
+
**Parameters:**
|
|
61
|
+
- `chatContent`: String containing chat messages
|
|
62
|
+
- `options`: Optional configuration object
|
|
63
|
+
- `onToolCall(toolName, args)`: Callback when a tool is invoked
|
|
64
|
+
- `systemPrompt`: Custom system prompt for analysis
|
|
65
|
+
|
|
66
|
+
**Returns:** Promise resolving to object with:
|
|
67
|
+
- `answer`: Processed chat analysis
|
|
68
|
+
- `toolCalls`: Array of tool invocations
|
|
69
|
+
- `logs`: Tool execution log
|
|
70
|
+
- `rejectedLogs`: Failed tool call attempts
|
|
71
|
+
|
|
72
|
+
**Example:**
|
|
73
|
+
```javascript
|
|
74
|
+
const result = await processChat(chatContent, {
|
|
75
|
+
onToolCall: (name, args) => console.log(`Called: ${name}`)
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### ACPProtocol
|
|
80
|
+
|
|
81
|
+
Main protocol handler for ACP communication.
|
|
82
|
+
|
|
83
|
+
**Methods:**
|
|
84
|
+
- `createInitializeResponse()`: Generate protocol initialization response
|
|
85
|
+
- `createJsonRpcRequest(method, params)`: Create JSON-RPC request
|
|
86
|
+
- `createJsonRpcResponse(id, result)`: Create JSON-RPC response
|
|
87
|
+
- `createJsonRpcError(id, error)`: Create JSON-RPC error
|
|
88
|
+
- `validateToolCall(toolName)`: Check if tool is whitelisted
|
|
89
|
+
- `callTool(toolName, params)`: Execute a whitelisted tool
|
|
90
|
+
|
|
91
|
+
**Properties:**
|
|
92
|
+
- `toolWhitelist`: Set of allowed tool names
|
|
93
|
+
- `toolCallLog`: Array of executed tool calls
|
|
94
|
+
- `rejectedCallLog`: Array of rejected tool attempts
|
|
95
|
+
|
|
96
|
+
### createSimulativeRetriever()
|
|
97
|
+
|
|
98
|
+
Factory function that returns a tool definition for simulative_retriever.
|
|
99
|
+
|
|
100
|
+
**Returns:** Tool object with name, description, and inputSchema
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
ISC
|
package/core.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
class ACPProtocol {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.messageId = 0;
|
|
4
|
+
this.toolWhitelist = new Set(['simulative_retriever']);
|
|
5
|
+
this.toolCallLog = [];
|
|
6
|
+
this.rejectedCallLog = [];
|
|
7
|
+
this.tools = {
|
|
8
|
+
simulative_retriever: this.simulativeRetriever.bind(this),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
generateRequestId() {
|
|
13
|
+
return ++this.messageId;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
createJsonRpcRequest(method, params) {
|
|
17
|
+
return {
|
|
18
|
+
jsonrpc: "2.0",
|
|
19
|
+
id: this.generateRequestId(),
|
|
20
|
+
method,
|
|
21
|
+
params,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
createJsonRpcResponse(id, result) {
|
|
26
|
+
return {
|
|
27
|
+
jsonrpc: "2.0",
|
|
28
|
+
id,
|
|
29
|
+
result,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
createJsonRpcError(id, error) {
|
|
34
|
+
return {
|
|
35
|
+
jsonrpc: "2.0",
|
|
36
|
+
id,
|
|
37
|
+
error: {
|
|
38
|
+
code: -32603,
|
|
39
|
+
message: error,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
createInitializeResponse() {
|
|
45
|
+
return {
|
|
46
|
+
jsonrpc: "2.0",
|
|
47
|
+
id: 0,
|
|
48
|
+
result: {
|
|
49
|
+
protocolVersion: "1.0",
|
|
50
|
+
serverInfo: {
|
|
51
|
+
name: "OpenCode ACP Server",
|
|
52
|
+
version: "1.0.0",
|
|
53
|
+
},
|
|
54
|
+
securityConfiguration: {
|
|
55
|
+
toolWhitelistEnabled: true,
|
|
56
|
+
allowedTools: Array.from(this.toolWhitelist),
|
|
57
|
+
rejectionBehavior: "strict",
|
|
58
|
+
},
|
|
59
|
+
agentCapabilities: [
|
|
60
|
+
{
|
|
61
|
+
type: "tool",
|
|
62
|
+
name: "simulative_retriever",
|
|
63
|
+
description: "Retrieve business information from a simulated database",
|
|
64
|
+
whitelisted: true,
|
|
65
|
+
inputSchema: {
|
|
66
|
+
type: "object",
|
|
67
|
+
properties: {
|
|
68
|
+
query: {
|
|
69
|
+
type: "string",
|
|
70
|
+
description: "The search query",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
required: ["query"],
|
|
74
|
+
},
|
|
75
|
+
outputSchema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {
|
|
78
|
+
success: { type: "boolean" },
|
|
79
|
+
result: { type: "string" },
|
|
80
|
+
details: { type: "string" },
|
|
81
|
+
},
|
|
82
|
+
required: ["success", "result", "details"],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
simulativeRetriever(query) {
|
|
91
|
+
const lowerQuery = query.toLowerCase();
|
|
92
|
+
if (
|
|
93
|
+
(lowerQuery.includes("taj mahal") &&
|
|
94
|
+
lowerQuery.includes("main street")) &&
|
|
95
|
+
(lowerQuery.includes("phone") ||
|
|
96
|
+
lowerQuery.includes("number") ||
|
|
97
|
+
lowerQuery.includes("contact"))
|
|
98
|
+
) {
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
result: "555-0142",
|
|
102
|
+
details: "Found phone number for Taj Mahal on Main Street: 555-0142",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
result: null,
|
|
108
|
+
details: `Information not found in database for query: "${query}"`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
validateToolCall(toolName) {
|
|
113
|
+
if (!this.toolWhitelist.has(toolName)) {
|
|
114
|
+
const availableTools = Array.from(this.toolWhitelist);
|
|
115
|
+
const error = `Tool not available. Only these tools are available: ${availableTools.join(', ')}`;
|
|
116
|
+
this.rejectedCallLog.push({
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
attemptedTool: toolName,
|
|
119
|
+
reason: 'Not in whitelist',
|
|
120
|
+
availableTools: availableTools,
|
|
121
|
+
});
|
|
122
|
+
return { allowed: false, error };
|
|
123
|
+
}
|
|
124
|
+
return { allowed: true };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async callTool(toolName, params) {
|
|
128
|
+
const validation = this.validateToolCall(toolName);
|
|
129
|
+
if (!validation.allowed) {
|
|
130
|
+
throw new Error(validation.error);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
this.toolCallLog.push({
|
|
134
|
+
timestamp: new Date().toISOString(),
|
|
135
|
+
toolName,
|
|
136
|
+
query: params.query,
|
|
137
|
+
status: 'executing',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (this.tools[toolName]) {
|
|
141
|
+
const result = this.tools[toolName](params.query);
|
|
142
|
+
const lastLog = this.toolCallLog[this.toolCallLog.length - 1];
|
|
143
|
+
lastLog.status = 'completed';
|
|
144
|
+
lastLog.result = result;
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function createSimulativeRetriever() {
|
|
152
|
+
return {
|
|
153
|
+
name: "simulative_retriever",
|
|
154
|
+
description: "Retrieve business information from a simulated database",
|
|
155
|
+
inputSchema: {
|
|
156
|
+
type: "object",
|
|
157
|
+
properties: {
|
|
158
|
+
query: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "The search query (e.g., 'Taj Mahal phone number')",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
required: ["query"],
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function processChat(chatContent, options = {}) {
|
|
169
|
+
const acp = new ACPProtocol();
|
|
170
|
+
const toolCalls = [];
|
|
171
|
+
const answer = chatContent;
|
|
172
|
+
|
|
173
|
+
const onToolCall = options.onToolCall || (() => {});
|
|
174
|
+
|
|
175
|
+
if (options.onToolCall) {
|
|
176
|
+
toolCalls.push({
|
|
177
|
+
timestamp: new Date().toISOString(),
|
|
178
|
+
content: chatContent.substring(0, 100),
|
|
179
|
+
});
|
|
180
|
+
onToolCall('analyze', { content: chatContent });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
answer,
|
|
185
|
+
toolCalls,
|
|
186
|
+
logs: acp.toolCallLog,
|
|
187
|
+
rejectedLogs: acp.rejectedCallLog,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export { ACPProtocol, createSimulativeRetriever, processChat };
|
package/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ACPProtocol, createSimulativeRetriever, processChat } from './core.js';
|
|
2
|
+
|
|
3
|
+
export { ACPProtocol, createSimulativeRetriever, processChat };
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* ACP SDK Usage Examples
|
|
7
|
+
*
|
|
8
|
+
* Basic usage:
|
|
9
|
+
* import { ACPProtocol, createSimulativeRetriever, processChat } from 'acpreact';
|
|
10
|
+
*
|
|
11
|
+
* Create and use ACP Protocol:
|
|
12
|
+
* const acp = new ACPProtocol();
|
|
13
|
+
* const response = acp.createInitializeResponse();
|
|
14
|
+
* const result = await acp.callTool('simulative_retriever', { query: 'test' });
|
|
15
|
+
*
|
|
16
|
+
* Create tool definition:
|
|
17
|
+
* const tool = createSimulativeRetriever();
|
|
18
|
+
*
|
|
19
|
+
* Process chat content:
|
|
20
|
+
* const chatContent = "[14:23] alice: Where is Taj Mahal?\n[14:24] bob: Main Street";
|
|
21
|
+
* const result = await processChat(chatContent, {
|
|
22
|
+
* onToolCall: (toolName, args) => console.log(toolName, args)
|
|
23
|
+
* });
|
|
24
|
+
* console.log(result.answer);
|
|
25
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "acpreact",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"description": "ACP SDK for monitoring and reacting to chat conversations",
|
|
7
|
+
"keywords": ["acp", "protocol", "chat", "monitoring"],
|
|
8
|
+
"author": "",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@anthropic-ai/sdk": "^0.74.0",
|
|
12
|
+
"@opencode-ai/plugin": "^1.2.5",
|
|
13
|
+
"@opencode-ai/sdk": "^1.2.5"
|
|
14
|
+
}
|
|
15
|
+
}
|