@lemoncat7/dsh-partner 0.1.0-alpha.13

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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/cordis.patch.yml +9 -0
  4. package/lib/agent-runtime.d.ts +42 -0
  5. package/lib/agent-runtime.d.ts.map +1 -0
  6. package/lib/agent-runtime.js +203 -0
  7. package/lib/agent-runtime.js.map +1 -0
  8. package/lib/api.d.ts +28 -0
  9. package/lib/api.d.ts.map +1 -0
  10. package/lib/api.js +196 -0
  11. package/lib/api.js.map +1 -0
  12. package/lib/channels/manager.d.ts +28 -0
  13. package/lib/channels/manager.d.ts.map +1 -0
  14. package/lib/channels/manager.js +205 -0
  15. package/lib/channels/manager.js.map +1 -0
  16. package/lib/channels/weixin/api.d.ts +15 -0
  17. package/lib/channels/weixin/api.d.ts.map +1 -0
  18. package/lib/channels/weixin/api.js +86 -0
  19. package/lib/channels/weixin/api.js.map +1 -0
  20. package/lib/channels/weixin/login.d.ts +24 -0
  21. package/lib/channels/weixin/login.d.ts.map +1 -0
  22. package/lib/channels/weixin/login.js +71 -0
  23. package/lib/channels/weixin/login.js.map +1 -0
  24. package/lib/channels/weixin/types.d.ts +40 -0
  25. package/lib/channels/weixin/types.d.ts.map +1 -0
  26. package/lib/channels/weixin/types.js +2 -0
  27. package/lib/channels/weixin/types.js.map +1 -0
  28. package/lib/client-api.d.ts +69 -0
  29. package/lib/client-api.d.ts.map +1 -0
  30. package/lib/client-api.js +20 -0
  31. package/lib/client-api.js.map +1 -0
  32. package/lib/client.d.ts +4 -0
  33. package/lib/client.d.ts.map +1 -0
  34. package/lib/client.js +1916 -0
  35. package/lib/client.js.map +7 -0
  36. package/lib/config.d.ts +11 -0
  37. package/lib/config.d.ts.map +1 -0
  38. package/lib/config.js +27 -0
  39. package/lib/config.js.map +1 -0
  40. package/lib/credentials.d.ts +14 -0
  41. package/lib/credentials.d.ts.map +1 -0
  42. package/lib/credentials.js +28 -0
  43. package/lib/credentials.js.map +1 -0
  44. package/lib/domain.d.ts +71 -0
  45. package/lib/domain.d.ts.map +1 -0
  46. package/lib/domain.js +57 -0
  47. package/lib/domain.js.map +1 -0
  48. package/lib/index.d.ts +9 -0
  49. package/lib/index.d.ts.map +1 -0
  50. package/lib/index.js +46 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/sidebar-anchor.d.ts +3 -0
  53. package/lib/sidebar-anchor.d.ts.map +1 -0
  54. package/lib/sidebar-anchor.js +38 -0
  55. package/lib/sidebar-anchor.js.map +1 -0
  56. package/lib/store.d.ts +12 -0
  57. package/lib/store.d.ts.map +1 -0
  58. package/lib/store.js +101 -0
  59. package/lib/store.js.map +1 -0
  60. package/package.json +111 -0
