@sympoies/dsh-telegram 0.0.0-bootstrap.0 → 0.6.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/LICENSE +1 -2
- package/NOTICE +19 -0
- package/README.md +589 -2
- package/cordis.patch.yml +14 -0
- package/lib/access.d.ts +76 -0
- package/lib/access.d.ts.map +1 -0
- package/lib/access.js +137 -0
- package/lib/access.js.map +1 -0
- package/lib/client.js +835 -0
- package/lib/commands.d.ts +51 -0
- package/lib/commands.d.ts.map +1 -0
- package/lib/commands.js +83 -0
- package/lib/commands.js.map +1 -0
- package/lib/config.d.ts +125 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +97 -0
- package/lib/config.js.map +1 -0
- package/lib/diagnostics.d.ts +58 -0
- package/lib/diagnostics.d.ts.map +1 -0
- package/lib/diagnostics.js +59 -0
- package/lib/diagnostics.js.map +1 -0
- package/lib/failures.d.ts +71 -0
- package/lib/failures.d.ts.map +1 -0
- package/lib/failures.js +139 -0
- package/lib/failures.js.map +1 -0
- package/lib/harness/host.d.ts +106 -0
- package/lib/harness/host.d.ts.map +1 -0
- package/lib/harness/host.js +142 -0
- package/lib/harness/host.js.map +1 -0
- package/lib/harness/message.d.ts +45 -0
- package/lib/harness/message.d.ts.map +1 -0
- package/lib/harness/message.js +28 -0
- package/lib/harness/message.js.map +1 -0
- package/lib/harness/model-selection.d.ts +82 -0
- package/lib/harness/model-selection.d.ts.map +1 -0
- package/lib/harness/model-selection.js +103 -0
- package/lib/harness/model-selection.js.map +1 -0
- package/lib/harness/questions-seam.d.ts +34 -0
- package/lib/harness/questions-seam.d.ts.map +1 -0
- package/lib/harness/questions-seam.js +45 -0
- package/lib/harness/questions-seam.js.map +1 -0
- package/lib/harness/types.d.ts +108 -0
- package/lib/harness/types.d.ts.map +1 -0
- package/lib/harness/types.js +23 -0
- package/lib/harness/types.js.map +1 -0
- package/lib/index.d.ts +65 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +977 -0
- package/lib/index.js.map +1 -0
- package/lib/interact/approvals.d.ts +59 -0
- package/lib/interact/approvals.d.ts.map +1 -0
- package/lib/interact/approvals.js +132 -0
- package/lib/interact/approvals.js.map +1 -0
- package/lib/interact/pending.d.ts +56 -0
- package/lib/interact/pending.d.ts.map +1 -0
- package/lib/interact/pending.js +89 -0
- package/lib/interact/pending.js.map +1 -0
- package/lib/interact/questions.d.ts +100 -0
- package/lib/interact/questions.d.ts.map +1 -0
- package/lib/interact/questions.js +255 -0
- package/lib/interact/questions.js.map +1 -0
- package/lib/interact/surface.d.ts +33 -0
- package/lib/interact/surface.d.ts.map +1 -0
- package/lib/interact/surface.js +39 -0
- package/lib/interact/surface.js.map +1 -0
- package/lib/interact/text-capture.d.ts +38 -0
- package/lib/interact/text-capture.d.ts.map +1 -0
- package/lib/interact/text-capture.js +75 -0
- package/lib/interact/text-capture.js.map +1 -0
- package/lib/media/collect.d.ts +157 -0
- package/lib/media/collect.d.ts.map +1 -0
- package/lib/media/collect.js +235 -0
- package/lib/media/collect.js.map +1 -0
- package/lib/media/extractor.d.ts +117 -0
- package/lib/media/extractor.d.ts.map +1 -0
- package/lib/media/extractor.js +207 -0
- package/lib/media/extractor.js.map +1 -0
- package/lib/media/intake.d.ts +57 -0
- package/lib/media/intake.d.ts.map +1 -0
- package/lib/media/intake.js +115 -0
- package/lib/media/intake.js.map +1 -0
- package/lib/media/limits.d.ts +69 -0
- package/lib/media/limits.d.ts.map +1 -0
- package/lib/media/limits.js +97 -0
- package/lib/media/limits.js.map +1 -0
- package/lib/media/ocr.d.ts +66 -0
- package/lib/media/ocr.d.ts.map +1 -0
- package/lib/media/ocr.js +131 -0
- package/lib/media/ocr.js.map +1 -0
- package/lib/media/screenshot.d.ts +57 -0
- package/lib/media/screenshot.d.ts.map +1 -0
- package/lib/media/screenshot.js +101 -0
- package/lib/media/screenshot.js.map +1 -0
- package/lib/media/vision.d.ts +60 -0
- package/lib/media/vision.d.ts.map +1 -0
- package/lib/media/vision.js +74 -0
- package/lib/media/vision.js.map +1 -0
- package/lib/render/clamp.d.ts +34 -0
- package/lib/render/clamp.d.ts.map +1 -0
- package/lib/render/clamp.js +65 -0
- package/lib/render/clamp.js.map +1 -0
- package/lib/render/escape.d.ts +15 -0
- package/lib/render/escape.d.ts.map +1 -0
- package/lib/render/escape.js +17 -0
- package/lib/render/escape.js.map +1 -0
- package/lib/reply/activity.d.ts +31 -0
- package/lib/reply/activity.d.ts.map +1 -0
- package/lib/reply/activity.js +88 -0
- package/lib/reply/activity.js.map +1 -0
- package/lib/reply/rich-stream.d.ts +173 -0
- package/lib/reply/rich-stream.d.ts.map +1 -0
- package/lib/reply/rich-stream.js +286 -0
- package/lib/reply/rich-stream.js.map +1 -0
- package/lib/reply/split-markdown.d.ts +21 -0
- package/lib/reply/split-markdown.d.ts.map +1 -0
- package/lib/reply/split-markdown.js +87 -0
- package/lib/reply/split-markdown.js.map +1 -0
- package/lib/reply/turn-bridge.d.ts +143 -0
- package/lib/reply/turn-bridge.d.ts.map +1 -0
- package/lib/reply/turn-bridge.js +182 -0
- package/lib/reply/turn-bridge.js.map +1 -0
- package/lib/router.d.ts +415 -0
- package/lib/router.d.ts.map +1 -0
- package/lib/router.js +663 -0
- package/lib/router.js.map +1 -0
- package/lib/secrets.d.ts +30 -0
- package/lib/secrets.d.ts.map +1 -0
- package/lib/secrets.js +51 -0
- package/lib/secrets.js.map +1 -0
- package/lib/session/bindings.d.ts +81 -0
- package/lib/session/bindings.d.ts.map +1 -0
- package/lib/session/bindings.js +170 -0
- package/lib/session/bindings.js.map +1 -0
- package/lib/session/history.d.ts +50 -0
- package/lib/session/history.d.ts.map +1 -0
- package/lib/session/history.js +127 -0
- package/lib/session/history.js.map +1 -0
- package/lib/session/models.d.ts +99 -0
- package/lib/session/models.d.ts.map +1 -0
- package/lib/session/models.js +123 -0
- package/lib/session/models.js.map +1 -0
- package/lib/session/permission.d.ts +83 -0
- package/lib/session/permission.d.ts.map +1 -0
- package/lib/session/permission.js +107 -0
- package/lib/session/permission.js.map +1 -0
- package/lib/session/picker.d.ts +49 -0
- package/lib/session/picker.d.ts.map +1 -0
- package/lib/session/picker.js +107 -0
- package/lib/session/picker.js.map +1 -0
- package/lib/session/preferences.d.ts +55 -0
- package/lib/session/preferences.d.ts.map +1 -0
- package/lib/session/preferences.js +102 -0
- package/lib/session/preferences.js.map +1 -0
- package/lib/session/recovery.d.ts +66 -0
- package/lib/session/recovery.d.ts.map +1 -0
- package/lib/session/recovery.js +112 -0
- package/lib/session/recovery.js.map +1 -0
- package/lib/session/runner.d.ts +223 -0
- package/lib/session/runner.d.ts.map +1 -0
- package/lib/session/runner.js +260 -0
- package/lib/session/runner.js.map +1 -0
- package/lib/session/workspaces.d.ts +28 -0
- package/lib/session/workspaces.d.ts.map +1 -0
- package/lib/session/workspaces.js +53 -0
- package/lib/session/workspaces.js.map +1 -0
- package/lib/telegram/addressing.d.ts +39 -0
- package/lib/telegram/addressing.d.ts.map +1 -0
- package/lib/telegram/addressing.js +81 -0
- package/lib/telegram/addressing.js.map +1 -0
- package/lib/telegram/albums.d.ts +46 -0
- package/lib/telegram/albums.d.ts.map +1 -0
- package/lib/telegram/albums.js +104 -0
- package/lib/telegram/albums.js.map +1 -0
- package/lib/telegram/api.d.ts +238 -0
- package/lib/telegram/api.d.ts.map +1 -0
- package/lib/telegram/api.js +518 -0
- package/lib/telegram/api.js.map +1 -0
- package/lib/telegram/poller.d.ts +59 -0
- package/lib/telegram/poller.d.ts.map +1 -0
- package/lib/telegram/poller.js +94 -0
- package/lib/telegram/poller.js.map +1 -0
- package/lib/telegram/types.d.ts +130 -0
- package/lib/telegram/types.d.ts.map +1 -0
- package/lib/telegram/types.js +9 -0
- package/lib/telegram/types.js.map +1 -0
- package/lib/telegram/typing.d.ts +47 -0
- package/lib/telegram/typing.d.ts.map +1 -0
- package/lib/telegram/typing.js +91 -0
- package/lib/telegram/typing.js.map +1 -0
- package/lib/versions.d.ts +63 -0
- package/lib/versions.d.ts.map +1 -0
- package/lib/versions.js +135 -0
- package/lib/versions.js.map +1 -0
- package/package.json +94 -10
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changing which model a live agent's next step runs on.
|
|
3
|
+
*
|
|
4
|
+
* The harness holds one mutable selection object per agent, installed while
|
|
5
|
+
* the agent is still unpublished, and reads `current` each time it assembles a
|
|
6
|
+
* prompt. Mutating that object is how the web UI's model picker changes a
|
|
7
|
+
* running session's model, and it is what lets a conversation carrying an
|
|
8
|
+
* image run somewhere its neighbours do not.
|
|
9
|
+
*
|
|
10
|
+
* `current: undefined` means "no override", so the agent falls back to the
|
|
11
|
+
* route it was created with. That is what makes reverting free: there is
|
|
12
|
+
* nothing to restore, only an override to drop.
|
|
13
|
+
*
|
|
14
|
+
* ## Why this is reproduced rather than imported
|
|
15
|
+
*
|
|
16
|
+
* The harness exports `installModelSelection` from `@deepseek-ai/dsh-agent`,
|
|
17
|
+
* and importing it would be the obvious thing to do. It cannot be done: under
|
|
18
|
+
* pnpm's isolated layout a plugin resolves only its own declared dependencies,
|
|
19
|
+
* and the harness packages are the host's, not ours. A dynamic import of them
|
|
20
|
+
* fails with `ERR_MODULE_NOT_FOUND` every time — which is exactly how this
|
|
21
|
+
* feature came to do nothing at all while looking like it worked.
|
|
22
|
+
*
|
|
23
|
+
* What it does is two listener registrations on the agent's own context, so
|
|
24
|
+
* that is what this does. The coupling is to two event names and their
|
|
25
|
+
* payloads; `test/model-selection.test.ts` pins both.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Make an agent follow a mutable selection.
|
|
29
|
+
*
|
|
30
|
+
* @param agentCtx - the agent's scoped context, during unpublished setup.
|
|
31
|
+
* @param selection - the object whose `current` decides each step's route.
|
|
32
|
+
* @returns a disposer removing both listeners.
|
|
33
|
+
*/
|
|
34
|
+
export function installModelSelection(agentCtx, selection) {
|
|
35
|
+
const disposeAssembly = agentCtx.on('system-prompt/assemble', async (_assembly, _context, next) => {
|
|
36
|
+
const selected = selection.current;
|
|
37
|
+
const assembled = await next();
|
|
38
|
+
// Recorded even when absent: the request half reads this, and a stale
|
|
39
|
+
// value would route one step on a selection another step assembled.
|
|
40
|
+
selection.assembled = selected;
|
|
41
|
+
if (selected === undefined)
|
|
42
|
+
return assembled;
|
|
43
|
+
return {
|
|
44
|
+
...assembled,
|
|
45
|
+
variables: {
|
|
46
|
+
...assembled.variables,
|
|
47
|
+
provider: selected.provider,
|
|
48
|
+
model: selected.model,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
const disposeRequest = agentCtx.on('agent/request', async (_payload, next) => {
|
|
53
|
+
const resolved = await next();
|
|
54
|
+
const selected = selection.assembled;
|
|
55
|
+
if (selected === undefined)
|
|
56
|
+
return resolved;
|
|
57
|
+
// The inherited effort is dropped rather than kept: it belongs to the
|
|
58
|
+
// model being replaced, and a effort one model offers another may not.
|
|
59
|
+
const { reasoningEffort: _inherited, ...withoutInheritedEffort } = resolved;
|
|
60
|
+
return {
|
|
61
|
+
...withoutInheritedEffort,
|
|
62
|
+
provider: selected.provider,
|
|
63
|
+
model: selected.model,
|
|
64
|
+
...(selected.reasoningEffort === undefined
|
|
65
|
+
? {}
|
|
66
|
+
: { reasoningEffort: selected.reasoningEffort }),
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return () => {
|
|
70
|
+
disposeAssembly();
|
|
71
|
+
disposeRequest();
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Whether two routes name the same model and reasoning effort. */
|
|
75
|
+
export function sameRoute(a, b) {
|
|
76
|
+
if (a === undefined || b === undefined)
|
|
77
|
+
return a === b;
|
|
78
|
+
return (a.provider === b.provider &&
|
|
79
|
+
a.model === b.model &&
|
|
80
|
+
a.reasoningEffort === b.reasoningEffort);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse a `provider/model` setting.
|
|
84
|
+
*
|
|
85
|
+
* A model id may itself contain slashes — `openai/gpt-5` on a router-style
|
|
86
|
+
* provider is ordinary — so only the first separator divides them.
|
|
87
|
+
*
|
|
88
|
+
* @param value - the configured string; empty means no vision model.
|
|
89
|
+
* @returns the route, or undefined when unset or malformed.
|
|
90
|
+
*/
|
|
91
|
+
export function parseRoute(value) {
|
|
92
|
+
const trimmed = value?.trim();
|
|
93
|
+
if (!trimmed)
|
|
94
|
+
return undefined;
|
|
95
|
+
const separator = trimmed.indexOf('/');
|
|
96
|
+
if (separator <= 0 || separator === trimmed.length - 1)
|
|
97
|
+
return undefined;
|
|
98
|
+
return {
|
|
99
|
+
provider: trimmed.slice(0, separator),
|
|
100
|
+
model: trimmed.slice(separator + 1),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=model-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../src/harness/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAmDH;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAA0B,EAC1B,SAA2B;IAE3B,MAAM,eAAe,GAAG,QAAQ,CAAC,EAAE,CACjC,wBAAwB,EACxB,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAA;QAClC,MAAM,SAAS,GAAG,MAAM,IAAI,EAAE,CAAA;QAE9B,sEAAsE;QACtE,oEAAoE;QACpE,SAAS,CAAC,SAAS,GAAG,QAAQ,CAAA;QAC9B,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAE5C,OAAO;YACL,GAAG,SAAS;YACZ,SAAS,EAAE;gBACT,GAAG,SAAS,CAAC,SAAS;gBACtB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;aACtB;SACF,CAAA;IACH,CAAC,CACF,CAAA;IAED,MAAM,cAAc,GAAG,QAAQ,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAC3E,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAA;QAC7B,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAA;QACpC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAA;QAE3C,sEAAsE;QACtE,uEAAuE;QACvE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,sBAAsB,EAAE,GAAG,QAAQ,CAAA;QAE3E,OAAO;YACL,GAAG,sBAAsB;YACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,GAAG,CAAC,QAAQ,CAAC,eAAe,KAAK,SAAS;gBACxC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC;SACnD,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,EAAE;QACV,eAAe,EAAE,CAAA;QACjB,cAAc,EAAE,CAAA;IAClB,CAAC,CAAA;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,SAAS,CAAC,CAAyB,EAAE,CAAyB;IAC5E,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IACtD,OAAO,CACL,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;QACzB,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK;QACnB,CAAC,CAAC,eAAe,KAAK,CAAC,CAAC,eAAe,CACxC,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAE9B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACtC,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAExE,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;QACrC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;KACpC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taking over the single user-questions provider without stealing it.
|
|
3
|
+
*
|
|
4
|
+
* `ctx.userQuestions` accepts exactly one provider and throws
|
|
5
|
+
* `DUPLICATE_PROVIDER` on a second registration. In a profile that also runs
|
|
6
|
+
* the web app, the browser has already claimed that slot — so a naive
|
|
7
|
+
* registration here would either fail to load or, worse, silently take every
|
|
8
|
+
* question away from the browser.
|
|
9
|
+
*
|
|
10
|
+
* Instead this seam swaps itself in and keeps the displaced provider as a
|
|
11
|
+
* fallback, so a question belonging to a browser session is forwarded straight
|
|
12
|
+
* back to it. Both surfaces keep working, and whichever one the user is
|
|
13
|
+
* actually looking at is the one that answers.
|
|
14
|
+
*
|
|
15
|
+
* On unload the previous provider is put back, so unloading this plugin
|
|
16
|
+
* restores exactly the arrangement that existed before it loaded.
|
|
17
|
+
*/
|
|
18
|
+
import type { Logger, UserQuestionProvider, UserQuestionService } from './types.js';
|
|
19
|
+
/** What was installed, and how to undo it. */
|
|
20
|
+
export interface QuestionSeam {
|
|
21
|
+
/** The provider that was registered before, if any. */
|
|
22
|
+
readonly previous: UserQuestionProvider | undefined;
|
|
23
|
+
/** Restore the previous arrangement. */
|
|
24
|
+
restore(): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Install a provider as the active one, chaining any incumbent.
|
|
28
|
+
*
|
|
29
|
+
* @param service - the live `ctx.userQuestions` service.
|
|
30
|
+
* @param build - builds the provider, given the incumbent to delegate to.
|
|
31
|
+
* @param logger - records which arrangement was chosen.
|
|
32
|
+
*/
|
|
33
|
+
export declare function installQuestionProvider(service: UserQuestionService, build: (previous: UserQuestionProvider | undefined) => UserQuestionProvider, logger?: Logger): QuestionSeam;
|
|
34
|
+
//# sourceMappingURL=questions-seam.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions-seam.d.ts","sourceRoot":"","sources":["../../src/harness/questions-seam.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEnF,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,CAAA;IACnD,wCAAwC;IACxC,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,KAAK,oBAAoB,EAC3E,MAAM,CAAC,EAAE,MAAM,GACd,YAAY,CAwBd"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taking over the single user-questions provider without stealing it.
|
|
3
|
+
*
|
|
4
|
+
* `ctx.userQuestions` accepts exactly one provider and throws
|
|
5
|
+
* `DUPLICATE_PROVIDER` on a second registration. In a profile that also runs
|
|
6
|
+
* the web app, the browser has already claimed that slot — so a naive
|
|
7
|
+
* registration here would either fail to load or, worse, silently take every
|
|
8
|
+
* question away from the browser.
|
|
9
|
+
*
|
|
10
|
+
* Instead this seam swaps itself in and keeps the displaced provider as a
|
|
11
|
+
* fallback, so a question belonging to a browser session is forwarded straight
|
|
12
|
+
* back to it. Both surfaces keep working, and whichever one the user is
|
|
13
|
+
* actually looking at is the one that answers.
|
|
14
|
+
*
|
|
15
|
+
* On unload the previous provider is put back, so unloading this plugin
|
|
16
|
+
* restores exactly the arrangement that existed before it loaded.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Install a provider as the active one, chaining any incumbent.
|
|
20
|
+
*
|
|
21
|
+
* @param service - the live `ctx.userQuestions` service.
|
|
22
|
+
* @param build - builds the provider, given the incumbent to delegate to.
|
|
23
|
+
* @param logger - records which arrangement was chosen.
|
|
24
|
+
*/
|
|
25
|
+
export function installQuestionProvider(service, build, logger) {
|
|
26
|
+
const previous = service.provider;
|
|
27
|
+
if (previous === undefined) {
|
|
28
|
+
const dispose = service.registerProvider(build(undefined));
|
|
29
|
+
logger?.info('[dsh-telegram] answering the agent\'s questions in Telegram');
|
|
30
|
+
return { previous: undefined, restore: dispose };
|
|
31
|
+
}
|
|
32
|
+
// Clearing the slot before re-registering is what makes the takeover
|
|
33
|
+
// possible; registerProvider refuses while one is present.
|
|
34
|
+
service.provider = undefined;
|
|
35
|
+
const dispose = service.registerProvider(build(previous));
|
|
36
|
+
logger?.info('[dsh-telegram] answering questions in Telegram, forwarding other sessions to the existing UI');
|
|
37
|
+
return {
|
|
38
|
+
previous,
|
|
39
|
+
restore() {
|
|
40
|
+
dispose();
|
|
41
|
+
service.provider = previous;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=questions-seam.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions-seam.js","sourceRoot":"","sources":["../../src/harness/questions-seam.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA4B,EAC5B,KAA2E,EAC3E,MAAe;IAEf,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IAEjC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;QAC1D,MAAM,EAAE,IAAI,CAAC,6DAA6D,CAAC,CAAA;QAC3E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;IAClD,CAAC;IAED,qEAAqE;IACrE,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAA;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IACzD,MAAM,EAAE,IAAI,CACV,8FAA8F,CAC/F,CAAA;IAED,OAAO;QACL,QAAQ;QACR,OAAO;YACL,OAAO,EAAE,CAAA;YACT,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAC7B,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural mirrors of the DeepSeek Harness seams this plugin plugs into.
|
|
3
|
+
*
|
|
4
|
+
* These are declared rather than imported so the package builds and tests on
|
|
5
|
+
* its own, without a harness checkout. They are structural types: the plugin
|
|
6
|
+
* entry casts the live `ctx` services to them at the single boundary where the
|
|
7
|
+
* harness is actually present, so a drift in the real contract shows up there
|
|
8
|
+
* instead of spreading through every module.
|
|
9
|
+
*
|
|
10
|
+
* Sources mirrored:
|
|
11
|
+
* - `@deepseek-ai/dsh-user-questions` — `ctx.userQuestions`
|
|
12
|
+
* - `@deepseek-ai/dsh-user-approval` — the `approval/request` waterfall
|
|
13
|
+
* - `@deepseek-ai/dsh-agent` — `ctx.agents`
|
|
14
|
+
* - `@deepseek-ai/dsh-session` — the `session/event` feed
|
|
15
|
+
*/
|
|
16
|
+
/** One selectable answer offered to the user. */
|
|
17
|
+
export interface AskUserQuestionOption {
|
|
18
|
+
readonly label: string;
|
|
19
|
+
readonly description?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A caller-declared presentation intent. `plan-review` means the question IS a
|
|
23
|
+
* plan approval, and `detail` carries the plan itself.
|
|
24
|
+
*/
|
|
25
|
+
export interface AskUserQuestionIntent {
|
|
26
|
+
readonly kind: 'plan-review';
|
|
27
|
+
/** The option label that approves; every other option declines. */
|
|
28
|
+
readonly approve: string;
|
|
29
|
+
}
|
|
30
|
+
/** One question in a user-questions request. */
|
|
31
|
+
export interface AskUserQuestionItem {
|
|
32
|
+
readonly id: string;
|
|
33
|
+
readonly question: string;
|
|
34
|
+
readonly detail?: string;
|
|
35
|
+
readonly header?: string;
|
|
36
|
+
readonly options?: readonly AskUserQuestionOption[];
|
|
37
|
+
readonly multiSelect?: boolean;
|
|
38
|
+
readonly intent?: AskUserQuestionIntent;
|
|
39
|
+
}
|
|
40
|
+
/** Answer to one question. */
|
|
41
|
+
export interface AskUserQuestionAnswerItem {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly selected: string[];
|
|
44
|
+
readonly custom?: string;
|
|
45
|
+
}
|
|
46
|
+
/** The human's answer to a whole request. */
|
|
47
|
+
export interface AskUserQuestionAnswer {
|
|
48
|
+
readonly answers: AskUserQuestionAnswerItem[];
|
|
49
|
+
}
|
|
50
|
+
/** A live agent, as far as this plugin needs to know. */
|
|
51
|
+
export interface HarnessAgent {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly session: {
|
|
54
|
+
readonly id: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** One `ctx.userQuestions.ask()` request. */
|
|
58
|
+
export interface UserQuestionRequest {
|
|
59
|
+
readonly questions: readonly AskUserQuestionItem[];
|
|
60
|
+
readonly agent?: HarnessAgent;
|
|
61
|
+
readonly signal?: AbortSignal;
|
|
62
|
+
}
|
|
63
|
+
/** The single UI provider registered on `ctx.userQuestions`. */
|
|
64
|
+
export interface UserQuestionProvider {
|
|
65
|
+
ask(request: UserQuestionRequest): Promise<AskUserQuestionAnswer>;
|
|
66
|
+
}
|
|
67
|
+
/** `ctx.userQuestions` — the seam we register against, and take over. */
|
|
68
|
+
export interface UserQuestionService {
|
|
69
|
+
/** Explicitly clearable: taking the slot over requires emptying it first. */
|
|
70
|
+
provider?: UserQuestionProvider | undefined;
|
|
71
|
+
registerProvider(provider: UserQuestionProvider): () => void;
|
|
72
|
+
}
|
|
73
|
+
/** Every outcome the approval waterfall may produce; only one is a grant. */
|
|
74
|
+
export type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable';
|
|
75
|
+
/** One pending approval decision. */
|
|
76
|
+
export interface ApprovalRequest {
|
|
77
|
+
readonly agent: HarnessAgent;
|
|
78
|
+
readonly toolName: string;
|
|
79
|
+
readonly callId?: string;
|
|
80
|
+
readonly reason?: string;
|
|
81
|
+
readonly signal?: AbortSignal;
|
|
82
|
+
}
|
|
83
|
+
/** The minimal logger surface the harness hands a plugin. */
|
|
84
|
+
export interface Logger {
|
|
85
|
+
info(message: string, ...rest: unknown[]): void;
|
|
86
|
+
warn(message: string, ...rest: unknown[]): void;
|
|
87
|
+
error(message: string, ...rest: unknown[]): void;
|
|
88
|
+
debug(message: string, ...rest: unknown[]): void;
|
|
89
|
+
}
|
|
90
|
+
/** A no-op logger, so every module can take a logger without a null check. */
|
|
91
|
+
export declare const SILENT_LOGGER: Logger;
|
|
92
|
+
/** One registered settings namespace, from the owner's side. */
|
|
93
|
+
export interface SettingsScope<T> {
|
|
94
|
+
/** The resolved value: schema defaults, then composition base, then user document. */
|
|
95
|
+
get(): T;
|
|
96
|
+
/** Observe committed changes; returns a disposer. */
|
|
97
|
+
watch(callback: (next: T, previous: T) => void): () => void;
|
|
98
|
+
/** Merge a patch into the user layer. */
|
|
99
|
+
update(patch: Partial<T>): Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
/** `ctx.settings` — the seam a configuration UI reads and writes through. */
|
|
102
|
+
export interface SettingsService {
|
|
103
|
+
register<T>(namespace: string, schema: unknown, options?: {
|
|
104
|
+
base?: unknown;
|
|
105
|
+
applies?: string;
|
|
106
|
+
}): SettingsScope<T>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural mirrors of the DeepSeek Harness seams this plugin plugs into.
|
|
3
|
+
*
|
|
4
|
+
* These are declared rather than imported so the package builds and tests on
|
|
5
|
+
* its own, without a harness checkout. They are structural types: the plugin
|
|
6
|
+
* entry casts the live `ctx` services to them at the single boundary where the
|
|
7
|
+
* harness is actually present, so a drift in the real contract shows up there
|
|
8
|
+
* instead of spreading through every module.
|
|
9
|
+
*
|
|
10
|
+
* Sources mirrored:
|
|
11
|
+
* - `@deepseek-ai/dsh-user-questions` — `ctx.userQuestions`
|
|
12
|
+
* - `@deepseek-ai/dsh-user-approval` — the `approval/request` waterfall
|
|
13
|
+
* - `@deepseek-ai/dsh-agent` — `ctx.agents`
|
|
14
|
+
* - `@deepseek-ai/dsh-session` — the `session/event` feed
|
|
15
|
+
*/
|
|
16
|
+
/** A no-op logger, so every module can take a logger without a null check. */
|
|
17
|
+
export const SILENT_LOGGER = {
|
|
18
|
+
info: () => undefined,
|
|
19
|
+
warn: () => undefined,
|
|
20
|
+
error: () => undefined,
|
|
21
|
+
debug: () => undefined,
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAsFH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,aAAa,GAAW;IACnC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;CACvB,CAAA"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-telegram — a Telegram front end for DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* Two things this plugin does that a plain channel bridge does not:
|
|
5
|
+
*
|
|
6
|
+
* 1. **The agent's markdown arrives as markdown.** Replies are rendered to
|
|
7
|
+
* Telegram HTML and sent with `parse_mode`, so bold is bold and a code
|
|
8
|
+
* block is a code block — including while the answer is still streaming.
|
|
9
|
+
* 2. **Questions and approvals can be answered from the chat.** The plugin
|
|
10
|
+
* registers a `ctx.userQuestions` provider and answers the
|
|
11
|
+
* `approval/request` waterfall, so `ask_user_question` and a tool that
|
|
12
|
+
* needs consent both become buttons in Telegram instead of a stall that
|
|
13
|
+
* only a browser can clear.
|
|
14
|
+
*
|
|
15
|
+
* Everything here is wiring. The behaviour lives in the modules below, each
|
|
16
|
+
* testable without a harness; this file is the single place that touches the
|
|
17
|
+
* live `ctx`.
|
|
18
|
+
*/
|
|
19
|
+
import { Config } from './config.js';
|
|
20
|
+
import type { AgentRegistryLike } from './harness/host.js';
|
|
21
|
+
import type { Logger } from './harness/types.js';
|
|
22
|
+
import type { TelegramConfig } from './config.js';
|
|
23
|
+
export { Config };
|
|
24
|
+
export type { TelegramConfig };
|
|
25
|
+
/** Cordis plugin name; the package name, which is also the module id. */
|
|
26
|
+
export declare const name = "@sympoies/dsh-telegram";
|
|
27
|
+
/**
|
|
28
|
+
* Settings namespace this plugin owns. The browser half binds the same string,
|
|
29
|
+
* which is the only thing pairing the two halves together.
|
|
30
|
+
*/
|
|
31
|
+
export declare const SETTINGS_NAMESPACE = "telegram";
|
|
32
|
+
/**
|
|
33
|
+
* Hard requirements only. Cordis reads this as a flat list of service names —
|
|
34
|
+
* an object form would be read as services literally named after its keys — so
|
|
35
|
+
* the interactive seams are bound inside `apply` with `ctx.inject()` instead.
|
|
36
|
+
* That is what lets the plugin load on a profile that provides neither.
|
|
37
|
+
*/
|
|
38
|
+
export declare const inject: string[];
|
|
39
|
+
/** The slice of the cordis context this plugin uses. */
|
|
40
|
+
interface PluginContext {
|
|
41
|
+
agents: AgentRegistryLike;
|
|
42
|
+
credentials: {
|
|
43
|
+
resolve(ref: unknown): Promise<{
|
|
44
|
+
value?: string;
|
|
45
|
+
} | undefined>;
|
|
46
|
+
};
|
|
47
|
+
logger(name: string): Logger;
|
|
48
|
+
get(key: string): unknown;
|
|
49
|
+
on(name: string, listener: (...args: never[]) => unknown, prepend?: boolean): () => void;
|
|
50
|
+
effect(callback: () => (() => void) | Promise<() => void>, label?: string): () => void;
|
|
51
|
+
/** Run `callback` once every named service is available; never, if one is not. */
|
|
52
|
+
inject(names: readonly string[], callback: (scope: PluginContext) => void): Disposable;
|
|
53
|
+
}
|
|
54
|
+
/** What `ctx.inject` hands back: a fiber whose disposal unwinds the callback. */
|
|
55
|
+
interface Disposable {
|
|
56
|
+
dispose(): unknown;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Load the plugin.
|
|
60
|
+
*
|
|
61
|
+
* @param ctx - the cordis context.
|
|
62
|
+
* @param config - resolved plugin configuration.
|
|
63
|
+
*/
|
|
64
|
+
export declare function apply(ctx: PluginContext, config: TelegramConfig): void;
|
|
65
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAaH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAqCpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,KAAK,EAGV,MAAM,EAGP,MAAM,oBAAoB,CAAA;AAG3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,MAAM,EAAE,CAAA;AACjB,YAAY,EAAE,cAAc,EAAE,CAAA;AAE9B,yEAAyE;AACzE,eAAO,MAAM,IAAI,2BAA2B,CAAA;AAE5C;;;GAGG;AACH,eAAO,MAAM,kBAAkB,aAAa,CAAA;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,MAAM,UAA4B,CAAA;AAE/C,wDAAwD;AACxD,UAAU,aAAa;IACrB,MAAM,EAAE,iBAAiB,CAAA;IACzB,WAAW,EAAE;QAAE,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC,CAAA;KAAE,CAAA;IAC/E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACzB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,IAAI,CAAA;IACxF,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAA;IACtF,kFAAkF;IAClF,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,UAAU,CAAA;CACvF;AAED,iFAAiF;AACjF,UAAU,UAAU;IAClB,OAAO,IAAI,OAAO,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuFtE"}
|