summaryrefslogtreecommitdiff
path: root/libpanto/src/public.zig
diff options
context:
space:
mode:
Diffstat (limited to 'libpanto/src/public.zig')
-rw-r--r--libpanto/src/public.zig93
1 files changed, 64 insertions, 29 deletions
diff --git a/libpanto/src/public.zig b/libpanto/src/public.zig
index 951bd3a..56a0676 100644
--- a/libpanto/src/public.zig
+++ b/libpanto/src/public.zig
@@ -64,7 +64,7 @@ pub const RetryConfig = config_mod.RetryConfig;
pub const WireIdentity = config_mod.WireIdentity;
// ===========================================================================
-// Conversation construction (data, aliased — Job 2)
+// Conversation construction (data, aliased)
// ===========================================================================
pub const ContentBlock = conversation_mod.ContentBlock;
@@ -82,9 +82,17 @@ pub const CompactionSummaryBlock = conversation_mod.CompactionSummaryBlock;
pub const Usage = conversation_mod.Usage;
pub const effectiveSystemBlocks = conversation_mod.effectiveSystemBlocks;
-/// A borrowed handle onto a conversation owned by an `Agent`, or a
-/// standalone-owned conversation built by hand. Pointer-wrapping makes the
-/// "don't move the conversation" invariant structural.
+/// The owned conversation value type. This is what `Session.load` returns
+/// and what `Agent.init` adopts. Build one standalone with `init` for
+/// by-hand construction; once handed to an `Agent` it is owned by the agent.
+/// For *operating on* an agent's live conversation, use the `Conversation`
+/// handle (below) via `Agent.conversation()`.
+pub const ConversationData = conversation_mod.Conversation;
+
+/// A borrowed handle onto a conversation owned by an `Agent`. Pointer-
+/// wrapping makes the "don't move the conversation" invariant structural:
+/// the handle is a cheap copyable view, minted per-call by
+/// `Agent.conversation()`, borrowing state owned by its `Agent`.
pub const Conversation = struct {
inner: *conversation_mod.Conversation,
@@ -113,7 +121,7 @@ pub const Conversation = struct {
};
// ===========================================================================
-// Tools (data + small façade — Job 1)
+// Tools (data + small façade)
// ===========================================================================
pub const Tool = tool_mod.Tool;
@@ -179,6 +187,31 @@ pub const CompactionResult = agent_mod.Agent.CompactionResult;
pub const Agent = struct {
inner: *agent_mod.Agent,
+ /// Construct an agent. The inner is heap-pinned at `init`, so the
+ /// returned `Agent` is a cheap copyable handle ("don't move the Agent"
+ /// stops being a rule anyone can violate). `session` is minted via
+ /// `store.create()` (fresh) or `resolve`/`latest` (resume). When
+ /// `maybe_conversation` is non-null it is adopted (ownership
+ /// transferred) — the resume path hands the value returned by
+ /// `Session.load`.
+ pub fn init(
+ allocator: std.mem.Allocator,
+ io: std.Io,
+ config: *const Config,
+ session: Session,
+ maybe_conversation: ?ConversationData,
+ ) !Agent {
+ const inner = try allocator.create(agent_mod.Agent);
+ inner.* = agent_mod.Agent.init(allocator, io, config, session, maybe_conversation);
+ return .{ .inner = inner };
+ }
+
+ pub fn deinit(self: Agent) void {
+ const allocator = self.inner.allocator;
+ self.inner.deinit();
+ allocator.destroy(self.inner);
+ }
+
pub fn registerTool(self: Agent, t: Tool) !void {
return self.inner.registerTool(t);
}
@@ -191,18 +224,41 @@ pub const Agent = struct {
pub fn run(self: Agent, message: UserMessage) !Stream {
return .{ .inner = try self.inner.run(.{ .text = message.text }) };
}
+
+ /// Append a system message to the conversation and persist it (the
+ /// `.append` `SystemMode`: it adds to the effective prompt).
+ pub fn addSystemMessage(self: Agent, text: []const u8) !void {
+ return self.inner.addSystemMessage(text, .append);
+ }
+ /// Replace the effective system prompt and persist it (the `.replace`
+ /// `SystemMode`: it discards all prior system text). On replay the log
+ /// reconstructs the same effective prompt.
+ pub fn setSystemPrompt(self: Agent, text: []const u8) !void {
+ return self.inner.addSystemMessage(text, .replace);
+ }
+
/// Compact and persist (the explicit `/compact` entry point).
- pub fn compact(self: Agent, system_prompt: []const u8, extra: ?[]const u8) !CompactionResult {
- return self.inner.compactAndPersist(system_prompt, extra);
+ /// `override_system_prompt` falls back to
+ /// `config.compaction.compaction_prompt` when null. `extra` is appended
+ /// to the compaction prompt for this run (the `/compact $ARGUMENTS`
+ /// path).
+ pub fn compact(self: Agent, override_system_prompt: ?[]const u8, extra: ?[]const u8) !CompactionResult {
+ return self.inner.compactAndPersist(override_system_prompt, extra);
}
+
/// A borrowed handle onto the agent's live conversation.
pub fn conversation(self: Agent) Conversation {
return .{ .inner = &self.inner.conversation };
}
+
+ /// The id of the session this agent appends to.
+ pub fn sessionId(self: Agent) []const u8 {
+ return self.inner.session.info.id;
+ }
};
// ===========================================================================
-// Pricing (data, aliased — Job 1)
+// Pricing (data, aliased)
// ===========================================================================
pub const Pricing = pricing_mod.Pricing;
@@ -220,27 +276,6 @@ pub const NullStore = null_store_mod.NullStore;
pub const FileSystemJSONLStore = fs_store_mod.FileSystemJSONLStore;
// ===========================================================================
-// Deep-embedder escape hatches.
-//
-// The `panto` CLI is a *deep* embedder: it drives the agent loop at a level
-// the curated `Agent`/`Conversation` façades deliberately do not expose
-// (system-prompt seeding through the agent, `compaction_system_prompt`, the
-// injectable `open_stream_fn` test seam, direct `conversation` field access,
-// raw standalone `Conversation` values, `compactAndPersist`, etc.). Rather
-// than inflate the curated surface to cover one in-tree embedder, these two
-// internal namespaces stay reachable for embedders who opt into the
-// unstable internal API. A C-ABI or language binding should use the curated
-// surface above, not these.
-//
-// FLAGGED (see docs/libpanto-cleanup.md): exposing `agent`/`conversation`
-// internals is a known gap between the curated façade and what a deep
-// embedder needs. Revisit if/when the façade grows the missing operations
-// (e.g. `Conversation` standalone construction, agent system-prompt and
-// compaction-prompt plumbing).
-pub const agent = agent_mod;
-pub const conversation = conversation_mod;
-
-// ===========================================================================
// Tests
// ===========================================================================