NeoGraph 0.16.0
A C++20 Graph Agent Engine Library — LangGraph for C++
Loading...
Searching...
No Matches
runtime_context.h
1#pragma once
2
3#include <neograph/api.h>
4#include <neograph/json.h>
5#include <neograph/types.h>
6#include <core/native_archive.h>
7
8#include <cstdint>
9#include <map>
10#include <memory>
11#include <optional>
12#include <stdexcept>
13#include <string>
14#include <string_view>
15#include <vector>
16
17namespace neograph {
18
19enum class RuntimeTrustClass : std::uint8_t {
20 UntrustedInput,
21 ModelOutput,
22 ToolOutput,
23 Developer,
24 HostPolicy,
25};
26
27enum class ContextArtifactKind : std::uint8_t {
28 RawHistory,
29 DerivedContext,
30 RequiredSkill,
31 HookOutput,
32 HardConstraint,
34 UntrustedSupplemental,
35};
36
37enum class ContextPlacement : std::uint8_t {
38 BeforeLatestUser,
39 AfterLatestUser,
41 AfterHistory,
43 BeforeHistory,
44};
45
46enum class RuntimeGuaranteeProfile : std::uint8_t {
47 Legacy,
48 Recorded,
49 Strict,
50};
51
56enum class StabilityClass : std::uint8_t {
58 Stable,
60 Slow,
62 Volatile,
63};
64
66enum class AnchorMode : std::uint8_t {
68 Replace,
70 KeepInPlace,
71};
72
74enum class ContextBreakReason : std::uint8_t {
75 Compaction,
76 StableChange,
77 LayoutChange,
78 AnchorDrop,
79 OrderChange,
80 Explicit,
81};
82
93enum class AssemblyLayout : std::uint8_t {
94 Legacy,
95 StableFirst,
96};
97
99enum class ClassSource : std::uint8_t {
101 Declared,
103 Derived,
104};
105
107enum class ContextPrefixClaim : std::uint8_t {
109 Extends,
111 Breaks,
112};
113
114NEOGRAPH_API std::string_view to_string(RuntimeTrustClass value) noexcept;
115NEOGRAPH_API std::string_view to_string(ContextArtifactKind value) noexcept;
116NEOGRAPH_API std::string_view to_string(ContextPlacement value) noexcept;
117NEOGRAPH_API std::string_view to_string(RuntimeGuaranteeProfile value) noexcept;
118NEOGRAPH_API std::string_view to_string(StabilityClass value) noexcept;
119NEOGRAPH_API std::string_view to_string(AnchorMode value) noexcept;
120NEOGRAPH_API std::string_view to_string(ContextBreakReason value) noexcept;
121NEOGRAPH_API std::string_view to_string(ContextPrefixClaim value) noexcept;
122NEOGRAPH_API std::string_view to_string(AssemblyLayout value) noexcept;
123NEOGRAPH_API std::string_view to_string(ClassSource value) noexcept;
124NEOGRAPH_API RuntimeTrustClass runtime_trust_class_from_string(std::string_view value);
125NEOGRAPH_API ContextArtifactKind context_artifact_kind_from_string(std::string_view value);
126NEOGRAPH_API ContextPlacement context_placement_from_string(std::string_view value);
127NEOGRAPH_API RuntimeGuaranteeProfile runtime_guarantee_profile_from_string(
128 std::string_view value);
129NEOGRAPH_API StabilityClass stability_class_from_string(std::string_view value);
130NEOGRAPH_API AnchorMode anchor_mode_from_string(std::string_view value);
131NEOGRAPH_API ContextBreakReason context_break_reason_from_string(std::string_view value);
132NEOGRAPH_API ContextPrefixClaim context_prefix_claim_from_string(std::string_view value);
133NEOGRAPH_API AssemblyLayout assembly_layout_from_string(std::string_view value);
134NEOGRAPH_API ClassSource class_source_from_string(std::string_view value);
135
137inline constexpr std::string_view COMPACTION_PRODUCER_ID = "neograph-compaction.v1";
138
140NEOGRAPH_API bool context_artifact_kind_renders_as_system(ContextArtifactKind kind) noexcept;
141
147inline constexpr std::uint32_t STABILITY_DERIVATION_RULE_VERSION = 1;
148
156NEOGRAPH_API StabilityClass derive_stability_class(
157 ContextArtifactKind kind, std::string_view producer_id) noexcept;
158
160enum class ContextStabilityRefusal : std::uint8_t {
162 VolatileSystemArtifact,
164 PredecessorUnavailable,
166 PredecessorOrderUnknown,
168 ArtifactsMismatch,
170 RawWindowMoved,
172 RawWindowNotGrown,
174 StablePrefixChanged,
176 AnchorDropped,
178 AnchorOutOfRange,
180 LayoutChangeUndeclared,
182 StableOutsideHistoryHead,
184 VolatileOutsideTail,
186 TierOrderViolated,
188 VolatileSystemText,
190 PrefixBoundaryUnavailable,
192 AmbiguousOrder,
193};
194
195NEOGRAPH_API std::string_view to_string(ContextStabilityRefusal value) noexcept;
196
198class NEOGRAPH_API ContextStabilityError final : public std::invalid_argument {
199public:
200 ContextStabilityError(ContextStabilityRefusal code, const std::string& message);
201 ContextStabilityRefusal code() const noexcept;
202
203private:
204 ContextStabilityRefusal code_;
205};
206
207struct RuntimeHistoryRecordData {
208 std::string feed_id;
209 std::uint64_t sequence = 0;
210 std::string message_id;
211 RuntimeTrustClass trust = RuntimeTrustClass::UntrustedInput;
212 sp::Message message;
213 std::optional<json> source_payload;
214 std::optional<std::string> source_media_type;
215 std::optional<std::string> predecessor_id;
216};
217
219class NEOGRAPH_API RuntimeHistoryRecord final {
220public:
221 // 3 since SchemaProvider interface 7 (provider-message/v3). A version 2 record is read
222 // with its bytes and id as stored, so a feed's predecessor chain stays intact.
223 static constexpr std::uint32_t STORAGE_SCHEMA_VERSION = 3;
224 static constexpr std::uint32_t LEGACY_STORAGE_SCHEMA_VERSION = 2;
225
226 static RuntimeHistoryRecord create(RuntimeHistoryRecordData data);
227 static RuntimeHistoryRecord parse(
228 std::string_view stored_bytes,
229 const std::shared_ptr<sp::NativeArchive>& archive = {},
230 std::string_view owner_id = {});
231
232 const std::string& feed_id() const noexcept;
233 std::uint64_t sequence() const noexcept;
234 const std::string& message_id() const noexcept;
235 RuntimeTrustClass trust() const noexcept;
236 const sp::Message& message() const noexcept;
237 std::optional<json> source_payload() const;
238 const std::optional<std::string>& source_media_type() const noexcept;
239 const std::optional<std::string>& predecessor_id() const noexcept;
240 const std::string& id() const noexcept;
241 std::string serialize_canonical() const;
244 const std::shared_ptr<sp::NativeArchive>& archive,
245 std::string_view owner_id) const;
246
247private:
248 struct Impl;
249 explicit RuntimeHistoryRecord(std::shared_ptr<const Impl> impl);
250 std::shared_ptr<const Impl> impl_;
251};
252
253struct ContextArtifactData {
254 ContextArtifactKind kind = ContextArtifactKind::DerivedContext;
255 std::string producer_id;
256 std::string source_digest;
257 std::string source_feed_id;
258 std::uint64_t covers_from_sequence = 0;
259 std::uint64_t covers_through_sequence = 0;
260 std::string media_type;
261 ContextPlacement placement = ContextPlacement::BeforeLatestUser;
262 std::int32_t priority = 0;
263 bool required = false;
264 json content;
270 std::optional<StabilityClass> stability_class;
272 std::optional<AnchorMode> anchor_mode;
273};
274
276class NEOGRAPH_API ContextArtifact final {
277public:
278 // 2 only for an artifact that sets stability_class or anchor_mode; every other
279 // artifact keeps version 1 and the identity it always had.
280 static constexpr std::uint32_t STORAGE_SCHEMA_VERSION = 2;
281 static constexpr std::uint32_t LEGACY_STORAGE_SCHEMA_VERSION = 1;
282
283 static ContextArtifact create(ContextArtifactData data);
284 static ContextArtifact parse(std::string_view stored_bytes);
285
286 ContextArtifactKind kind() const noexcept;
287 const std::string& producer_id() const noexcept;
288 const std::string& source_digest() const noexcept;
289 const std::string& source_feed_id() const noexcept;
290 std::uint64_t covers_from_sequence() const noexcept;
291 std::uint64_t covers_through_sequence() const noexcept;
292 const std::string& media_type() const noexcept;
293 ContextPlacement placement() const noexcept;
294 std::int32_t priority() const noexcept;
295 bool required() const noexcept;
296 json content() const;
297 const std::string& content_digest() const noexcept;
299 StabilityClass stability_class() const noexcept;
300 const std::optional<StabilityClass>& declared_stability_class() const noexcept;
302 AnchorMode anchor_mode() const noexcept;
303 const std::optional<AnchorMode>& declared_anchor_mode() const noexcept;
304 const std::string& id() const noexcept;
305 std::string serialize_canonical() const;
306
307private:
308 struct Impl;
309 explicit ContextArtifact(std::shared_ptr<const Impl> impl);
310 std::shared_ptr<const Impl> impl_;
311};
312
313struct ContextEpochData {
314 std::string run_id;
315 std::uint64_t sequence = 0;
316 std::optional<std::string> predecessor_id;
317 std::string feed_id;
318 std::uint64_t raw_from_sequence = 0;
319 std::uint64_t raw_through_sequence = 0;
320 std::string raw_window_digest;
321 std::vector<std::string> artifact_ids;
322 RuntimeGuaranteeProfile guarantee_profile = RuntimeGuaranteeProfile::Recorded;
329 std::optional<std::vector<std::string>> ordered_artifact_ids;
336 std::optional<ContextPrefixClaim> prefix_claim;
337 std::optional<ContextBreakReason> break_reason;
343 AssemblyLayout assembly_layout = AssemblyLayout::Legacy;
344};
345
347class NEOGRAPH_API ContextEpoch final {
348public:
349 // 2 only for an epoch that sets ordered_artifact_ids, prefix_claim, break_reason
350 // or the StableFirst layout; every other epoch keeps version 1 and the identity it had.
351 static constexpr std::uint32_t STORAGE_SCHEMA_VERSION = 2;
352 static constexpr std::uint32_t LEGACY_STORAGE_SCHEMA_VERSION = 1;
353
354 static ContextEpoch create(ContextEpochData data);
355 static ContextEpoch parse(std::string_view stored_bytes);
356
357 const std::string& run_id() const noexcept;
358 std::uint64_t sequence() const noexcept;
359 const std::optional<std::string>& predecessor_id() const noexcept;
360 const std::string& feed_id() const noexcept;
361 std::uint64_t raw_from_sequence() const noexcept;
362 std::uint64_t raw_through_sequence() const noexcept;
363 const std::string& raw_window_digest() const noexcept;
364 const std::vector<std::string>& artifact_ids() const noexcept;
365 RuntimeGuaranteeProfile guarantee_profile() const noexcept;
366 const std::optional<std::vector<std::string>>& ordered_artifact_ids() const noexcept;
367 const std::optional<ContextPrefixClaim>& prefix_claim() const noexcept;
368 const std::optional<ContextBreakReason>& break_reason() const noexcept;
369 AssemblyLayout assembly_layout() const noexcept;
370 const std::string& id() const noexcept;
371 std::string serialize_canonical() const;
372
373private:
374 struct Impl;
375 explicit ContextEpoch(std::shared_ptr<const Impl> impl);
376 std::shared_ptr<const Impl> impl_;
377};
378
389 std::uint64_t message_index = 0;
390 std::uint64_t part_index = 0;
391 auto operator<=>(const ContextPrefixBoundary&) const = default;
392};
393
394struct ContextAssemblyReceiptData {
395 std::string context_epoch_id;
396 std::string normalized_request_digest;
397 std::string message_window_digest;
398 std::vector<std::string> artifact_ids;
399 std::vector<std::string> required_skill_artifact_ids;
400 std::uint64_t raw_from_sequence = 0;
401 std::uint64_t raw_through_sequence = 0;
406 std::uint64_t estimated_input_tokens = 0;
408 std::uint64_t mandatory_input_tokens = 0;
409
410 // Version 2. Each field is part of the identity only when set, and a receipt
411 // that sets none is a version 1 receipt. A version 1 receipt knows none of
412 // them: its prefix is unknown, not empty.
414 std::optional<std::vector<std::string>> assembled_artifact_ids;
419 std::optional<std::map<std::string, StabilityClass>> artifact_classes;
421 std::optional<std::map<std::string, ClassSource>> class_sources;
427 std::optional<std::uint32_t> class_rule_version;
429 std::optional<std::string> encoder_family;
434 std::optional<ContextPrefixBoundary> stable_boundary;
436 std::optional<ContextPrefixBoundary> prefix_boundary;
441 std::optional<std::string> prefix_digest;
443 std::optional<std::string> tools_digest;
445 std::optional<ContextBreakReason> break_reason;
446};
447
449class NEOGRAPH_API ContextAssemblyReceipt final {
450public:
451 static constexpr std::uint32_t STORAGE_SCHEMA_VERSION = 2;
452 static constexpr std::uint32_t LEGACY_STORAGE_SCHEMA_VERSION = 1;
453
454 static ContextAssemblyReceipt create(
455 ContextAssemblyReceiptData data,
456 const ContextEpoch& epoch,
457 const std::vector<ContextArtifact>& artifacts);
458 static ContextAssemblyReceipt parse(
459 std::string_view stored_bytes,
460 const ContextEpoch& epoch,
461 const std::vector<ContextArtifact>& artifacts);
462
463 const std::string& context_epoch_id() const noexcept;
464 const std::string& normalized_request_digest() const noexcept;
465 const std::string& message_window_digest() const noexcept;
466 const std::vector<std::string>& artifact_ids() const noexcept;
467 const std::vector<std::string>& required_skill_artifact_ids() const noexcept;
468 std::uint64_t raw_from_sequence() const noexcept;
469 std::uint64_t raw_through_sequence() const noexcept;
470 std::uint64_t estimated_input_tokens() const noexcept;
471 std::uint64_t mandatory_input_tokens() const noexcept;
472 const std::optional<std::vector<std::string>>& assembled_artifact_ids() const noexcept;
473 const std::optional<std::map<std::string, StabilityClass>>& artifact_classes() const noexcept;
474 const std::optional<std::map<std::string, ClassSource>>& class_sources() const noexcept;
475 const std::optional<std::uint32_t>& class_rule_version() const noexcept;
476 const std::optional<std::string>& encoder_family() const noexcept;
477 const std::optional<ContextPrefixBoundary>& stable_boundary() const noexcept;
478 const std::optional<ContextPrefixBoundary>& prefix_boundary() const noexcept;
479 const std::optional<std::string>& prefix_digest() const noexcept;
480 const std::optional<std::string>& tools_digest() const noexcept;
481 const std::optional<ContextBreakReason>& break_reason() const noexcept;
482 const std::string& id() const noexcept;
483 std::string serialize_canonical() const;
484
485private:
486 struct Impl;
487 explicit ContextAssemblyReceipt(std::shared_ptr<const Impl> impl);
488 static ContextAssemblyReceipt create_structural(ContextAssemblyReceiptData data);
489 std::shared_ptr<const Impl> impl_;
490};
491
493NEOGRAPH_API void validate_context_assembly_receipt(
494 const ContextAssemblyReceipt& receipt,
495 const ContextEpoch& epoch,
496 const std::vector<ContextArtifact>& artifacts);
497
530 ContextArtifact artifact;
531 std::string order_key;
532};
533
541NEOGRAPH_API std::vector<std::string> order_context_artifacts(
542 const std::vector<ContextArtifactOrderEntry>& entries);
543
550NEOGRAPH_API void validate_context_layout(
551 const ContextEpoch& epoch, const std::vector<ContextArtifact>& artifacts);
552
553NEOGRAPH_API void verify_context_epoch_claim(
554 const ContextEpoch& epoch,
555 const std::vector<ContextArtifact>& artifacts,
556 const ContextEpoch* predecessor,
557 const std::vector<ContextArtifact>& predecessor_artifacts);
558
559} // namespace neograph
NEOGRAPH_API export/import macro for shared-library builds.
Immutable context material.
StabilityClass stability_class() const noexcept
The declared class, or the derived one when none is declared.
Evidence that one normalized provider request was assembled from one exact epoch.
Immutable selection of exact RAW and derived material for provider turns.
A stability rule or an epoch claim was refused.
One immutable, content-addressed line in the authoritative RAW history feed.
std::string serialize_canonical(const std::shared_ptr< sp::NativeArchive > &archive, std::string_view owner_id) const
Persist authentic seals under the host's owner-scoped archive.
Thin C++ RAII wrapper around yyjson with nlohmann-compatible API.
@ Legacy
Existing parent-thread/step/task namespace (compatibility default).
@ Replace
Rebuild the conversation as [system messages, first user message, the rejected plan,...
Check what an epoch declares about the request prefix of its predecessor.
Where a prefix of an encoded request body ends, as the first message and part that is not in it.