@prismshadow/penguin-core 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.
- package/LICENSE +201 -0
- package/README.md +41 -0
- package/dist/chunk-FX4CCIN7.js +379 -0
- package/dist/chunk-FX4CCIN7.js.map +1 -0
- package/dist/chunk-HRIXWKKE.js +1 -0
- package/dist/chunk-HRIXWKKE.js.map +1 -0
- package/dist/chunk-JC6SC6KF.js +336 -0
- package/dist/chunk-JC6SC6KF.js.map +1 -0
- package/dist/index.d.ts +1462 -0
- package/dist/index.js +5187 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces-CMSN7-pO.d.ts +487 -0
- package/dist/interfaces.d.ts +2 -0
- package/dist/interfaces.js +2 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/model-catalog-DTu0IPjs.d.ts +266 -0
- package/dist/omnimessage/index.d.ts +110 -0
- package/dist/omnimessage/index.js +69 -0
- package/dist/omnimessage/index.js.map +1 -0
- package/dist/state/model-catalog.d.ts +1 -0
- package/dist/state/model-catalog.js +19 -0
- package/dist/state/model-catalog.js.map +1 -0
- package/dist/types-D6FERSdT.d.ts +293 -0
- package/package.json +58 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OmniMessage — PenguinHarness's primary message protocol.
|
|
3
|
+
*
|
|
4
|
+
* All messages share one envelope: `timestamp` (ISO 8601 UTC), `type`, and `payload`.
|
|
5
|
+
* The outer `type` falls into three categories:
|
|
6
|
+
* - `session_meta`: Session metadata;
|
|
7
|
+
* - `model_msg`: model input/output messages (both complete messages and streaming
|
|
8
|
+
* `partial_*` messages);
|
|
9
|
+
* - `event_msg`: control/statistics events during execution.
|
|
10
|
+
*
|
|
11
|
+
* Trace records only: `session_meta`, complete `model_msg`, and all `event_msg`;
|
|
12
|
+
* the Human interface communicates using: complete `model_msg`, streaming `partial_*`, and all
|
|
13
|
+
* `event_msg`.
|
|
14
|
+
*
|
|
15
|
+
* Docs: packages/docs/content/omni-message.{zh,en}.md (site path /docs/omni-message) documents
|
|
16
|
+
* this protocol payload-for-payload — keep the page in sync when changing types here.
|
|
17
|
+
*/
|
|
18
|
+
/** The outer message category. */
|
|
19
|
+
type OmniMessageType = "session_meta" | "model_msg" | "event_msg";
|
|
20
|
+
/** The message's originating role. */
|
|
21
|
+
type Role = "user" | "assistant";
|
|
22
|
+
/**
|
|
23
|
+
* The reason a model response or message generation ended. Only five protocol values are
|
|
24
|
+
* allowed:
|
|
25
|
+
* - `completed`: finished normally, including completed text, thinking, tool requests, or
|
|
26
|
+
* tool output;
|
|
27
|
+
* - `failed`: a non-retryable error or tool execution failure;
|
|
28
|
+
* - `aborted`: user-initiated interruption or cancellation;
|
|
29
|
+
* - `timeout`: LLM request timed out;
|
|
30
|
+
* - `malformed`: the LLM response was malformed (e.g. AgentHub JSON parsing exception).
|
|
31
|
+
* Only LLM timeout / malformed trigger a context_engine reconnect.
|
|
32
|
+
* Docs: /docs/omni-message § "stop_reason".
|
|
33
|
+
*/
|
|
34
|
+
type StopReason = "completed" | "failed" | "aborted" | "timeout" | "malformed";
|
|
35
|
+
/** The event phase of a streaming fragment. `stop` marks the end of a fragment and usually carries no incremental content. */
|
|
36
|
+
type StreamEventType = "start" | "delta" | "stop";
|
|
37
|
+
/**
|
|
38
|
+
* Nested-origin marker: a child Session id. The message envelope's `origin` is a chain of child
|
|
39
|
+
* Session ids ordered **outer-to-inner**, identifying that the message comes from a nested child
|
|
40
|
+
* session (e.g. a child Session derived by `run_subagent`); each layer of host-tool forwarding
|
|
41
|
+
* prepends one more hop at the front. **An absent `origin` (the message carries no `origin`)
|
|
42
|
+
* means the message comes from the main Session itself** (an empty array is never produced
|
|
43
|
+
* either). Only session_id is recorded: the corresponding tool_call / agent info can be obtained
|
|
44
|
+
* from the `run_subagent` tool_call in the parent session's stream and the child Session's own
|
|
45
|
+
* Trace (session_meta).
|
|
46
|
+
* Docs: /docs/omni-message § "origin: the Subagent chain".
|
|
47
|
+
*/
|
|
48
|
+
type MessageOrigin = string;
|
|
49
|
+
/** The approval decision for a tool call. */
|
|
50
|
+
type ApprovalDecision = "allow" | "deny";
|
|
51
|
+
/** Token counts (input/output/cache/total). */
|
|
52
|
+
interface TokenCounts {
|
|
53
|
+
cache_read: number;
|
|
54
|
+
cache_write: number;
|
|
55
|
+
output: number;
|
|
56
|
+
total: number;
|
|
57
|
+
}
|
|
58
|
+
/** Tool definition passed to the LLM (OpenAI/JSON Schema style). */
|
|
59
|
+
interface ToolDefinition {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
parameters?: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
interface SessionMetaPayload {
|
|
65
|
+
session_id: string;
|
|
66
|
+
/** The session model's provider group (paired with `model_id` to form a model reference). */
|
|
67
|
+
provider: string;
|
|
68
|
+
/** The session model's upstream model_id (the request id sent to AgentHub; paired with `provider`). */
|
|
69
|
+
model_id: string;
|
|
70
|
+
model_context_window: number | string;
|
|
71
|
+
/** The system prompt actually used by this Session (the assembled result with environment placeholders already substituted). */
|
|
72
|
+
system_prompt: string;
|
|
73
|
+
/** The list of tool definitions this Session exposes to the model (full schema, matching what's sent to the LLM). */
|
|
74
|
+
tools: ToolDefinition[];
|
|
75
|
+
/** The model's thinking level (from system_config.model.thinking_level; "default" when unconfigured). */
|
|
76
|
+
thinking_level: string;
|
|
77
|
+
/** Absolute path to the Agent State. */
|
|
78
|
+
agent_state: string;
|
|
79
|
+
/** Absolute path to the Workspace. */
|
|
80
|
+
workspace: string;
|
|
81
|
+
}
|
|
82
|
+
interface TextPayload {
|
|
83
|
+
type: "text";
|
|
84
|
+
role: Role;
|
|
85
|
+
text: string;
|
|
86
|
+
stop_reason?: StopReason;
|
|
87
|
+
/** Provider fidelity field: text phase marker (e.g. GPT-5 segments by phase), kept as-is and restored verbatim. */
|
|
88
|
+
phase?: string | null;
|
|
89
|
+
/** Provider fidelity field: signature, kept as-is and restored verbatim. */
|
|
90
|
+
signature?: string;
|
|
91
|
+
}
|
|
92
|
+
interface ImageUrlPayload {
|
|
93
|
+
type: "image_url";
|
|
94
|
+
role: "user";
|
|
95
|
+
/** A web URL or a base64 data URL. */
|
|
96
|
+
image_url: string;
|
|
97
|
+
stop_reason?: StopReason;
|
|
98
|
+
}
|
|
99
|
+
interface InlineDataPayload {
|
|
100
|
+
type: "inline_data";
|
|
101
|
+
role: Role;
|
|
102
|
+
/** Base64-encoded bytes. */
|
|
103
|
+
data: string;
|
|
104
|
+
mime_type: string;
|
|
105
|
+
stop_reason?: StopReason;
|
|
106
|
+
/** Provider fidelity field: signature, kept as-is and restored verbatim. */
|
|
107
|
+
signature?: string;
|
|
108
|
+
}
|
|
109
|
+
interface ThinkingPayload {
|
|
110
|
+
type: "thinking";
|
|
111
|
+
role: "assistant";
|
|
112
|
+
thinking: string;
|
|
113
|
+
stop_reason?: StopReason;
|
|
114
|
+
/**
|
|
115
|
+
* Provider fidelity field: thinking-block signature (Claude thinking blocks / redacted
|
|
116
|
+
* thinking, GPT-5 encrypted reasoning, etc. — **required** when some models replay history),
|
|
117
|
+
* kept as-is and restored verbatim — losing it breaks Session resumption.
|
|
118
|
+
*/
|
|
119
|
+
signature?: string;
|
|
120
|
+
}
|
|
121
|
+
interface InlineThinkingPayload {
|
|
122
|
+
type: "inline_thinking";
|
|
123
|
+
role: "assistant";
|
|
124
|
+
/** Base64-encoded bytes. */
|
|
125
|
+
data: string;
|
|
126
|
+
mime_type: string;
|
|
127
|
+
stop_reason?: StopReason;
|
|
128
|
+
/** Provider fidelity field: signature, kept as-is and restored verbatim. */
|
|
129
|
+
signature?: string;
|
|
130
|
+
}
|
|
131
|
+
interface ToolCallPayload {
|
|
132
|
+
type: "tool_call";
|
|
133
|
+
role: "assistant";
|
|
134
|
+
name: string;
|
|
135
|
+
/** Tool arguments as a JSON string. */
|
|
136
|
+
arguments: string;
|
|
137
|
+
tool_call_id: string;
|
|
138
|
+
stop_reason?: StopReason;
|
|
139
|
+
/** Provider fidelity field: signature, kept as-is and restored verbatim. */
|
|
140
|
+
signature?: string;
|
|
141
|
+
}
|
|
142
|
+
interface ToolCallOutputPayload {
|
|
143
|
+
type: "tool_call_output";
|
|
144
|
+
role: "user";
|
|
145
|
+
output: string;
|
|
146
|
+
/**
|
|
147
|
+
* Images carried by the tool output (optional): each is a `data:<mime>;base64,...` data URL,
|
|
148
|
+
* fed back to the model alongside the text (e.g. images read by read_image). Images aren't
|
|
149
|
+
* incremental: the streaming path carries the whole set once via a single delta (see
|
|
150
|
+
* `PartialToolCallOutputPayload.images`), and the complete message carries them again — the
|
|
151
|
+
* streamed-and-joined result equals the complete message.
|
|
152
|
+
*/
|
|
153
|
+
images?: string[];
|
|
154
|
+
tool_call_id: string;
|
|
155
|
+
stop_reason?: StopReason;
|
|
156
|
+
}
|
|
157
|
+
interface PartialTextPayload {
|
|
158
|
+
type: "partial_text";
|
|
159
|
+
role: "assistant";
|
|
160
|
+
event_type: StreamEventType;
|
|
161
|
+
text: string;
|
|
162
|
+
stop_reason?: StopReason;
|
|
163
|
+
}
|
|
164
|
+
interface PartialThinkingPayload {
|
|
165
|
+
type: "partial_thinking";
|
|
166
|
+
role: "assistant";
|
|
167
|
+
event_type: StreamEventType;
|
|
168
|
+
thinking: string;
|
|
169
|
+
stop_reason?: StopReason;
|
|
170
|
+
}
|
|
171
|
+
interface PartialToolCallPayload {
|
|
172
|
+
type: "partial_tool_call";
|
|
173
|
+
role: "assistant";
|
|
174
|
+
event_type: StreamEventType;
|
|
175
|
+
name: string;
|
|
176
|
+
/** Incremental fragment of the arguments JSON. */
|
|
177
|
+
arguments: string;
|
|
178
|
+
tool_call_id: string;
|
|
179
|
+
stop_reason?: StopReason;
|
|
180
|
+
}
|
|
181
|
+
interface PartialToolCallOutputPayload {
|
|
182
|
+
type: "partial_tool_call_output";
|
|
183
|
+
role: "user";
|
|
184
|
+
event_type: StreamEventType;
|
|
185
|
+
output: string;
|
|
186
|
+
/** Images carried by the tool output (optional): images aren't incremental, carried as a whole by a single delta (consistent with the complete message). */
|
|
187
|
+
images?: string[];
|
|
188
|
+
tool_call_id: string;
|
|
189
|
+
stop_reason?: StopReason;
|
|
190
|
+
}
|
|
191
|
+
interface ApprovalDecisionPayload {
|
|
192
|
+
type: "approval_decision";
|
|
193
|
+
decision: ApprovalDecision;
|
|
194
|
+
tool_call_id: string;
|
|
195
|
+
}
|
|
196
|
+
interface AbortPayload {
|
|
197
|
+
type: "abort";
|
|
198
|
+
reason?: string | null;
|
|
199
|
+
}
|
|
200
|
+
interface TokenUsagePayload {
|
|
201
|
+
type: "token_usage";
|
|
202
|
+
/** Current Session cumulative token usage. */
|
|
203
|
+
session: TokenCounts;
|
|
204
|
+
/** Token usage for the most recent Request. */
|
|
205
|
+
request: TokenCounts;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Request boundary event: the boundary of one LLM Request, produced **in pairs** by
|
|
209
|
+
* `context_engine` and written to Trace. `request_end`
|
|
210
|
+
* with `status` of `completed` means the turn has been committed by AgentHub — this is the
|
|
211
|
+
* mechanical criterion Trace replay (Session resumption) uses to determine whether a turn was
|
|
212
|
+
* committed, and it also gives performance analysis a basis for Request latency and turn counts.
|
|
213
|
+
* A compaction request produces this same event pair too (written to Trace only, not streamed).
|
|
214
|
+
*/
|
|
215
|
+
interface RequestBeginPayload {
|
|
216
|
+
type: "request_begin";
|
|
217
|
+
}
|
|
218
|
+
interface RequestEndPayload {
|
|
219
|
+
type: "request_end";
|
|
220
|
+
/** Terminal state of this Request (reuses the five StopReason values, sharing its source with this turn's complete message's stop_reason / LLMOutcome). */
|
|
221
|
+
status: StopReason;
|
|
222
|
+
}
|
|
223
|
+
/** Compaction trigger reason: context threshold / turn-count threshold / user-initiated request. */
|
|
224
|
+
type CompactionReason = "context" | "turns" | "manual";
|
|
225
|
+
/** Context compaction mode: summary relay / direct discard. */
|
|
226
|
+
type CompactionMode = "summarize" | "discard";
|
|
227
|
+
/**
|
|
228
|
+
* Compaction boundary event: the compaction process exposes
|
|
229
|
+
* only this event pair to Human, produced **in pairs** by `context_engine`. Both `reason` and
|
|
230
|
+
* `mode` are carried on both events, for stateless frontend rendering; `status` reuses the
|
|
231
|
+
* five-value `StopReason` protocol (compaction converges to a terminal state, taking
|
|
232
|
+
* `completed` / `failed` / `aborted` in practice — `timeout` / `malformed` are handled internally
|
|
233
|
+
* by the compaction request's existing retry mechanism, collapsing to `failed` once retries are
|
|
234
|
+
* exhausted).
|
|
235
|
+
*/
|
|
236
|
+
interface CompactionBeginPayload {
|
|
237
|
+
type: "compaction_begin";
|
|
238
|
+
reason: CompactionReason;
|
|
239
|
+
mode: CompactionMode;
|
|
240
|
+
/** Current context token usage (the most recent token_usage's request.total). */
|
|
241
|
+
context: number;
|
|
242
|
+
/** Session cumulative turn count. */
|
|
243
|
+
turns: number;
|
|
244
|
+
}
|
|
245
|
+
interface CompactionEndPayload {
|
|
246
|
+
type: "compaction_end";
|
|
247
|
+
reason: CompactionReason;
|
|
248
|
+
mode: CompactionMode;
|
|
249
|
+
/** Compaction result; non-`completed` means compaction was abandoned and the original context was kept. */
|
|
250
|
+
status: StopReason;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Subagent pointer event: when the parent Session spawns a
|
|
254
|
+
* **direct** child session, `context_engine` writes this to the parent Trace (not streamed),
|
|
255
|
+
* recording only the child session's Session id — the child session's other details live in its
|
|
256
|
+
* own Trace's `session_meta`. When the session is reopened, the server uses this to recursively
|
|
257
|
+
* expand the child Trace and reconstruct the `origin` chain; a grandchild session's pointer is
|
|
258
|
+
* recorded by the child Trace itself.
|
|
259
|
+
*/
|
|
260
|
+
interface SubagentPayload {
|
|
261
|
+
type: "subagent";
|
|
262
|
+
/** The direct child session's Session id. */
|
|
263
|
+
session_id: string;
|
|
264
|
+
}
|
|
265
|
+
/** Complete model_msg payload (written to Trace and exposed externally). */
|
|
266
|
+
type CompleteModelPayload = TextPayload | ImageUrlPayload | InlineDataPayload | ThinkingPayload | InlineThinkingPayload | ToolCallPayload | ToolCallOutputPayload;
|
|
267
|
+
/** Streaming model_msg payload. */
|
|
268
|
+
type PartialModelPayload = PartialTextPayload | PartialThinkingPayload | PartialToolCallPayload | PartialToolCallOutputPayload;
|
|
269
|
+
type ModelPayload = CompleteModelPayload | PartialModelPayload;
|
|
270
|
+
type EventPayload = ApprovalDecisionPayload | AbortPayload | RequestBeginPayload | RequestEndPayload | TokenUsagePayload | CompactionBeginPayload | CompactionEndPayload | SubagentPayload;
|
|
271
|
+
type OmniPayload = SessionMetaPayload | ModelPayload | EventPayload;
|
|
272
|
+
/** The unified message envelope. */
|
|
273
|
+
interface OmniMessage<P extends OmniPayload = OmniPayload> {
|
|
274
|
+
/** ISO 8601 UTC timestamp. */
|
|
275
|
+
timestamp: string;
|
|
276
|
+
type: OmniMessageType;
|
|
277
|
+
payload: P;
|
|
278
|
+
/** Nested-origin marker: the chain of child Session ids ordered outer-to-inner; absent = from the main Session (see MessageOrigin). */
|
|
279
|
+
origin?: MessageOrigin[];
|
|
280
|
+
}
|
|
281
|
+
type SessionMetaMessage = OmniMessage<SessionMetaPayload>;
|
|
282
|
+
type ModelMessage = OmniMessage<ModelPayload>;
|
|
283
|
+
type EventMessage = OmniMessage<EventPayload>;
|
|
284
|
+
type CompleteModelMessage = OmniMessage<CompleteModelPayload>;
|
|
285
|
+
type PartialModelMessage = OmniMessage<PartialModelPayload>;
|
|
286
|
+
declare function isPartialPayload(p: OmniPayload): p is PartialModelPayload;
|
|
287
|
+
declare function isModelMessage(msg: OmniMessage): msg is ModelMessage;
|
|
288
|
+
declare function isEventMessage(msg: OmniMessage): msg is EventMessage;
|
|
289
|
+
declare function isSessionMeta(msg: OmniMessage): msg is SessionMetaMessage;
|
|
290
|
+
/** A complete model_msg (not partial_*), i.e. a message that can be written to Trace. */
|
|
291
|
+
declare function isCompleteModelMessage(msg: OmniMessage): msg is CompleteModelMessage;
|
|
292
|
+
|
|
293
|
+
export { type ApprovalDecision as A, type SubagentPayload as B, type CompactionMode as C, type TextPayload as D, type EventMessage as E, type ThinkingPayload as F, type TokenUsagePayload as G, type ToolCallOutputPayload as H, type ImageUrlPayload as I, isCompleteModelMessage as J, isEventMessage as K, isModelMessage as L, type MessageOrigin as M, isPartialPayload as N, type OmniMessage as O, type PartialModelMessage as P, isSessionMeta as Q, type RequestBeginPayload as R, type StopReason as S, type ToolDefinition as T, type ToolCallPayload as a, type TokenCounts as b, type CompleteModelMessage as c, type SessionMetaMessage as d, type SessionMetaPayload as e, type AbortPayload as f, type ApprovalDecisionPayload as g, type CompactionBeginPayload as h, type CompactionEndPayload as i, type CompactionReason as j, type CompleteModelPayload as k, type EventPayload as l, type InlineDataPayload as m, type InlineThinkingPayload as n, type ModelMessage as o, type ModelPayload as p, type OmniMessageType as q, type OmniPayload as r, type PartialModelPayload as s, type PartialTextPayload as t, type PartialThinkingPayload as u, type PartialToolCallOutputPayload as v, type PartialToolCallPayload as w, type RequestEndPayload as x, type Role as y, type StreamEventType as z };
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prismshadow/penguin-core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "PenguinHarness core SDK: context_engine, OmniMessage protocol, LLM/Environment interfaces.",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Prism-Shadow/penguin-harness.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./omnimessage": {
|
|
18
|
+
"types": "./dist/omnimessage/index.d.ts",
|
|
19
|
+
"import": "./dist/omnimessage/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./interfaces": {
|
|
22
|
+
"types": "./dist/interfaces.d.ts",
|
|
23
|
+
"import": "./dist/interfaces.js"
|
|
24
|
+
},
|
|
25
|
+
"./model-catalog": {
|
|
26
|
+
"types": "./dist/state/model-catalog.d.ts",
|
|
27
|
+
"import": "./dist/state/model-catalog.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"main": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@prismshadow/agenthub": "^0.3.3",
|
|
34
|
+
"smol-toml": "^1.3.0",
|
|
35
|
+
"yaml": "^2.5.0",
|
|
36
|
+
"@prismshadow/penguin-skills": "0.0.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^24.0.0",
|
|
40
|
+
"dotenv": "^17.0.0",
|
|
41
|
+
"tsup": "^8.3.0",
|
|
42
|
+
"typescript": "^5.6.0",
|
|
43
|
+
"vitest": "^2.1.0"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
54
|
+
"test": "vitest run --passWithNoTests",
|
|
55
|
+
"test:e2e": "PENGUIN_E2E=1 vitest run test/llm.e2e.test.ts",
|
|
56
|
+
"build": "tsup"
|
|
57
|
+
}
|
|
58
|
+
}
|