@ai-ecoverse/slicc-agent 4.1.0 → 4.3.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.
Files changed (42) hide show
  1. package/README.md +7 -1
  2. package/dist/client.js +3 -1
  3. package/dist/client.js.map +2 -2
  4. package/dist/control.js +3 -2
  5. package/dist/control.js.map +2 -2
  6. package/dist/host.js +18 -8
  7. package/dist/host.js.map +3 -3
  8. package/dist/index.js +6 -0
  9. package/dist/index.js.map +2 -2
  10. package/dist/main.js +18 -11
  11. package/dist/main.js.map +2 -2
  12. package/dist/memory/runtime.js +1 -1
  13. package/dist/memory/runtime.js.map +2 -2
  14. package/dist/preferred.js +14 -0
  15. package/dist/preferred.js.map +7 -0
  16. package/dist/readonly.js +2 -1
  17. package/dist/readonly.js.map +2 -2
  18. package/dist/services.js.map +2 -2
  19. package/dist/settings.js +18 -2
  20. package/dist/settings.js.map +3 -3
  21. package/dist/spectrum/agent-port.js +6 -0
  22. package/dist/spectrum/agent-port.js.map +2 -2
  23. package/dist/spectrum/settings-port.js +23 -8
  24. package/dist/spectrum/settings-port.js.map +2 -2
  25. package/dist/titles/generate.js +33 -13
  26. package/dist/titles/generate.js.map +2 -2
  27. package/dist/titles/labels.js +207 -0
  28. package/dist/titles/labels.js.map +7 -0
  29. package/dist/titles/shown.js +12 -0
  30. package/dist/titles/shown.js.map +7 -0
  31. package/dist/types/client.d.ts +1 -0
  32. package/dist/types/control.d.ts +2 -1
  33. package/dist/types/host.d.ts +2 -0
  34. package/dist/types/index.d.ts +1 -1
  35. package/dist/types/preferred.d.ts +5 -0
  36. package/dist/types/services.d.ts +2 -0
  37. package/dist/types/settings.d.ts +5 -1
  38. package/dist/types/spectrum/agent-port.d.ts +1 -0
  39. package/dist/types/titles/generate.d.ts +13 -1
  40. package/dist/types/titles/labels.d.ts +39 -0
  41. package/dist/types/titles/shown.d.ts +2 -0
  42. package/package.json +2 -2
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/titles/labels.ts"],
4
+ "sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AssistantMessage, Usage } from '@earendil-works/pi-ai';\nimport {\n type ConversationId,\n type ConversationView,\n defineDoc,\n type EntryRecord,\n type Harness,\n type Tx,\n UsageDoc,\n} from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport type { Agents } from '../agents.ts';\nimport type { VaultState } from '../secrets/vault.ts';\nimport { vaultHold } from '../secrets/view.ts';\nimport { type Labeler, scrubbed } from './generate.ts';\nimport { labelKey, shownLabel } from './shown.ts';\n\nexport type LabelsState = { labels: Record<string, string> };\n\nexport const LabelsDoc = defineDoc<LabelsState>({\n kind: 'slicc.labels',\n version: 1,\n scope: 'session',\n initial: () => ({ labels: {} }),\n});\n\nexport const LABELS_KEPT = 500;\nexport const LABELS_PER_MINUTE = 6;\nconst MINUTE = 60_000;\nconst LABEL_WORDS = 8;\nconst LABEL_LENGTH = 80;\nconst OUTPUT_LENGTH = 600;\n\nexport const LABEL_WAIT_MS = 30_000;\n\nfunction callIdsOf(views: readonly ConversationView[]): Set<string> {\n const ids = new Set<string>();\n for (const view of views)\n for (const entry of view.entries) {\n const content = (entry.model?.[0] as Said | undefined)?.content;\n if (entry.kind === 'pi.assistant' && Array.isArray(content))\n for (const block of content as Block[])\n if (block.type === 'toolCall' && block.id) ids.add(block.id);\n }\n return ids;\n}\n\nexport function visibleLabels(\n labels: ReplicatedState<Record<string, string>>,\n sources: readonly ReplicatedState<unknown>[],\n views: () => readonly ConversationView[]\n) {\n const pick = () => {\n const ids = callIdsOf(views());\n return Object.fromEntries(\n Object.entries(labels.value as Record<string, string>).filter(([key]) =>\n key.split(' ').every((id) => ids.has(id))\n )\n );\n };\n const state = replicatedState<Record<string, string>>(pick());\n let queued = false;\n const update = () => {\n if (queued) return;\n queued = true;\n queueMicrotask(() => {\n queued = false;\n const next = pick();\n const before = state.value;\n const keys = Object.keys(next);\n if (\n keys.length !== Object.keys(before).length ||\n keys.some((key) => before[key] !== next[key])\n )\n state.replace(BACKGROUND_CONTEXT, next);\n });\n };\n const offs = [labels, ...sources].map((source) => source.subscribe(update));\n return {\n state,\n dispose() {\n for (const off of offs) off();\n },\n };\n}\n\nexport function watchLabel(\n labels: ReplicatedState<Record<string, string>>,\n waitMs = LABEL_WAIT_MS\n) {\n return (_agentId: string, callIds: readonly string[]): Promise<string | null> => {\n const found = shownLabel(labels.value, callIds);\n if (found !== undefined || !callIds.length) return Promise.resolve(found ?? null);\n return new Promise((resolve) => {\n const done = (label: string | null) => {\n clearTimeout(timer);\n off();\n resolve(label);\n };\n const timer = setTimeout(() => done(null), waitMs);\n const off = labels.subscribe(() => {\n const label = shownLabel(labels.value, callIds);\n if (label !== undefined) done(label);\n });\n });\n };\n}\n\nexport function cleanLabel(text: string): string {\n return text\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/^[\"'\u201C\u201D]+|[\"'\u201C\u201D]+$/g, '')\n .replace(/\\.+$/, '')\n .trim()\n .split(' ')\n .slice(0, LABEL_WORDS)\n .join(' ')\n .slice(0, LABEL_LENGTH);\n}\n\nexport type Run = { name: string; input: string; output: string; at: number };\n\ntype Block = { type?: string; id?: string; name?: string; arguments?: unknown };\n\ntype Said = { content?: unknown; toolCallId?: string; timestamp?: number };\n\nexport function clusterOf(\n entries: readonly EntryRecord[],\n callIds: readonly string[]\n): Run[] | undefined {\n const calls = new Map<string, Pick<Run, 'name' | 'input'>>();\n const results = new Map<string, Pick<Run, 'output' | 'at'>>();\n for (const entry of entries) {\n const said = entry.model?.[0] as Said | undefined;\n if (entry.kind === 'pi.assistant' && Array.isArray(said?.content))\n for (const block of said.content as Block[])\n if (block.type === 'toolCall' && block.id)\n calls.set(block.id, {\n name: block.name ?? 'tool',\n input: JSON.stringify(block.arguments ?? {}),\n });\n if (entry.kind === 'pi.tool-result' && said?.toolCallId)\n results.set(said.toolCallId, {\n output: answerText(said.content),\n at: said.timestamp ?? 0,\n });\n }\n const runs: Run[] = [];\n for (const id of callIds) {\n const call = calls.get(id);\n const result = results.get(id);\n if (!call || !result) return undefined;\n runs.push({ ...call, ...result });\n }\n return runs;\n}\n\nexport function describe(runs: readonly Run[]): string {\n return runs\n .map((run) => `${run.name}: ${run.input}\\n=> ${run.output.slice(0, OUTPUT_LENGTH)}`)\n .join('\\n\\n');\n}\n\ntype Counted = Record<'input' | 'output' | 'cacheRead' | 'cacheWrite' | 'totalTokens', number> & {\n cost: Record<'input' | 'output' | 'cacheRead' | 'cacheWrite' | 'total', number>;\n};\n\nasync function spend(tx: Tx, conversation: ConversationId, answer: AssistantMessage) {\n const models = (await tx.doc(UsageDoc, conversation)).models as unknown as Record<\n string,\n Counted\n >;\n const key = `${answer.provider}/${answer.model}`;\n const usage = answer.usage as Usage;\n const total = Object.hasOwn(models, key) ? models[key] : undefined;\n if (!total) {\n models[key] = JSON.parse(JSON.stringify(usage)) as Counted;\n return;\n }\n for (const field of ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'] as const)\n total[field] += usage[field];\n for (const field of ['input', 'output', 'cacheRead', 'cacheWrite', 'total'] as const)\n total.cost[field] += usage.cost[field];\n}\n\nexport interface LabelsAttach {\n harness: Pick<Harness, 'commit'>;\n agents: Pick<Agents, 'conversation'>;\n label: Labeler;\n vault?: Pick<ReplicatedState<VaultState>, 'value'>;\n now?: () => number;\n perMinute?: number;\n}\n\nexport interface LabelsRuntime {\n labels: ReplicatedState<Record<string, string>>;\n label(agentId: string, callIds: readonly string[], context: Context): Promise<string | null>;\n}\n\nfunction modelName(model: { provider: string; modelId: string } | undefined): string {\n return model ? `${model.provider}/${model.modelId}` : '';\n}\n\nexport async function attachLabels(\n options: LabelsAttach,\n context: Context = BACKGROUND_CONTEXT\n): Promise<LabelsRuntime> {\n const { harness, agents } = options;\n const now = options.now ?? Date.now;\n const started = now();\n const cap = options.perMinute ?? LABELS_PER_MINUTE;\n const loaded = await harness.commit(\n async (tx) => ({ ...(await tx.doc(LabelsDoc)).labels }),\n context\n );\n const labels = replicatedState<Record<string, string>>(loaded);\n const flying = new Map<string, Promise<string | null>>();\n const spent = new Map<string, number[]>();\n const admit = (agentId: string) => () => {\n const at = now();\n const recent = (spent.get(agentId) ?? []).filter((time) => at - time < MINUTE);\n spent.set(agentId, recent);\n if (recent.length >= cap) return false;\n recent.push(at);\n return true;\n };\n const keep = (\n key: string,\n label: string,\n conversation: ConversationId,\n answer: AssistantMessage\n ) =>\n harness.commit(async (tx) => {\n const doc = await tx.doc(LabelsDoc);\n doc.labels[key] = label;\n const keys = Object.keys(doc.labels);\n for (const old of keys.slice(0, Math.max(0, keys.length - LABELS_KEPT)))\n delete doc.labels[old];\n await spend(tx, conversation, answer);\n return { ...doc.labels };\n }, BACKGROUND_CONTEXT);\n const make = async (agentId: string, callIds: readonly string[], key: string) => {\n const conversation = await agents.conversation(agentId, BACKGROUND_CONTEXT);\n if (!conversation) return null;\n const runs = clusterOf((await conversation.context(BACKGROUND_CONTEXT)).entries, callIds);\n if (!runs || Math.max(...runs.map((run) => run.at)) < started) return null;\n if (vaultHold(options.vault?.value)) return null;\n const text = await scrubbed(describe(runs));\n const model = modelName((await conversation.agent(BACKGROUND_CONTEXT)).model);\n const asked = await options.label(text, model, BACKGROUND_CONTEXT, admit(agentId));\n if (!asked) return null;\n const label = cleanLabel(asked.text);\n labels.replace(BACKGROUND_CONTEXT, await keep(key, label, conversation.id, asked.answer));\n return label || null;\n };\n return {\n labels,\n label(agentId, callIds, _context) {\n if (!callIds.length) return Promise.resolve(null);\n const key = labelKey(callIds);\n const found = shownLabel(labels.value, callIds);\n if (found !== undefined) return Promise.resolve(found);\n const known = flying.get(key);\n if (known !== undefined) return known;\n const made = make(agentId, callIds, key)\n .catch(() => null)\n .finally(() => flying.delete(key));\n flying.set(key, made);\n return made;\n },\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,12 @@
1
+ function labelKey(callIds) {
2
+ return callIds.join(" ");
3
+ }
4
+ function shownLabel(labels, callIds) {
5
+ const key = labelKey(callIds);
6
+ return labels && Object.hasOwn(labels, key) ? labels[key] || null : void 0;
7
+ }
8
+ export {
9
+ labelKey,
10
+ shownLabel
11
+ };
12
+ //# sourceMappingURL=shown.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/titles/shown.ts"],
4
+ "sourcesContent": ["export function labelKey(callIds: readonly string[]): string {\n return callIds.join(' ');\n}\n\nexport function shownLabel(\n labels: Readonly<Record<string, string>> | undefined,\n callIds: readonly string[]\n): string | null | undefined {\n const key = labelKey(callIds);\n return labels && Object.hasOwn(labels, key) ? labels[key] || null : undefined;\n}\n"],
5
+ "mappings": "AAAO,SAAS,SAAS,SAAoC;AAC3D,SAAO,QAAQ,KAAK,GAAG;AACzB;AAEO,SAAS,WACd,QACA,SAC2B;AAC3B,QAAM,MAAM,SAAS,OAAO;AAC5B,SAAO,UAAU,OAAO,OAAO,QAAQ,GAAG,IAAI,OAAO,GAAG,KAAK,OAAO;AACtE;",
6
+ "names": []
7
+ }
@@ -25,6 +25,7 @@ export interface AgentConnection {
25
25
  readonly changes?: ReplicatedState<ChangesView>;
26
26
  readonly monitor?: ReplicatedState<MonitorFeed>;
27
27
  readonly vault?: ReplicatedState<VaultState>;
28
+ readonly labels?: ReplicatedState<Record<string, string>>;
28
29
  readonly settings: AgentSettings;
29
30
  readonly remote?: AgentRemote;
30
31
  readonly pages?: AgentPages;
@@ -11,6 +11,7 @@ import type { SecretName } from './secrets/names.ts';
11
11
  import type { AgentControl } from './services.ts';
12
12
  import type { SkillsRuntime } from './skills/index.ts';
13
13
  import type { SprinklesRuntime } from './sprinkles/index.ts';
14
+ import type { LabelsRuntime } from './titles/labels.ts';
14
15
  import { type Uploads } from './uploads.ts';
15
16
  export interface HostLicks {
16
17
  licks: Licks;
@@ -22,4 +23,4 @@ export interface HostScoops {
22
23
  }
23
24
  export declare function readable(out: string): string;
24
25
  export declare function submissionId(value: string): SubmissionId | undefined;
25
- export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads): AgentControl;
26
+ export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads, labels?: Pick<LabelsRuntime, 'label'>): AgentControl;
@@ -14,6 +14,7 @@ import { AgentSettings } from './services.ts';
14
14
  import type { SkillsRuntime } from './skills/index.ts';
