@ai-ecoverse/slicc-agent 3.31.0 → 3.33.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/README.md +6 -1
- package/dist/host.js +35 -15
- package/dist/host.js.map +2 -2
- package/dist/link.js +146 -0
- package/dist/link.js.map +7 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +2 -2
- package/dist/mcp/config.js +2 -2
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/connection.js +2 -2
- package/dist/mcp/connection.js.map +1 -1
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +2 -2
- package/dist/mcp/label.js +14 -0
- package/dist/mcp/label.js.map +7 -0
- package/dist/mcp/runtime.js +65 -4
- package/dist/mcp/runtime.js.map +2 -2
- package/dist/owner.js +5 -4
- package/dist/owner.js.map +2 -2
- package/dist/page.js +14 -0
- package/dist/page.js.map +2 -2
- package/dist/readonly.js +54 -0
- package/dist/readonly.js.map +7 -0
- package/dist/remote/events.js +2 -1
- package/dist/remote/events.js.map +2 -2
- package/dist/remote/host.js +1 -1
- package/dist/remote/host.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/settings.js +14 -2
- package/dist/settings.js.map +2 -2
- package/dist/spectrum/messages.js +2 -1
- package/dist/spectrum/messages.js.map +2 -2
- package/dist/types/host.d.ts +3 -1
- package/dist/types/link.d.ts +17 -0
- package/dist/types/mcp/index.d.ts +1 -1
- package/dist/types/mcp/label.d.ts +2 -0
- package/dist/types/mcp/runtime.d.ts +9 -1
- package/dist/types/owner.d.ts +5 -2
- package/dist/types/page.d.ts +3 -1
- package/dist/types/readonly.d.ts +7 -0
- package/dist/types/services.d.ts +3 -1
- package/dist/types/settings.d.ts +2 -0
- package/dist/types/view-only.d.ts +1 -0
- package/dist/view-only.js +5 -0
- package/dist/view-only.js.map +7 -0
- package/dist/worker.js +3 -2
- package/dist/worker.js.map +2 -2
- package/package.json +2 -2
package/dist/remote/host.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/remote/host.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT, withCancel } from '@earendil-works/chord/context';\nimport {\n type AgentEvent,\n type AgentEventStream,\n type Conversation,\n type EntryRecord,\n type Harness,\n type SnapshotEvent,\n type SubmissionId,\n watchEvents,\n} from '@earendil-works/pi-durable';\nimport type { Delivered, SendMode, SendRequest, SendResponse } from '../services.ts';\nimport { type EndReason, idOf, Mapper, type RemoteEvent, replayOf } from './events.ts';\n\nexport const MAX_QUEUED = 10000;\nexport const IDLE_MS = 120000;\n\nexport type RemoteOpened =\n | { ok: true; stream: string; delivered: Delivered | null; head: string | null; gap: boolean }\n | { ok: false; code: string; message: string };\n\nexport interface RemoteBatch {\n events: RemoteEvent[];\n done: boolean;\n}\n\nexport interface AgentRemote {\n prompt(\n request: { agentId: string | null; text: string; whenBusy: SendMode; thinking: boolean },\n context: Context\n ): Promise<RemoteOpened>;\n watch(\n request: { agentId: string | null; since: string | null; thinking: boolean },\n context: Context\n ): Promise<RemoteOpened>;\n next(stream: string, waitMs: number, context: Context): Promise<RemoteBatch>;\n close(stream: string, context: Context): Promise<void>;\n abort(agentId: string | null, context: Context): Promise<{ aborted: boolean }>;\n}\n\nexport interface RemoteHost {\n harness: Harness;\n conversation(agentId: string | null, context: Context): Promise<Conversation>;\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n now?: () => number;\n limit?: number;\n sweepMs?: number;\n}\n\nclass Stream {\n readonly queue: RemoteEvent[] = [];\n done = false;\n touched: number;\n #wake: (() => void) | undefined;\n readonly #stop: () => Promise<unknown>;\n readonly #limit: number;\n\n constructor(stop: () => Promise<unknown>, now: number, limit: number) {\n this.#stop = stop;\n this.touched = now;\n this.#limit = limit;\n }\n\n push(events: readonly RemoteEvent[]): void {\n if (this.done || !events.length) return;\n this.queue.push(...events);\n if (this.queue.length > this.#limit) {\n this.queue.length = 0;\n this.queue.push({ t: 'end', reason: 'error', message: 'the stream fell too far behind' });\n void this.finish();\n }\n this.#wake?.();\n }\n\n async finish(): Promise<void> {\n if (this.done) return;\n this.done = true;\n this.#wake?.();\n await this.#stop().catch(() => undefined);\n }\n\n wait(ms: number): Promise<void> {\n if (this.queue.length || this.done) return Promise.resolve();\n return new Promise((resolve) => {\n const timer = setTimeout(done, ms);\n function done() {\n clearTimeout(timer);\n resolve();\n }\n this.#wake = () => {\n this.#wake = undefined;\n done();\n };\n });\n }\n}\n\nfunction deliveredOf(\n status: { status: string } | undefined,\n whenBusy: SendMode,\n busy: boolean\n): Delivered {\n if (status?.status === 'queued') return whenBusy === 'followUp' ? 'follow-up' : 'steer';\n return busy ? 'steer' : 'run';\n}\n\nfunction headOf(events: readonly RemoteEvent[]): string | null {\n for (let at = events.length - 1; at >= 0; at--) {\n const id = idOf(events[at] as RemoteEvent);\n if (id) return id;\n }\n return null;\n}\n\nexport function followed(mapper: Mapper, event: AgentEvent): RemoteEvent[] {\n return event.type === 'snapshot' ? resync(mapper, event) : mapper.event(event);\n}\n\nexport function resync(mapper: Mapper, snapshot: SnapshotEvent): RemoteEvent[] {\n const last = mapper.last();\n return [\n ...snapshot.entries.filter((entry) => entry.id > last).flatMap((entry) => mapper.entry(entry)),\n ...mapper.partial(snapshot.generation?.message as never),\n ];\n}\n\nfunction placedEntry(value: unknown): number | undefined {\n const entry = (value as { entry?: unknown } | undefined)?.entry;\n return typeof entry === 'number' ? entry : undefined;\n}\n\nexport class Follower {\n readonly #mapper: Mapper;\n readonly #entries: Map<number, EntryRecord>;\n readonly #submission: SubmissionId;\n readonly #delivered: Delivered;\n readonly #out: RemoteEvent[] = [];\n #user: number | undefined;\n #started = false;\n\n constructor(\n mapper: Mapper,\n entries: readonly EntryRecord[],\n submission: SubmissionId,\n delivered: Delivered,\n record: unknown\n ) {\n this.#mapper = mapper;\n this.#entries = new Map(entries.map((entry) => [entry.id, entry]));\n this.#submission = submission;\n this.#delivered = delivered;\n this.#user = placedEntry(record);\n }\n\n drain(): RemoteEvent[] {\n return this.#out.splice(0);\n }\n\n #begin(): void {\n const entry = this.#user === undefined ? undefined : this.#entries.get(this.#user);\n if (!entry) return;\n this.#started = true;\n this.#out.push(...this.#mapper.entry(entry, this.#delivered));\n }\n\n #end(reason: EndReason, message?: string): true {\n this.#out.push({ t: 'end', reason, ...(message ? { message } : {}) });\n return true;\n }\n\n #ours(event: AgentEvent): boolean {\n if (event.type !== 'submission' || event.record.id !== this.#submission) return false;\n this.#user = placedEntry(event.record) ?? this.#user;\n return this.#user === undefined && !['queued', 'placed'].includes(event.record.status);\n }\n\n take(batch: readonly AgentEvent[]): boolean {\n for (const event of batch) {\n if (event.type === 'message_end') this.#entries.set(event.entry.id, event.entry);\n if (this.#ours(event)) return this.#end('aborted');\n if (!this.#started) {\n this.#begin();\n continue;\n }\n const mapped = this.#mapper.event(event).filter((item) => item.t !== 'user');\n this.#out.push(...mapped);\n if (mapped.some((item) => item.t === 'run' && item.state === 'end'))\n return this.#end(this.#mapper.reason, this.#mapper.error);\n }\n return false;\n }\n}\n\nexport function createRemote(host: RemoteHost): AgentRemote & { dispose(): Promise<void> } {\n const now = host.now ?? Date.now;\n const streams = new Map<string, Stream>();\n let serial = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n const sweep = () => {\n for (const [id, stream] of streams)\n if (now() - stream.touched > IDLE_MS) {\n streams.delete(id);\n void stream.finish();\n }\n if (!streams.size && timer !== undefined) {\n clearInterval(timer);\n timer = undefined;\n }\n };\n const track = (id: string, stream: Stream) => {\n streams.set(id, stream);\n timer ??= setInterval(sweep, host.sweepMs ?? IDLE_MS / 4);\n };\n const watching = async (agentId: string | null, context: Context) => {\n const conversation = await host.conversation(agentId, context);\n const cancel = withCancel(BACKGROUND_CONTEXT);\n const events: AgentEventStream = await watchEvents(\n host.harness,\n conversation.id,\n cancel.context\n );\n const open = (onEvents: (batch: readonly AgentEvent[]) => void) => {\n const stream = new Stream(\n async () => {\n await events.stop();\n cancel.cancel();\n },\n now(),\n host.limit ?? MAX_QUEUED\n );\n const id = `s${++serial}`;\n track(id, stream);\n events.start(async (batch) => onEvents(batch));\n return { id, stream };\n };\n return { conversation, snapshot: events.snapshot, open, stop: () => events.stop() };\n };\n return {\n async prompt(request, context) {\n sweep();\n const watched = await watching(request.agentId, context);\n const busy = Boolean(watched.snapshot.run);\n const response = await host.send(\n {\n text: request.text,\n whenBusy: request.whenBusy,\n requestId: null,\n ...(request.agentId ? { agentId: request.agentId } : {}),\n },\n context\n );\n if (!response.accepted) {\n await watched.stop();\n return {\n ok: false,\n code: response.error.code === 'busy' ? 'EBUSY' : 'EIO',\n message: response.error.message,\n };\n }\n const submission = Number(response.submissionId) as SubmissionId;\n const record = await (await host.harness.submission(submission, context))?.status(context);\n const delivered = deliveredOf(record, request.whenBusy, busy);\n const follower = new Follower(\n new Mapper(request.thinking),\n watched.snapshot.entries,\n submission,\n delivered,\n record\n );\n const { id, stream } = watched.open((batch) => {\n const ended = follower.take(batch);\n stream.push(follower.drain());\n if (ended) void stream.finish();\n });\n return { ok: true, stream: id, delivered, head: null, gap: false };\n },\n async watch(request, context) {\n sweep();\n const watched = await watching(request.agentId, context);\n const partial = watched.snapshot.generation?.message as never;\n const all = replayOf(watched.snapshot.entries, partial, request.thinking);\n const head = headOf(all);\n const at = request.since === null ? -1 : all.findIndex((e) => idOf(e) === request.since);\n const gap = request.since !== null && at < 0;\n const mapper = new Mapper(request.thinking);\n for (const entry of watched.snapshot.entries) mapper.entry(entry);\n mapper.partial(partial);\n const { id, stream } = watched.open((batch) =>\n stream.push(batch.flatMap((event) => followed(mapper, event)))\n );\n if (at >= 0) {\n const own = all[at] as RemoteEvent;\n const sinceId = idOf(own);\n let last = at;\n while (last + 1 < all.length && idOf(all[last + 1] as RemoteEvent) === sinceId) last++;\n const replay = own.t === 'text' || own.t === 'thinking' ? [own] : [];\n stream.push([...replay, ...all.slice(last + 1)]);\n }\n return { ok: true, stream: id, delivered: null, head, gap };\n },\n async next(id, waitMs, context) {\n const stream = streams.get(id);\n if (!stream) return { events: [], done: true };\n stream.touched = now();\n await stream.wait(Math.max(0, Math.min(waitMs, 30000)));\n context.abortSignal?.throwIfAborted();\n const events = stream.queue.splice(0);\n const done = stream.done && stream.queue.length === 0;\n if (done) streams.delete(id);\n return { events, done };\n },\n async close(id) {\n const stream = streams.get(id);\n streams.delete(id);\n await stream?.finish();\n },\n async abort(agentId, context) {\n const conversation = await host.conversation(agentId, context);\n const watched = await watchEvents(host.harness, conversation.id, context);\n const busy = Boolean(watched.snapshot.run);\n await watched.stop();\n if (busy) await conversation.abort(context);\n return { aborted: busy };\n },\n async dispose() {\n clearInterval(timer);\n timer = undefined;\n const all = [...streams.values()];\n streams.clear();\n await Promise.all(all.map((stream) => stream.finish()));\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT, withCancel } from '@earendil-works/chord/context';\nimport {\n type AgentEvent,\n type AgentEventStream,\n type Conversation,\n type EntryRecord,\n type Harness,\n type SnapshotEvent,\n type SubmissionId,\n watchEvents,\n} from '@earendil-works/pi-durable';\nimport type { Delivered, SendMode, SendRequest, SendResponse } from '../services.ts';\nimport { type EndReason, idOf, Mapper, type RemoteEvent, replayOf } from './events.ts';\n\nexport const MAX_QUEUED = 10000;\nexport const IDLE_MS = 120000;\n\nexport type RemoteOpened =\n | { ok: true; stream: string; delivered: Delivered | null; head: string | null; gap: boolean }\n | { ok: false; code: string; message: string };\n\nexport interface RemoteBatch {\n events: RemoteEvent[];\n done: boolean;\n}\n\nexport interface AgentRemote {\n prompt(\n request: { agentId: string | null; text: string; whenBusy: SendMode; thinking: boolean },\n context: Context\n ): Promise<RemoteOpened>;\n watch(\n request: { agentId: string | null; since: string | null; thinking: boolean },\n context: Context\n ): Promise<RemoteOpened>;\n next(stream: string, waitMs: number, context: Context): Promise<RemoteBatch>;\n close(stream: string, context: Context): Promise<void>;\n abort(agentId: string | null, context: Context): Promise<{ aborted: boolean }>;\n}\n\nexport interface RemoteHost {\n harness: Harness;\n conversation(agentId: string | null, context: Context): Promise<Conversation>;\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n now?: () => number;\n limit?: number;\n sweepMs?: number;\n}\n\nclass Stream {\n readonly queue: RemoteEvent[] = [];\n done = false;\n touched: number;\n #wake: (() => void) | undefined;\n readonly #stop: () => Promise<unknown>;\n readonly #limit: number;\n\n constructor(stop: () => Promise<unknown>, now: number, limit: number) {\n this.#stop = stop;\n this.touched = now;\n this.#limit = limit;\n }\n\n push(events: readonly RemoteEvent[]): void {\n if (this.done || !events.length) return;\n this.queue.push(...events);\n if (this.queue.length > this.#limit) {\n this.queue.length = 0;\n this.queue.push({ t: 'end', reason: 'error', message: 'the stream fell too far behind' });\n void this.finish();\n }\n this.#wake?.();\n }\n\n async finish(): Promise<void> {\n if (this.done) return;\n this.done = true;\n this.#wake?.();\n await this.#stop().catch(() => undefined);\n }\n\n wait(ms: number): Promise<void> {\n if (this.queue.length || this.done) return Promise.resolve();\n return new Promise((resolve) => {\n const timer = setTimeout(done, ms);\n function done() {\n clearTimeout(timer);\n resolve();\n }\n this.#wake = () => {\n this.#wake = undefined;\n done();\n };\n });\n }\n}\n\nfunction deliveredOf(\n status: { status: string } | undefined,\n whenBusy: SendMode,\n busy: boolean\n): Delivered {\n if (status?.status === 'queued') return whenBusy === 'followUp' ? 'follow-up' : 'steer';\n return busy ? 'steer' : 'run';\n}\n\nfunction headOf(events: readonly RemoteEvent[]): string | null {\n for (let at = events.length - 1; at >= 0; at--) {\n const id = idOf(events[at] as RemoteEvent);\n if (id) return id;\n }\n return null;\n}\n\nexport function followed(mapper: Mapper, event: AgentEvent): RemoteEvent[] {\n return event.type === 'snapshot' ? resync(mapper, event) : mapper.event(event);\n}\n\nexport function resync(mapper: Mapper, snapshot: SnapshotEvent): RemoteEvent[] {\n const last = mapper.last();\n return [\n ...snapshot.entries.filter((entry) => entry.id > last).flatMap((entry) => mapper.entry(entry)),\n ...mapper.partial(snapshot.generation?.message as never),\n ];\n}\n\nfunction placedEntry(value: unknown): number | undefined {\n const entry = (value as { entry?: unknown } | undefined)?.entry;\n return typeof entry === 'number' ? entry : undefined;\n}\n\nexport class Follower {\n readonly #mapper: Mapper;\n readonly #entries: Map<number, EntryRecord>;\n readonly #submission: SubmissionId;\n readonly #delivered: Delivered;\n readonly #out: RemoteEvent[] = [];\n #user: number | undefined;\n #started = false;\n\n constructor(\n mapper: Mapper,\n entries: readonly EntryRecord[],\n submission: SubmissionId,\n delivered: Delivered,\n record: unknown\n ) {\n this.#mapper = mapper;\n this.#entries = new Map(entries.map((entry) => [entry.id, entry]));\n this.#submission = submission;\n this.#delivered = delivered;\n this.#user = placedEntry(record);\n }\n\n drain(): RemoteEvent[] {\n return this.#out.splice(0);\n }\n\n #begin(): void {\n const entry = this.#user === undefined ? undefined : this.#entries.get(this.#user);\n if (!entry) return;\n this.#started = true;\n this.#out.push(...this.#mapper.entry(entry, this.#delivered));\n }\n\n #end(reason: EndReason, message?: string): true {\n this.#out.push({ t: 'end', reason, ...(message ? { message } : {}) });\n return true;\n }\n\n #ours(event: AgentEvent): boolean {\n if (event.type !== 'submission' || event.record.id !== this.#submission) return false;\n this.#user = placedEntry(event.record) ?? this.#user;\n return this.#user === undefined && !['queued', 'placed'].includes(event.record.status);\n }\n\n take(batch: readonly AgentEvent[]): boolean {\n for (const event of batch) {\n if (event.type === 'message_end') this.#entries.set(event.entry.id, event.entry);\n if (this.#ours(event)) return this.#end('aborted');\n if (!this.#started) {\n this.#begin();\n continue;\n }\n const mapped = this.#mapper.event(event).filter((item) => item.t !== 'user');\n this.#out.push(...mapped);\n if (mapped.some((item) => item.t === 'run' && item.state === 'end'))\n return this.#end(this.#mapper.reason, this.#mapper.error);\n }\n return false;\n }\n}\n\nexport function createRemote(host: RemoteHost): AgentRemote & { dispose(): Promise<void> } {\n const now = host.now ?? Date.now;\n const streams = new Map<string, Stream>();\n let serial = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n const sweep = () => {\n for (const [id, stream] of streams)\n if (now() - stream.touched > IDLE_MS) {\n streams.delete(id);\n void stream.finish();\n }\n if (!streams.size && timer !== undefined) {\n clearInterval(timer);\n timer = undefined;\n }\n };\n const track = (id: string, stream: Stream) => {\n streams.set(id, stream);\n timer ??= setInterval(sweep, host.sweepMs ?? IDLE_MS / 4);\n };\n const watching = async (agentId: string | null, context: Context) => {\n const conversation = await host.conversation(agentId, context);\n const cancel = withCancel(BACKGROUND_CONTEXT);\n const events: AgentEventStream = await watchEvents(\n host.harness,\n conversation.id,\n cancel.context\n );\n const open = (onEvents: (batch: readonly AgentEvent[]) => void) => {\n const stream = new Stream(\n async () => {\n await events.stop();\n cancel.cancel();\n },\n now(),\n host.limit ?? MAX_QUEUED\n );\n const id = `s${++serial}-${crypto.randomUUID()}`;\n track(id, stream);\n events.start(async (batch) => onEvents(batch));\n return { id, stream };\n };\n return { conversation, snapshot: events.snapshot, open, stop: () => events.stop() };\n };\n return {\n async prompt(request, context) {\n sweep();\n const watched = await watching(request.agentId, context);\n const busy = Boolean(watched.snapshot.run);\n const response = await host.send(\n {\n text: request.text,\n whenBusy: request.whenBusy,\n requestId: null,\n ...(request.agentId ? { agentId: request.agentId } : {}),\n },\n context\n );\n if (!response.accepted) {\n await watched.stop();\n return {\n ok: false,\n code: response.error.code === 'busy' ? 'EBUSY' : 'EIO',\n message: response.error.message,\n };\n }\n const submission = Number(response.submissionId) as SubmissionId;\n const record = await (await host.harness.submission(submission, context))?.status(context);\n const delivered = deliveredOf(record, request.whenBusy, busy);\n const follower = new Follower(\n new Mapper(request.thinking),\n watched.snapshot.entries,\n submission,\n delivered,\n record\n );\n const { id, stream } = watched.open((batch) => {\n const ended = follower.take(batch);\n stream.push(follower.drain());\n if (ended) void stream.finish();\n });\n return { ok: true, stream: id, delivered, head: null, gap: false };\n },\n async watch(request, context) {\n sweep();\n const watched = await watching(request.agentId, context);\n const partial = watched.snapshot.generation?.message as never;\n const all = replayOf(watched.snapshot.entries, partial, request.thinking);\n const head = headOf(all);\n const at = request.since === null ? -1 : all.findIndex((e) => idOf(e) === request.since);\n const gap = request.since !== null && at < 0;\n const mapper = new Mapper(request.thinking);\n for (const entry of watched.snapshot.entries) mapper.entry(entry);\n mapper.partial(partial);\n const { id, stream } = watched.open((batch) =>\n stream.push(batch.flatMap((event) => followed(mapper, event)))\n );\n if (at >= 0) {\n const own = all[at] as RemoteEvent;\n const sinceId = idOf(own);\n let last = at;\n while (last + 1 < all.length && idOf(all[last + 1] as RemoteEvent) === sinceId) last++;\n const replay = own.t === 'text' || own.t === 'thinking' ? [own] : [];\n stream.push([...replay, ...all.slice(last + 1)]);\n }\n return { ok: true, stream: id, delivered: null, head, gap };\n },\n async next(id, waitMs, context) {\n const stream = streams.get(id);\n if (!stream) return { events: [], done: true };\n stream.touched = now();\n await stream.wait(Math.max(0, Math.min(waitMs, 30000)));\n context.abortSignal?.throwIfAborted();\n const events = stream.queue.splice(0);\n const done = stream.done && stream.queue.length === 0;\n if (done) streams.delete(id);\n return { events, done };\n },\n async close(id) {\n const stream = streams.get(id);\n streams.delete(id);\n await stream?.finish();\n },\n async abort(agentId, context) {\n const conversation = await host.conversation(agentId, context);\n const watched = await watchEvents(host.harness, conversation.id, context);\n const busy = Boolean(watched.snapshot.run);\n await watched.stop();\n if (busy) await conversation.abort(context);\n return { aborted: busy };\n },\n async dispose() {\n clearInterval(timer);\n timer = undefined;\n const all = [...streams.values()];\n streams.clear();\n await Promise.all(all.map((stream) => stream.finish()));\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/services.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/services.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type Context,\n defineService,\n type JsonValue,\n type ReplicatedState,\n} from '@earendil-works/chord';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { ChangesView } from './changes/git.ts';\nimport type { FrozenCone } from './freezer/index.ts';\nimport type { MemoryEntry, MemoryScope, MemoryTag } from './memory/format.ts';\nimport type { AgentRemote } from './remote/host.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\n\nexport type SendMode = 'steer' | 'followUp' | 'reject';\n\nexport interface SendRequest {\n text: string;\n whenBusy: SendMode;\n requestId: string | null;\n agentId?: string | null;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n}\n\nexport type SendResponse =\n | { accepted: true; submissionId: string; error: null }\n | { accepted: false; submissionId: null; error: OperationError };\n\nexport type PromptResult =\n | { status: 'done'; text: string; reason: null }\n | { status: 'unanswered'; text: null; reason: string };\n\nexport interface AgentControl {\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n wait(submissionId: string, context: Context): Promise<PromptResult>;\n withdraw(\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n abort(context: Context): Promise<void>;\n compact(instructions: string | null, context: Context): Promise<SendResponse>;\n compactAgent(\n agentId: string,\n instructions: string | null,\n context: Context\n ): Promise<SendResponse>;\n reset(handoff: string | null, context: Context): Promise<void>;\n configure(change: AgentSettingsChange, context: Context): Promise<void>;\n rewind(messageId: string | null, context: Context): Promise<Rewound>;\n rewindAgent(agentId: string, messageId: string | null, context: Context): Promise<Rewound>;\n resolveLick(\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n resolveAgentLick(\n agentId: string,\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n webhook(\n name: string,\n delivery: WebhookRequest,\n context: Context\n ): Promise<{ delivered: boolean }>;\n stopAgent(agentId: string, context: Context): Promise<void>;\n selectCone(agentId: string, context: Context): Promise<void>;\n createCone(name: string, context: Context): Promise<Created>;\n createScoop(parentId: string, name: string, context: Context): Promise<Created>;\n drop(agentId: string, context: Context): Promise<Created>;\n unqueue(\n agentId: string | null,\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n sprinkleSend(\n sprinkleId: string,\n payload: { action: string; data: JsonValue | null; target: string | null },\n context: Context\n ): Promise<{ delivered: boolean }>;\n sprinkleCall(\n sprinkleId: string,\n method: string,\n args: JsonValue[],\n context: Context\n ): Promise<JsonValue>;\n memorySave(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n memoryRemove(id: string, context: Context): Promise<{ removed: boolean }>;\n freeze(agentId: string, context: Context): Promise<Created>;\n newChat(agentId: string, context: Context): Promise<Created>;\n thaw(frozenId: string, context: Context): Promise<Created>;\n discard(frozenId: string, context: Context): Promise<Created>;\n changesOpen(context: Context): Promise<void>;\n changeAccept(path: string, context: Context): Promise<Created>;\n changeRevert(path: string, context: Context): Promise<Created>;\n}\n\nexport interface MemoryDraft {\n id: string | null;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport type Created = { id: string; error: null } | { id: null; error: string };\n\nexport interface AgentSummary {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n role: string | null;\n}\n\nexport interface AgentsSummary {\n active: string;\n agents: AgentSummary[];\n}\n\nexport type LickResolved =\n | { done: true; text: string; error: null }\n | { done: false; text: null; error: string };\n\nexport interface WebhookRequest {\n id: string | null;\n headers: Record<string, string>;\n body: string;\n}\n\nexport type Rewound =\n | { done: true; text: string; reason: null }\n | { done: false; text: null; reason: 'busy' | 'no-turn' };\n\nexport interface AgentSettingsChange {\n model: { provider: string; modelId: string } | null;\n thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;\n agentId?: string | null;\n}\n\nexport const AgentControl = defineService<AgentControl>('slicc.agent.control');\n\nexport type Delivered = 'run' | 'steer' | 'follow-up';\n\nexport interface AgentTranscript {\n readonly state: ReplicatedState<ConversationView>;\n readonly deliveries: ReplicatedState<Record<string, Delivered>>;\n readonly agents: ReplicatedState<AgentsSummary>;\n readonly views: ReplicatedState<Record<string, ConversationView>>;\n readonly commands: ReplicatedState<Command[]>;\n readonly sprinkles: ReplicatedState<Sprinkle[]>;\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly memoryScopes: ReplicatedState<MemoryScope[]>;\n readonly frozen: ReplicatedState<FrozenCone[]>;\n readonly changes: ReplicatedState<ChangesView>;\n}\n\nexport interface Command {\n name: string;\n description: string;\n kind: 'prompt' | 'skill';\n}\n\nexport const AgentTranscript = defineService<AgentTranscript>('slicc.agent.transcript');\n\nexport interface AgentSessions {\n attach(sessionId: string, context: Context): Promise<void>;\n detach(context: Context): Promise<void>;\n}\n\nexport const AgentSessions = defineService<AgentSessions>('slicc.agent.sessions');\n\nexport const AgentRemoteService = defineService<AgentRemote>('slicc.agent.remote');\n\nexport const AGENT_SESSION = 'agent';\n\nexport interface ModelChoice {\n id: string;\n label: string;\n provider: string;\n kind: 'chat' | 'classifier';\n reasoning: boolean;\n images?: boolean;\n contextWindow: number;\n}\n\nexport interface AccountState {\n id: string;\n provider: string;\n identity: string;\n status: 'connected' | 'disconnected';\n auth: 'api-key' | 'oauth';\n needs: 'cors-free-transport' | null;\n}\n\nexport interface BudgetState {\n provider: string;\n percent: number;\n window: 'weekly';\n resets: string;\n}\n\nexport interface SignIn {\n clientId: string;\n scopes: string;\n imsEnvironment: string;\n}\n\nexport interface SettingsState {\n models: ModelChoice[];\n accounts: AccountState[];\n budget?: BudgetState | null;\n}\n\nexport interface AgentSettings {\n readonly state: ReplicatedState<SettingsState>;\n connect(\n providerId: string,\n secret: string,\n region: string | null,\n context: Context\n ): Promise<void>;\n disconnect(providerId: string, context: Context): Promise<void>;\n signIn(providerId: string, context: Context): Promise<SignIn | null>;\n}\n\nexport const AgentSettings = defineService<AgentSettings>('slicc.agent.settings');\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EAEE;AAAA,OAGK;AA4IA,MAAM,eAAe,cAA4B,qBAAqB;AAuBtE,MAAM,kBAAkB,cAA+B,wBAAwB;AAO/E,MAAM,gBAAgB,cAA6B,sBAAsB;AAEzE,MAAM,qBAAqB,cAA2B,oBAAoB;AAE1E,MAAM,gBAAgB;
|
|
4
|
+
"sourcesContent": ["import {\n type Context,\n defineService,\n type JsonValue,\n type ReplicatedState,\n} from '@earendil-works/chord';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { ChangesView } from './changes/git.ts';\nimport type { FrozenCone } from './freezer/index.ts';\nimport type { MemoryEntry, MemoryScope, MemoryTag } from './memory/format.ts';\nimport type { AgentRemote } from './remote/host.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\n\nexport type SendMode = 'steer' | 'followUp' | 'reject';\n\nexport interface SendRequest {\n text: string;\n whenBusy: SendMode;\n requestId: string | null;\n agentId?: string | null;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n}\n\nexport type SendResponse =\n | { accepted: true; submissionId: string; error: null }\n | { accepted: false; submissionId: null; error: OperationError };\n\nexport type PromptResult =\n | { status: 'done'; text: string; reason: null }\n | { status: 'unanswered'; text: null; reason: string };\n\nexport interface AgentControl {\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n wait(submissionId: string, context: Context): Promise<PromptResult>;\n withdraw(\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n abort(context: Context): Promise<void>;\n compact(instructions: string | null, context: Context): Promise<SendResponse>;\n compactAgent(\n agentId: string,\n instructions: string | null,\n context: Context\n ): Promise<SendResponse>;\n reset(handoff: string | null, context: Context): Promise<void>;\n configure(change: AgentSettingsChange, context: Context): Promise<void>;\n rewind(messageId: string | null, context: Context): Promise<Rewound>;\n rewindAgent(agentId: string, messageId: string | null, context: Context): Promise<Rewound>;\n resolveLick(\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n resolveAgentLick(\n agentId: string,\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n webhook(\n name: string,\n delivery: WebhookRequest,\n context: Context\n ): Promise<{ delivered: boolean }>;\n stopAgent(agentId: string, context: Context): Promise<void>;\n selectCone(agentId: string, context: Context): Promise<void>;\n createCone(name: string, context: Context): Promise<Created>;\n createScoop(parentId: string, name: string, context: Context): Promise<Created>;\n drop(agentId: string, context: Context): Promise<Created>;\n unqueue(\n agentId: string | null,\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n sprinkleSend(\n sprinkleId: string,\n payload: { action: string; data: JsonValue | null; target: string | null },\n context: Context\n ): Promise<{ delivered: boolean }>;\n sprinkleCall(\n sprinkleId: string,\n method: string,\n args: JsonValue[],\n context: Context\n ): Promise<JsonValue>;\n memorySave(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n memoryRemove(id: string, context: Context): Promise<{ removed: boolean }>;\n freeze(agentId: string, context: Context): Promise<Created>;\n newChat(agentId: string, context: Context): Promise<Created>;\n thaw(frozenId: string, context: Context): Promise<Created>;\n discard(frozenId: string, context: Context): Promise<Created>;\n changesOpen(context: Context): Promise<void>;\n changeAccept(path: string, context: Context): Promise<Created>;\n changeRevert(path: string, context: Context): Promise<Created>;\n}\n\nexport interface MemoryDraft {\n id: string | null;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport type Created = { id: string; error: null } | { id: null; error: string };\n\nexport interface AgentSummary {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n role: string | null;\n}\n\nexport interface AgentsSummary {\n active: string;\n agents: AgentSummary[];\n}\n\nexport type LickResolved =\n | { done: true; text: string; error: null }\n | { done: false; text: null; error: string };\n\nexport interface WebhookRequest {\n id: string | null;\n headers: Record<string, string>;\n body: string;\n}\n\nexport type Rewound =\n | { done: true; text: string; reason: null }\n | { done: false; text: null; reason: 'busy' | 'no-turn' };\n\nexport interface AgentSettingsChange {\n model: { provider: string; modelId: string } | null;\n thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;\n agentId?: string | null;\n}\n\nexport const AgentControl = defineService<AgentControl>('slicc.agent.control');\n\nexport type Delivered = 'run' | 'steer' | 'follow-up';\n\nexport interface AgentTranscript {\n readonly state: ReplicatedState<ConversationView>;\n readonly deliveries: ReplicatedState<Record<string, Delivered>>;\n readonly agents: ReplicatedState<AgentsSummary>;\n readonly views: ReplicatedState<Record<string, ConversationView>>;\n readonly commands: ReplicatedState<Command[]>;\n readonly sprinkles: ReplicatedState<Sprinkle[]>;\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly memoryScopes: ReplicatedState<MemoryScope[]>;\n readonly frozen: ReplicatedState<FrozenCone[]>;\n readonly changes: ReplicatedState<ChangesView>;\n}\n\nexport interface Command {\n name: string;\n description: string;\n kind: 'prompt' | 'skill';\n}\n\nexport const AgentTranscript = defineService<AgentTranscript>('slicc.agent.transcript');\n\nexport interface AgentSessions {\n attach(sessionId: string, context: Context): Promise<void>;\n detach(context: Context): Promise<void>;\n}\n\nexport const AgentSessions = defineService<AgentSessions>('slicc.agent.sessions');\n\nexport const AgentRemoteService = defineService<AgentRemote>('slicc.agent.remote');\n\nexport const AGENT_SESSION = 'agent';\n\nexport interface ModelChoice {\n id: string;\n label: string;\n provider: string;\n kind: 'chat' | 'classifier';\n reasoning: boolean;\n images?: boolean;\n contextWindow: number;\n}\n\nexport interface AccountState {\n id: string;\n provider: string;\n identity: string;\n status: 'connected' | 'disconnected' | 'expired';\n auth: 'api-key' | 'oauth';\n needs: 'cors-free-transport' | null;\n group?: 'providers' | 'mcp';\n secret?: 'api-key' | 'token';\n}\n\nexport interface BudgetState {\n provider: string;\n percent: number;\n window: 'weekly';\n resets: string;\n}\n\nexport interface SignIn {\n clientId: string;\n scopes: string;\n imsEnvironment: string;\n}\n\nexport interface SettingsState {\n models: ModelChoice[];\n accounts: AccountState[];\n budget?: BudgetState | null;\n}\n\nexport interface AgentSettings {\n readonly state: ReplicatedState<SettingsState>;\n connect(\n providerId: string,\n secret: string,\n region: string | null,\n context: Context\n ): Promise<void>;\n disconnect(providerId: string, context: Context): Promise<void>;\n signIn(providerId: string, context: Context): Promise<SignIn | null>;\n}\n\nexport const AgentSettings = defineService<AgentSettings>('slicc.agent.settings');\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EAEE;AAAA,OAGK;AA4IA,MAAM,eAAe,cAA4B,qBAAqB;AAuBtE,MAAM,kBAAkB,cAA+B,wBAAwB;AAO/E,MAAM,gBAAgB,cAA6B,sBAAsB;AAEzE,MAAM,qBAAqB,cAA2B,oBAAoB;AAE1E,MAAM,gBAAgB;AAsDtB,MAAM,gBAAgB,cAA6B,sBAAsB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/settings.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
adobeProvider,
|
|
10
10
|
adobeUsage
|
|
11
11
|
} from "./adobe.js";
|
|
12
|
+
import { MCP_ACCOUNT } from "./mcp/label.js";
|
|
12
13
|
const BEDROCK = "amazon-bedrock";
|
|
13
14
|
const DEFAULT_MODEL = { provider: BEDROCK, modelId: "us.anthropic.claude-sonnet-5-5" };
|
|
14
15
|
const DEFAULT_REGIONS = { [BEDROCK]: "us-west-2" };
|
|
@@ -68,13 +69,15 @@ async function budget(credentials, usage) {
|
|
|
68
69
|
return found ? { provider: ADOBE, ...found } : null;
|
|
69
70
|
}
|
|
70
71
|
async function createAgentSettings(models, credentials, providers = sliccProviders(), options = {}) {
|
|
72
|
+
const { mcp } = options;
|
|
73
|
+
const routed = (providerId) => providerId.startsWith(MCP_ACCOUNT) ? mcp : void 0;
|
|
71
74
|
const endpoint = providers.find((provider) => provider.id === ADOBE)?.baseUrl ?? ADOBE_PROXY;
|
|
72
75
|
const usage = options.usage ?? ((token) => adobeUsage(token, { endpoint }));
|
|
73
76
|
const snapshot = async () => {
|
|
74
77
|
const stored = new Set((await credentials.list()).map((info) => info.providerId));
|
|
75
78
|
return {
|
|
76
79
|
models: choices(models, providers, stored),
|
|
77
|
-
accounts: accounts(stored, providers),
|
|
80
|
+
accounts: [...accounts(stored, providers), ...await mcp?.accounts() ?? []],
|
|
78
81
|
budget: await budget(credentials, usage)
|
|
79
82
|
};
|
|
80
83
|
};
|
|
@@ -96,9 +99,16 @@ async function createAgentSettings(models, credentials, providers = sliccProvide
|
|
|
96
99
|
const timer = setInterval(cycle, options.every ?? BUDGET_EVERY);
|
|
97
100
|
timer.unref?.();
|
|
98
101
|
}
|
|
102
|
+
mcp?.onChange(() => void refresh(BACKGROUND_CONTEXT).catch(() => void 0));
|
|
99
103
|
return {
|
|
100
104
|
state,
|
|
101
105
|
async connect(providerId, secret, region, context) {
|
|
106
|
+
const server = routed(providerId);
|
|
107
|
+
if (server) {
|
|
108
|
+
await server.connect(providerId, secret);
|
|
109
|
+
await refresh(context);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
102
112
|
await credentials.modify(providerId, async () => ({
|
|
103
113
|
type: "api_key",
|
|
104
114
|
key: secret,
|
|
@@ -116,7 +126,9 @@ async function createAgentSettings(models, credentials, providers = sliccProvide
|
|
|
116
126
|
return { clientId, scopes, imsEnvironment: imsEnvironment || "prod" };
|
|
117
127
|
},
|
|
118
128
|
async disconnect(providerId, context) {
|
|
119
|
-
|
|
129
|
+
const server = routed(providerId);
|
|
130
|
+
if (server) await server.disconnect(providerId);
|
|
131
|
+
else await credentials.delete(providerId);
|
|
120
132
|
await refresh(context);
|
|
121
133
|
}
|
|
122
134
|
};
|
package/dist/settings.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/settings.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Context, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport { createModels, type MutableModels } from '@earendil-works/pi-ai/models';\nimport { amazonBedrockProvider } from '@earendil-works/pi-ai/providers/amazon-bedrock';\nimport {\n ADOBE,\n ADOBE_PROXY,\n adobeConfig,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nimport type { AccountState, AgentSettings, ModelChoice, SettingsState } from './services.ts';\n\nexport const BEDROCK = 'amazon-bedrock';\nexport const DEFAULT_MODEL = { provider: BEDROCK, modelId: 'us.anthropic.claude-sonnet-5-5' };\nexport const DEFAULT_REGIONS: Readonly<Record<string, string>> = { [BEDROCK]: 'us-west-2' };\n\nconst corsFree = new Set([BEDROCK, ADOBE]);\nconst signIn = new Set([ADOBE]);\nconst BUDGET_EVERY = 5 * 60 * 1000;\n\nexport function sliccProviders(): Provider[] {\n return [amazonBedrockProvider() as Provider, adobeProvider()];\n}\n\nexport function withDefaultRegions(credentials: CredentialStore): CredentialStore {\n return {\n async read(providerId, options) {\n const credential = await credentials.read(providerId, options);\n const region = DEFAULT_REGIONS[providerId];\n if (credential?.type !== 'api_key' || !region || credential.env?.AWS_REGION) {\n return credential;\n }\n return { ...credential, env: { ...credential.env, AWS_REGION: region } };\n },\n list: (options) => credentials.list(options),\n modify: (providerId, fn, options) => credentials.modify(providerId, fn, options),\n delete: (providerId, options) => credentials.delete(providerId, options),\n };\n}\n\nexport function createSliccModels(\n credentials: CredentialStore,\n providers = sliccProviders()\n): MutableModels {\n const models = createModels({ credentials: withDefaultRegions(credentials) });\n for (const provider of providers) models.setProvider(provider);\n return models;\n}\n\nfunction choices(\n models: MutableModels,\n providers: Provider[],\n stored: ReadonlySet<string>\n): ModelChoice[] {\n return providers\n .filter((provider) => stored.has(provider.id))\n .flatMap((provider) =>\n models.getModels(provider.id).map((model) => ({\n id: `${provider.id}/${model.id}`,\n label: model.name,\n provider: provider.name ?? provider.id,\n kind: 'chat' as const,\n reasoning: Boolean(model.reasoning),\n images: model.input.includes('image'),\n contextWindow: model.contextWindow,\n }))\n );\n}\n\nfunction accounts(stored: ReadonlySet<string>, providers: Provider[]): AccountState[] {\n return providers.map((provider) => ({\n id: provider.id,\n provider: provider.name ?? provider.id,\n identity: stored.has(provider.id) ? (signIn.has(provider.id) ? 'Adobe ID' : 'API key') : '',\n status: stored.has(provider.id) ? 'connected' : 'disconnected',\n auth: signIn.has(provider.id) ? 'oauth' : 'api-key',\n needs: corsFree.has(provider.id) ? 'cors-free-transport' : null,\n }));\n}\n\nexport type UsageReader = (token: string) => Promise<Budget | null>;\n\nasync function budget(credentials: CredentialStore, usage: UsageReader) {\n const credential = await credentials.read(ADOBE);\n const key = credential?.type === 'api_key' ? credential.key : undefined;\n const found = key ? await usage(key).catch(() => null) : null;\n return found ? { provider: ADOBE, ...found } : null;\n}\n\nexport async function createAgentSettings(\n models: MutableModels,\n credentials: CredentialStore,\n providers = sliccProviders(),\n options: { usage?: UsageReader; every?: number } = {}\n): Promise<AgentSettings> {\n const endpoint = providers.find((provider) => provider.id === ADOBE)?.baseUrl ?? ADOBE_PROXY;\n const usage = options.usage ?? ((token: string) => adobeUsage(token, { endpoint }));\n const snapshot = async (): Promise<SettingsState> => {\n const stored = new Set((await credentials.list()).map((info) => info.providerId));\n return {\n models: choices(models, providers, stored),\n accounts: accounts(stored, providers),\n budget: await budget(credentials, usage),\n };\n };\n const state = replicatedState<SettingsState>(await snapshot());\n let latest = Promise.resolve();\n const refresh = (context: Context) => {\n const next = latest.then(async () => state.replace(context, await snapshot()));\n latest = next.catch(() => undefined);\n return next;\n };\n const signedIn = providers\n .filter((provider) => signIn.has(provider.id))\n .map((provider) => provider.id);\n const discover = (ids: string[]) =>\n models.refresh({ providers: ids }).then(\n () => undefined,\n () => undefined\n );\n if (signedIn.length) {\n const cycle = () =>\n void discover(signedIn)\n .then(() => refresh(BACKGROUND_CONTEXT))\n .catch(() => undefined);\n cycle();\n const timer: unknown = setInterval(cycle, options.every ?? BUDGET_EVERY);\n (timer as { unref?: () => void }).unref?.();\n }\n return {\n state,\n async connect(providerId, secret, region, context) {\n await credentials.modify(providerId, async () => ({\n type: 'api_key',\n key: secret,\n ...(region ? { env: { AWS_REGION: region } } : {}),\n }));\n if (signIn.has(providerId)) await discover([providerId]);\n await refresh(context);\n },\n async signIn(providerId) {\n if (providerId !== ADOBE) return null;\n const { clientId, scopes, imsEnvironment } = await adobeConfig(endpoint, (input, init) =>\n globalThis.fetch(input, init)\n );\n return { clientId, scopes, imsEnvironment: imsEnvironment || 'prod' };\n },\n async disconnect(providerId, context) {\n await credentials.delete(providerId);\n await refresh(context);\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAuB,uBAAuB;AAC9C,SAAS,0BAA0B;AAEnC,SAAS,oBAAwC;AACjD,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;
|
|
4
|
+
"sourcesContent": ["import { type Context, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport { createModels, type MutableModels } from '@earendil-works/pi-ai/models';\nimport { amazonBedrockProvider } from '@earendil-works/pi-ai/providers/amazon-bedrock';\nimport {\n ADOBE,\n ADOBE_PROXY,\n adobeConfig,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nimport type { McpAccounts } from './mcp/index.ts';\nimport { MCP_ACCOUNT } from './mcp/label.ts';\nimport type { AccountState, AgentSettings, ModelChoice, SettingsState } from './services.ts';\n\nexport const BEDROCK = 'amazon-bedrock';\nexport const DEFAULT_MODEL = { provider: BEDROCK, modelId: 'us.anthropic.claude-sonnet-5-5' };\nexport const DEFAULT_REGIONS: Readonly<Record<string, string>> = { [BEDROCK]: 'us-west-2' };\n\nconst corsFree = new Set([BEDROCK, ADOBE]);\nconst signIn = new Set([ADOBE]);\nconst BUDGET_EVERY = 5 * 60 * 1000;\n\nexport function sliccProviders(): Provider[] {\n return [amazonBedrockProvider() as Provider, adobeProvider()];\n}\n\nexport function withDefaultRegions(credentials: CredentialStore): CredentialStore {\n return {\n async read(providerId, options) {\n const credential = await credentials.read(providerId, options);\n const region = DEFAULT_REGIONS[providerId];\n if (credential?.type !== 'api_key' || !region || credential.env?.AWS_REGION) {\n return credential;\n }\n return { ...credential, env: { ...credential.env, AWS_REGION: region } };\n },\n list: (options) => credentials.list(options),\n modify: (providerId, fn, options) => credentials.modify(providerId, fn, options),\n delete: (providerId, options) => credentials.delete(providerId, options),\n };\n}\n\nexport function createSliccModels(\n credentials: CredentialStore,\n providers = sliccProviders()\n): MutableModels {\n const models = createModels({ credentials: withDefaultRegions(credentials) });\n for (const provider of providers) models.setProvider(provider);\n return models;\n}\n\nfunction choices(\n models: MutableModels,\n providers: Provider[],\n stored: ReadonlySet<string>\n): ModelChoice[] {\n return providers\n .filter((provider) => stored.has(provider.id))\n .flatMap((provider) =>\n models.getModels(provider.id).map((model) => ({\n id: `${provider.id}/${model.id}`,\n label: model.name,\n provider: provider.name ?? provider.id,\n kind: 'chat' as const,\n reasoning: Boolean(model.reasoning),\n images: model.input.includes('image'),\n contextWindow: model.contextWindow,\n }))\n );\n}\n\nfunction accounts(stored: ReadonlySet<string>, providers: Provider[]): AccountState[] {\n return providers.map((provider) => ({\n id: provider.id,\n provider: provider.name ?? provider.id,\n identity: stored.has(provider.id) ? (signIn.has(provider.id) ? 'Adobe ID' : 'API key') : '',\n status: stored.has(provider.id) ? 'connected' : 'disconnected',\n auth: signIn.has(provider.id) ? 'oauth' : 'api-key',\n needs: corsFree.has(provider.id) ? 'cors-free-transport' : null,\n }));\n}\n\nexport type UsageReader = (token: string) => Promise<Budget | null>;\n\nasync function budget(credentials: CredentialStore, usage: UsageReader) {\n const credential = await credentials.read(ADOBE);\n const key = credential?.type === 'api_key' ? credential.key : undefined;\n const found = key ? await usage(key).catch(() => null) : null;\n return found ? { provider: ADOBE, ...found } : null;\n}\n\nexport async function createAgentSettings(\n models: MutableModels,\n credentials: CredentialStore,\n providers = sliccProviders(),\n options: { usage?: UsageReader; every?: number; mcp?: McpAccounts } = {}\n): Promise<AgentSettings> {\n const { mcp } = options;\n const routed = (providerId: string) => (providerId.startsWith(MCP_ACCOUNT) ? mcp : undefined);\n const endpoint = providers.find((provider) => provider.id === ADOBE)?.baseUrl ?? ADOBE_PROXY;\n const usage = options.usage ?? ((token: string) => adobeUsage(token, { endpoint }));\n const snapshot = async (): Promise<SettingsState> => {\n const stored = new Set((await credentials.list()).map((info) => info.providerId));\n return {\n models: choices(models, providers, stored),\n accounts: [...accounts(stored, providers), ...((await mcp?.accounts()) ?? [])],\n budget: await budget(credentials, usage),\n };\n };\n const state = replicatedState<SettingsState>(await snapshot());\n let latest = Promise.resolve();\n const refresh = (context: Context) => {\n const next = latest.then(async () => state.replace(context, await snapshot()));\n latest = next.catch(() => undefined);\n return next;\n };\n const signedIn = providers\n .filter((provider) => signIn.has(provider.id))\n .map((provider) => provider.id);\n const discover = (ids: string[]) =>\n models.refresh({ providers: ids }).then(\n () => undefined,\n () => undefined\n );\n if (signedIn.length) {\n const cycle = () =>\n void discover(signedIn)\n .then(() => refresh(BACKGROUND_CONTEXT))\n .catch(() => undefined);\n cycle();\n const timer: unknown = setInterval(cycle, options.every ?? BUDGET_EVERY);\n (timer as { unref?: () => void }).unref?.();\n }\n mcp?.onChange(() => void refresh(BACKGROUND_CONTEXT).catch(() => undefined));\n return {\n state,\n async connect(providerId, secret, region, context) {\n const server = routed(providerId);\n if (server) {\n await server.connect(providerId, secret);\n await refresh(context);\n return;\n }\n await credentials.modify(providerId, async () => ({\n type: 'api_key',\n key: secret,\n ...(region ? { env: { AWS_REGION: region } } : {}),\n }));\n if (signIn.has(providerId)) await discover([providerId]);\n await refresh(context);\n },\n async signIn(providerId) {\n if (providerId !== ADOBE) return null;\n const { clientId, scopes, imsEnvironment } = await adobeConfig(endpoint, (input, init) =>\n globalThis.fetch(input, init)\n );\n return { clientId, scopes, imsEnvironment: imsEnvironment || 'prod' };\n },\n async disconnect(providerId, context) {\n const server = routed(providerId);\n if (server) await server.disconnect(providerId);\n else await credentials.delete(providerId);\n await refresh(context);\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseLick } from "../licks/lick.js";
|
|
2
2
|
import { entryLick, LICK_TOOLS, lickDecisions } from "../licks/state.js";
|
|
3
|
+
import { mcpLabel } from "../mcp/label.js";
|
|
3
4
|
import { FROM_KIND } from "../scoops/from.js";
|
|
4
5
|
import { SPRINKLE_KIND } from "../sprinkles/kind.js";
|
|
5
6
|
function textOf(content) {
|
|
@@ -74,7 +75,7 @@ function toolCall(block) {
|
|
|
74
75
|
return {
|
|
75
76
|
id: block.id ?? "",
|
|
76
77
|
name: block.name ?? "tool",
|
|
77
|
-
title: title(block.arguments),
|
|
78
|
+
title: mcpLabel(block.name ?? "") ?? title(block.arguments),
|
|
78
79
|
...shape(block.name ?? "tool", args),
|
|
79
80
|
output: "",
|
|
80
81
|
status: "running",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/spectrum/messages.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n AssistantMessage,\n AssistantStatus,\n ErrorAction,\n LickMessage,\n Message,\n MessagePart,\n SystemMessage,\n ToolCall,\n ToolStatus,\n Usage,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { ConversationView, EntryRecord } from '@earendil-works/pi-durable';\nimport { parseLick } from '../licks/lick.ts';\nimport { entryLick, LICK_TOOLS, type LickDecision, lickDecisions } from '../licks/state.ts';\nimport { FROM_KIND, type From } from '../scoops/from.ts';\nimport type { Delivered } from '../services.ts';\nimport { SPRINKLE_KIND } from '../sprinkles/kind.ts';\n\ntype Json = Record<string, unknown>;\n\ninterface Block {\n type: string;\n text?: string;\n thinking?: string;\n id?: string;\n name?: string;\n arguments?: Json;\n}\n\ninterface ModelMessage {\n role: string;\n content?: string | Block[];\n timestamp?: number;\n stopReason?: string;\n errorMessage?: string;\n provider?: string;\n model?: string;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n cost?: { total?: number };\n };\n toolCallId?: string;\n isError?: boolean;\n details?: { patch?: unknown };\n}\n\ninterface Slot {\n callId: string;\n status: string;\n output?: string;\n}\n\ninterface Live {\n run?: unknown;\n generation?: { message?: ModelMessage; retry?: { at: number; error: string } };\n tools?: Slot[];\n compactions?: { taskId: number; reason: string }[];\n}\n\nexport function textOf(content: ModelMessage['content']): string {\n if (typeof content === 'string') return content;\n return (content ?? []).map((block) => (block.type === 'text' ? (block.text ?? '') : '')).join('');\n}\n\nconst paths = (args: Json | undefined): string[] =>\n typeof args?.path === 'string' ? [args.path] : [];\n\nfunction title(args: Json | undefined): string {\n const subject = args?.command ?? args?.path;\n return typeof subject === 'string' ? subject : '';\n}\n\ninterface Replacement {\n oldText?: string;\n newText?: string;\n}\n\nconst GAP = '\u2026';\n\nfunction seconds(value: unknown): string | undefined {\n return typeof value === 'number' ? `timeout ${value}s` : undefined;\n}\n\nfunction lines(args: Json): string | undefined {\n const { offset, limit } = args as { offset?: number; limit?: number };\n if (typeof offset === 'number' && typeof limit === 'number')\n return `lines ${offset}\u2013${offset + limit - 1}`;\n if (typeof offset === 'number') return `from line ${offset}`;\n return typeof limit === 'number' ? `first ${limit} lines` : undefined;\n}\n\nfunction edits(args: Json): ToolCall['diff'] {\n const list = Array.isArray(args.edits) ? (args.edits as Replacement[]) : [];\n if (list.length === 0) return undefined;\n return {\n before: list.map((edit) => edit.oldText ?? '').join(`\\n${GAP}\\n`),\n after: list.map((edit) => edit.newText ?? '').join(`\\n${GAP}\\n`),\n };\n}\n\nexport function fromPatch(patch: string): ToolCall['diff'] {\n const before: string[] = [];\n const after: string[] = [];\n let hunks = 0;\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) {\n if (hunks++ > 0) {\n before.push(GAP);\n after.push(GAP);\n }\n continue;\n }\n if (hunks === 0 || line === '' || line.startsWith('\\\\')) continue;\n const text = line.slice(1);\n if (line.startsWith('-')) before.push(text);\n else if (line.startsWith('+')) after.push(text);\n else {\n before.push(text);\n after.push(text);\n }\n }\n return hunks ? { before: before.join('\\n'), after: after.join('\\n') } : undefined;\n}\n\nfunction shape(name: string, args: Json): Pick<ToolCall, 'input' | 'meta' | 'diff'> {\n const path = typeof args.path === 'string' ? args.path : '';\n const meta = name === 'bash' ? seconds(args.timeout) : name === 'read' ? lines(args) : undefined;\n const base = meta ? { meta } : {};\n if (name === 'bash' && typeof args.command === 'string') return { input: args.command, ...base };\n if (name === 'read' || name === 'write') return { input: path, ...base };\n if (name === 'edit') {\n const diff = edits(args);\n return { input: path, ...(diff ? { diff } : {}) };\n }\n return { input: JSON.stringify(args, null, 2) };\n}\n\nfunction toolCall(block: Block): ToolCall {\n const args = block.arguments ?? {};\n return {\n id: block.id ?? '',\n name: block.name ?? 'tool',\n title: title(block.arguments),\n ...shape(block.name ?? 'tool', args),\n output: '',\n status: 'running',\n paths: paths(block.arguments),\n };\n}\n\nfunction part(block: Block): MessagePart | undefined {\n if (block.type === 'text') return { type: 'text', text: block.text ?? '' };\n if (block.type === 'thinking') return { type: 'thinking', text: block.thinking ?? '' };\n if (block.type === 'toolCall') return { type: 'tool', tool: toolCall(block) };\n return undefined;\n}\n\nfunction usage(message: ModelMessage): Usage | undefined {\n const used = message.usage;\n if (!used) return undefined;\n return {\n input: used.input ?? 0,\n output: used.output ?? 0,\n cost: used.cost?.total ?? 0,\n cacheRead: used.cacheRead ?? 0,\n cacheWrite: used.cacheWrite ?? 0,\n };\n}\n\nconst statuses: Record<string, AssistantStatus> = { error: 'error', aborted: 'stopped' };\n\nconst credentials =\n /security token|unrecognizedclient|not authori[sz]ed|unauthori[sz]ed|forbidden|\\b40[13]\\b|api key|credential|bearer/i;\nconst models = /model/i;\nconst unavailable =\n /access|invalid|not found|identifier|unsupported|not supported|isn['\u2019]t supported|not available|isn['\u2019]t available/i;\n\nconst providerNames: Record<string, string> = { 'amazon-bedrock': 'Bedrock' };\nconst filtered =\n /Provider (?:stopped with|finish_reason): (?:content_filter(?:ed)?|guardrail_intervened|sensitive)|content[_ ]filter(?:ed|ing)?\\b|guardrail[_ ]intervened/i;\nconst refused =\n /refused to complete the request|Provider (?:stopped with|finish_reason): refusal|\\bstop_?reason\\W+refusal\\b/i;\nconst missing = /no api key|missing|not configured|no credentials/i;\n\nexport function errorPart(error: string, provider?: string): MessagePart {\n const action = errorAction(error);\n if (action === 'drop-turn') {\n return {\n type: 'error',\n message: filtered.test(error)\n ? \"The model's content filter stopped this reply.\"\n : 'The model refused to answer this turn.',\n detail: error,\n action,\n };\n }\n if (action === 'settings' && provider === 'adobe') {\n return {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n };\n }\n const name = providerNames[provider ?? ''] ?? 'The provider';\n const lead =\n action === 'settings'\n ? missing.test(error)\n ? `${name} needs an API key.`\n : `${name} rejected the API key.`\n : action === 'change-model'\n ? \"This model isn't available with the current account.\"\n : null;\n return lead\n ? { type: 'error', message: lead, detail: error, action }\n : { type: 'error', message: error, action };\n}\n\nexport function errorAction(message: string): ErrorAction {\n if (filtered.test(message) || refused.test(message)) return 'drop-turn';\n if (credentials.test(message)) return 'settings';\n if (models.test(message) && unavailable.test(message)) return 'change-model';\n return 'retry';\n}\n\nfunction sprinkleMessage(id: string, entry: EntryRecord): AssistantMessage {\n const data = (entry.data ?? {}) as { sprinkle?: unknown; at?: unknown };\n return {\n id,\n role: 'assistant',\n parts: [{ type: 'sprinkle', sprinkle: String(data.sprinkle ?? '') }],\n status: 'done',\n createdAt: typeof data.at === 'number' ? data.at : 0,\n };\n}\n\nexport function assistant(\n id: string,\n message: ModelMessage,\n status?: AssistantStatus\n): AssistantMessage {\n const blocks = Array.isArray(message.content) ? message.content : [];\n const parts = blocks.map(part).filter((item): item is MessagePart => item !== undefined);\n if (message.errorMessage) parts.push(errorPart(message.errorMessage, message.provider));\n const used = usage(message);\n return {\n id,\n role: 'assistant',\n parts,\n status: status ?? statuses[message.stopReason ?? ''] ?? 'done',\n createdAt: message.timestamp ?? 0,\n ...(message.provider && message.model ? { model: `${message.provider}/${message.model}` } : {}),\n ...(used ? { usage: used } : {}),\n };\n}\n\nfunction user(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n from: From | undefined\n): UserMessage {\n return {\n id,\n role: 'user',\n text: textOf(message.content),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n ...(from ? { from: from.from } : {}),\n ...(from?.agent ? { origin: 'agent' as const } : {}),\n };\n}\n\nexport function origins(entries: readonly EntryRecord[]): Map<number, From> {\n const out = new Map<number, From>();\n for (const entry of entries)\n if (entry.kind === FROM_KIND) {\n const note = entry.data as From;\n out.set(note.entry, note);\n }\n return out;\n}\n\nfunction lickMessage(\n id: string,\n entry: EntryRecord,\n decisions: ReadonlyMap<string, LickDecision>\n): LickMessage | undefined {\n const lick = entryLick(entry);\n if (!lick) return undefined;\n const state = lick.actions?.length ? (decisions.get(lick.id) ?? 'pending') : undefined;\n return {\n id,\n role: 'lick',\n channel: lick.channel,\n title: lick.title,\n text: lick.text,\n createdAt: lick.at,\n ...(lick.body ? { body: lick.body } : {}),\n ...(lick.count > 1 ? { count: lick.count } : {}),\n ...(state ? { state } : {}),\n ...(lick.severity ? { severity: lick.severity } : {}),\n };\n}\n\nfunction withoutLickTools(message: AssistantMessage): AssistantMessage {\n const parts = message.parts.filter((item) => item.type !== 'tool' || !LICK_TOOLS[item.tool.name]);\n return parts.length === message.parts.length ? message : { ...message, parts };\n}\n\nfunction system(id: string, entry: EntryRecord, text: string): SystemMessage {\n const reason = (entry.data as Json | undefined)?.reason as SystemMessage['trigger'] | undefined;\n return {\n id,\n role: 'system',\n kind: 'compaction',\n text,\n createdAt: 0,\n state: 'summarized',\n ...(reason ? { trigger: reason } : {}),\n };\n}\n\nfunction tools(messages: Message[]): Map<string, ToolCall> {\n const found = new Map<string, ToolCall>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const item of message.parts) if (item.type === 'tool') found.set(item.tool.id, item.tool);\n }\n return found;\n}\n\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage): void {\n const call = calls.get(result.toolCallId ?? '');\n if (!call) return;\n call.output = textOf(result.content);\n call.status = result.isError ? 'error' : 'done';\n const image = Array.isArray(result.content)\n ? (result.content as { type: string; data?: string; mimeType?: string }[]).find(\n (part) => part.type === 'image' && part.data && part.mimeType\n )\n : undefined;\n if (image) call.image = `data:${image.mimeType};base64,${image.data}`;\n const patch = result.details?.patch;\n const diff = typeof patch === 'string' ? fromPatch(patch) : undefined;\n if (diff) call.diff = diff;\n else if (result.isError) delete call.diff;\n}\n\nfunction rewound(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { stopped?: string[]; restored?: string[]; files?: boolean };\n const notes = [\n 'Its prompt is back in the composer.',\n ...(data.stopped?.length\n ? [`Stopped ${data.stopped.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.restored?.length\n ? [`Restored ${data.restored.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.files ? ['Changed files stay; use Changes or git to revert them.'] : []),\n ];\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Rewound 1 turn',\n text: notes.join(' '),\n createdAt: 0,\n };\n}\n\nfunction thawed(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { name?: string; kind?: string };\n const what = data.kind === 'agent' ? 'agent run' : 'scoop';\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: `Thawed from ${what} ${data.name ?? ''}`.trim(),\n text: textOf(entry.model?.[0]?.content ?? ''),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nfunction entryMessage(\n entry: EntryRecord,\n out: Message[],\n calls: Map<string, ToolCall>,\n delivered: Delivered | undefined,\n notes: { decisions: ReadonlyMap<string, LickDecision>; origins: ReadonlyMap<number, From> }\n): void {\n const id = `e${entry.id}`;\n const model = entry.model?.[0] as ModelMessage | undefined;\n if (entry.kind === 'slicc.rewound') out.push(rewound(id, entry));\n if (entry.kind === 'slicc.thawed') out.push(thawed(id, entry));\n else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));\n else if (entry.kind === 'pi.user' && model)\n out.push(\n lickMessage(id, entry, notes.decisions) ??\n user(id, model, delivered, notes.origins.get(entry.id))\n );\n else if (entry.kind === 'pi.assistant' && model) {\n const message = assistant(id, model);\n out.push(withoutLickTools(message));\n for (const [key, value] of tools([message])) calls.set(key, value);\n } else if (entry.kind === 'pi.tool-result' && model) settle(calls, model);\n else if (entry.kind === 'pi.compaction') out.push(system(id, entry, textOf(model?.content)));\n}\n\nconst slotStatus: Record<string, ToolStatus> = {\n pending: 'running',\n running: 'running',\n done: 'done',\n};\n\nfunction live(view: ConversationView, out: Message[], calls: Map<string, ToolCall>): void {\n const state = view.docs['pi.live'] as Live | undefined;\n for (const slot of state?.tools ?? []) {\n const call = calls.get(slot.callId);\n if (call && call.status === 'running') {\n call.status = slotStatus[slot.status] ?? 'running';\n call.output = slot.output ?? call.output;\n }\n }\n const partial = state?.generation?.message;\n if (partial) out.push(assistant('live', partial, 'streaming'));\n for (const compaction of state?.compactions ?? []) {\n out.push({\n id: `compaction-${compaction.taskId}`,\n role: 'system',\n kind: 'compaction',\n text: '',\n createdAt: 0,\n state: 'summarizing',\n trigger: compaction.reason as SystemMessage['trigger'],\n });\n }\n const retry = state?.generation?.retry;\n if (retry)\n out.push({\n id: 'retry',\n role: 'system',\n kind: 'notice',\n text: retry.error,\n createdAt: retry.at,\n });\n}\n\nexport function toMessages(\n view: ConversationView | undefined,\n deliveries: Readonly<Record<string, Delivered>> = {}\n): Message[] {\n const out: Message[] = [];\n if (!view) return out;\n const calls = new Map<string, ToolCall>();\n const notes = { decisions: lickDecisions(view.entries), origins: origins(view.entries) };\n let previous: EntryRecord | undefined;\n for (const entry of view.entries) {\n const steered = previous?.kind === 'pi.tool-result' ? 'steer' : undefined;\n entryMessage(entry, out, calls, deliveries[String(entry.id)] ?? steered, notes);\n previous = entry;\n }\n live(view, out, calls);\n return out;\n}\n\nexport function isBusy(view: ConversationView | undefined): boolean {\n return Boolean((view?.docs['pi.live'] as Live | undefined)?.run);\n}\n\nexport function queued(view: ConversationView | undefined): UserMessage[] {\n const items = ((view?.docs['pi.inbox'] as { items?: Json[] } | undefined)?.items ?? []) as {\n id: number;\n mode: string;\n content?: ModelMessage['content'];\n }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => ({\n id: `q${item.id}`,\n role: 'user',\n text: textOf(item.content),\n createdAt: 0,\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\n }));\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type {\n AssistantMessage,\n AssistantStatus,\n ErrorAction,\n LickMessage,\n Message,\n MessagePart,\n SystemMessage,\n ToolCall,\n ToolStatus,\n Usage,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { ConversationView, EntryRecord } from '@earendil-works/pi-durable';\nimport { parseLick } from '../licks/lick.ts';\nimport { entryLick, LICK_TOOLS, type LickDecision, lickDecisions } from '../licks/state.ts';\nimport { mcpLabel } from '../mcp/label.ts';\nimport { FROM_KIND, type From } from '../scoops/from.ts';\nimport type { Delivered } from '../services.ts';\nimport { SPRINKLE_KIND } from '../sprinkles/kind.ts';\n\ntype Json = Record<string, unknown>;\n\ninterface Block {\n type: string;\n text?: string;\n thinking?: string;\n id?: string;\n name?: string;\n arguments?: Json;\n}\n\ninterface ModelMessage {\n role: string;\n content?: string | Block[];\n timestamp?: number;\n stopReason?: string;\n errorMessage?: string;\n provider?: string;\n model?: string;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n cost?: { total?: number };\n };\n toolCallId?: string;\n isError?: boolean;\n details?: { patch?: unknown };\n}\n\ninterface Slot {\n callId: string;\n status: string;\n output?: string;\n}\n\ninterface Live {\n run?: unknown;\n generation?: { message?: ModelMessage; retry?: { at: number; error: string } };\n tools?: Slot[];\n compactions?: { taskId: number; reason: string }[];\n}\n\nexport function textOf(content: ModelMessage['content']): string {\n if (typeof content === 'string') return content;\n return (content ?? []).map((block) => (block.type === 'text' ? (block.text ?? '') : '')).join('');\n}\n\nconst paths = (args: Json | undefined): string[] =>\n typeof args?.path === 'string' ? [args.path] : [];\n\nfunction title(args: Json | undefined): string {\n const subject = args?.command ?? args?.path;\n return typeof subject === 'string' ? subject : '';\n}\n\ninterface Replacement {\n oldText?: string;\n newText?: string;\n}\n\nconst GAP = '\u2026';\n\nfunction seconds(value: unknown): string | undefined {\n return typeof value === 'number' ? `timeout ${value}s` : undefined;\n}\n\nfunction lines(args: Json): string | undefined {\n const { offset, limit } = args as { offset?: number; limit?: number };\n if (typeof offset === 'number' && typeof limit === 'number')\n return `lines ${offset}\u2013${offset + limit - 1}`;\n if (typeof offset === 'number') return `from line ${offset}`;\n return typeof limit === 'number' ? `first ${limit} lines` : undefined;\n}\n\nfunction edits(args: Json): ToolCall['diff'] {\n const list = Array.isArray(args.edits) ? (args.edits as Replacement[]) : [];\n if (list.length === 0) return undefined;\n return {\n before: list.map((edit) => edit.oldText ?? '').join(`\\n${GAP}\\n`),\n after: list.map((edit) => edit.newText ?? '').join(`\\n${GAP}\\n`),\n };\n}\n\nexport function fromPatch(patch: string): ToolCall['diff'] {\n const before: string[] = [];\n const after: string[] = [];\n let hunks = 0;\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) {\n if (hunks++ > 0) {\n before.push(GAP);\n after.push(GAP);\n }\n continue;\n }\n if (hunks === 0 || line === '' || line.startsWith('\\\\')) continue;\n const text = line.slice(1);\n if (line.startsWith('-')) before.push(text);\n else if (line.startsWith('+')) after.push(text);\n else {\n before.push(text);\n after.push(text);\n }\n }\n return hunks ? { before: before.join('\\n'), after: after.join('\\n') } : undefined;\n}\n\nfunction shape(name: string, args: Json): Pick<ToolCall, 'input' | 'meta' | 'diff'> {\n const path = typeof args.path === 'string' ? args.path : '';\n const meta = name === 'bash' ? seconds(args.timeout) : name === 'read' ? lines(args) : undefined;\n const base = meta ? { meta } : {};\n if (name === 'bash' && typeof args.command === 'string') return { input: args.command, ...base };\n if (name === 'read' || name === 'write') return { input: path, ...base };\n if (name === 'edit') {\n const diff = edits(args);\n return { input: path, ...(diff ? { diff } : {}) };\n }\n return { input: JSON.stringify(args, null, 2) };\n}\n\nfunction toolCall(block: Block): ToolCall {\n const args = block.arguments ?? {};\n return {\n id: block.id ?? '',\n name: block.name ?? 'tool',\n title: mcpLabel(block.name ?? '') ?? title(block.arguments),\n ...shape(block.name ?? 'tool', args),\n output: '',\n status: 'running',\n paths: paths(block.arguments),\n };\n}\n\nfunction part(block: Block): MessagePart | undefined {\n if (block.type === 'text') return { type: 'text', text: block.text ?? '' };\n if (block.type === 'thinking') return { type: 'thinking', text: block.thinking ?? '' };\n if (block.type === 'toolCall') return { type: 'tool', tool: toolCall(block) };\n return undefined;\n}\n\nfunction usage(message: ModelMessage): Usage | undefined {\n const used = message.usage;\n if (!used) return undefined;\n return {\n input: used.input ?? 0,\n output: used.output ?? 0,\n cost: used.cost?.total ?? 0,\n cacheRead: used.cacheRead ?? 0,\n cacheWrite: used.cacheWrite ?? 0,\n };\n}\n\nconst statuses: Record<string, AssistantStatus> = { error: 'error', aborted: 'stopped' };\n\nconst credentials =\n /security token|unrecognizedclient|not authori[sz]ed|unauthori[sz]ed|forbidden|\\b40[13]\\b|api key|credential|bearer/i;\nconst models = /model/i;\nconst unavailable =\n /access|invalid|not found|identifier|unsupported|not supported|isn['\u2019]t supported|not available|isn['\u2019]t available/i;\n\nconst providerNames: Record<string, string> = { 'amazon-bedrock': 'Bedrock' };\nconst filtered =\n /Provider (?:stopped with|finish_reason): (?:content_filter(?:ed)?|guardrail_intervened|sensitive)|content[_ ]filter(?:ed|ing)?\\b|guardrail[_ ]intervened/i;\nconst refused =\n /refused to complete the request|Provider (?:stopped with|finish_reason): refusal|\\bstop_?reason\\W+refusal\\b/i;\nconst missing = /no api key|missing|not configured|no credentials/i;\n\nexport function errorPart(error: string, provider?: string): MessagePart {\n const action = errorAction(error);\n if (action === 'drop-turn') {\n return {\n type: 'error',\n message: filtered.test(error)\n ? \"The model's content filter stopped this reply.\"\n : 'The model refused to answer this turn.',\n detail: error,\n action,\n };\n }\n if (action === 'settings' && provider === 'adobe') {\n return {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n };\n }\n const name = providerNames[provider ?? ''] ?? 'The provider';\n const lead =\n action === 'settings'\n ? missing.test(error)\n ? `${name} needs an API key.`\n : `${name} rejected the API key.`\n : action === 'change-model'\n ? \"This model isn't available with the current account.\"\n : null;\n return lead\n ? { type: 'error', message: lead, detail: error, action }\n : { type: 'error', message: error, action };\n}\n\nexport function errorAction(message: string): ErrorAction {\n if (filtered.test(message) || refused.test(message)) return 'drop-turn';\n if (credentials.test(message)) return 'settings';\n if (models.test(message) && unavailable.test(message)) return 'change-model';\n return 'retry';\n}\n\nfunction sprinkleMessage(id: string, entry: EntryRecord): AssistantMessage {\n const data = (entry.data ?? {}) as { sprinkle?: unknown; at?: unknown };\n return {\n id,\n role: 'assistant',\n parts: [{ type: 'sprinkle', sprinkle: String(data.sprinkle ?? '') }],\n status: 'done',\n createdAt: typeof data.at === 'number' ? data.at : 0,\n };\n}\n\nexport function assistant(\n id: string,\n message: ModelMessage,\n status?: AssistantStatus\n): AssistantMessage {\n const blocks = Array.isArray(message.content) ? message.content : [];\n const parts = blocks.map(part).filter((item): item is MessagePart => item !== undefined);\n if (message.errorMessage) parts.push(errorPart(message.errorMessage, message.provider));\n const used = usage(message);\n return {\n id,\n role: 'assistant',\n parts,\n status: status ?? statuses[message.stopReason ?? ''] ?? 'done',\n createdAt: message.timestamp ?? 0,\n ...(message.provider && message.model ? { model: `${message.provider}/${message.model}` } : {}),\n ...(used ? { usage: used } : {}),\n };\n}\n\nfunction user(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n from: From | undefined\n): UserMessage {\n return {\n id,\n role: 'user',\n text: textOf(message.content),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n ...(from ? { from: from.from } : {}),\n ...(from?.agent ? { origin: 'agent' as const } : {}),\n };\n}\n\nexport function origins(entries: readonly EntryRecord[]): Map<number, From> {\n const out = new Map<number, From>();\n for (const entry of entries)\n if (entry.kind === FROM_KIND) {\n const note = entry.data as From;\n out.set(note.entry, note);\n }\n return out;\n}\n\nfunction lickMessage(\n id: string,\n entry: EntryRecord,\n decisions: ReadonlyMap<string, LickDecision>\n): LickMessage | undefined {\n const lick = entryLick(entry);\n if (!lick) return undefined;\n const state = lick.actions?.length ? (decisions.get(lick.id) ?? 'pending') : undefined;\n return {\n id,\n role: 'lick',\n channel: lick.channel,\n title: lick.title,\n text: lick.text,\n createdAt: lick.at,\n ...(lick.body ? { body: lick.body } : {}),\n ...(lick.count > 1 ? { count: lick.count } : {}),\n ...(state ? { state } : {}),\n ...(lick.severity ? { severity: lick.severity } : {}),\n };\n}\n\nfunction withoutLickTools(message: AssistantMessage): AssistantMessage {\n const parts = message.parts.filter((item) => item.type !== 'tool' || !LICK_TOOLS[item.tool.name]);\n return parts.length === message.parts.length ? message : { ...message, parts };\n}\n\nfunction system(id: string, entry: EntryRecord, text: string): SystemMessage {\n const reason = (entry.data as Json | undefined)?.reason as SystemMessage['trigger'] | undefined;\n return {\n id,\n role: 'system',\n kind: 'compaction',\n text,\n createdAt: 0,\n state: 'summarized',\n ...(reason ? { trigger: reason } : {}),\n };\n}\n\nfunction tools(messages: Message[]): Map<string, ToolCall> {\n const found = new Map<string, ToolCall>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const item of message.parts) if (item.type === 'tool') found.set(item.tool.id, item.tool);\n }\n return found;\n}\n\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage): void {\n const call = calls.get(result.toolCallId ?? '');\n if (!call) return;\n call.output = textOf(result.content);\n call.status = result.isError ? 'error' : 'done';\n const image = Array.isArray(result.content)\n ? (result.content as { type: string; data?: string; mimeType?: string }[]).find(\n (part) => part.type === 'image' && part.data && part.mimeType\n )\n : undefined;\n if (image) call.image = `data:${image.mimeType};base64,${image.data}`;\n const patch = result.details?.patch;\n const diff = typeof patch === 'string' ? fromPatch(patch) : undefined;\n if (diff) call.diff = diff;\n else if (result.isError) delete call.diff;\n}\n\nfunction rewound(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { stopped?: string[]; restored?: string[]; files?: boolean };\n const notes = [\n 'Its prompt is back in the composer.',\n ...(data.stopped?.length\n ? [`Stopped ${data.stopped.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.restored?.length\n ? [`Restored ${data.restored.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.files ? ['Changed files stay; use Changes or git to revert them.'] : []),\n ];\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Rewound 1 turn',\n text: notes.join(' '),\n createdAt: 0,\n };\n}\n\nfunction thawed(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { name?: string; kind?: string };\n const what = data.kind === 'agent' ? 'agent run' : 'scoop';\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: `Thawed from ${what} ${data.name ?? ''}`.trim(),\n text: textOf(entry.model?.[0]?.content ?? ''),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nfunction entryMessage(\n entry: EntryRecord,\n out: Message[],\n calls: Map<string, ToolCall>,\n delivered: Delivered | undefined,\n notes: { decisions: ReadonlyMap<string, LickDecision>; origins: ReadonlyMap<number, From> }\n): void {\n const id = `e${entry.id}`;\n const model = entry.model?.[0] as ModelMessage | undefined;\n if (entry.kind === 'slicc.rewound') out.push(rewound(id, entry));\n if (entry.kind === 'slicc.thawed') out.push(thawed(id, entry));\n else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));\n else if (entry.kind === 'pi.user' && model)\n out.push(\n lickMessage(id, entry, notes.decisions) ??\n user(id, model, delivered, notes.origins.get(entry.id))\n );\n else if (entry.kind === 'pi.assistant' && model) {\n const message = assistant(id, model);\n out.push(withoutLickTools(message));\n for (const [key, value] of tools([message])) calls.set(key, value);\n } else if (entry.kind === 'pi.tool-result' && model) settle(calls, model);\n else if (entry.kind === 'pi.compaction') out.push(system(id, entry, textOf(model?.content)));\n}\n\nconst slotStatus: Record<string, ToolStatus> = {\n pending: 'running',\n running: 'running',\n done: 'done',\n};\n\nfunction live(view: ConversationView, out: Message[], calls: Map<string, ToolCall>): void {\n const state = view.docs['pi.live'] as Live | undefined;\n for (const slot of state?.tools ?? []) {\n const call = calls.get(slot.callId);\n if (call && call.status === 'running') {\n call.status = slotStatus[slot.status] ?? 'running';\n call.output = slot.output ?? call.output;\n }\n }\n const partial = state?.generation?.message;\n if (partial) out.push(assistant('live', partial, 'streaming'));\n for (const compaction of state?.compactions ?? []) {\n out.push({\n id: `compaction-${compaction.taskId}`,\n role: 'system',\n kind: 'compaction',\n text: '',\n createdAt: 0,\n state: 'summarizing',\n trigger: compaction.reason as SystemMessage['trigger'],\n });\n }\n const retry = state?.generation?.retry;\n if (retry)\n out.push({\n id: 'retry',\n role: 'system',\n kind: 'notice',\n text: retry.error,\n createdAt: retry.at,\n });\n}\n\nexport function toMessages(\n view: ConversationView | undefined,\n deliveries: Readonly<Record<string, Delivered>> = {}\n): Message[] {\n const out: Message[] = [];\n if (!view) return out;\n const calls = new Map<string, ToolCall>();\n const notes = { decisions: lickDecisions(view.entries), origins: origins(view.entries) };\n let previous: EntryRecord | undefined;\n for (const entry of view.entries) {\n const steered = previous?.kind === 'pi.tool-result' ? 'steer' : undefined;\n entryMessage(entry, out, calls, deliveries[String(entry.id)] ?? steered, notes);\n previous = entry;\n }\n live(view, out, calls);\n return out;\n}\n\nexport function isBusy(view: ConversationView | undefined): boolean {\n return Boolean((view?.docs['pi.live'] as Live | undefined)?.run);\n}\n\nexport function queued(view: ConversationView | undefined): UserMessage[] {\n const items = ((view?.docs['pi.inbox'] as { items?: Json[] } | undefined)?.items ?? []) as {\n id: number;\n mode: string;\n content?: ModelMessage['content'];\n }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => ({\n id: `q${item.id}`,\n role: 'user',\n text: textOf(item.content),\n createdAt: 0,\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\n }));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["part"]
|
|
7
7
|
}
|
package/dist/types/host.d.ts
CHANGED
|
@@ -12,7 +12,9 @@ import type { PortEndpoint } from './wire.ts';
|
|
|
12
12
|
export interface AgentHost {
|
|
13
13
|
readonly serverId: string;
|
|
14
14
|
readonly agent: Agent;
|
|
15
|
-
connect(endpoint: PortEndpoint
|
|
15
|
+
connect(endpoint: PortEndpoint, options?: {
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
}): void;
|
|
16
18
|
close(): Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
export declare function hostAgent(agent: Agent, options?: {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Frame, PortEndpoint } from './wire.ts';
|
|
2
|
+
export declare const MAX_FRAME: number;
|
|
3
|
+
export interface ByteSink {
|
|
4
|
+
write(chunk: Uint8Array): void;
|
|
5
|
+
close(): void;
|
|
6
|
+
}
|
|
7
|
+
export interface LinkEnd {
|
|
8
|
+
receive(chunk: Uint8Array): void;
|
|
9
|
+
end(error?: Error): void;
|
|
10
|
+
}
|
|
11
|
+
export declare function encodeFrame(frame: Frame): Uint8Array;
|
|
12
|
+
export declare class FrameReader {
|
|
13
|
+
#private;
|
|
14
|
+
push(chunk: Uint8Array): Frame[];
|
|
15
|
+
}
|
|
16
|
+
export declare function linkEndpoint(sink: ByteSink): PortEndpoint & LinkEnd;
|
|
17
|
+
export declare function bridgePort(port: PortEndpoint, sink: ByteSink): LinkEnd;
|
|
@@ -4,7 +4,7 @@ import type { CodemodeExtra } from './allow.ts';
|
|
|
4
4
|
import type { McpCatalog } from './catalog.ts';
|
|
5
5
|
import type { McpAttach, McpRuntime } from './runtime.ts';
|
|
6
6
|
export { allows, type CodemodeExtra, McpAllowDoc, mcpEntries, serverAllowed } from './allow.ts';
|
|
7
|
-
export type { McpAttach, McpRuntime, ServerStatus } from './runtime.ts';
|
|
7
|
+
export type { McpAccounts, McpAttach, McpRuntime, ServerStatus } from './runtime.ts';
|
|
8
8
|
export type McpLoader = () => Promise<typeof import('./runtime.ts')>;
|
|
9
9
|
export declare const loadRuntime: McpLoader;
|
|
10
10
|
export interface McpSetup {
|
|
@@ -3,6 +3,7 @@ import type { CredentialStore } from '@earendil-works/pi-ai';
|
|
|
3
3
|
import type { Registry } from '@earendil-works/pi-durable';
|
|
4
4
|
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
5
5
|
import type { LickEvent, Licks } from '../licks/licks.ts';
|
|
6
|
+
import type { AccountState } from '../services.ts';
|
|
6
7
|
import { McpCatalog } from './catalog.ts';
|
|
7
8
|
import { type McpConfigProblem } from './config.ts';
|
|
8
9
|
import { McpServerConnection } from './connection.ts';
|
|
@@ -26,7 +27,13 @@ export interface ServerStatus {
|
|
|
26
27
|
tools: number;
|
|
27
28
|
error?: string;
|
|
28
29
|
}
|
|
29
|
-
export interface
|
|
30
|
+
export interface McpAccounts {
|
|
31
|
+
accounts(): Promise<AccountState[]>;
|
|
32
|
+
connect(id: string, secret: string): Promise<void>;
|
|
33
|
+
disconnect(id: string): Promise<void>;
|
|
34
|
+
onChange(listener: () => void): () => void;
|
|
35
|
+
}
|
|
36
|
+
export interface McpRuntime extends McpAccounts {
|
|
30
37
|
status(): ServerStatus[];
|
|
31
38
|
reload(context: Context): Promise<void>;
|
|
32
39
|
close(context: Context): Promise<void>;
|
|
@@ -35,6 +42,7 @@ export declare function problemLick(problem: McpConfigProblem, home: string): Li
|
|
|
35
42
|
export declare function stateLick(connection: McpServerConnection, cors: boolean): LickEvent | undefined;
|
|
36
43
|
export declare function connectedLick(connection: McpServerConnection): LickEvent;
|
|
37
44
|
export declare function logLine(server: string, params: unknown, secrets: readonly string[], at: Date): string;
|
|
45
|
+
export declare function mcpAccounts(catalog: McpCatalog, credentials: CredentialStore, restart: (connection: McpServerConnection) => void, listeners: Set<() => void>): McpAccounts;
|
|
38
46
|
export declare function attachMcp(catalog: McpCatalog, options: McpAttach, context: Context): Promise<McpRuntime>;
|
|
39
47
|
export declare function startMcp(registry: Registry, options: McpAttach, context: Context): Promise<{
|
|
40
48
|
catalog: McpCatalog;
|
package/dist/types/owner.d.ts
CHANGED
|
@@ -5,9 +5,12 @@ export interface AgentWorker {
|
|
|
5
5
|
postMessage(message: unknown, transfer: Transferable[]): void;
|
|
6
6
|
terminate(): void;
|
|
7
7
|
}
|
|
8
|
+
export interface PortOptions {
|
|
9
|
+
readOnly?: boolean;
|
|
10
|
+
}
|
|
8
11
|
export interface AgentOwner {
|
|
9
|
-
connect(): Promise<AgentConnection>;
|
|
10
|
-
port(): Promise<Transferable>;
|
|
12
|
+
connect(options?: PortOptions): Promise<AgentConnection>;
|
|
13
|
+
port(options?: PortOptions): Promise<PortEndpoint & Transferable>;
|
|
11
14
|
restart(): Promise<void>;
|
|
12
15
|
release(): Promise<void>;
|
|
13
16
|
}
|
package/dist/types/page.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { type AgentConnection, connectAgent } from './client.ts';
|
|
2
|
-
export {
|
|
2
|
+
export { type ByteSink, bridgePort, encodeFrame, FrameReader, type LinkEnd, linkEndpoint, MAX_FRAME, } from './link.ts';
|
|
3
|
+
export { AGENT_LOCK, type AgentOwner, type AgentWorker, type KernelSource, type OwnerOptions, type PortOptions, startAgent, } from './owner.ts';
|
|
3
4
|
export { type RemoteControl, type RemoteEvent, type RemoteOptions, remoteControl, } from './remote/client.ts';
|
|
5
|
+
export { VIEW_ONLY } from './view-only.ts';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentRemote } from './remote/host.ts';
|
|
2
|
+
import type { AgentControl, AgentSettings } from './services.ts';
|
|
3
|
+
import { VIEW_ONLY } from './view-only.ts';
|
|
4
|
+
export { VIEW_ONLY };
|
|
5
|
+
export declare function viewControl(control: AgentControl): AgentControl;
|
|
6
|
+
export declare function viewSettings(settings: AgentSettings): AgentSettings;
|
|
7
|
+
export declare function viewRemote(remote: AgentRemote): AgentRemote;
|
package/dist/types/services.d.ts
CHANGED
|
@@ -177,9 +177,11 @@ export interface AccountState {
|
|
|
177
177
|
id: string;
|
|
178
178
|
provider: string;
|
|
179
179
|
identity: string;
|
|
180
|
-
status: 'connected' | 'disconnected';
|
|
180
|
+
status: 'connected' | 'disconnected' | 'expired';
|
|
181
181
|
auth: 'api-key' | 'oauth';
|
|
182
182
|
needs: 'cors-free-transport' | null;
|
|
183
|
+
group?: 'providers' | 'mcp';
|
|
184
|
+
secret?: 'api-key' | 'token';
|
|
183
185
|
}
|
|
184
186
|
export interface BudgetState {
|
|
185
187
|
provider: string;
|
package/dist/types/settings.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CredentialStore, Provider } from '@earendil-works/pi-ai';
|
|
2
2
|
import { type MutableModels } from '@earendil-works/pi-ai/models';
|
|
3
3
|
import { type Budget } from './adobe.ts';
|
|
4
|
+
import type { McpAccounts } from './mcp/index.ts';
|
|
4
5
|
import type { AgentSettings } from './services.ts';
|
|
5
6
|
export declare const BEDROCK = "amazon-bedrock";
|
|
6
7
|
export declare const DEFAULT_MODEL: {
|
|
@@ -15,4 +16,5 @@ export type UsageReader = (token: string) => Promise<Budget | null>;
|
|
|
15
16
|
export declare function createAgentSettings(models: MutableModels, credentials: CredentialStore, providers?: Provider<import("@earendil-works/pi-ai").Api>[], options?: {
|
|
16
17
|
usage?: UsageReader;
|
|
17
18
|
every?: number;
|
|
19
|
+
mcp?: McpAccounts;
|
|
18
20
|
}): Promise<AgentSettings>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VIEW_ONLY = "this follower can watch, but not send, steer or abort";
|
package/dist/worker.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
function serveConnections(scope, host) {
|
|
2
2
|
scope.addEventListener("message", ({ data }) => {
|
|
3
|
-
const
|
|
3
|
+
const message = data;
|
|
4
|
+
const port = message?.connect;
|
|
4
5
|
if (!port) return;
|
|
5
6
|
host.then(
|
|
6
|
-
(ready) => ready.connect(port),
|
|
7
|
+
(ready) => ready.connect(port, { readOnly: message?.readOnly === true }),
|
|
7
8
|
() => port.close?.()
|
|
8
9
|
);
|
|
9
10
|
});
|
package/dist/worker.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/worker.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AgentHost } from './host.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface WorkerScope {\n addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;\n}\n\nexport function serveConnections(scope: WorkerScope, host: Promise<AgentHost>): void {\n scope.addEventListener('message', ({ data }) => {\n const
|
|
5
|
-
"mappings": "AAOO,SAAS,iBAAiB,OAAoB,MAAgC;AACnF,QAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,UAAM,
|
|
4
|
+
"sourcesContent": ["import type { AgentHost } from './host.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface WorkerScope {\n addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;\n}\n\nexport function serveConnections(scope: WorkerScope, host: Promise<AgentHost>): void {\n scope.addEventListener('message', ({ data }) => {\n const message = data as { connect?: PortEndpoint; readOnly?: boolean } | null;\n const port = message?.connect;\n if (!port) return;\n host.then(\n (ready) => ready.connect(port, { readOnly: message?.readOnly === true }),\n () => port.close?.()\n );\n });\n}\n\nexport function kernelPort(scope: WorkerScope): Promise<MessagePort> {\n return new Promise((resolve) => {\n scope.addEventListener('message', ({ data }) => {\n const port = (data as { kernel?: MessagePort } | null)?.kernel;\n if (port) resolve(port);\n });\n });\n}\n"],
|
|
5
|
+
"mappings": "AAOO,SAAS,iBAAiB,OAAoB,MAAgC;AACnF,QAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,UAAM,UAAU;AAChB,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,KAAM;AACX,SAAK;AAAA,MACH,CAAC,UAAU,MAAM,QAAQ,MAAM,EAAE,UAAU,SAAS,aAAa,KAAK,CAAC;AAAA,MACvE,MAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAEO,SAAS,WAAW,OAA0C;AACnE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,YAAM,OAAQ,MAA0C;AACxD,UAAI,KAAM,SAAQ,IAAI;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|