codebase-cli 2.0.0-pre.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 +21 -0
- package/README.md +266 -0
- package/bin/codebase +2 -0
- package/dist/agent/agent.js +198 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/config.js +117 -0
- package/dist/agent/config.js.map +1 -0
- package/dist/agent/events.js +153 -0
- package/dist/agent/events.js.map +1 -0
- package/dist/agent/router.js +35 -0
- package/dist/agent/router.js.map +1 -0
- package/dist/agent/system-prompt.js +21 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/auth/cli.js +138 -0
- package/dist/auth/cli.js.map +1 -0
- package/dist/auth/credentials.js +105 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/flow.js +222 -0
- package/dist/auth/flow.js.map +1 -0
- package/dist/auth/pkce.js +46 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/cli.js +69 -0
- package/dist/cli.js.map +1 -0
- package/dist/clipboard/copy.js +106 -0
- package/dist/clipboard/copy.js.map +1 -0
- package/dist/commands/builtins.js +203 -0
- package/dist/commands/builtins.js.map +1 -0
- package/dist/commands/registry.js +65 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/compaction/engine.js +209 -0
- package/dist/compaction/engine.js.map +1 -0
- package/dist/compaction/tokens.js +79 -0
- package/dist/compaction/tokens.js.map +1 -0
- package/dist/compaction/types.js +2 -0
- package/dist/compaction/types.js.map +1 -0
- package/dist/diagnostics/checkers.js +211 -0
- package/dist/diagnostics/checkers.js.map +1 -0
- package/dist/diagnostics/engine.js +71 -0
- package/dist/diagnostics/engine.js.map +1 -0
- package/dist/diagnostics/types.js +2 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/dotenv/loader.js +115 -0
- package/dist/dotenv/loader.js.map +1 -0
- package/dist/glue/client.js +47 -0
- package/dist/glue/client.js.map +1 -0
- package/dist/glue/intent.js +78 -0
- package/dist/glue/intent.js.map +1 -0
- package/dist/glue/narration.js +55 -0
- package/dist/glue/narration.js.map +1 -0
- package/dist/headless/run.js +89 -0
- package/dist/headless/run.js.map +1 -0
- package/dist/hooks/manager.js +158 -0
- package/dist/hooks/manager.js.map +1 -0
- package/dist/hooks/runner.js +70 -0
- package/dist/hooks/runner.js.map +1 -0
- package/dist/hooks/types.js +2 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/memory/inject.js +12 -0
- package/dist/memory/inject.js.map +1 -0
- package/dist/memory/store.js +178 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.js +10 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/store.js +172 -0
- package/dist/permissions/store.js.map +1 -0
- package/dist/plan/flow.js +214 -0
- package/dist/plan/flow.js.map +1 -0
- package/dist/plan/prompts.js +69 -0
- package/dist/plan/prompts.js.map +1 -0
- package/dist/plan/store.js +37 -0
- package/dist/plan/store.js.map +1 -0
- package/dist/plan/types.js +3 -0
- package/dist/plan/types.js.map +1 -0
- package/dist/sessions/store.js +105 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/skills/loader.js +41 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/platform-loader.js +63 -0
- package/dist/skills/platform-loader.js.map +1 -0
- package/dist/skills/types.js +21 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/ask-user.js +61 -0
- package/dist/tools/ask-user.js.map +1 -0
- package/dist/tools/dispatch-agent.js +178 -0
- package/dist/tools/dispatch-agent.js.map +1 -0
- package/dist/tools/edit-file.js +80 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/errors.js +89 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/file-ops.js +136 -0
- package/dist/tools/file-ops.js.map +1 -0
- package/dist/tools/file-state-cache.js +92 -0
- package/dist/tools/file-state-cache.js.map +1 -0
- package/dist/tools/git/branch.js +84 -0
- package/dist/tools/git/branch.js.map +1 -0
- package/dist/tools/git/commit.js +83 -0
- package/dist/tools/git/commit.js.map +1 -0
- package/dist/tools/git/diff.js +72 -0
- package/dist/tools/git/diff.js.map +1 -0
- package/dist/tools/git/git-helpers.js +58 -0
- package/dist/tools/git/git-helpers.js.map +1 -0
- package/dist/tools/git/log.js +70 -0
- package/dist/tools/git/log.js.map +1 -0
- package/dist/tools/git/status.js +97 -0
- package/dist/tools/git/status.js.map +1 -0
- package/dist/tools/git/worktree.js +132 -0
- package/dist/tools/git/worktree.js.map +1 -0
- package/dist/tools/glob.js +128 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.js +199 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/list-files.js +120 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/memory-tools.js +127 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/multi-edit.js +87 -0
- package/dist/tools/multi-edit.js.map +1 -0
- package/dist/tools/notebook-edit.js +147 -0
- package/dist/tools/notebook-edit.js.map +1 -0
- package/dist/tools/permission.js +168 -0
- package/dist/tools/permission.js.map +1 -0
- package/dist/tools/plan-mode.js +76 -0
- package/dist/tools/plan-mode.js.map +1 -0
- package/dist/tools/read-file.js +135 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.js +52 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/shell.js +216 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/task-store.js +70 -0
- package/dist/tools/task-store.js.map +1 -0
- package/dist/tools/tasks.js +131 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-fetch.js +152 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.js +169 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.js +70 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/App.js +216 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/Input.js +90 -0
- package/dist/ui/Input.js.map +1 -0
- package/dist/ui/Message.js +89 -0
- package/dist/ui/Message.js.map +1 -0
- package/dist/ui/MessageList.js +35 -0
- package/dist/ui/MessageList.js.map +1 -0
- package/dist/ui/Permission.js +39 -0
- package/dist/ui/Permission.js.map +1 -0
- package/dist/ui/Status.js +34 -0
- package/dist/ui/Status.js.map +1 -0
- package/dist/ui/TaskPanel.js +43 -0
- package/dist/ui/TaskPanel.js.map +1 -0
- package/dist/ui/Throbber.js +20 -0
- package/dist/ui/Throbber.js.map +1 -0
- package/dist/ui/ToolPanel.js +83 -0
- package/dist/ui/ToolPanel.js.map +1 -0
- package/dist/ui/UserQuery.js +38 -0
- package/dist/ui/UserQuery.js.map +1 -0
- package/dist/ui/input-state.js +210 -0
- package/dist/ui/input-state.js.map +1 -0
- package/dist/ui/wrap.js +30 -0
- package/dist/ui/wrap.js.map +1 -0
- package/dist/user-queries/store.js +60 -0
- package/dist/user-queries/store.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { EMPTY_USAGE } from "../types.js";
|
|
2
|
+
export function initialState(model) {
|
|
3
|
+
return {
|
|
4
|
+
messages: [],
|
|
5
|
+
tools: new Map(),
|
|
6
|
+
status: "idle",
|
|
7
|
+
usage: EMPTY_USAGE,
|
|
8
|
+
model,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function reducer(state, action) {
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case "user-prompt": {
|
|
14
|
+
const userMsg = {
|
|
15
|
+
role: "user",
|
|
16
|
+
content: action.text,
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
...state,
|
|
21
|
+
messages: [...state.messages, userMsg],
|
|
22
|
+
status: "thinking",
|
|
23
|
+
error: undefined,
|
|
24
|
+
turnUsage: undefined,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
case "chat-reply": {
|
|
28
|
+
// Glue replied to a small-talk turn; we render it as a synthetic
|
|
29
|
+
// assistant message but never feed it to pi-agent-core, so the
|
|
30
|
+
// agent's actual context stays clean of meta-banter.
|
|
31
|
+
const message = {
|
|
32
|
+
role: "assistant",
|
|
33
|
+
content: [{ type: "text", text: action.text }],
|
|
34
|
+
api: "chat",
|
|
35
|
+
provider: "chat",
|
|
36
|
+
model: state.model.id,
|
|
37
|
+
usage: EMPTY_USAGE,
|
|
38
|
+
stopReason: "stop",
|
|
39
|
+
timestamp: Date.now(),
|
|
40
|
+
};
|
|
41
|
+
return { ...state, messages: [...state.messages, message], status: "idle" };
|
|
42
|
+
}
|
|
43
|
+
case "abort":
|
|
44
|
+
return { ...state, status: "aborted", streaming: undefined };
|
|
45
|
+
case "error":
|
|
46
|
+
return { ...state, status: "error", error: action.message, streaming: undefined };
|
|
47
|
+
case "reset":
|
|
48
|
+
return initialState(state.model);
|
|
49
|
+
case "agent-event":
|
|
50
|
+
return applyAgentEvent(state, action.event);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function applyAgentEvent(state, event) {
|
|
54
|
+
switch (event.type) {
|
|
55
|
+
case "agent_start":
|
|
56
|
+
return { ...state, status: "thinking" };
|
|
57
|
+
case "turn_start":
|
|
58
|
+
return { ...state, status: "thinking", streaming: undefined };
|
|
59
|
+
case "message_start":
|
|
60
|
+
if (event.message.role !== "assistant")
|
|
61
|
+
return state;
|
|
62
|
+
return { ...state, status: "streaming", streaming: event.message };
|
|
63
|
+
case "message_update":
|
|
64
|
+
if (event.message.role !== "assistant")
|
|
65
|
+
return state;
|
|
66
|
+
return { ...state, streaming: event.message };
|
|
67
|
+
case "message_end": {
|
|
68
|
+
const final = event.message;
|
|
69
|
+
// User messages are added via the "user-prompt" action for immediate UI feedback.
|
|
70
|
+
// Tool result messages flow through here so we capture them in source order.
|
|
71
|
+
if (final.role === "user")
|
|
72
|
+
return state;
|
|
73
|
+
const turnUsage = "usage" in final ? final.usage : undefined;
|
|
74
|
+
return {
|
|
75
|
+
...state,
|
|
76
|
+
messages: [...state.messages, final],
|
|
77
|
+
streaming: undefined,
|
|
78
|
+
turnUsage: turnUsage ?? state.turnUsage,
|
|
79
|
+
usage: turnUsage ? mergeUsage(state.usage, turnUsage) : state.usage,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
case "tool_execution_start": {
|
|
83
|
+
const exec = {
|
|
84
|
+
id: event.toolCallId,
|
|
85
|
+
name: event.toolName,
|
|
86
|
+
args: event.args,
|
|
87
|
+
status: "running",
|
|
88
|
+
startedAt: Date.now(),
|
|
89
|
+
};
|
|
90
|
+
const tools = new Map(state.tools);
|
|
91
|
+
tools.set(exec.id, exec);
|
|
92
|
+
return { ...state, status: "tool", tools };
|
|
93
|
+
}
|
|
94
|
+
case "tool_execution_update": {
|
|
95
|
+
const tools = new Map(state.tools);
|
|
96
|
+
const existing = tools.get(event.toolCallId);
|
|
97
|
+
if (existing) {
|
|
98
|
+
tools.set(event.toolCallId, { ...existing, result: stringifyResult(event.partialResult) });
|
|
99
|
+
}
|
|
100
|
+
return { ...state, tools };
|
|
101
|
+
}
|
|
102
|
+
case "tool_execution_end": {
|
|
103
|
+
const tools = new Map(state.tools);
|
|
104
|
+
const existing = tools.get(event.toolCallId);
|
|
105
|
+
if (existing) {
|
|
106
|
+
tools.set(event.toolCallId, {
|
|
107
|
+
...existing,
|
|
108
|
+
status: event.isError ? "error" : "done",
|
|
109
|
+
endedAt: Date.now(),
|
|
110
|
+
result: stringifyResult(event.result),
|
|
111
|
+
error: event.isError ? stringifyResult(event.result) : undefined,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return { ...state, tools };
|
|
115
|
+
}
|
|
116
|
+
case "turn_end":
|
|
117
|
+
// Tool results are already appended via message_end events; just update status.
|
|
118
|
+
return { ...state, status: "thinking" };
|
|
119
|
+
case "agent_end":
|
|
120
|
+
return { ...state, status: state.error ? "error" : "idle", streaming: undefined };
|
|
121
|
+
default:
|
|
122
|
+
return state;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function mergeUsage(a, b) {
|
|
126
|
+
return {
|
|
127
|
+
input: a.input + b.input,
|
|
128
|
+
output: a.output + b.output,
|
|
129
|
+
cacheRead: a.cacheRead + b.cacheRead,
|
|
130
|
+
cacheWrite: a.cacheWrite + b.cacheWrite,
|
|
131
|
+
totalTokens: a.totalTokens + b.totalTokens,
|
|
132
|
+
cost: {
|
|
133
|
+
input: a.cost.input + b.cost.input,
|
|
134
|
+
output: a.cost.output + b.cost.output,
|
|
135
|
+
cacheRead: a.cost.cacheRead + b.cost.cacheRead,
|
|
136
|
+
cacheWrite: a.cost.cacheWrite + b.cost.cacheWrite,
|
|
137
|
+
total: a.cost.total + b.cost.total,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function stringifyResult(value) {
|
|
142
|
+
if (value === undefined || value === null)
|
|
143
|
+
return "";
|
|
144
|
+
if (typeof value === "string")
|
|
145
|
+
return value;
|
|
146
|
+
try {
|
|
147
|
+
return JSON.stringify(value);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return String(value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/agent/events.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,WAAW,EAAsB,MAAM,aAAa,CAAC;AAU9E,MAAM,UAAU,YAAY,CAAC,KAAyB;IACrD,OAAO;QACN,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,WAAW;QAClB,KAAK;KACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAgB,EAAE,MAAc;IACvD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,aAAa,CAAC,CAAC,CAAC;YACpB,MAAM,OAAO,GAAiB;gBAC7B,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,MAAM,CAAC,IAAI;gBACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;YACF,OAAO;gBACN,GAAG,KAAK;gBACR,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC;gBACtC,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,SAAS;gBAChB,SAAS,EAAE,SAAS;aACpB,CAAC;QACH,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YACnB,iEAAiE;YACjE,+DAA+D;YAC/D,qDAAqD;YACrD,MAAM,OAAO,GAAiB;gBAC7B,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC9C,GAAG,EAAE,MAAM;gBACX,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE;gBACrB,KAAK,EAAE,WAAW;gBAClB,UAAU,EAAE,MAAM;gBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;YACF,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC7E,CAAC;QAED,KAAK,OAAO;YACX,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAE9D,KAAK,OAAO;YACX,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAEnF,KAAK,OAAO;YACX,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAElC,KAAK,aAAa;YACjB,OAAO,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;AACF,CAAC;AAED,SAAS,eAAe,CAAC,KAAgB,EAAE,KAAiB;IAC3D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,aAAa;YACjB,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAEzC,KAAK,YAAY;YAChB,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAE/D,KAAK,eAAe;YACnB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC;YACrD,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAEpE,KAAK,gBAAgB;YACpB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC;YACrD,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAE/C,KAAK,aAAa,CAAC,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC;YAC5B,kFAAkF;YAClF,6EAA6E;YAC7E,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAC;YACxC,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,KAA2B,CAAC,CAAC,CAAC,SAAS,CAAC;YACpF,OAAO;gBACN,GAAG,KAAK;gBACR,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC;gBACpC,SAAS,EAAE,SAAS;gBACpB,SAAS,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS;gBACvC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;aACnE,CAAC;QACH,CAAC;QAED,KAAK,sBAAsB,CAAC,CAAC,CAAC;YAC7B,MAAM,IAAI,GAAkB;gBAC3B,EAAE,EAAE,KAAK,CAAC,UAAU;gBACpB,IAAI,EAAE,KAAK,CAAC,QAAQ;gBACpB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACzB,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QAED,KAAK,uBAAuB,CAAC,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI,QAAQ,EAAE,CAAC;gBACd,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC;YACD,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC3B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI,QAAQ,EAAE,CAAC;gBACd,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE;oBAC3B,GAAG,QAAQ;oBACX,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;oBACxC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;oBACnB,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC;oBACrC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;iBAChE,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,KAAK,UAAU;YACd,gFAAgF;YAChF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAEzC,KAAK,WAAW;YACf,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAEnF;YACC,OAAO,KAAK,CAAC;IACf,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,CAAQ,EAAE,CAAQ;IACrC,OAAO;QACN,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAC3B,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;QACpC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;QACvC,WAAW,EAAE,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;QAC1C,IAAI,EAAE;YACL,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK;YAClC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM;YACrC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS;YAC9C,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU;YACjD,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK;SAClC;KACD,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACtC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { classifyIntent } from "../glue/intent.js";
|
|
2
|
+
const CHAT_SYSTEM_PROMPT = "You're chatting casually with the user — small talk, gratitude, greetings, meta-questions. Reply briefly (one or two sentences), warm tone, no code unless explicitly asked.";
|
|
3
|
+
/**
|
|
4
|
+
* Decide what to do with a user input before involving the main agent:
|
|
5
|
+
* - "chat" → glue reply, no agent run (greetings, thanks, meta)
|
|
6
|
+
* - "plan" → caller enters the plan flow (Q&A → reviewable plan → agent)
|
|
7
|
+
* - "agent" → fall through to agent.prompt as before
|
|
8
|
+
*
|
|
9
|
+
* Glue failures degrade to "agent" so a flaky cheap model never silently
|
|
10
|
+
* eats a real request — same fallback policy classifyIntent already uses.
|
|
11
|
+
*/
|
|
12
|
+
export async function routeUserInput(glue, text, options) {
|
|
13
|
+
const intent = await classifyIntent(glue, text, options);
|
|
14
|
+
if (intent === "chat") {
|
|
15
|
+
const reply = await chatReply(glue, text, options.signal);
|
|
16
|
+
return { kind: "chat", reply };
|
|
17
|
+
}
|
|
18
|
+
if (intent === "plan") {
|
|
19
|
+
return { kind: "plan" };
|
|
20
|
+
}
|
|
21
|
+
// agent + clarify both go through the main agent for now; clarify-as-soft-hint
|
|
22
|
+
// could surface a system reminder when we wire steering messages in Phase 11b.
|
|
23
|
+
return { kind: "agent" };
|
|
24
|
+
}
|
|
25
|
+
async function chatReply(glue, text, signal) {
|
|
26
|
+
try {
|
|
27
|
+
const out = await glue.fast(text, CHAT_SYSTEM_PROMPT, signal);
|
|
28
|
+
return out.trim() || "👍";
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Glue down — at least acknowledge so the input row isn't dead silent.
|
|
32
|
+
return "👍";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/agent/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,kBAAkB,GACvB,8KAA8K,CAAC;AAShL;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAgB,EAAE,IAAY,EAAE,OAAqB;IACzF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACzD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAChC,CAAC;IACD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC;IACD,+EAA+E;IAC/E,+EAA+E;IAC/E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAgB,EAAE,IAAY,EAAE,MAAoB;IAC5E,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QAC9D,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACR,uEAAuE;QACvE,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { hostname, platform } from "node:os";
|
|
2
|
+
/**
|
|
3
|
+
* Phase 1 system prompt — minimal but useful. Phase 4 (glue) and Phase 6
|
|
4
|
+
* (output styles) layer atop. The static prefix vs. dynamic suffix split
|
|
5
|
+
* lands in Phase 7 along with prompt caching.
|
|
6
|
+
*/
|
|
7
|
+
export function buildSystemPrompt(cwd = process.cwd()) {
|
|
8
|
+
const lines = [
|
|
9
|
+
"You are codebase, a CLI coding agent. You help with software engineering tasks in the user's terminal.",
|
|
10
|
+
"",
|
|
11
|
+
"Be concise. Prefer code over prose. When you don't have a tool to act, say what you would do.",
|
|
12
|
+
"",
|
|
13
|
+
"Environment:",
|
|
14
|
+
` cwd: ${cwd}`,
|
|
15
|
+
` platform: ${platform()}`,
|
|
16
|
+
` host: ${hostname()}`,
|
|
17
|
+
` date: ${new Date().toISOString().slice(0, 10)}`,
|
|
18
|
+
];
|
|
19
|
+
return lines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=system-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/agent/system-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,KAAK,GAAG;QACb,wGAAwG;QACxG,EAAE;QACF,+FAA+F;QAC/F,EAAE;QACF,cAAc;QACd,UAAU,GAAG,EAAE;QACf,eAAe,QAAQ,EAAE,EAAE;QAC3B,WAAW,QAAQ,EAAE,EAAE;QACvB,WAAW,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;KAClD,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC"}
|
package/dist/auth/cli.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { CredentialsStore } from "./credentials.js";
|
|
2
|
+
import { refreshAccessToken, revokeToken, runOAuthLogin } from "./flow.js";
|
|
3
|
+
const DEFAULT_AUTH_BASE = "https://codebase.foundation";
|
|
4
|
+
function defaultOAuthConfig(env = process.env) {
|
|
5
|
+
const base = (env.CODEBASE_AUTH_BASE_URL ?? DEFAULT_AUTH_BASE).replace(/\/+$/, "");
|
|
6
|
+
return {
|
|
7
|
+
authorizationUrl: `${base}/cli/auth`,
|
|
8
|
+
tokenUrl: `${base}/api/cli/token`,
|
|
9
|
+
refreshUrl: `${base}/api/cli/refresh`,
|
|
10
|
+
revokeUrl: `${base}/api/cli/revoke`,
|
|
11
|
+
clientId: env.CODEBASE_CLIENT_ID ?? "codebase-cli",
|
|
12
|
+
scopes: (env.CODEBASE_SCOPES ?? "inference projects credits").split(/\s+/).filter(Boolean),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Dispatch a `codebase auth …` subcommand. Returns the exit code to
|
|
17
|
+
* surface from the parent process.
|
|
18
|
+
*
|
|
19
|
+
* Recognized argv:
|
|
20
|
+
* auth → status
|
|
21
|
+
* auth status → status
|
|
22
|
+
* auth login → run OAuth browser flow, persist tokens
|
|
23
|
+
* auth logout → clear credentials, best-effort server revoke
|
|
24
|
+
* auth refresh → force a refresh against the stored refresh token
|
|
25
|
+
* auth <key> → save a manual API key (headless / SSH)
|
|
26
|
+
*/
|
|
27
|
+
export async function runAuthSubcommand(argv, options = {}) {
|
|
28
|
+
const store = options.store ?? new CredentialsStore();
|
|
29
|
+
const config = options.config ?? defaultOAuthConfig();
|
|
30
|
+
const out = options.stdout ?? ((m) => process.stdout.write(`${m}\n`));
|
|
31
|
+
const err = options.stderr ?? ((m) => process.stderr.write(`${m}\n`));
|
|
32
|
+
const subcommand = argv[1] ?? "status";
|
|
33
|
+
try {
|
|
34
|
+
switch (subcommand) {
|
|
35
|
+
case "status":
|
|
36
|
+
return statusCmd(store, out);
|
|
37
|
+
case "login":
|
|
38
|
+
return await loginCmd(store, config, out, err);
|
|
39
|
+
case "logout":
|
|
40
|
+
return await logoutCmd(store, config, out);
|
|
41
|
+
case "refresh":
|
|
42
|
+
return await refreshCmd(store, config, out, err);
|
|
43
|
+
default: {
|
|
44
|
+
if (subcommand.startsWith("-")) {
|
|
45
|
+
err(`unknown flag: ${subcommand}`);
|
|
46
|
+
return 2;
|
|
47
|
+
}
|
|
48
|
+
// Treat as a manual API key
|
|
49
|
+
return manualKeyCmd(store, subcommand, out);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
err(e instanceof Error ? e.message : String(e));
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function statusCmd(store, out) {
|
|
59
|
+
const creds = store.load();
|
|
60
|
+
if (!creds) {
|
|
61
|
+
out("not signed in");
|
|
62
|
+
out("run: codebase auth login");
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
const expiry = creds.expiresAt
|
|
66
|
+
? `expires ${new Date(creds.expiresAt).toISOString()}${store.isExpired(creds) ? " (expired)" : ""}`
|
|
67
|
+
: "no expiry";
|
|
68
|
+
out(`signed in via ${creds.source}`);
|
|
69
|
+
if (creds.email)
|
|
70
|
+
out(` email: ${creds.email}`);
|
|
71
|
+
if (creds.userId)
|
|
72
|
+
out(` userId: ${creds.userId}`);
|
|
73
|
+
out(` scopes: ${creds.scopes.join(" ")}`);
|
|
74
|
+
out(` ${expiry}`);
|
|
75
|
+
out(` file: ${store.filePath} (mode ${(store.mode() ?? 0).toString(8)})`);
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
async function loginCmd(store, config, out, err) {
|
|
79
|
+
out("opening your browser to sign in…");
|
|
80
|
+
out("(if it doesn't open, the URL will be printed)");
|
|
81
|
+
try {
|
|
82
|
+
const creds = await runOAuthLogin(config);
|
|
83
|
+
store.save(creds);
|
|
84
|
+
out(`signed in${creds.email ? ` as ${creds.email}` : ""}.`);
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
err(`login failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function logoutCmd(store, config, out) {
|
|
93
|
+
const creds = store.load();
|
|
94
|
+
if (creds && creds.source === "codebase") {
|
|
95
|
+
await revokeToken(config, creds.accessToken);
|
|
96
|
+
}
|
|
97
|
+
const removed = store.clear();
|
|
98
|
+
out(removed ? "signed out." : "no credentials to remove.");
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
async function refreshCmd(store, config, out, err) {
|
|
102
|
+
const creds = store.load();
|
|
103
|
+
if (!creds) {
|
|
104
|
+
err("not signed in");
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
if (!creds.refreshToken) {
|
|
108
|
+
err("no refresh token saved (manual API keys can't be refreshed)");
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const next = await refreshAccessToken(config, creds.refreshToken);
|
|
113
|
+
store.save({
|
|
114
|
+
...next,
|
|
115
|
+
email: next.email ?? creds.email,
|
|
116
|
+
userId: next.userId ?? creds.userId,
|
|
117
|
+
});
|
|
118
|
+
out("refreshed");
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
err(`refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function manualKeyCmd(store, key, out) {
|
|
127
|
+
if (!key || key.length < 16) {
|
|
128
|
+
throw new Error("API key looks too short — paste the full token from the dashboard.");
|
|
129
|
+
}
|
|
130
|
+
store.save({
|
|
131
|
+
accessToken: key,
|
|
132
|
+
scopes: ["inference"],
|
|
133
|
+
source: "manual",
|
|
134
|
+
});
|
|
135
|
+
out("API key saved.");
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/auth/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
export const CREDENTIALS_VERSION = 1;
|
|
6
|
+
/**
|
|
7
|
+
* Stores OAuth/API credentials at `~/.codebase/credentials.json`. File
|
|
8
|
+
* mode is enforced to 0600 on every write — readable only by the user.
|
|
9
|
+
*
|
|
10
|
+
* load() returns null when the file is missing, malformed, an
|
|
11
|
+
* unrecognized version, or fails the basic shape check. Clearing
|
|
12
|
+
* malformed files prevents the agent from getting stuck on a corrupt
|
|
13
|
+
* artifact between releases.
|
|
14
|
+
*/
|
|
15
|
+
export class CredentialsStore {
|
|
16
|
+
path;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
const dataRoot = options.dataRoot ?? join(homedir(), ".codebase");
|
|
19
|
+
this.path = join(dataRoot, "credentials.json");
|
|
20
|
+
}
|
|
21
|
+
get filePath() {
|
|
22
|
+
return this.path;
|
|
23
|
+
}
|
|
24
|
+
load() {
|
|
25
|
+
if (!existsSync(this.path))
|
|
26
|
+
return null;
|
|
27
|
+
let raw;
|
|
28
|
+
try {
|
|
29
|
+
raw = readFileSync(this.path, "utf8");
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
let parsed;
|
|
35
|
+
try {
|
|
36
|
+
parsed = JSON.parse(raw);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
this.clear();
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (parsed.version !== CREDENTIALS_VERSION)
|
|
43
|
+
return null;
|
|
44
|
+
if (typeof parsed.accessToken !== "string" || !parsed.accessToken)
|
|
45
|
+
return null;
|
|
46
|
+
if (!Array.isArray(parsed.scopes))
|
|
47
|
+
return null;
|
|
48
|
+
if (parsed.source !== "codebase" && parsed.source !== "manual")
|
|
49
|
+
return null;
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
save(credentials) {
|
|
53
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
54
|
+
const payload = { version: CREDENTIALS_VERSION, ...credentials };
|
|
55
|
+
const tmp = `${this.path}.${randomBytes(4).toString("hex")}.tmp`;
|
|
56
|
+
try {
|
|
57
|
+
writeFileSync(tmp, JSON.stringify(payload, null, 2), { mode: 0o600 });
|
|
58
|
+
renameSync(tmp, this.path);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
try {
|
|
62
|
+
unlinkSync(tmp);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// best effort
|
|
66
|
+
}
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
// Re-assert mode after rename — some platforms preserve the tmp's
|
|
70
|
+
// mode but it's cheap insurance.
|
|
71
|
+
try {
|
|
72
|
+
require("node:fs").chmodSync(this.path, 0o600);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// non-fatal on systems that don't support chmod (Windows w/ ACLs)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
clear() {
|
|
79
|
+
if (!existsSync(this.path))
|
|
80
|
+
return false;
|
|
81
|
+
try {
|
|
82
|
+
unlinkSync(this.path);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** True when credentials exist and the access token has expired (with 60s skew). */
|
|
90
|
+
isExpired(credentials) {
|
|
91
|
+
const creds = credentials ?? this.load();
|
|
92
|
+
if (!creds)
|
|
93
|
+
return false;
|
|
94
|
+
if (!creds.expiresAt)
|
|
95
|
+
return false;
|
|
96
|
+
return creds.expiresAt - 60_000 <= Date.now();
|
|
97
|
+
}
|
|
98
|
+
/** Inspect file mode — used by tests and `codebase auth status` to verify the 0600 invariant. */
|
|
99
|
+
mode() {
|
|
100
|
+
if (!existsSync(this.path))
|
|
101
|
+
return null;
|
|
102
|
+
return statSync(this.path).mode & 0o777;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"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"}
|