15
15
  import type { SprinklesRuntime } from './sprinkles/index.ts';
16
16
  import { type Thumbnail } from './thumbs.ts';
17
+ import { type LabelsRuntime } from './titles/labels.ts';
17
18
  import type { Uploads } from './uploads.ts';
18
19
  import type { PortEndpoint } from './wire.ts';
19
20
  export interface ConnectOptions {
@@ -51,4 +52,5 @@ export declare function hostAgent(agent: Agent, options?: {
51
52
  secrets?: HostSecrets;
52
53
  uploads?: Uploads;
53
54
  thumbnail?: Thumbnail;
55
+ labels?: LabelsRuntime;
54
56
  }): Promise<AgentHost>;
@@ -15,7 +15,7 @@ export { applyPatches, patchServerAccept } from './patches.ts';
15
15
  export { SliccPrompt, sliccPrompt } from './prompt.ts';
16
16
  export { type AgentPages, createPages, type PageBatch, type PageCaller, type PageRequest, type PageResult, type Pages, type PagesOpened, type PageTab, } from './remote/pages.ts';
17
17
  export { type AccountState, AGENT_SESSION, AgentControl, AgentPagesService, AgentSessions, AgentSettings, type AgentSettingsChange, AgentTranscript, type BudgetState, type ModelChoice, type OperationError, type PromptResult, type SendMode, type SendRequest, type SendResponse, type SettingsState, type SignIn, } from './services.ts';
18
- export { BEDROCK, createAgentSettings, createSliccModels, DEFAULT_MODEL, DEFAULT_REGIONS, sliccProviders, withDefaultRegions, } from './settings.ts';
18
+ export { BEDROCK, createAgentSettings, createSliccModels, DEFAULT_MODEL, DEFAULT_REGIONS, PREFERRED_MODELS, preferredModel, resolveDefaultModel, sliccProviders, withDefaultRegions, } from './settings.ts';
19
19
  export { AGENT_DIRECTORY, type OpfsSqliteOptions, openMemorySqliteStorage, openOpfsSqliteStorage, WasmSqliteDatabase, } from './sqlite.ts';
20
20
  export { type SystemFacts, systemSection } from './system.ts';
21
21
  export { UPLOADS, type Uploads, upload } from './uploads.ts';
@@ -0,0 +1,5 @@
1
+ export declare const BEDROCK = "amazon-bedrock";
2
+ export declare const PREFERRED_MODELS: Readonly<Record<string, string>>;
3
+ export declare function preferredModel<T extends {
4
+ id: string;
5
+ }>(providerId: string, available: readonly T[]): T | undefined;
@@ -87,6 +87,7 @@ export interface AgentControl {
87
87
  monitorClose(lease: string, context: Context): Promise<void>;
88
88
  image(ref: ImageRef, context: Context): Promise<StoredImage>;
89
89
  agentCommands(agentId: string, context: Context): Promise<Command[]>;
90
+ toolLabel(agentId: string, callIds: string[], context: Context): Promise<string | null>;
90
91
  }
91
92
  export interface ImageRef {
92
93
  entry: number;
@@ -247,6 +248,7 @@ export interface AgentTranscript {
247
248
  readonly changes: ReplicatedState<ChangesView>;
248
249
  readonly monitor: ReplicatedState<MonitorFeed>;
249
250
  readonly vault: ReplicatedState<VaultState>;
251
+ readonly labels: ReplicatedState<Record<string, string>>;
250
252
  }
251
253
  export interface PrivateRevision {
252
254
  revision: number;
@@ -5,7 +5,7 @@ import type { McpAccounts } from './mcp/index.ts';
5
5
  import type { VaultRecords } from './secrets/records.ts';
6
6
  import type { PlainStore } from './secrets/store.ts';
7
7
  import type { AccountField, AgentSettings } from './services.ts';
8
- export declare const BEDROCK = "amazon-bedrock";
8
+ export { BEDROCK, PREFERRED_MODELS, preferredModel } from './preferred.ts';
9
9
  export declare const DEFAULT_MODEL: {
10
10
  provider: string;
11
11
  modelId: string;
@@ -14,6 +14,10 @@ export declare const DEFAULT_REGIONS: Readonly<Record<string, string>>;
14
14
  export declare const ACCOUNT_FIELDS: Readonly<Record<string, readonly AccountField[]>>;
15
15
  export declare const SIGN_IN_NEEDS_VAULT = "Adobe sign-in needs seven's vault: update seven";
16
16
  export declare const KEY_NEEDS_VAULT = "API keys are kept in seven's vault: update seven";
17
+ export declare function resolveDefaultModel(credentials: CredentialStore, providers: Provider[], models: MutableModels): Promise<{
18
+ provider: string;
19
+ modelId: string;
20
+ }>;
17
21
  export declare function sliccProviders(version?: string): Provider[];
18
22
  export declare function withDefaultRegions(credentials: CredentialStore): CredentialStore;
19
23
  export declare function createSliccModels(credentials: CredentialStore, providers?: Provider<import("@earendil-works/pi-ai").Api>[]): MutableModels;
@@ -38,6 +38,7 @@ export declare class AgentAdapter extends Emitter<AgentAdapterEvents> implements
38
38
  createScoop(parentId: string, name: string): Agent;
39
39
  drop(agentId: string): Promise<void>;
40
40
  createCone(name: string): Promise<Agent>;
41
+ toolLabel(agentId: string, callIds: readonly string[]): Promise<string | null>;
41
42
  frozen(): readonly FrozenCone[];
42
43
  thaw(id: string): Agent | null;
43
44
  discard(id: string): void;
@@ -1,11 +1,23 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
+ import type { AssistantMessage } from '@earendil-works/pi-ai';
2
3
  import type { Models } from '@earendil-works/pi-ai/models';
3
4
  import type { EntryRecord } from '@earendil-works/pi-durable';
4
5
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
5
6
  export declare const TITLE_PROMPT = "Give this chat a title of three to six words that says what it is about, in the language the user writes in. Answer with the title only, without quotes.";
7
+ export declare const LABEL_PROMPT = "Label this group of tool runs in three to eight words, as an imperative that says what they do, such as \"Check the failing build logs\". Answer with the label only, without quotes.";
6
8
  export declare const TRANSCRIPT_LENGTH = 4000;
7
9
  export declare function titlesOn(text: string | undefined): boolean;
10
+ export declare function labelsOn(text: string | undefined): boolean;
8
11
  export declare function settingsText(env: Pick<ExecutionEnv, 'readTextFile'>, home: string, dir?: string): (context: Context) => Promise<string | undefined>;
9
12
  export declare function transcriptOf(entries: readonly EntryRecord[]): string;
13
+ export declare function scrubbed(raw: string): Promise<string>;
10
14
  export declare function scrubTranscript(entries: readonly EntryRecord[]): Promise<string>;
11
- export declare function titler(models: Models, settings: (context: Context) => Promise<string | undefined>): (transcript: string, model: string, context: Context) => Promise<string | undefined>;
15
+ type Settings = (context: Context) => Promise<string | undefined>;
16
+ export type Asked = {
17
+ text: string;
18
+ answer: AssistantMessage;
19
+ };
20
+ export declare function titler(models: Models, settings: Settings): (transcript: string, model: string, context: Context) => Promise<string | undefined>;
21
+ export declare function labeler(models: Models, settings: Settings): (transcript: string, model: string, context: Context, admit?: () => boolean) => Promise<Asked | undefined>;
22
+ export type Labeler = ReturnType<typeof labeler>;
23
+ export {};
@@ -0,0 +1,39 @@
1
+ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
+ import { type ConversationView, type EntryRecord, type Harness } from '@earendil-works/pi-durable';
3
+ import type { Agents } from '../agents.ts';
4
+ import type { VaultState } from '../secrets/vault.ts';
5
+ import { type Labeler } from './generate.ts';
6
+ export type LabelsState = {
7
+ labels: Record<string, string>;
8
+ };
9
+ export declare const LabelsDoc: import("@earendil-works/pi-durable").SessionDocToken<LabelsState>;
10
+ export declare const LABELS_KEPT = 500;
11
+ export declare const LABELS_PER_MINUTE = 6;
12
+ export declare const LABEL_WAIT_MS = 30000;
13
+ export declare function visibleLabels(labels: ReplicatedState<Record<string, string>>, sources: readonly ReplicatedState<unknown>[], views: () => readonly ConversationView[]): {
14
+ state: import("@earendil-works/chord").MutableReplicatedState<Record<string, string>>;
15
+ dispose(): void;
16
+ };
17
+ export declare function watchLabel(labels: ReplicatedState<Record<string, string>>, waitMs?: number): (_agentId: string, callIds: readonly string[]) => Promise<string | null>;
18
+ export declare function cleanLabel(text: string): string;
19
+ export type Run = {
20
+ name: string;
21
+ input: string;
22
+ output: string;
23
+ at: number;
24
+ };
25
+ export declare function clusterOf(entries: readonly EntryRecord[], callIds: readonly string[]): Run[] | undefined;
26
+ export declare function describe(runs: readonly Run[]): string;
27
+ export interface LabelsAttach {
28
+ harness: Pick<Harness, 'commit'>;
29
+ agents: Pick<Agents, 'conversation'>;
30
+ label: Labeler;
31
+ vault?: Pick<ReplicatedState<VaultState>, 'value'>;
32
+ now?: () => number;
33
+ perMinute?: number;
34
+ }
35
+ export interface LabelsRuntime {
36
+ labels: ReplicatedState<Record<string, string>>;
37
+ label(agentId: string, callIds: readonly string[], context: Context): Promise<string | null>;
38
+ }
39
+ export declare function attachLabels(options: LabelsAttach, context?: Context): Promise<LabelsRuntime>;
@@ -0,0 +1,2 @@
1
+ export declare function labelKey(callIds: readonly string[]): string;
2
+ export declare function shownLabel(labels: Readonly<Record<string, string>> | undefined, callIds: readonly string[]): string | null | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-agent",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -63,7 +63,7 @@
63
63
  "devDependencies": {
64
64
  "@ai-ecoverse/slicc-kernel": "1.47.1",
65
65
  "@ai-ecoverse/slicc-scrub": "1.0.0",
66
- "@ai-ecoverse/slicc-shared-web": "1.13.2",
66
+ "@ai-ecoverse/slicc-shared-web": "1.13.3",
67
67
  "@ai-ecoverse/slicc-spectrum": "1.69.2",
68
68
  "@ai-ecoverse/wasm-bash": "5.3.0-18",
69
69
  "@ai-ecoverse/wasm-coreutils": "9.12.0-5",