dsh-live-teams 0.1.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 +176 -0
- package/NOTICE +11 -0
- package/README.md +85 -0
- package/cordis.patch.yml +25 -0
- package/lib/binding.d.ts +18 -0
- package/lib/binding.js +42 -0
- package/lib/changed-paths.d.ts +26 -0
- package/lib/changed-paths.js +69 -0
- package/lib/client.js +6753 -0
- package/lib/command-queue.d.ts +60 -0
- package/lib/command-queue.js +185 -0
- package/lib/compatibility.js +109 -0
- package/lib/context-provider.d.ts +110 -0
- package/lib/context-provider.js +249 -0
- package/lib/dispatch.d.ts +174 -0
- package/lib/dispatch.js +624 -0
- package/lib/errors.d.ts +36 -0
- package/lib/errors.js +103 -0
- package/lib/git-artifacts.d.ts +50 -0
- package/lib/git-artifacts.js +242 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.js +14 -0
- package/lib/mailbox.d.ts +274 -0
- package/lib/mailbox.js +721 -0
- package/lib/member-tools.d.ts +57 -0
- package/lib/member-tools.js +1265 -0
- package/lib/migrations.d.ts +17 -0
- package/lib/migrations.js +47 -0
- package/lib/plugin.d.ts +106 -0
- package/lib/plugin.js +1003 -0
- package/lib/roles.d.ts +35 -0
- package/lib/roles.js +284 -0
- package/lib/routes.d.ts +586 -0
- package/lib/routes.js +2816 -0
- package/lib/scope.d.ts +62 -0
- package/lib/scope.js +133 -0
- package/lib/session-bridge.d.ts +76 -0
- package/lib/session-bridge.js +147 -0
- package/lib/session-title.js +35 -0
- package/lib/storage.d.ts +9 -0
- package/lib/storage.js +65 -0
- package/lib/task-store.d.ts +729 -0
- package/lib/task-store.js +2205 -0
- package/lib/team-store.d.ts +216 -0
- package/lib/team-store.js +765 -0
- package/lib/tree-snapshot.d.ts +28 -0
- package/lib/tree-snapshot.js +80 -0
- package/lib/types/client/TeamView.d.ts +26 -0
- package/lib/types/client/TeamView.dom.test.d.ts +1 -0
- package/lib/types/client/api.d.ts +522 -0
- package/lib/types/client/api.test.d.ts +1 -0
- package/lib/types/client/attention.d.ts +65 -0
- package/lib/types/client/attention.test.d.ts +1 -0
- package/lib/types/client/index.d.ts +31 -0
- package/lib/types/client/locales.d.ts +577 -0
- package/lib/types/client/member-name.d.ts +14 -0
- package/lib/types/client/member-name.test.d.ts +1 -0
- package/lib/types/client/roster.d.ts +26 -0
- package/lib/types/client/roster.test.d.ts +1 -0
- package/lib/types/client/styles.d.ts +3 -0
- package/package.json +104 -0
- package/roles/builder.md +40 -0
- package/roles/delegate.md +36 -0
- package/roles/lead.md +46 -0
- package/roles/oracle.md +36 -0
- package/roles/researcher.md +37 -0
- package/roles/reviewer.md +45 -0
- package/roles/scout.md +36 -0
- package/roles/verifier.md +36 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/migrations.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Bringing stored state forward.
|
|
4
|
+
*
|
|
5
|
+
* Every state file carries a `schemaVersion`. Reading already tolerates an older one — the fields
|
|
6
|
+
* that exist are the fields the reader knows — but nothing *brings it forward*: a field added in a
|
|
7
|
+
* later version would simply be missing until something happened to write the file again, and no
|
|
8
|
+
* record said the state had been read at an older version. A version from the future was refused with
|
|
9
|
+
* a bare "invalid state", which reads like corruption rather than "this was written by a newer DSH".
|
|
10
|
+
*
|
|
11
|
+
* A migration is a pure function from one version to the next. They are registered here by the
|
|
12
|
+
* version they migrate *from*, so the chain is explicit and testable; the list is empty today because
|
|
13
|
+
* version 1 is the first, and the framework exists so the first real change is a two-line addition
|
|
14
|
+
* rather than a redesign.
|
|
15
|
+
*/
|
|
16
|
+
export type Migration = (state: unknown) => unknown;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ERROR_CODES, LiveTeamsError } from "./errors.js";
|
|
2
|
+
//#region src/migrations.ts
|
|
3
|
+
const MIGRATIONS = Object.freeze({});
|
|
4
|
+
/**
|
|
5
|
+
* What has to happen to read this state. `future` is a refusal with both numbers in it: a state
|
|
6
|
+
* written by a newer product is not corruption, and saying so is the difference between a person
|
|
7
|
+
* updating DSH and a person hunting a bug that is not there.
|
|
8
|
+
*/
|
|
9
|
+
function planMigration(stored, current, what, migrations = MIGRATIONS) {
|
|
10
|
+
if (!Number.isInteger(stored) || stored < 0) return {
|
|
11
|
+
kind: "future",
|
|
12
|
+
error: new LiveTeamsError(ERROR_CODES.STATE_CORRUPT, `${what} has no usable schemaVersion: ${String(stored)}`)
|
|
13
|
+
};
|
|
14
|
+
const from = stored;
|
|
15
|
+
if (from === current) return { kind: "current" };
|
|
16
|
+
if (from > current) return {
|
|
17
|
+
kind: "future",
|
|
18
|
+
error: new LiveTeamsError(ERROR_CODES.SCHEMA_UNSUPPORTED, `${what} was written by a newer DSH (schema ${from}, this build understands ${current}); update DSH rather than editing the state`)
|
|
19
|
+
};
|
|
20
|
+
const steps = [];
|
|
21
|
+
for (let version = from; version < current; version += 1) {
|
|
22
|
+
if (migrations[version] === void 0) return {
|
|
23
|
+
kind: "future",
|
|
24
|
+
error: new LiveTeamsError(ERROR_CODES.SCHEMA_UNSUPPORTED, `${what} is at schema ${from} and no migration from ${version} to ${version + 1} is registered; this build cannot read it`)
|
|
25
|
+
};
|
|
26
|
+
steps.push(version);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
kind: "migrate",
|
|
30
|
+
from,
|
|
31
|
+
to: current,
|
|
32
|
+
steps
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Run the plan's steps in order. Returns the state as the current version sees it. */
|
|
36
|
+
function applyMigration(state, plan, migrations = MIGRATIONS) {
|
|
37
|
+
if (plan.kind !== "migrate") return state;
|
|
38
|
+
let working = state;
|
|
39
|
+
for (const step of plan.steps) {
|
|
40
|
+
const migration = migrations[step];
|
|
41
|
+
if (migration === void 0) throw new LiveTeamsError(ERROR_CODES.SCHEMA_UNSUPPORTED, `migration from ${step} to ${step + 1} disappeared while it was running`);
|
|
42
|
+
working = migration(working);
|
|
43
|
+
}
|
|
44
|
+
return working;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { MIGRATIONS, applyMigration, planMigration };
|
package/lib/plugin.d.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { MailboxService } from "./mailbox.js";
|
|
2
|
+
import { MemberRecord, TeamStore } from "./team-store.js";
|
|
3
|
+
import { TaskStore } from "./task-store.js";
|
|
4
|
+
import { ReconcileResult } from "./dispatch.js";
|
|
5
|
+
import { SessionBridge, createSessionBridge } from "./session-bridge.js";
|
|
6
|
+
import { SessionCommandQueue } from "./command-queue.js";
|
|
7
|
+
import { MembershipContextProvider } from "./context-provider.js";
|
|
8
|
+
import { LiveTeamsDispatch, LiveTeamsWebServer } from "./routes.js";
|
|
9
|
+
import { ToolRuntime } from "@deepseek-ai/dsh-tools";
|
|
10
|
+
//#region src/plugin.d.ts
|
|
11
|
+
export declare const name = "live-teams-host";
|
|
12
|
+
export declare const inject: readonly ["sessionController", "sessions", "agents", "systemPrompt", "workspaceRegistry"];
|
|
13
|
+
type WorkspaceEntry = {
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly title?: unknown;
|
|
17
|
+
readonly sessionIds?: readonly unknown[];
|
|
18
|
+
};
|
|
19
|
+
type AgentRegistry = {
|
|
20
|
+
readonly get?: (sessionId: string) => unknown;
|
|
21
|
+
readonly isOwnedBy?: (sessionId: string, owner: unknown) => boolean;
|
|
22
|
+
};
|
|
23
|
+
type NativePathController = {
|
|
24
|
+
readonly canOpenWorkspacePath?: () => boolean | Promise<boolean>;
|
|
25
|
+
readonly openWorkspacePath?: (request: {
|
|
26
|
+
path: string;
|
|
27
|
+
action: 'reveal' | 'open';
|
|
28
|
+
}, signal: AbortSignal) => Promise<unknown>;
|
|
29
|
+
};
|
|
30
|
+
type HostContext = {
|
|
31
|
+
effect: (effect: () => (() => void), name?: string) => void;
|
|
32
|
+
workspaceRegistry?: {
|
|
33
|
+
list?: () => WorkspaceEntry[];
|
|
34
|
+
};
|
|
35
|
+
tools?: Pick<ToolRuntime, 'register'>;
|
|
36
|
+
/** Optional service lookup: returns undefined instead of failing without inject. */
|
|
37
|
+
get?: (name: string) => unknown;
|
|
38
|
+
sessionController: Parameters<typeof createSessionBridge>[0]['controller'] & NativePathController;
|
|
39
|
+
agents?: AgentRegistry;
|
|
40
|
+
systemPrompt: {
|
|
41
|
+
context: (definition: ReturnType<MembershipContextProvider['definition']>) => unknown;
|
|
42
|
+
};
|
|
43
|
+
provide: (key: string, value: LiveTeamsService) => unknown;
|
|
44
|
+
logger?: {
|
|
45
|
+
warn?: (message: string) => void;
|
|
46
|
+
};
|
|
47
|
+
settingsController?: {
|
|
48
|
+
canOpenAgentPresetDirectory?: () => boolean | Promise<boolean>;
|
|
49
|
+
};
|
|
50
|
+
webServer?: LiveTeamsWebServer;
|
|
51
|
+
inject?: (deps: readonly string[], callback: (ctx: HostContext & {
|
|
52
|
+
webServer: LiveTeamsWebServer;
|
|
53
|
+
}) => void) => unknown;
|
|
54
|
+
};
|
|
55
|
+
export type PluginConfig = {
|
|
56
|
+
enabled?: boolean;
|
|
57
|
+
workspacePath?: string;
|
|
58
|
+
workspaceId?: string;
|
|
59
|
+
teamId?: string;
|
|
60
|
+
teamName?: string; /** How often the dispatcher sweeps as a safety net; a signal wakes it sooner. */
|
|
61
|
+
dispatchSweepMs?: number; /**
|
|
62
|
+
* Whether the dispatcher may start *coding* work on its own. `manual` (the default)
|
|
63
|
+
* keeps this product inside design §22, where the isolation it asked for is unavailable on this
|
|
64
|
+
* host (ADR 0008 is rejected): research
|
|
65
|
+
* and documentation tasks are dispatched, code is not. It is a deployment flag, not
|
|
66
|
+
* a team switch, because Gate C is a property of the product rather than of a team.
|
|
67
|
+
*/
|
|
68
|
+
codingDispatch?: 'manual' | 'automatic'; /** Shared hotspots, on top of the built-in list (B30). */
|
|
69
|
+
sharedPaths?: string[];
|
|
70
|
+
/**
|
|
71
|
+
* B32: how the scope record observes the workspace. `auto` uses git in a work tree and a
|
|
72
|
+
* tree fingerprint otherwise, so a folder that is not a repository is a first-class case.
|
|
73
|
+
* The explicit values exist for a repository whose status is unusable, and for verifying
|
|
74
|
+
* the fingerprint path inside a repository.
|
|
75
|
+
*/
|
|
76
|
+
scopeMode?: 'auto' | 'git' | 'files';
|
|
77
|
+
};
|
|
78
|
+
export type LiveTeamsService = {
|
|
79
|
+
teamId: string;
|
|
80
|
+
workspacePath: string;
|
|
81
|
+
bridge: SessionBridge;
|
|
82
|
+
queue: SessionCommandQueue;
|
|
83
|
+
mailbox: MailboxService;
|
|
84
|
+
contextProvider: MembershipContextProvider;
|
|
85
|
+
store: () => Promise<TeamStore>;
|
|
86
|
+
taskStore: () => Promise<TaskStore>;
|
|
87
|
+
/** The dispatch projection: what the reconciler would do, and why (B29). */
|
|
88
|
+
readDispatch: () => Promise<LiveTeamsDispatch>;
|
|
89
|
+
/** Run one reconcile pass now instead of waiting for a signal or the sweep. */
|
|
90
|
+
reconcile: (trigger?: string) => Promise<ReconcileResult>;
|
|
91
|
+
openMember: (sessionId: string) => Promise<MemberRecord | undefined>;
|
|
92
|
+
bindMember: (request: {
|
|
93
|
+
memberId: string;
|
|
94
|
+
sessionId: string;
|
|
95
|
+
expectedRevision: number;
|
|
96
|
+
}) => Promise<MemberRecord>;
|
|
97
|
+
readonly disposing: boolean;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Mount one host instance. The optional workspacePath is a deliberate pin:
|
|
101
|
+
* with a pin the old single-workspace route shape is retained, while without it
|
|
102
|
+
* every request is resolved through its Session's cwd.
|
|
103
|
+
*/
|
|
104
|
+
export declare function apply(ctx: HostContext, config?: PluginConfig): void;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { apply as default };
|