@poncho-ai/harness 0.34.1 → 0.35.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/.turbo/turbo-build.log +11 -11
- package/.turbo/turbo-lint.log +6 -0
- package/.turbo/turbo-test.log +11931 -0
- package/CHANGELOG.md +19 -0
- package/dist/index.d.ts +77 -9
- package/dist/index.js +610 -105
- package/package.json +3 -2
- package/src/config.ts +6 -0
- package/src/harness.ts +61 -5
- package/src/index.ts +2 -0
- package/src/mcp.ts +140 -9
- package/src/memory.ts +33 -13
- package/src/reminder-store.ts +6 -0
- package/src/reminder-tools.ts +15 -2
- package/src/secrets-store.ts +252 -0
- package/src/state.ts +41 -19
- package/src/subagent-manager.ts +1 -0
- package/src/subagent-tools.ts +1 -0
- package/src/telemetry.ts +5 -1
- package/src/tenant-token.ts +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.35.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`83d3c5f`](https://github.com/cesr/poncho-ai/commit/83d3c5f841fe84965d1f9fec6dfc5d8832e4489a) Thanks [@cesr](https://github.com/cesr)! - feat: add multi-tenancy with JWT-based tenant scoping
|
|
8
|
+
|
|
9
|
+
Deploy one agent, serve many tenants with fully isolated conversations, memory, reminders, and secrets. Tenancy activates automatically when a valid JWT is received — no config changes needed.
|
|
10
|
+
- **Auth**: `createTenantToken()` in client SDK, `poncho auth create-token` CLI, or any HS256 JWT library.
|
|
11
|
+
- **Isolation**: conversations, memory, reminders, and todos scoped per tenant.
|
|
12
|
+
- **Per-tenant secrets**: encrypted secret overrides for MCP auth tokens, manageable via CLI (`poncho secrets`), API, and web UI settings panel.
|
|
13
|
+
- **MCP**: per-tenant token resolution with deferred discovery for servers without a default env var.
|
|
14
|
+
- **Web UI**: `?token=` tenant access, settings cog for secret management, dark mode support.
|
|
15
|
+
- **Backward compatible**: existing single-user deployments work unchanged.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`83d3c5f`](https://github.com/cesr/poncho-ai/commit/83d3c5f841fe84965d1f9fec6dfc5d8832e4489a)]:
|
|
20
|
+
- @poncho-ai/sdk@1.8.0
|
|
21
|
+
|
|
3
22
|
## 0.34.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel } from 'ai';
|
|
2
2
|
import * as _poncho_ai_sdk from '@poncho-ai/sdk';
|
|
3
|
-
import { Message, ToolDefinition, RunResult, AgentFailure,
|
|
3
|
+
import { Message, ToolContext, ToolDefinition, RunResult, AgentFailure, RunInput, AgentEvent, JsonSchema } from '@poncho-ai/sdk';
|
|
4
4
|
export { ToolDefinition, defineTool } from '@poncho-ai/sdk';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
@@ -206,10 +206,16 @@ interface Conversation {
|
|
|
206
206
|
updatedAt: number;
|
|
207
207
|
}
|
|
208
208
|
interface ConversationStore {
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
/**
|
|
210
|
+
* List conversations. tenantId semantics:
|
|
211
|
+
* undefined = no filter (builder/admin sees everything)
|
|
212
|
+
* null = legacy single-user only
|
|
213
|
+
* string = tenant-scoped
|
|
214
|
+
*/
|
|
215
|
+
list(ownerId?: string, tenantId?: string | null): Promise<Conversation[]>;
|
|
216
|
+
listSummaries(ownerId?: string, tenantId?: string | null): Promise<ConversationSummary[]>;
|
|
211
217
|
get(conversationId: string): Promise<Conversation | undefined>;
|
|
212
|
-
create(ownerId?: string, title?: string): Promise<Conversation>;
|
|
218
|
+
create(ownerId?: string, title?: string, tenantId?: string | null): Promise<Conversation>;
|
|
213
219
|
update(conversation: Conversation): Promise<void>;
|
|
214
220
|
rename(conversationId: string, title: string): Promise<Conversation | undefined>;
|
|
215
221
|
delete(conversationId: string): Promise<boolean>;
|
|
@@ -245,10 +251,10 @@ declare class InMemoryConversationStore implements ConversationStore {
|
|
|
245
251
|
constructor(ttlSeconds?: number);
|
|
246
252
|
private isExpired;
|
|
247
253
|
private purgeExpired;
|
|
248
|
-
list(ownerId?: string): Promise<Conversation[]>;
|
|
249
|
-
listSummaries(ownerId?: string): Promise<ConversationSummary[]>;
|
|
254
|
+
list(ownerId?: string, tenantId?: string | null): Promise<Conversation[]>;
|
|
255
|
+
listSummaries(ownerId?: string, tenantId?: string | null): Promise<ConversationSummary[]>;
|
|
250
256
|
get(conversationId: string): Promise<Conversation | undefined>;
|
|
251
|
-
create(ownerId?: string, title?: string): Promise<Conversation>;
|
|
257
|
+
create(ownerId?: string, title?: string, tenantId?: string | null): Promise<Conversation>;
|
|
252
258
|
update(conversation: Conversation): Promise<void>;
|
|
253
259
|
rename(conversationId: string, title: string): Promise<Conversation | undefined>;
|
|
254
260
|
delete(conversationId: string): Promise<boolean>;
|
|
@@ -261,6 +267,7 @@ type ConversationSummary = {
|
|
|
261
267
|
updatedAt: number;
|
|
262
268
|
createdAt?: number;
|
|
263
269
|
ownerId: string;
|
|
270
|
+
tenantId?: string | null;
|
|
264
271
|
parentConversationId?: string;
|
|
265
272
|
messageCount?: number;
|
|
266
273
|
hasPendingApprovals?: boolean;
|
|
@@ -301,8 +308,9 @@ interface MemoryStore {
|
|
|
301
308
|
}
|
|
302
309
|
declare const createMemoryStore: (agentId: string, config?: MemoryConfig, options?: {
|
|
303
310
|
workingDir?: string;
|
|
311
|
+
tenantId?: string;
|
|
304
312
|
}) => MemoryStore;
|
|
305
|
-
declare const createMemoryTools: (store: MemoryStore, options?: {
|
|
313
|
+
declare const createMemoryTools: (store: MemoryStore | ((context: ToolContext) => MemoryStore), options?: {
|
|
306
314
|
maxRecallConversations?: number;
|
|
307
315
|
}) => ToolDefinition[];
|
|
308
316
|
|
|
@@ -328,10 +336,24 @@ declare class LocalMcpBridge {
|
|
|
328
336
|
private readonly toolCatalog;
|
|
329
337
|
private readonly unavailableServers;
|
|
330
338
|
private readonly authFailedServers;
|
|
339
|
+
private envResolver?;
|
|
340
|
+
/**
|
|
341
|
+
* Set a resolver for per-tenant env vars (e.g. MCP auth tokens).
|
|
342
|
+
* Called by the harness after creating the secrets store.
|
|
343
|
+
*/
|
|
344
|
+
setEnvResolver(resolver: (tenantId: string | undefined, envName: string) => Promise<string | undefined>): void;
|
|
331
345
|
constructor(config: McpConfig | undefined);
|
|
332
346
|
private getServerName;
|
|
333
347
|
private log;
|
|
348
|
+
/** Set of servers where discovery was deferred (no default token, has env resolver). */
|
|
349
|
+
private readonly deferredDiscoveryServers;
|
|
334
350
|
discoverTools(): Promise<void>;
|
|
351
|
+
/**
|
|
352
|
+
* Run deferred discovery and return ToolDefinitions for all newly discovered tools.
|
|
353
|
+
* Call this during run() so the tools are available to the model immediately.
|
|
354
|
+
*/
|
|
355
|
+
discoverAndLoadDeferred(tenantId: string): Promise<ToolDefinition[]>;
|
|
356
|
+
private tryDeferredDiscovery;
|
|
335
357
|
startLocalServers(): Promise<void>;
|
|
336
358
|
stopLocalServers(): Promise<void>;
|
|
337
359
|
listServers(): RemoteMcpServerConfig[];
|
|
@@ -344,6 +366,11 @@ declare class LocalMcpBridge {
|
|
|
344
366
|
toSerializableConfig(): McpConfig;
|
|
345
367
|
getLocalServers(): never[];
|
|
346
368
|
listDiscoveredTools(serverName?: string): string[];
|
|
369
|
+
hasDeferredServers(): boolean;
|
|
370
|
+
/**
|
|
371
|
+
* Return ToolDefinitions for catalog tools not already registered in the dispatcher.
|
|
372
|
+
*/
|
|
373
|
+
getUnregisteredTools(registeredNames: Set<string>): ToolDefinition[];
|
|
347
374
|
loadTools(requestedPatterns: string[]): Promise<ToolDefinition[]>;
|
|
348
375
|
private toToolDefinitions;
|
|
349
376
|
}
|
|
@@ -467,6 +494,12 @@ interface PonchoConfig extends McpConfig {
|
|
|
467
494
|
/** Cron expression controlling how often the reminder poll runs (local and serverless). Default: every 10 minutes. */
|
|
468
495
|
pollSchedule?: string;
|
|
469
496
|
};
|
|
497
|
+
/**
|
|
498
|
+
* Declare env var names that tenants can self-manage via the web UI or API.
|
|
499
|
+
* Key = env var name, value = human-readable label shown in the settings panel.
|
|
500
|
+
* Example: { LINEAR_API_KEY: "Linear API Key", STRIPE_KEY: "Stripe Secret Key" }
|
|
501
|
+
*/
|
|
502
|
+
tenantSecrets?: Record<string, string>;
|
|
470
503
|
/** Set to `false` to disable the built-in web UI (headless / API-only mode). */
|
|
471
504
|
webUi?: false;
|
|
472
505
|
/** Enable browser automation tools. Set `true` for defaults, or provide config. */
|
|
@@ -567,6 +600,7 @@ interface Reminder {
|
|
|
567
600
|
createdAt: number;
|
|
568
601
|
conversationId: string;
|
|
569
602
|
ownerId?: string;
|
|
603
|
+
tenantId?: string | null;
|
|
570
604
|
}
|
|
571
605
|
interface ReminderStore {
|
|
572
606
|
list(): Promise<Reminder[]>;
|
|
@@ -576,6 +610,7 @@ interface ReminderStore {
|
|
|
576
610
|
timezone?: string;
|
|
577
611
|
conversationId: string;
|
|
578
612
|
ownerId?: string;
|
|
613
|
+
tenantId?: string | null;
|
|
579
614
|
}): Promise<Reminder>;
|
|
580
615
|
cancel(id: string): Promise<Reminder>;
|
|
581
616
|
delete(id: string): Promise<void>;
|
|
@@ -584,6 +619,20 @@ declare const createReminderStore: (agentId: string, config?: StateConfig, optio
|
|
|
584
619
|
workingDir?: string;
|
|
585
620
|
}) => ReminderStore;
|
|
586
621
|
|
|
622
|
+
interface SecretsStore {
|
|
623
|
+
get(tenantId: string): Promise<Record<string, string>>;
|
|
624
|
+
set(tenantId: string, key: string, value: string): Promise<void>;
|
|
625
|
+
delete(tenantId: string, key: string): Promise<void>;
|
|
626
|
+
list(tenantId: string): Promise<string[]>;
|
|
627
|
+
}
|
|
628
|
+
declare const createSecretsStore: (agentId: string, signingKey: string, config?: StateConfig, options?: {
|
|
629
|
+
workingDir?: string;
|
|
630
|
+
}) => SecretsStore;
|
|
631
|
+
/**
|
|
632
|
+
* Resolve an env var name: check tenant secrets first, then process.env.
|
|
633
|
+
*/
|
|
634
|
+
declare function resolveEnv(secretsStore: SecretsStore | undefined, tenantId: string | null | undefined, envName: string): Promise<string | undefined>;
|
|
635
|
+
|
|
587
636
|
declare const OPENAI_CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
588
637
|
interface OpenAICodexAuthConfig {
|
|
589
638
|
refreshTokenEnv?: string;
|
|
@@ -660,6 +709,7 @@ interface SubagentManager {
|
|
|
660
709
|
task: string;
|
|
661
710
|
parentConversationId: string;
|
|
662
711
|
ownerId: string;
|
|
712
|
+
tenantId?: string | null;
|
|
663
713
|
}): Promise<SubagentSpawnResult>;
|
|
664
714
|
sendMessage(subagentId: string, message: string): Promise<SubagentSpawnResult>;
|
|
665
715
|
stop(subagentId: string): Promise<void>;
|
|
@@ -720,8 +770,11 @@ declare class AgentHarness {
|
|
|
720
770
|
readonly uploadStore?: UploadStore;
|
|
721
771
|
private skillContextWindow;
|
|
722
772
|
private memoryStore?;
|
|
773
|
+
private readonly tenantMemoryStores;
|
|
774
|
+
private memoryConfig?;
|
|
723
775
|
private todoStore?;
|
|
724
776
|
reminderStore?: ReminderStore;
|
|
777
|
+
secretsStore?: SecretsStore;
|
|
725
778
|
private loadedConfig?;
|
|
726
779
|
private loadedSkills;
|
|
727
780
|
private skillFingerprint;
|
|
@@ -759,6 +812,11 @@ declare class AgentHarness {
|
|
|
759
812
|
private truncateHistoricalToolResults;
|
|
760
813
|
private shouldPreserveSkillToolResult;
|
|
761
814
|
getTodos(conversationId: string): Promise<TodoItem[]>;
|
|
815
|
+
/**
|
|
816
|
+
* Get a memory store, optionally scoped to a tenant.
|
|
817
|
+
* Returns the default (agent-wide) store when tenantId is null/undefined.
|
|
818
|
+
*/
|
|
819
|
+
private getMemoryStore;
|
|
762
820
|
private listActiveSkills;
|
|
763
821
|
private getAgentMcpIntent;
|
|
764
822
|
private getAgentScriptIntent;
|
|
@@ -921,6 +979,16 @@ declare class TelemetryEmitter {
|
|
|
921
979
|
private sendOtlp;
|
|
922
980
|
}
|
|
923
981
|
|
|
982
|
+
interface TenantTokenPayload {
|
|
983
|
+
tenantId: string;
|
|
984
|
+
metadata?: Record<string, unknown>;
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Verify a tenant JWT (HS256) signed with the given key.
|
|
988
|
+
* Returns the decoded payload on success, or undefined on any failure.
|
|
989
|
+
*/
|
|
990
|
+
declare function verifyTenantToken(signingKey: string, token: string): Promise<TenantTokenPayload | undefined>;
|
|
991
|
+
|
|
924
992
|
declare const createSubagentTools: (manager: SubagentManager) => ToolDefinition[];
|
|
925
993
|
|
|
926
|
-
export { type AgentFrontmatter, AgentHarness, type AgentIdentity, type AgentLimitsConfig, type AgentModelConfig, type ArchivedToolResult$1 as ArchivedToolResult, type BuiltInToolToggles, type CompactMessagesOptions, type CompactResult, type CompactionConfig, type Conversation, type ConversationState, type ConversationStore, type ConversationSummary, type CronJobConfig, type HarnessOptions, type HarnessRunOutput, InMemoryConversationStore, InMemoryStateStore, LocalMcpBridge, LocalUploadStore, type MainMemory, type McpConfig, type MemoryConfig, type MemoryStore, type MessagingChannelConfig, type ModelProviderFactory, OPENAI_CODEX_CLIENT_ID, type OpenAICodexAuthConfig, type OpenAICodexDeviceAuthRequest, type OpenAICodexSession, type OtlpConfig, type OtlpOption, PONCHO_UPLOAD_SCHEME, type ParsedAgent, type PendingSubagentResult, type PonchoConfig, type ProviderConfig, type Reminder, type ReminderStatus, type ReminderStore, type RemoteMcpServerConfig, type RuntimeRenderContext, S3UploadStore, STORAGE_SCHEMA_VERSION, type SkillContextEntry, type SkillMetadata, type StateConfig, type StateProviderName, type StateStore, type StorageConfig, type SubagentManager, type SubagentResult, type SubagentSpawnResult, type SubagentSummary, type TelemetryConfig, TelemetryEmitter, type ToolAccess, type ToolCall, ToolDispatcher, type ToolExecutionResult, type UploadStore, type UploadsConfig, VercelBlobUploadStore, buildAgentDirectoryName, buildSkillContextWindow, compactMessages, completeOpenAICodexDeviceAuth, createConversationStore, createDefaultTools, createDeleteDirectoryTool, createDeleteTool, createEditTool, createMemoryStore, createMemoryTools, createModelProvider, createReminderStore, createReminderTools, createSearchTools, createSkillTools, createStateStore, createSubagentTools, createUploadStore, createWriteTool, deleteOpenAICodexSession, deriveUploadKey, ensureAgentIdentity, estimateTokens, estimateTotalTokens, findSafeSplitPoint, generateAgentId, getAgentStoreDirectory, getModelContextWindow, getOpenAICodexAccessToken, getOpenAICodexAuthFilePath, getOpenAICodexRequiredScopes, getPonchoStoreRoot, jsonSchemaToZod, loadPonchoConfig, loadSkillContext, loadSkillInstructions, loadSkillMetadata, normalizeOtlp, normalizeScriptPolicyPath, parseAgentFile, parseAgentMarkdown, ponchoDocsTool, readOpenAICodexSession, readSkillResource, renderAgentPrompt, resolveAgentIdentity, resolveCompactionConfig, resolveMemoryConfig, resolveSkillDirs, resolveStateConfig, slugifyStorageComponent, startOpenAICodexDeviceAuth, writeOpenAICodexSession };
|
|
994
|
+
export { type AgentFrontmatter, AgentHarness, type AgentIdentity, type AgentLimitsConfig, type AgentModelConfig, type ArchivedToolResult$1 as ArchivedToolResult, type BuiltInToolToggles, type CompactMessagesOptions, type CompactResult, type CompactionConfig, type Conversation, type ConversationState, type ConversationStore, type ConversationSummary, type CronJobConfig, type HarnessOptions, type HarnessRunOutput, InMemoryConversationStore, InMemoryStateStore, LocalMcpBridge, LocalUploadStore, type MainMemory, type McpConfig, type MemoryConfig, type MemoryStore, type MessagingChannelConfig, type ModelProviderFactory, OPENAI_CODEX_CLIENT_ID, type OpenAICodexAuthConfig, type OpenAICodexDeviceAuthRequest, type OpenAICodexSession, type OtlpConfig, type OtlpOption, PONCHO_UPLOAD_SCHEME, type ParsedAgent, type PendingSubagentResult, type PonchoConfig, type ProviderConfig, type Reminder, type ReminderStatus, type ReminderStore, type RemoteMcpServerConfig, type RuntimeRenderContext, S3UploadStore, STORAGE_SCHEMA_VERSION, type SecretsStore, type SkillContextEntry, type SkillMetadata, type StateConfig, type StateProviderName, type StateStore, type StorageConfig, type SubagentManager, type SubagentResult, type SubagentSpawnResult, type SubagentSummary, type TelemetryConfig, TelemetryEmitter, type TenantTokenPayload, type ToolAccess, type ToolCall, ToolDispatcher, type ToolExecutionResult, type UploadStore, type UploadsConfig, VercelBlobUploadStore, buildAgentDirectoryName, buildSkillContextWindow, compactMessages, completeOpenAICodexDeviceAuth, createConversationStore, createDefaultTools, createDeleteDirectoryTool, createDeleteTool, createEditTool, createMemoryStore, createMemoryTools, createModelProvider, createReminderStore, createReminderTools, createSearchTools, createSecretsStore, createSkillTools, createStateStore, createSubagentTools, createUploadStore, createWriteTool, deleteOpenAICodexSession, deriveUploadKey, ensureAgentIdentity, estimateTokens, estimateTotalTokens, findSafeSplitPoint, generateAgentId, getAgentStoreDirectory, getModelContextWindow, getOpenAICodexAccessToken, getOpenAICodexAuthFilePath, getOpenAICodexRequiredScopes, getPonchoStoreRoot, jsonSchemaToZod, loadPonchoConfig, loadSkillContext, loadSkillInstructions, loadSkillMetadata, normalizeOtlp, normalizeScriptPolicyPath, parseAgentFile, parseAgentMarkdown, ponchoDocsTool, readOpenAICodexSession, readSkillResource, renderAgentPrompt, resolveAgentIdentity, resolveCompactionConfig, resolveEnv, resolveMemoryConfig, resolveSkillDirs, resolveStateConfig, slugifyStorageComponent, startOpenAICodexDeviceAuth, verifyTenantToken, writeOpenAICodexSession };
|