dimcode-darwin-x64 0.1.0-alpha.16 → 0.1.0-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/bin/dimcode +2 -2
  2. package/default-plugins.json +0 -1
  3. package/package.json +1 -1
  4. package/plugins/scheduler/README.md +4 -9
  5. package/plugins/scheduler/data.ts +8 -29
  6. package/plugins/scheduler/settings.ts +0 -9
  7. package/plugins/workflow/README.md +22 -19
  8. package/plugins/workflow/store.ts +61 -18
  9. package/release-manifest.json +9 -26
  10. package/plugins/session-title/README.md +0 -76
  11. package/plugins/session-title/dim-plugin.json +0 -11
  12. package/plugins/session-title/index.ts +0 -13
  13. package/plugins/session-title/node_modules/.package-lock.json +0 -18
  14. package/plugins/session-title/node_modules/@arcships/rutis/README.md +0 -32
  15. package/plugins/session-title/node_modules/@arcships/rutis/package.json +0 -46
  16. package/plugins/session-title/node_modules/@arcships/rutis/src/advanced.d.ts +0 -90
  17. package/plugins/session-title/node_modules/@arcships/rutis/src/advanced.mjs +0 -32
  18. package/plugins/session-title/node_modules/@arcships/rutis/src/index.d.ts +0 -43
  19. package/plugins/session-title/node_modules/@arcships/rutis/src/index.mjs +0 -71
  20. package/plugins/session-title/node_modules/@arcships/rutis/src/testing.d.ts +0 -77
  21. package/plugins/session-title/node_modules/@arcships/rutis/src/testing.mjs +0 -350
  22. package/plugins/session-title/node_modules/@arcships/rutis/src/values.mjs +0 -261
  23. package/plugins/session-title/package-lock.json +0 -45
  24. package/plugins/session-title/package.json +0 -9
  25. package/plugins/session-title/part.ts +0 -172
  26. package/plugins/session-title/settings.ts +0 -49
