@punktechnologies/sdk 0.1.0 → 0.1.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.
- package/LICENSE +75 -81
- package/README.md +216 -94
- package/SECURITY.md +11 -0
- package/dist/index.js +14 -4
- package/package.json +35 -19
- package/src/index.ts +1559 -0
- package/src/types.ts +512 -0
package/LICENSE
CHANGED
|
@@ -9,51 +9,50 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
|
9
9
|
"License" shall mean the terms and conditions for use, reproduction, and
|
|
10
10
|
distribution as defined by Sections 1 through 9 of this document.
|
|
11
11
|
|
|
12
|
-
"Licensor" shall mean the copyright owner or entity authorized by the
|
|
13
|
-
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
|
13
|
+
owner that is granting the License.
|
|
14
14
|
|
|
15
|
-
"Legal Entity" shall mean the union of the acting entity and all other
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
entity.
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities
|
|
16
|
+
that control, are controlled by, or are under common control with that entity.
|
|
17
|
+
For the purposes of this definition, "control" means (i) the power, direct or
|
|
18
|
+
indirect, to cause the direction or management of such entity, whether by
|
|
19
|
+
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
20
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
21
|
|
|
23
22
|
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
|
24
23
|
permissions granted by this License.
|
|
25
24
|
|
|
26
|
-
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
"Source" form shall mean the preferred form for making modifications, including
|
|
26
|
+
but not limited to software source code, documentation source, and configuration
|
|
27
|
+
files.
|
|
29
28
|
|
|
30
29
|
"Object" form shall mean any form resulting from mechanical transformation or
|
|
31
|
-
translation of a Source form, including but not limited to compiled object
|
|
32
|
-
|
|
30
|
+
translation of a Source form, including but not limited to compiled object code,
|
|
31
|
+
generated documentation, and conversions to other media types.
|
|
33
32
|
|
|
34
|
-
"Work" shall mean the work of authorship, whether in Source or Object form,
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
|
34
|
+
available under the License, as indicated by a copyright notice that is included
|
|
35
|
+
in or attached to the work.
|
|
37
36
|
|
|
38
37
|
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
|
39
38
|
is based on (or derived from) the Work and for which the editorial revisions,
|
|
40
39
|
annotations, elaborations, or other modifications represent, as a whole, an
|
|
41
|
-
original work of authorship. For the purposes of this License, Derivative
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"Contribution" shall mean any work of authorship, including the original
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
40
|
+
original work of authorship. For the purposes of this License, Derivative Works
|
|
41
|
+
shall not include works that remain separable from, or merely link (or bind by
|
|
42
|
+
name) to the interfaces of, the Work and Derivative Works thereof.
|
|
43
|
+
|
|
44
|
+
"Contribution" shall mean any work of authorship, including the original version
|
|
45
|
+
of the Work and any modifications or additions to that Work or Derivative Works
|
|
46
|
+
thereof, that is intentionally submitted to Licensor for inclusion in the Work by
|
|
47
|
+
the copyright owner or by an individual or Legal Entity authorized to submit on
|
|
48
|
+
behalf of the copyright owner. For the purposes of this definition, "submitted"
|
|
49
|
+
means any form of electronic, verbal, or written communication sent to the
|
|
50
|
+
Licensor or its representatives, including but not limited to communication on
|
|
51
|
+
electronic mailing lists, source code control systems, and issue tracking systems
|
|
52
|
+
that are managed by, or on behalf of, the Licensor for the purpose of discussing
|
|
53
|
+
and improving the Work, but excluding communication that is conspicuously marked
|
|
54
|
+
or otherwise designated in writing by the copyright owner as "Not a
|
|
55
|
+
Contribution."
|
|
57
56
|
|
|
58
57
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
|
59
58
|
of whom a Contribution has been received by Licensor and subsequently
|
|
@@ -66,54 +65,51 @@ reproduce, prepare Derivative Works of, publicly display, publicly perform,
|
|
|
66
65
|
sublicense, and distribute the Work and such Derivative Works in Source or
|
|
67
66
|
Object form.
|
|
68
67
|
|
|
69
|
-
3. Grant of Patent License. Subject to the terms and conditions of this
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
licenses granted to You under this License for that Work shall terminate as of
|
|
81
|
-
the date such litigation is filed.
|
|
68
|
+
3. Grant of Patent License. Subject to the terms and conditions of this License,
|
|
69
|
+
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
|
70
|
+
no-charge, royalty-free, irrevocable patent license to make, have made, use,
|
|
71
|
+
offer to sell, sell, import, and otherwise transfer the Work, where such license
|
|
72
|
+
applies only to those patent claims licensable by such Contributor that are
|
|
73
|
+
necessarily infringed by their Contribution alone or by combination of their
|
|
74
|
+
Contribution with the Work to which such Contribution was submitted. If You
|
|
75
|
+
institute patent litigation against any entity alleging that the Work or a
|
|
76
|
+
Contribution incorporated within the Work constitutes direct or contributory
|
|
77
|
+
patent infringement, then any patent licenses granted to You under this License
|
|
78
|
+
for that Work shall terminate as of the date such litigation is filed.
|
|
82
79
|
|
|
83
80
|
4. Redistribution. You may reproduce and distribute copies of the Work or
|
|
84
81
|
Derivative Works thereof in any medium, with or without modifications, and in
|
|
85
82
|
Source or Object form, provided that You meet the following conditions:
|
|
86
83
|
|
|
87
|
-
(a) You must give any other recipients of the Work or Derivative Works a copy
|
|
88
|
-
|
|
84
|
+
(a) You must give any other recipients of the Work or Derivative Works a copy of
|
|
85
|
+
this License; and
|
|
89
86
|
|
|
90
|
-
(b) You must cause any modified files to carry prominent notices stating that
|
|
91
|
-
|
|
87
|
+
(b) You must cause any modified files to carry prominent notices stating that You
|
|
88
|
+
changed the files; and
|
|
92
89
|
|
|
93
90
|
(c) You must retain, in the Source form of any Derivative Works that You
|
|
94
91
|
distribute, all copyright, patent, trademark, and attribution notices from the
|
|
95
|
-
Source form of the Work, excluding those notices that do not pertain to any
|
|
96
|
-
|
|
92
|
+
Source form of the Work, excluding those notices that do not pertain to any part
|
|
93
|
+
of the Derivative Works; and
|
|
97
94
|
|
|
98
95
|
(d) If the Work includes a "NOTICE" text file as part of its distribution, then
|
|
99
96
|
any Derivative Works that You distribute must include a readable copy of the
|
|
100
97
|
attribution notices contained within such NOTICE file, excluding those notices
|
|
101
98
|
that do not pertain to any part of the Derivative Works, in at least one of the
|
|
102
|
-
following places: within a NOTICE text file distributed as part of the
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
modifying the License.
|
|
99
|
+
following places: within a NOTICE text file distributed as part of the Derivative
|
|
100
|
+
Works; within the Source form or documentation, if provided along with the
|
|
101
|
+
Derivative Works; or, within a display generated by the Derivative Works, if and
|
|
102
|
+
wherever such third-party notices normally appear. The contents of the NOTICE
|
|
103
|
+
file are for informational purposes only and do not modify the License. You may
|
|
104
|
+
add Your own attribution notices within Derivative Works that You distribute,
|
|
105
|
+
alongside or as an addendum to the NOTICE text from the Work, provided that such
|
|
106
|
+
additional attribution notices cannot be construed as modifying the License.
|
|
111
107
|
|
|
112
108
|
You may add Your own copyright statement to Your modifications and may provide
|
|
113
109
|
additional or different license terms and conditions for use, reproduction, or
|
|
114
|
-
distribution of Your modifications, or for any such Derivative Works as a
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
distribution of Your modifications, or for any such Derivative Works as a whole,
|
|
111
|
+
provided Your use, reproduction, and distribution of the Work otherwise complies
|
|
112
|
+
with the conditions stated in this License.
|
|
117
113
|
|
|
118
114
|
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
|
119
115
|
Contribution intentionally submitted for inclusion in the Work by You to the
|
|
@@ -130,8 +126,8 @@ reproducing the content of the NOTICE file.
|
|
|
130
126
|
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
|
|
131
127
|
writing, Licensor provides the Work (and each Contributor provides its
|
|
132
128
|
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
133
|
-
KIND, either express or implied, including, without limitation, any warranties
|
|
134
|
-
|
|
129
|
+
KIND, either express or implied, including, without limitation, any warranties or
|
|
130
|
+
conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
135
131
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
136
132
|
appropriateness of using or redistributing the Work and assume any risks
|
|
137
133
|
associated with Your exercise of permissions under this License.
|
|
@@ -140,23 +136,21 @@ associated with Your exercise of permissions under this License.
|
|
|
140
136
|
tort (including negligence), contract, or otherwise, unless required by
|
|
141
137
|
applicable law (such as deliberate and grossly negligent acts) or agreed to in
|
|
142
138
|
writing, shall any Contributor be liable to You for damages, including any
|
|
143
|
-
direct, indirect, special, incidental, or consequential damages of any
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
139
|
+
direct, indirect, special, incidental, or consequential damages of any character
|
|
140
|
+
arising as a result of this License or out of the use or inability to use the
|
|
141
|
+
Work (including but not limited to damages for loss of goodwill, work stoppage,
|
|
142
|
+
computer failure or malfunction, or any and all other commercial damages or
|
|
143
|
+
losses), even if such Contributor has been advised of the possibility of such
|
|
144
|
+
damages.
|
|
149
145
|
|
|
150
146
|
9. Accepting Warranty or Additional Liability. While redistributing the Work or
|
|
151
147
|
Derivative Works thereof, You may choose to offer, and charge a fee for,
|
|
152
|
-
acceptance of support, warranty, indemnity, or other liability obligations
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
acceptance of support, warranty, indemnity, or other liability obligations and/or
|
|
149
|
+
rights consistent with this License. However, in accepting such obligations, You
|
|
150
|
+
may act only on Your own behalf and on Your sole responsibility, not on behalf of
|
|
151
|
+
any other Contributor, and only if You agree to indemnify, defend, and hold each
|
|
152
|
+
Contributor harmless for any liability incurred by, or claims asserted against,
|
|
153
|
+
such Contributor by reason of your accepting any such warranty or additional
|
|
154
|
+
liability.
|
|
159
155
|
|
|
160
156
|
END OF TERMS AND CONDITIONS
|
|
161
|
-
|
|
162
|
-
Copyright 2026 Punk Technologies, Inc.
|
package/README.md
CHANGED
|
@@ -1,169 +1,291 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @punktechnologies/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
OpenAI-compatible AI gateway SDK for agent tracing, tool caching, governance, observability, and cost optimization.
|
|
4
4
|
|
|
5
|
-
Punk
|
|
5
|
+
Punk is the adaptive runtime for production AI agents. Put the gateway between your agents and model providers, then use this SDK where gateway traffic alone cannot see enough context: tool tracing, side-effect declarations, tool-result caching, semantic web fetches, feedback, receipts, evidence packets, MCP registry helpers, prompt ingest, and learning/artifact APIs.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Links: [SDK docs](https://punktechnologies.com/docs/sdk), [OpenAI gateway guide](https://punktechnologies.com/docs/openai-compatible-ai-gateway), [Vercel AI SDK](https://punktechnologies.com/docs/vercel-ai-sdk), [LangChain](https://punktechnologies.com/docs/langchain), [Anthropic SDK](https://punktechnologies.com/docs/anthropic-sdk), [Claude Code](https://punktechnologies.com/docs/claude-code).
|
|
8
|
+
|
|
9
|
+
The public SDK contains only the client integration surface. Punk's gateway, learning runtime, policies, replay/shadow engine, dashboard, and operators stay in the private runtime repo and are not part of this package.
|
|
8
10
|
|
|
9
11
|
## Install
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
|
-
npm
|
|
14
|
+
npm i @punktechnologies/sdk
|
|
13
15
|
# or
|
|
14
16
|
bun add @punktechnologies/sdk
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Zero runtime dependencies. Requires Node 18+ or Bun and a running Punk gateway. For local evaluation from the Punk repo:
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
bun install
|
|
23
|
+
bun run dev # gateway + dashboard + learning loop on http://localhost:4100
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
For
|
|
26
|
+
For hosted trials, use `baseUrl: "https://app.punktechnologies.com"` with a tenant API key from the dashboard.
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
export PUNK_BASE_URL=http://localhost:4100
|
|
28
|
-
```
|
|
28
|
+
## Choose Your Path
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
| Path | Best when | Start here |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| Gateway-only | You already use OpenAI, Anthropic, Vercel AI SDK, LangChain, or another compatible client. | Change `baseURL` and add `X-Punk-*` headers. |
|
|
33
|
+
| SDK client | You want typed helpers for chat, feedback, savings, runs, artifacts, SOM fetches, web sessions, and MCP registry calls. | Use `new Punk(...)`. |
|
|
34
|
+
| Tool tracing | You need Punk to see tool calls, side-effect levels, and read-only tool-cache eligibility. | Wrap tools with `traceTool(...)`. |
|
|
35
|
+
| Evidence reads | You need route explanations, receipts, or security/support evidence packets. | Call `runDetail`, `receipt`, or `evidencePacket`. |
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
## 60-Second Start
|
|
38
|
+
|
|
39
|
+
**1. Point existing OpenAI-style traffic at Punk.**
|
|
40
|
+
|
|
41
|
+
You do not need this SDK for the core gateway value. OpenAI-style and Anthropic-style clients can talk to Punk by changing the gateway URL.
|
|
33
42
|
|
|
34
43
|
```ts
|
|
35
44
|
import OpenAI from "openai";
|
|
36
45
|
|
|
37
|
-
const root = process.env.PUNK_BASE_URL ?? "https://api.punktechnologies.com";
|
|
38
|
-
|
|
39
46
|
const client = new OpenAI({
|
|
40
|
-
baseURL:
|
|
41
|
-
apiKey: process.env.PUNK_API_KEY,
|
|
42
|
-
defaultHeaders: {
|
|
43
|
-
"X-Punk-App": "support-app",
|
|
44
|
-
"X-Punk-Agent": "triage-agent",
|
|
45
|
-
"X-Punk-Subject": "user-123"
|
|
46
|
-
}
|
|
47
|
+
baseURL: "http://localhost:4100/v1",
|
|
48
|
+
apiKey: process.env.PUNK_API_KEY ?? "punk-local",
|
|
49
|
+
defaultHeaders: { "X-Punk-App": "my-app" },
|
|
47
50
|
});
|
|
51
|
+
```
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
.create({
|
|
51
|
-
model: "gpt-4o",
|
|
52
|
-
messages: [{ role: "user", content: "Classify this ticket: refund request" }]
|
|
53
|
-
})
|
|
54
|
-
.withResponse();
|
|
53
|
+
**2. Use the SDK when you need the richer runtime surface.**
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
```ts
|
|
56
|
+
import { Punk } from "@punktechnologies/sdk";
|
|
57
|
+
|
|
58
|
+
const punk = new Punk({ app: "my-app", agent: "my-bot" });
|
|
59
|
+
const result = await punk.chat({
|
|
60
|
+
model: "gpt-4o",
|
|
61
|
+
messages: [{ role: "user", content: "Classify this ticket: refund request" }],
|
|
62
|
+
});
|
|
63
|
+
console.log(result.content, result.route, result.runId);
|
|
64
|
+
// route is "live" on the first call; repeats become "exact_cache" and,
|
|
65
|
+
// once learned and proven, "artifact".
|
|
59
66
|
```
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
**3. Open the dashboard and inspect the run.**
|
|
62
69
|
|
|
63
|
-
|
|
70
|
+
Open `http://localhost:4100` locally, or `https://app.punktechnologies.com` for hosted trials. Every response carries a run id and route; the run detail explains why Punk chose that path and what it saved.
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
## API tour
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
import { Punk } from "@punktechnologies/sdk";
|
|
74
|
+
Construct once per app/agent identity:
|
|
69
75
|
|
|
76
|
+
```ts
|
|
70
77
|
const punk = new Punk({
|
|
71
|
-
baseUrl:
|
|
72
|
-
apiKey: process.env.PUNK_API_KEY,
|
|
73
|
-
app: "support-
|
|
74
|
-
agent: "triage-
|
|
75
|
-
subject: "user-123"
|
|
78
|
+
baseUrl: "http://localhost:4100", // default
|
|
79
|
+
apiKey: process.env.PUNK_API_KEY, // only if the gateway requires bearer auth
|
|
80
|
+
app: "support-triage", // X-Punk-App
|
|
81
|
+
agent: "triage-bot", // X-Punk-Agent
|
|
82
|
+
subject: "user-123", // X-Punk-Subject (pseudonymous end user)
|
|
76
83
|
});
|
|
84
|
+
```
|
|
77
85
|
|
|
78
|
-
|
|
86
|
+
### `chat(params)` — OpenAI-style completions through the gateway
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const r = await punk.chat({
|
|
79
90
|
model: "gpt-4o",
|
|
80
|
-
messages: [{ role: "user", content: "
|
|
91
|
+
messages: [{ role: "user", content: "hello" }],
|
|
92
|
+
temperature: 0,
|
|
81
93
|
});
|
|
94
|
+
r.content; // assistant text
|
|
95
|
+
r.runId; // from the x-punk-run-id response header — use it for tracing/feedback
|
|
96
|
+
r.route; // "live" | "exact_cache" | "artifact" | ... (x-punk-route header)
|
|
97
|
+
r.raw; // the full OpenAI-shaped response body
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Every response carries a run id and the route Punk chose. `punk.runDetail(r.runId)` returns the full trace and the `RouteExplanation` — why this route, what was rejected, what it saved.
|
|
101
|
+
|
|
102
|
+
For Punk Chorus, use `model: "punk/chorus"` and add Chorus-specific routing fields to the same body. The SDK helper below uses the OpenAI-style chat wire; direct HTTP callers can use the same model id through supported gateway wires.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { Punk, punkChorusChat } from "@punktechnologies/sdk";
|
|
106
|
+
|
|
107
|
+
const punk = new Punk({ app: "support", agent: "chorus-client" });
|
|
108
|
+
|
|
109
|
+
const r = await punk.chat(punkChorusChat({
|
|
110
|
+
messages: [{ role: "user", content: "Build a claim-graph answer with a receipt." }],
|
|
111
|
+
budget_limit_usd: 0.25,
|
|
112
|
+
latency_mode: "balanced",
|
|
113
|
+
quality_mode: "maximum_quality",
|
|
114
|
+
policy_profile: "regulated-support",
|
|
115
|
+
receipt_mode: "full",
|
|
116
|
+
circuit_mode: "learn",
|
|
117
|
+
shadow_mode: true,
|
|
118
|
+
chorus: { requestId: "req_123", workflowId: "wf_support" },
|
|
119
|
+
}));
|
|
82
120
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
121
|
+
const receipt = await punk.receipt(r.runId); // GET /api/v1/receipts/:id
|
|
122
|
+
// Current gateways may expose the same receipt-style material as an evidence packet:
|
|
123
|
+
const packet = await punk.evidencePacket(r.runId); // GET /api/v1/runs/:id/evidence-packet
|
|
86
124
|
```
|
|
87
125
|
|
|
88
|
-
|
|
126
|
+
Chorus uses one model id with per-request focus controls:
|
|
89
127
|
|
|
90
|
-
|
|
128
|
+
| Focus | SDK fields |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| Fast | `latency_mode: "fast"`, optional `quality_mode: "economy"` |
|
|
131
|
+
| Balanced | `latency_mode: "balanced"`, `quality_mode: "balanced"` |
|
|
132
|
+
| Deep reasoning | `latency_mode: "deep"`, `quality_mode: "frontier_optional"` |
|
|
133
|
+
| Source-backed research | `research_mode: "som"`, `research_max_queries`, `research_max_sources` |
|
|
134
|
+
| Maximum quality | `latency_mode: "maximum_quality"`, `quality_mode: "maximum_quality"`, optional `sota_mix`, `live_panel_models`, and `live_synthesis_model` |
|
|
135
|
+
| Private/local | `local_only: true`, optional `allowed_model_classes` |
|
|
136
|
+
| Shadow evaluation | `shadow_mode: true`, `circuit_mode: "learn"` |
|
|
137
|
+
|
|
138
|
+
Use `receipt_mode: "off"` to suppress receipt material. The gateway also accepts `"none"` as a compatibility alias. Use `live_synthesis_required: true` for benchmark or production gates where falling back to a mock or local path would be misleading.
|
|
139
|
+
|
|
140
|
+
### `traceTool(def)` — declare tools with side-effect levels
|
|
141
|
+
|
|
142
|
+
Wrap a tool so each invocation is traced into its run, and read-only results flow through the tool-result cache:
|
|
91
143
|
|
|
92
144
|
```ts
|
|
93
145
|
const lookupAccount = punk.traceTool({
|
|
94
146
|
name: "crm.lookupAccount",
|
|
95
|
-
sideEffectLevel: 1,
|
|
96
|
-
ttlSeconds: 300,
|
|
97
|
-
execute: async (args: { accountId: string }) => crm.get(args.accountId)
|
|
147
|
+
sideEffectLevel: 1, // read-only external
|
|
148
|
+
ttlSeconds: 300, // level <= 1 + TTL => tool-result cache participation
|
|
149
|
+
execute: async (args: { accountId: string }) => crm.get(args.accountId),
|
|
98
150
|
});
|
|
99
151
|
|
|
100
|
-
|
|
152
|
+
// Pass the runId from the chat that triggered the tool:
|
|
153
|
+
const account = await lookupAccount({ accountId: "acct_42" }, { runId: r.runId });
|
|
101
154
|
```
|
|
102
155
|
|
|
103
|
-
Side-effect levels:
|
|
156
|
+
Side-effect levels (PRD §17):
|
|
104
157
|
|
|
105
158
|
| Level | Meaning | Example |
|
|
106
159
|
| --- | --- | --- |
|
|
107
|
-
| 0 | Pure computation | parse, format,
|
|
108
|
-
| 1 | Read-only external |
|
|
109
|
-
| 2 | Reversible/idempotent write |
|
|
110
|
-
| 3 | User-visible write | email, Slack, ticket
|
|
111
|
-
| 4 | High-impact
|
|
160
|
+
| 0 | Pure computation | parse, format, math |
|
|
161
|
+
| 1 | Read-only external | CRM read, search, fetch |
|
|
162
|
+
| 2 | Reversible/idempotent write | upsert with idempotency key |
|
|
163
|
+
| 3 | User-visible write | email, Slack, ticket creation |
|
|
164
|
+
| 4 | High-impact | payments, deletion, permissions |
|
|
112
165
|
|
|
113
|
-
Undeclared tools default to level 3. Levels 0
|
|
166
|
+
Undeclared tools default to **level 3** (conservative). Levels 0–1 with a TTL are cached per tenant/subject; levels ≥ 2 emit `side_effect.planned` before execution so replay and shadow runs can suppress them. Without a `runId`, the tool still executes — just untraced. Cache and trace failures never break the tool call.
|
|
114
167
|
|
|
115
|
-
###
|
|
168
|
+
### `feedback(runId, rating, correction?)` — close the loop
|
|
116
169
|
|
|
117
170
|
```ts
|
|
118
|
-
await punk.feedback(
|
|
171
|
+
await punk.feedback(r.runId, 1); // thumbs up
|
|
172
|
+
await punk.feedback(r.runId, -1, "should be: billing"); // correction
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Feedback feeds the learner: corrections count against pattern stability and artifact confidence.
|
|
119
176
|
|
|
120
|
-
|
|
121
|
-
console.log(detail.run.routeExplanation);
|
|
177
|
+
### `fetchSom(url)` — semantic web fetch (token savings)
|
|
122
178
|
|
|
123
|
-
|
|
124
|
-
|
|
179
|
+
Compiles a page to a Semantic Object Model instead of handing your model raw HTML:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
const page = await punk.fetchSom("https://example.com/pricing");
|
|
183
|
+
page.som; // regions/elements with stable ids
|
|
184
|
+
page.context; // compact text ready for a prompt
|
|
185
|
+
page.tokensSavedEstimate; // raw-HTML tokens you didn't pay for
|
|
186
|
+
page.cached; // second fetch of the same URL hits the SOM cache
|
|
187
|
+
page.diff; // semantic diff vs. the previous snapshot, when bypassing cache
|
|
125
188
|
```
|
|
126
189
|
|
|
127
|
-
|
|
190
|
+
A typical marketing page compresses ~10–50x; the savings show up in `punk.savings().somTokensSaved`. Pass `{ bypassCache: true }` to force a refetch and get a semantic diff (pricing changed ≠ footer changed).
|
|
128
191
|
|
|
129
|
-
|
|
192
|
+
### Web sessions & actions — `punk.web.*`
|
|
193
|
+
|
|
194
|
+
Observation is half the loop; sessions close it. Open a stateful session, act on SOM element ids, get back a fresh SOM + semantic diff after every action:
|
|
130
195
|
|
|
131
196
|
```ts
|
|
132
|
-
|
|
197
|
+
const { sessionId, som, context } = await punk.web.openSession("https://example.com");
|
|
133
198
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
})
|
|
199
|
+
// click a link by its SOM element id (e_…) — navigates and recompiles
|
|
200
|
+
const link = som.regions.flatMap((r) => r.elements).find((e) => e.role === "link");
|
|
201
|
+
const r1 = await punk.web.act(sessionId, { action: "click", target: link.id });
|
|
202
|
+
r1.result.navigated; // true
|
|
203
|
+
r1.diff; // what changed, semantically weighted
|
|
204
|
+
|
|
205
|
+
// fill and submit a form (target a field for type/select, the r_form region for submit)
|
|
206
|
+
await punk.web.act(sessionId, { action: "type", target: "e_abc123", value: "k@example.com" });
|
|
207
|
+
await punk.web.act(sessionId, { action: "select", target: "e_def456", value: "pro" });
|
|
208
|
+
const submit = await punk.web.act(sessionId, { action: "submit", target: "r_form" });
|
|
209
|
+
submit.result.posted; // serialized fields sent by the form submission
|
|
210
|
+
|
|
211
|
+
await punk.web.closeSession(sessionId); // idle sessions auto-close after 5 minutes
|
|
212
|
+
```
|
|
142
213
|
|
|
143
|
-
|
|
214
|
+
Actions are protocol-level (link follows, urlencoded form submits — no JS engine) and **policy-governed server-side**:
|
|
215
|
+
|
|
216
|
+
| action | side-effect level | governed action | notes |
|
|
217
|
+
| --- | --- | --- | --- |
|
|
218
|
+
| `type`, `select` | 0 | `read:web` | mutate session-local form state only |
|
|
219
|
+
| form-local `click` | 0 | `read:web` | checkbox/radio/reset mutate session state only |
|
|
220
|
+
| navigation `click` | 1 | `read:web` | link navigation = a read of another page |
|
|
221
|
+
| submit-button `click` | 3 | `write:web` | same governance as submitting the form |
|
|
222
|
+
| `submit` | 3 | `write:web` | a real remote write — deniable/holdable by policy (403) |
|
|
223
|
+
|
|
224
|
+
Observe-mode keys can read (click/type/select) but never perform web writes. Every action is audited, and every navigation destination is SSRF-guarded by the gateway.
|
|
225
|
+
|
|
226
|
+
### Read APIs
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
await punk.savings(); // SavingsSummary: runs, cost, saved USD/ms, hit rates
|
|
230
|
+
await punk.patterns(); // discovered patterns and their lifecycle state
|
|
231
|
+
await punk.artifacts(); // synthesized artifacts with confidence + evidence counts
|
|
232
|
+
await punk.artifactDetail(id); // artifact + replay/shadow evaluations + source pattern
|
|
233
|
+
await punk.runDetail(id); // run + full trace events + side-effect records
|
|
234
|
+
await punk.receipt(id); // Chorus receipt for a run
|
|
235
|
+
await punk.evidencePacket(id); // support/security evidence packet for a run
|
|
236
|
+
await punk.cacheStats(); // per-tier entries and hits
|
|
144
237
|
```
|
|
145
238
|
|
|
146
|
-
|
|
239
|
+
### Learning lifecycle
|
|
147
240
|
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
examples/ integration examples for common agent stacks
|
|
152
|
-
docs/ SDK reference
|
|
241
|
+
```ts
|
|
242
|
+
const report = await punk.learningTick(); // force a learning pass (it also runs on a timer)
|
|
243
|
+
const artifact = await punk.promoteArtifact(id); // operator approval after replay+shadow proof
|
|
153
244
|
```
|
|
154
245
|
|
|
155
|
-
|
|
246
|
+
Promotion is gated: an artifact needs passing replay evidence against historical traces and shadow agreement against live traffic before `promoteArtifact` succeeds. Rollback/quarantine are available via the API and dashboard.
|
|
156
247
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
248
|
+
### Low-level
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
await punk.trace(runId, "tool.completed", { name: "x", result }); // append a trace event
|
|
252
|
+
await punk.ingestPrompt("claude-code", prompt); // side-load an observed prompt
|
|
253
|
+
await punk.toolCacheCheck("crm.lookupAccount", args); // manual cache check (degrades to miss)
|
|
254
|
+
await punk.toolCacheStore("crm.lookupAccount", args, result, 300); // manual store (failures swallowed)
|
|
163
255
|
```
|
|
164
256
|
|
|
165
|
-
|
|
257
|
+
External MCP servers for workflow `tool_call` nodes are available through `punk.mcp.listServers()`, `punk.mcp.createServer(...)`, and `punk.mcp.testServer(id)`.
|
|
258
|
+
|
|
259
|
+
## Headers reference
|
|
260
|
+
|
|
261
|
+
Request headers (set automatically by the SDK; set them yourself with raw OpenAI clients):
|
|
262
|
+
|
|
263
|
+
| Header | Meaning |
|
|
264
|
+
| --- | --- |
|
|
265
|
+
| `X-Punk-App` | Logical application name (groups runs and patterns) |
|
|
266
|
+
| `X-Punk-Agent` | Agent identity within the app |
|
|
267
|
+
| `X-Punk-Subject` | Pseudonymous end-user id — a cache-key safety dimension |
|
|
268
|
+
| `Authorization: Bearer …` | Only when the gateway sets `PUNK_API_KEY` |
|
|
269
|
+
|
|
270
|
+
Response headers on `/v1/chat/completions`:
|
|
271
|
+
|
|
272
|
+
| Header | Meaning |
|
|
273
|
+
| --- | --- |
|
|
274
|
+
| `x-punk-run-id` | The run this response belongs to — feed it to `trace`/`feedback`/`runDetail` |
|
|
275
|
+
| `x-punk-route` | The route served: `live`, `exact_cache`, `tool_cache`, `artifact`, `blocked`, … |
|
|
276
|
+
|
|
277
|
+
## Error behavior
|
|
278
|
+
|
|
279
|
+
All methods throw `Error("Punk API <METHOD> <path> failed: <status> <statusText> — <body>")` on non-2xx — except telemetry and caching, which degrade silently: trace appends inside `traceTool` never fail the tool call, `toolCacheCheck` degrades to a miss, `toolCacheStore` is fire-and-forget. The gateway itself fails open: if an optimized route errors, the request falls back to the live provider.
|
|
166
280
|
|
|
167
|
-
##
|
|
281
|
+
## More
|
|
168
282
|
|
|
169
|
-
|
|
283
|
+
- [Punk in 30 Minutes](https://punktechnologies.com/docs/onboarding)
|
|
284
|
+
- [SDK Reference](https://punktechnologies.com/docs/sdk)
|
|
285
|
+
- [OpenAI-Compatible AI Gateway](https://punktechnologies.com/docs/openai-compatible-ai-gateway)
|
|
286
|
+
- [Vercel AI SDK](https://punktechnologies.com/docs/vercel-ai-sdk)
|
|
287
|
+
- [LangChain](https://punktechnologies.com/docs/langchain)
|
|
288
|
+
- [Anthropic SDK](https://punktechnologies.com/docs/anthropic-sdk)
|
|
289
|
+
- [Claude Code](https://punktechnologies.com/docs/claude-code)
|
|
290
|
+
- [Agent Observability & Tool Caching](https://punktechnologies.com/docs/agent-observability-tool-caching)
|
|
291
|
+
- [examples/](https://github.com/PunkTechnologies/punk/tree/main/examples) — OpenAI SDK, Anthropic SDK, Vercel AI SDK, LangChain, SDK, Claude Code, raw curl
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Please report suspected vulnerabilities privately:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
security@punktechnologies.com
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Do not open a public issue for suspected credential exposure, auth bypass, tenant isolation issues, side-effect governance bypasses, replay/shadow suppression failures, SSRF, or package supply-chain compromise.
|
|
10
|
+
|
|
11
|
+
The SDK is dependency-free and published from `packages/sdk` in `PunkTechnologies/punk`. Release provenance is enabled in package metadata.
|