package/lib/domain.js ADDED
@@ -0,0 +1,57 @@
1
+ export function normalizeCompanionDraft(value) {
2
+ const input = object(value, 'companion');
3
+ const capabilities = Array.isArray(input.capabilities)
4
+ ? input.capabilities.map(item => text(item, 'capability', 32)).filter(isCapability)
5
+ : [];
6
+ const draft = {
7
+ name: text(input.name, 'name', 60),
8
+ role: optionalText(input.role, 'role', 120) ?? '长期 AI 工作伙伴',
9
+ description: optionalText(input.description, 'description', 500) ?? '',
10
+ instructions: optionalText(input.instructions, 'instructions', 12_000) ?? '',
11
+ capabilities: [...new Set(capabilities)],
12
+ };
13
+ const presetId = optionalText(input.presetId, 'presetId', 100);
14
+ const provider = optionalText(input.provider, 'provider', 100);
15
+ const model = optionalText(input.model, 'model', 200);
16
+ if (presetId !== undefined)
17
+ draft.presetId = presetId;
18
+ if (provider !== undefined)
19
+ draft.provider = provider;
20
+ if (model !== undefined)
21
+ draft.model = model;
22
+ return draft;
23
+ }
24
+ export function createDefaultCompanion(now = Date.now()) {
25
+ return {
26
+ id: 'companion-default',
27
+ name: '墨伴',
28
+ role: '长期 AI 工作伙伴',
29
+ description: '在桌面和微信之间保持同一工作身份与独立上下文。',
30
+ instructions: '你是用户长期信任的工作伙伴。保持清晰、可靠、克制;需要使用工具时先核对目标和权限,不要猜测执行结果。',
31
+ capabilities: ['knowledge', 'skills'],
32
+ createdAt: now,
33
+ updatedAt: now,
34
+ };
35
+ }
36
+ export function object(value, label) {
37
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
38
+ throw new Error(`${label} must be an object`);
39
+ return value;
40
+ }
41
+ export function text(value, label, max) {
42
+ if (typeof value !== 'string' || value.trim().length === 0)
43
+ throw new Error(`${label} is required`);
44
+ const normalized = value.trim();
45
+ if (normalized.length > max)
46
+ throw new Error(`${label} is too long`);
47
+ return normalized;
48
+ }
49
+ function optionalText(value, label, max) {
50
+ if (value === undefined || value === null || value === '')
51
+ return undefined;
52
+ return text(value, label, max);
53
+ }
54
+ function isCapability(value) {
55
+ return value === 'knowledge' || value === 'skills' || value === 'ssh' || value === 'git';
56
+ }
57
+ //# sourceMappingURL=domain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.js","sourceRoot":"","sources":["../src/domain.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import { Config as ConfigSchema, type Config as PartnerConfig } from './config.js';
3
+ export declare const Config: import("@deepseek-ai/schemastery").default<ConfigSchema>;
4
+ export type Config = PartnerConfig;
5
+ export * from './domain.js';
6
+ export declare const name = "dsh-partner";
7
+ export declare const inject: string[];
8
+ export declare function apply(context: Context, config: PartnerConfig): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAKlD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,KAAK,MAAM,IAAI,aAAa,EAAE,MAAM,aAAa,CAAA;AAQjG,eAAO,MAAM,MAAM,0DAAe,CAAA;AAClC,MAAM,MAAM,MAAM,GAAG,aAAa,CAAA;AAClC,cAAc,aAAa,CAAA;AAC3B,eAAO,MAAM,IAAI,gBAAgB,CAAA;AACjC,eAAO,MAAM,MAAM,UAAsG,CAAA;AAWzH,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA2BnE"}
package/lib/index.js ADDED
@@ -0,0 +1,46 @@
1
+ import { Config as ConfigSchema, resolveConfig } from './config.js';
2
+ import { PartnerStore } from './store.js';
3
+ import { PartnerCredentialVault } from './credentials.js';
4
+ import { PartnerAgentRuntime } from './agent-runtime.js';
5
+ import { ChannelManager } from './channels/manager.js';
6
+ import { WeixinLoginManager } from './channels/weixin/login.js';
7
+ import { registerPartnerApi } from './api.js';
8
+ export const Config = ConfigSchema;
9
+ export * from './domain.js';
10
+ export const name = 'dsh-partner';
11
+ export const inject = ['credentials', 'agents', 'agentDefaultModel', 'agentPresets', 'systemPrompt', 'workspaceRegistry'];
12
+ export function apply(context, config) {
13
+ const ctx = context;
14
+ const resolved = resolveConfig(config);
15
+ ctx.effect(async () => {
16
+ const store = await PartnerStore.open(resolved.statePath);
17
+ const credentials = new PartnerCredentialVault(ctx.credentials);
18
+ const agents = new PartnerAgentRuntime(ctx, store, resolved.defaultCwd);
19
+ const channels = new ChannelManager(ctx, store, credentials, agents);
20
+ const login = new WeixinLoginManager();
21
+ let disposeApi;
22
+ const mountApi = (runtime) => {
23
+ if (!resolved.exposeWeb)
24
+ return;
25
+ const webServer = runtime.webServer ?? runtime.get('webServer');
26
+ if (webServer === undefined)
27
+ throw new Error('dsh-partner exposeWeb requires webServer');
28
+ disposeApi = registerPartnerApi(webServer, resolved.apiPrefix, { ctx, store, credentials, channels, agents, login });
29
+ };
30
+ if (ctx.inject !== undefined)
31
+ ctx.inject(['webServer'], mountApi);
32
+ else if (ctx.webServer !== undefined)
33
+ mountApi(ctx);
34
+ else
35
+ ctx.logger.warn('dsh-partner: webServer is unavailable; companion management is disabled');
36
+ if (resolved.autoStartChannels)
37
+ await channels.startEnabled();
38
+ ctx.logger.info(`dsh-partner: ready with ${store.snapshot().companions.length} companion(s)`);
39
+ return async () => {
40
+ disposeApi?.();
41
+ await channels.close();
42
+ await agents.close();
43
+ };
44
+ }, 'dsh-partner.runtime');
45
+ }
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAsB,MAAM,UAAU,CAAA;AAEjE,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAA;AAElC,cAAc,aAAa,CAAA;AAC3B,MAAM,CAAC,MAAM,IAAI,GAAG,aAAa,CAAA;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,mBAAmB,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,CAAC,CAAA;AAWzH,MAAM,UAAU,KAAK,CAAC,OAAgB,EAAE,MAAqB;IAC3D,MAAM,GAAG,GAAG,OAAyB,CAAA;IACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACtC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;QACzD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,IAAI,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;QACvE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QACpE,MAAM,KAAK,GAAG,IAAI,kBAAkB,EAAE,CAAA;QACtC,IAAI,UAAoC,CAAA;QACxC,MAAM,QAAQ,GAAG,CAAC,OAAuB,EAAQ,EAAE;YACjD,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAAE,OAAM;YAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAA8B,CAAA;YAC5F,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;YACxF,UAAU,GAAG,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACtH,CAAC,CAAA;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAA;aAC5D,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAA;;YAC9C,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAA;QAC/F,IAAI,QAAQ,CAAC,iBAAiB;YAAE,MAAM,QAAQ,CAAC,YAAY,EAAE,CAAA;QAC7D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,KAAK,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,MAAM,eAAe,CAAC,CAAA;QAC7F,OAAO,KAAK,IAAI,EAAE;YAChB,UAAU,EAAE,EAAE,CAAA;YACd,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAA;YACtB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;QACtB,CAAC,CAAA;IACH,CAAC,EAAE,qBAAqB,CAAC,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type RefObject } from 'react';
2
+ export declare function useWorkspaceTopAnchor(ref: RefObject<HTMLElement>): void;
3
+ //# sourceMappingURL=sidebar-anchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar-anchor.d.ts","sourceRoot":"","sources":["../src/sidebar-anchor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,IAAI,CAgCvE"}
@@ -0,0 +1,38 @@
1
+ import { useEffect } from 'react';
2
+ export function useWorkspaceTopAnchor(ref) {
3
+ useEffect(() => {
4
+ const element = ref.current;
5
+ const originalParent = element?.parentElement;
6
+ if (!element || !originalParent)
7
+ return;
8
+ let moved = false;
9
+ let observer;
10
+ const place = () => {
11
+ let ancestor = element.parentElement;
12
+ while (ancestor && ancestor !== document.body) {
13
+ const candidate = ancestor.previousElementSibling;
14
+ if (candidate instanceof HTMLElement) {
15
+ const style = getComputedStyle(candidate);
16
+ if (style.display === 'flex' && style.flexDirection === 'column' && Number.parseFloat(style.flexGrow) > 0) {
17
+ candidate.insertBefore(element, candidate.firstChild);
18
+ moved = true;
19
+ return true;
20
+ }
21
+ }
22
+ ancestor = ancestor.parentElement;
23
+ }
24
+ return false;
25
+ };
26
+ if (!place()) {
27
+ observer = new MutationObserver(() => { if (place())
28
+ observer?.disconnect(); });
29
+ observer.observe(document.body, { childList: true, subtree: true });
30
+ }
31
+ return () => {
32
+ observer?.disconnect();
33
+ if (moved && originalParent.isConnected)
34
+ originalParent.append(element);
35
+ };
36
+ }, [ref]);
37
+ }
38
+ //# sourceMappingURL=sidebar-anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar-anchor.js","sourceRoot":"","sources":["../src/sidebar-anchor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAA;AAEjD,MAAM,UAAU,qBAAqB,CAAC,GAA2B;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAA;QAC3B,MAAM,cAAc,GAAG,OAAO,EAAE,aAAa,CAAA;QAC7C,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc;YAAE,OAAM;QACvC,IAAI,KAAK,GAAG,KAAK,CAAA;QACjB,IAAI,QAAsC,CAAA;QAC1C,MAAM,KAAK,GAAG,GAAY,EAAE;YAC1B,IAAI,QAAQ,GAAuB,OAAO,CAAC,aAAa,CAAA;YACxD,OAAO,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,sBAAsB,CAAA;gBACjD,IAAI,SAAS,YAAY,WAAW,EAAE,CAAC;oBACrC,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAA;oBACzC,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC1G,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,CAAA;wBACrD,KAAK,GAAG,IAAI,CAAA;wBACZ,OAAO,IAAI,CAAA;oBACb,CAAC;gBACH,CAAC;gBACD,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAA;YACnC,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC,CAAA;QACD,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACb,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,EAAE;gBAAE,QAAQ,EAAE,UAAU,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;YAC9E,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;QACrE,CAAC;QACD,OAAO,GAAG,EAAE;YACV,QAAQ,EAAE,UAAU,EAAE,CAAA;YACtB,IAAI,KAAK,IAAI,cAAc,CAAC,WAAW;gBAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACzE,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;AACX,CAAC"}
package/lib/store.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { type PartnerState } from './domain.js';
2
+ export declare class PartnerStore {
3
+ private readonly path;
4
+ private state;
5
+ private writes;
6
+ private constructor();
7
+ static open(path: string): Promise<PartnerStore>;
8
+ snapshot(): PartnerState;
9
+ update(change: (draft: PartnerState) => void): Promise<PartnerState>;
10
+ private persist;
11
+ }
12
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAEvE,qBAAa,YAAY;IAIH,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHzC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAAmC;IAEjD,OAAO;WAIM,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAetD,QAAQ,IAAI,YAAY;IAIlB,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAe5D,OAAO;CAmBtB"}
package/lib/store.js ADDED
@@ -0,0 +1,101 @@
1
+ import { mkdir, open, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ import { randomBytes } from 'node:crypto';
4
+ import { createDefaultCompanion } from './domain.js';
5
+ export class PartnerStore {
6
+ path;
7
+ state;
8
+ writes = Promise.resolve();
9
+ constructor(path, state) {
10
+ this.path = path;
11
+ this.state = state;
12
+ }
13
+ static async open(path) {
14
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
15
+ let state;
16
+ try {
17
+ state = parseState(JSON.parse(await readFile(path, 'utf8')));
18
+ }
19
+ catch (error) {
20
+ if (error.code !== 'ENOENT')
21
+ throw error;
22
+ state = emptyState();
23
+ const store = new PartnerStore(path, state);
24
+ await store.persist(state);
25
+ return store;
26
+ }
27
+ return new PartnerStore(path, state);
28
+ }
29
+ snapshot() {
30
+ return structuredClone(this.state);
31
+ }
32
+ async update(change) {
33
+ let resolveResult;
34
+ let rejectResult;
35
+ const result = new Promise((resolve, reject) => { resolveResult = resolve; rejectResult = reject; });
36
+ this.writes = this.writes.then(async () => {
37
+ const next = structuredClone(this.state);
38
+ change(next);
39
+ validateState(next);
40
+ await this.persist(next);
41
+ this.state = next;
42
+ resolveResult(this.snapshot());
43
+ }).catch(error => { rejectResult(error); });
44
+ return result;
45
+ }
46
+ async persist(state) {
47
+ const temporary = `${this.path}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`;
48
+ await writeFile(temporary, `${JSON.stringify(state, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
49
+ const file = await open(temporary, 'r+');
50
+ try {
51
+ await file.sync();
52
+ }
53
+ finally {
54
+ await file.close();
55
+ }
56
+ try {
57
+ await rename(temporary, this.path);
58
+ }
59
+ catch (error) {
60
+ if (process.platform !== 'win32' || !replaceError(error))
61
+ throw error;
62
+ await rm(this.path, { force: true });
63
+ await rename(temporary, this.path);
64
+ }
65
+ finally {
66
+ await rm(temporary, { force: true }).catch(() => { });
67
+ }
68
+ if (process.platform !== 'win32') {
69
+ const directory = await open(dirname(this.path), 'r');
70
+ try {
71
+ await directory.sync();
72
+ }
73
+ finally {
74
+ await directory.close();
75
+ }
76
+ }
77
+ }
78
+ }
79
+ function emptyState() {
80
+ return { schemaVersion: 1, companions: [createDefaultCompanion()], channels: [], pairings: [], sessions: [], recentReceipts: [] };
81
+ }
82
+ function parseState(value) {
83
+ validateState(value);
84
+ return value;
85
+ }
86
+ function validateState(value) {
87
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
88
+ throw new Error('partner state must be an object');
89
+ const state = value;
90
+ if (state.schemaVersion !== 1)
91
+ throw new Error('unsupported partner state schema');
92
+ for (const key of ['companions', 'channels', 'pairings', 'sessions', 'recentReceipts']) {
93
+ if (!Array.isArray(state[key]))
94
+ throw new Error(`partner state ${key} must be an array`);
95
+ }
96
+ }
97
+ function replaceError(error) {
98
+ const code = error.code;
99
+ return code === 'EPERM' || code === 'EACCES' || code === 'EEXIST';
100
+ }
101
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,111 @@
1
+ {
2
+ "name": "@lemoncat7/dsh-partner",
3
+ "version": "0.1.0-alpha.13",
4
+ "description": "Long-lived AI companions with WeChat channel routing for DeepSeek Harness",
5
+ "keywords": [
6
+ "deepseek-harness",
7
+ "dsh",
8
+ "dsh-plugin",
9
+ "companion",
10
+ "wechat",
11
+ "weixin"
12
+ ],
13
+ "license": "MIT",
14
+ "type": "module",
15
+ "main": "./lib/index.js",
16
+ "types": "./lib/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./lib/index.d.ts",
20
+ "default": "./lib/index.js"
21
+ },
22
+ "./client": {
23
+ "default": "./lib/client.js"
24
+ },
25
+ "./cordis.patch.yml": "./cordis.patch.yml",
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "lib/**/*.js",
30
+ "lib/**/*.d.ts",
31
+ "lib/**/*.map",
32
+ "cordis.patch.yml",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "dsh": {
37
+ "bundle": {
38
+ "patch": "./cordis.patch.yml"
39
+ },
40
+ "client": {
41
+ "platform": "web",
42
+ "inject": [
43
+ "@deepseek-ai/dsh-client-runtime",
44
+ "@deepseek-ai/dsh-client-ui-sidebar",
45
+ "@deepseek-ai/dsh-client-ui-layout",
46
+ "@deepseek-ai/dsh-client-ui-slots",
47
+ "@deepseek-ai/dsh-client-ui-theme"
48
+ ]
49
+ }
50
+ },
51
+ "engines": {
52
+ "node": "^22.19.0 || >=24.0.0"
53
+ },
54
+ "scripts": {
55
+ "clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
56
+ "build": "tsc -p tsconfig.json && node scripts/build-client.mjs",
57
+ "prepare": "npm run clean && npm run build",
58
+ "test": "npm run build && node --test test/*.test.mjs",
59
+ "pack:check": "npm pack --dry-run"
60
+ },
61
+ "dependencies": {
62
+ "@deepseek-ai/schemastery": "^3.18.1"
63
+ },
64
+ "peerDependencies": {
65
+ "@deepseek-ai/cordis": "^4.0.1",
66
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
67
+ "@deepseek-ai/dsh-agent-default-model": "^0.1.1-rc.2",
68
+ "@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.2",
69
+ "@deepseek-ai/dsh-credentials": "^0.1.1-rc.2",
70
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
71
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
72
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
73
+ "@deepseek-ai/dsh-workspace": "^0.1.1-rc.2"
74
+ },
75
+ "devDependencies": {
76
+ "@deepseek-ai/cordis": "^4.0.1",
77
+ "@deepseek-ai/dsh-agent": "0.1.1-rc.2",
78
+ "@deepseek-ai/dsh-agent-default-model": "0.1.1-rc.2",
79
+ "@deepseek-ai/dsh-agent-presets": "0.1.1-rc.2",
80
+ "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
81
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
82
+ "@deepseek-ai/dsh-client-ui-layout": "0.1.1-rc.2",
83
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
84
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.1.1-rc.2",
85
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
86
+ "@deepseek-ai/dsh-client-ui-theme": "0.1.1-rc.2",
87
+ "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
88
+ "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
89
+ "@deepseek-ai/dsh-session": "0.1.1-rc.2",
90
+ "@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
91
+ "@deepseek-ai/dsh-workspace": "0.1.1-rc.2",
92
+ "@lemoncat7/dsh-plugin-ui": "file:../dsh-plugin-ui",
93
+ "@types/node": "^24.0.0",
94
+ "@types/react": "18.3.28",
95
+ "esbuild": "^0.25.0",
96
+ "qrcode.react": "^4.2.0",
97
+ "react": "18.3.1",
98
+ "typescript": "^5.9.3"
99
+ },
100
+ "publishConfig": {
101
+ "access": "public"
102
+ },
103
+ "repository": {
104
+ "type": "git",
105
+ "url": "git+https://github.com/lemoncat7/dsh-partner.git"
106
+ },
107
+ "bugs": {
108
+ "url": "https://github.com/lemoncat7/dsh-partner/issues"
109
+ },
110
+ "homepage": "https://github.com/lemoncat7/dsh-partner#readme"
111
+ }