@@ -1,172 +0,0 @@
1
- // The SessionTitle part, in a module of its own so a test loads its default
2
- // export (the rutis test tool loads a module's default plugin).
3
- import { definePlugin } from '@arcships/rutis'
4
- import type {
5
- AgentEvent, AuxiliaryModel, ModelId, Services, SessionBroadcast, SessionMetadata,
6
- SessionMethods, SessionMethodReply, Sessions, Settings, SettingsResult,
7
- } from '../../../npm/plugin.d.ts'
8
- import type { UserInput } from '../../../npm/branch-services.d.ts'
9
-
10
- type Document = { enabled: boolean; maxLength: number; model: ModelId | null }
11
- type TitleSettings = { read(request: Parameters<Settings['read']>[0]): Promise<SettingsResult<{ document: Document }>> }
12
- type HistoryEvent = Omit<AgentEvent, 'data'> & { data: Record<string, any> }
13
- const SYSTEM = "Write a short title for this conversation: at most 8 words, in the language of the user's message, no quotes, no trailing punctuation. Reply with the title only."
14
- const failure = (code: string, message: string): SessionMethodReply => ({ code, message })
15
- const reloading = () => failure('service_reloading', 'SessionTitle is closing or reloading')
16
-
17
- async function prefix(sessions: Sessions, sessionId: string, sequence: number, inputId: string) {
18
- const inputs = new Map<string, UserInput>()
19
- let first: UserInput | undefined
20
- let model: ModelId | undefined
21
- let operator = false
22
- let after: number | undefined
23
- let through: number | undefined
24
- do {
25
- const page = await sessions.history({ sessionId, branchId: 'main', after,
26
- ...(through === undefined ? { atLeast: sequence } : { through }) })
27
- if (!page.ok) throw new Error('history_failed')
28
- through = page.value.through
29
- if (page.value.events.length === 0) break
30
- const events: HistoryEvent[] = page.value.events
31
- for (const event of events) {
32
- if (event.type === 'input' && event.name === 'message' && event.data.user) {
33
- if (!first) inputs.set(event.id, event.data.user)
34
- if (event.id === inputId) operator = true
35
- }
36
- if (event.type === 'input' && event.name === 'applied' && !first) {
37
- first = inputs.get(event.data.input_id)
38
- }
39
- if (event.type === 'context' && event.name === 'configured') {
40
- model = { providerId: event.data.settings.providerId, modelId: event.data.settings.modelId }
41
- }
42
- }
43
- after = page.value.events.at(-1)!.sequence
44
- } while (after < through)
45
- return { first, model, operator }
46
- }
47
-
48
- /** The Session part SessionTitle registers: one copy per Session. */
49
- export default definePlugin({
50
- name: 'SessionTitle',
51
- inject: ['sessions', 'settings', 'sessionMetadata', 'auxiliaryModel', 'sessionIdentity', 'sessionConfig', 'sessionLifecycle', 'sessionMethods'],
52
- async apply(ctx) {
53
- const sessions = ctx.use<Sessions>('sessions')
54
- const settings = ctx.use<TitleSettings>('settings')
55
- const metadata = ctx.use<SessionMetadata>('sessionMetadata')
56
- const auxiliary = ctx.use<AuxiliaryModel>('auxiliaryModel')
57
- const { sessionId } = await ctx.use<Services['sessionIdentity']>('sessionIdentity').get()
58
- const config = await ctx.use<Services['sessionConfig']>('sessionConfig').get()
59
- const lifecycle = ctx.use<Services['sessionLifecycle']>('sessionLifecycle')
60
- const tasks = new Set<Promise<void>>()
61
- let closed = false
62
- let generating = false
63
- let epoch = 0
64
- let failures = 0
65
- let noText = false
66
- let cancel: (() => void) | undefined
67
- const close = () => { closed = true; cancel?.() }
68
- ctx.effect(async () => { close(); await Promise.all(tasks) })
69
- void lifecycle.closing().then(close)
70
-
71
- async function attempt(sequence: number, inputId: string, observedEpoch: number) {
72
- const started = performance.now()
73
- const current = () => !closed && observedEpoch === epoch
74
- let entered = false
75
- let timer: ReturnType<typeof setTimeout> | undefined
76
- let cancelled = false
77
- const diagnostic = (outcome: string) => console.warn('SessionTitle', outcome, Math.round(performance.now() - started))
78
- try {
79
- const configured = await settings.read({ source: 'session-title', scope: 'user' })
80
- if (!current() || (configured.ok && !configured.value.document.enabled)) return
81
- const stored = await metadata.read({ sessionId: sessionId })
82
- if (!current() || (stored.ok && stored.value.title)) return
83
- const snapshot = await prefix(sessions, sessionId, sequence, inputId)
84
- if (!current() || !snapshot.operator || !snapshot.first) return
85
- epoch++
86
- entered = true
87
- generating = true
88
- const cancellation = new Promise<void>(resolve => {
89
- cancel = () => { cancelled = true; resolve() }
90
- })
91
- timer = setTimeout(() => cancel?.(), 30_000)
92
- if (!stored.ok) throw new Error('metadata_failed')
93
- if (!configured.ok) throw new Error('settings_failed')
94
- const document = configured.value.document
95
- const text = [...snapshot.first.content.filter(block => block.type === 'text').map(block => block.text).join('\n')].slice(0, 2000).join('')
96
- if (!text) { noText = true; return }
97
- const model = document.model ?? snapshot.model
98
- if (!model) throw new Error('model_unavailable')
99
- const reply = await auxiliary.complete({ model, request: {
100
- system: SYSTEM, messages: [{ role: 'user', content: text }],
101
- } }, () => cancellation)
102
- if (closed) return
103
- if (cancelled) throw new Error('timed_out')
104
- const line = reply.text.trim().split(/[\r\n\u2028\u2029]/, 1)[0].trim()
105
- const title = [...line.replace(/^\p{Quotation_Mark}+|\p{P}+$/gu, '').replace(/[\s\p{Cc}]+/gu, ' ').trim()].slice(0, document.maxLength).join('').trim()
106
- if (!title) throw new Error('empty_title')
107
- const written = await metadata.setTitle({ sessionId: sessionId,
108
- expectedRevision: stored.value.revision, title: { text: title, source: 'auto' } })
109
- if (!written.ok && written.error.code === 'storage') throw new Error('storage_failed')
110
- diagnostic(written.ok ? 'completed' : 'discarded')
111
- } catch {
112
- if (!closed) {
113
- if (entered) failures++
114
- diagnostic('failed')
115
- }
116
- } finally {
117
- if (entered) {
118
- clearTimeout(timer)
119
- cancel = undefined
120
- generating = false
121
- }
122
- }
123
- }
124
-
125
- if (config.interactive !== false && config.collaborationRole === 'leader') {
126
- ctx.on(`session/${sessionId}`, (record: SessionBroadcast) => {
127
- if (closed || record.kind !== 'event' || record.branchId !== 'main') return
128
- const event = record.event as HistoryEvent
129
- if (generating || noText || failures >= 3
130
- || event.type !== 'input' || event.name !== 'applied') return
131
- const task = attempt(event.sequence, event.data.input_id, epoch)
132
- tasks.add(task)
133
- void task.finally(() => tasks.delete(task))
134
- })
135
- }
136
-
137
- await ctx.use<SessionMethods>('sessionMethods').register(
138
- 'session.rename',
139
- [{ name: 'session.rename', mutating: true, interruption: 'report', progress: false }],
140
- async (call, cancelled) => {
141
- if (closed) return reloading()
142
- const value = call.params.title
143
- if (call.method !== 'session.rename' || (value !== null && typeof value !== 'string')) {
144
- return failure('invalid_params', 'title must be a string or null')
145
- }
146
- const text = value === null ? null : value.trim()
147
- if (text !== null && (!text || /[\p{Cc}\p{Zl}\p{Zp}]/u.test(value!))) {
148
- return failure('invalid_params', 'Invalid title or control character')
149
- }
150
- let aborted = false
151
- cancelled.then(() => { aborted = true })
152
- const configured = await settings.read({ source: 'session-title', scope: 'user' })
153
- if (closed || aborted) return reloading()
154
- if (!configured.ok) return failure('storage_failed', 'Cannot read title settings')
155
- if (text !== null && [...text].length > configured.value.document.maxLength) {
156
- return failure('invalid_params', 'Invalid title length')
157
- }
158
- for (let retry = 0; retry <= 3; retry++) {
159
- const stored = await metadata.read({ sessionId })
160
- if (closed || aborted) return reloading()
161
- if (!stored.ok) return failure(stored.error.code === 'not_found' ? 'session_not_found' : 'storage_failed', 'Cannot read title metadata')
162
- const written = await metadata.setTitle({ sessionId,
163
- expectedRevision: stored.value.revision, title: text === null ? null : { text, source: 'manual' } })
164
- if (written.ok) return { kind: 'value', value: { title: text, titleSource: text === null ? null : 'manual', revision: written.value.revision } }
165
- if (written.error.code !== 'conflict') return failure(written.error.code === 'not_found' ? 'session_not_found' : 'storage_failed', 'Cannot write title metadata')
166
- if (closed || aborted) return reloading()
167
- }
168
- return failure('service_reloading', 'Title changed during rename')
169
- },
170
- )
171
- },
172
- })
@@ -1,49 +0,0 @@
1
- import type { SourceDeclaration } from '../../../npm/plugin.js'
2
-
3
- export const settings: SourceDeclaration = {
4
- "source": "session-title",
5
- "userFile": "session-title.json",
6
- "userOnly": [],
7
- "schema": {
8
- "type": "object",
9
- "additionalProperties": false,
10
- "properties": {
11
- "enabled": {
12
- "type": "boolean",
13
- "default": true
14
- },
15
- "maxLength": {
16
- "type": "integer",
17
- "minimum": 10,
18
- "maximum": 200,
19
- "default": 80
20
- },
21
- "model": {
22
- "default": null,
23
- "anyOf": [
24
- {
25
- "type": "null"
26
- },
27
- {
28
- "type": "object",
29
- "required": [
30
- "providerId",
31
- "modelId"
32
- ],
33
- "additionalProperties": false,
34
- "properties": {
35
- "providerId": {
36
- "type": "string",
37
- "minLength": 1
38
- },
39
- "modelId": {
40
- "type": "string",
41
- "minLength": 1
42
- }
43
- }
44
- }
45
- ]
46
- }
47
- }
48
- }
49
- }