mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
Add feedback voting and thumbs capture flow
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
3db6bdfc3c
commit
c0d0d03bce
66 changed files with 18988 additions and 78 deletions
|
|
@ -138,6 +138,16 @@ export {
|
|||
|
||||
export type {
|
||||
Company,
|
||||
FeedbackVote,
|
||||
FeedbackDataSharingPreference,
|
||||
FeedbackTargetType,
|
||||
FeedbackVoteValue,
|
||||
FeedbackTrace,
|
||||
FeedbackTraceStatus,
|
||||
FeedbackTraceTargetSummary,
|
||||
FeedbackTraceBundleCaptureStatus,
|
||||
FeedbackTraceBundleFile,
|
||||
FeedbackTraceBundle,
|
||||
CompanySkillSourceType,
|
||||
CompanySkillTrustLevel,
|
||||
CompanySkillCompatibility,
|
||||
|
|
@ -325,6 +335,15 @@ export type {
|
|||
ProviderQuotaResult,
|
||||
} from "./types/index.js";
|
||||
|
||||
export {
|
||||
DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE,
|
||||
FEEDBACK_TARGET_TYPES,
|
||||
FEEDBACK_DATA_SHARING_PREFERENCES,
|
||||
FEEDBACK_TRACE_STATUSES,
|
||||
FEEDBACK_VOTE_VALUES,
|
||||
DEFAULT_FEEDBACK_DATA_SHARING_TERMS_VERSION,
|
||||
} from "./types/feedback.js";
|
||||
|
||||
export {
|
||||
instanceGeneralSettingsSchema,
|
||||
patchInstanceGeneralSettingsSchema,
|
||||
|
|
@ -338,9 +357,14 @@ export {
|
|||
createCompanySchema,
|
||||
updateCompanySchema,
|
||||
updateCompanyBrandingSchema,
|
||||
feedbackTargetTypeSchema,
|
||||
feedbackTraceStatusSchema,
|
||||
feedbackVoteValueSchema,
|
||||
upsertIssueFeedbackVoteSchema,
|
||||
type CreateCompany,
|
||||
type UpdateCompany,
|
||||
type UpdateCompanyBranding,
|
||||
type UpsertIssueFeedbackVote,
|
||||
agentSkillStateSchema,
|
||||
agentSkillSyncModeSchema,
|
||||
agentSkillEntrySchema,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ export interface CompanyPortabilityCompanyManifestEntry {
|
|||
brandColor: string | null;
|
||||
logoPath: string | null;
|
||||
requireBoardApprovalForNewAgents: boolean;
|
||||
feedbackDataSharingEnabled: boolean;
|
||||
feedbackDataSharingConsentAt: string | null;
|
||||
feedbackDataSharingConsentByUserId: string | null;
|
||||
feedbackDataSharingTermsVersion: string | null;
|
||||
}
|
||||
|
||||
export interface CompanyPortabilitySidebarOrder {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ export interface Company {
|
|||
budgetMonthlyCents: number;
|
||||
spentMonthlyCents: number;
|
||||
requireBoardApprovalForNewAgents: boolean;
|
||||
feedbackDataSharingEnabled: boolean;
|
||||
feedbackDataSharingConsentAt: Date | null;
|
||||
feedbackDataSharingConsentByUserId: string | null;
|
||||
feedbackDataSharingTermsVersion: string | null;
|
||||
brandColor: string | null;
|
||||
logoAssetId: string | null;
|
||||
logoUrl: string | null;
|
||||
|
|
|
|||
120
packages/shared/src/types/feedback.ts
Normal file
120
packages/shared/src/types/feedback.ts
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
export const FEEDBACK_TARGET_TYPES = ["issue_comment", "issue_document_revision"] as const;
|
||||
export type FeedbackTargetType = (typeof FEEDBACK_TARGET_TYPES)[number];
|
||||
|
||||
export const FEEDBACK_VOTE_VALUES = ["up", "down"] as const;
|
||||
export type FeedbackVoteValue = (typeof FEEDBACK_VOTE_VALUES)[number];
|
||||
|
||||
export const FEEDBACK_DATA_SHARING_PREFERENCES = ["allowed", "not_allowed", "prompt"] as const;
|
||||
export type FeedbackDataSharingPreference = (typeof FEEDBACK_DATA_SHARING_PREFERENCES)[number];
|
||||
|
||||
export const DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE: FeedbackDataSharingPreference = "prompt";
|
||||
|
||||
export const FEEDBACK_TRACE_STATUSES = ["local_only", "pending", "sent", "failed"] as const;
|
||||
export type FeedbackTraceStatus = (typeof FEEDBACK_TRACE_STATUSES)[number];
|
||||
|
||||
export const DEFAULT_FEEDBACK_DATA_SHARING_TERMS_VERSION = "feedback-data-sharing-v1";
|
||||
|
||||
export interface FeedbackVote {
|
||||
id: string;
|
||||
companyId: string;
|
||||
issueId: string;
|
||||
targetType: FeedbackTargetType;
|
||||
targetId: string;
|
||||
authorUserId: string;
|
||||
vote: FeedbackVoteValue;
|
||||
reason: string | null;
|
||||
sharedWithLabs: boolean;
|
||||
sharedAt: Date | null;
|
||||
consentVersion: string | null;
|
||||
redactionSummary: Record<string, unknown> | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface FeedbackTraceTargetSummary {
|
||||
label: string;
|
||||
excerpt: string | null;
|
||||
authorAgentId: string | null;
|
||||
authorUserId: string | null;
|
||||
createdAt: Date | null;
|
||||
documentKey: string | null;
|
||||
documentTitle: string | null;
|
||||
revisionNumber: number | null;
|
||||
}
|
||||
|
||||
export interface FeedbackTrace {
|
||||
id: string;
|
||||
companyId: string;
|
||||
feedbackVoteId: string;
|
||||
issueId: string;
|
||||
projectId: string | null;
|
||||
issueIdentifier: string | null;
|
||||
issueTitle: string;
|
||||
authorUserId: string;
|
||||
targetType: FeedbackTargetType;
|
||||
targetId: string;
|
||||
vote: FeedbackVoteValue;
|
||||
status: FeedbackTraceStatus;
|
||||
destination: string | null;
|
||||
exportId: string | null;
|
||||
consentVersion: string | null;
|
||||
schemaVersion: string;
|
||||
bundleVersion: string;
|
||||
payloadVersion: string;
|
||||
payloadDigest: string | null;
|
||||
payloadSnapshot: Record<string, unknown> | null;
|
||||
targetSummary: FeedbackTraceTargetSummary;
|
||||
redactionSummary: Record<string, unknown> | null;
|
||||
attemptCount: number;
|
||||
lastAttemptedAt: Date | null;
|
||||
exportedAt: Date | null;
|
||||
failureReason: string | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export type FeedbackTraceBundleCaptureStatus = "full" | "partial" | "unavailable";
|
||||
|
||||
export interface FeedbackTraceBundleFile {
|
||||
path: string;
|
||||
contentType: string;
|
||||
encoding: "utf8";
|
||||
byteLength: number;
|
||||
sha256: string;
|
||||
source:
|
||||
| "paperclip_run"
|
||||
| "paperclip_run_events"
|
||||
| "paperclip_run_log"
|
||||
| "codex_session"
|
||||
| "claude_stream_json"
|
||||
| "claude_project_session"
|
||||
| "claude_project_artifact"
|
||||
| "claude_debug_log"
|
||||
| "claude_task_metadata"
|
||||
| "opencode_session"
|
||||
| "opencode_session_diff"
|
||||
| "opencode_message"
|
||||
| "opencode_message_part"
|
||||
| "opencode_project"
|
||||
| "opencode_todo";
|
||||
contents: string;
|
||||
}
|
||||
|
||||
export interface FeedbackTraceBundle {
|
||||
traceId: string;
|
||||
exportId: string | null;
|
||||
companyId: string;
|
||||
issueId: string;
|
||||
issueIdentifier: string | null;
|
||||
adapterType: string | null;
|
||||
captureStatus: FeedbackTraceBundleCaptureStatus;
|
||||
notes: string[];
|
||||
envelope: Record<string, unknown>;
|
||||
surface: Record<string, unknown> | null;
|
||||
paperclipRun: Record<string, unknown> | null;
|
||||
rawAdapterTrace: Record<string, unknown> | null;
|
||||
normalizedAdapterTrace: Record<string, unknown> | null;
|
||||
privacy: Record<string, unknown> | null;
|
||||
integrity: Record<string, unknown>;
|
||||
files: FeedbackTraceBundleFile[];
|
||||
}
|
||||
|
|
@ -1,4 +1,16 @@
|
|||
export type { Company } from "./company.js";
|
||||
export type {
|
||||
FeedbackVote,
|
||||
FeedbackDataSharingPreference,
|
||||
FeedbackTargetType,
|
||||
FeedbackVoteValue,
|
||||
FeedbackTrace,
|
||||
FeedbackTraceStatus,
|
||||
FeedbackTraceTargetSummary,
|
||||
FeedbackTraceBundleCaptureStatus,
|
||||
FeedbackTraceBundleFile,
|
||||
FeedbackTraceBundle,
|
||||
} from "./feedback.js";
|
||||
export type { InstanceExperimentalSettings, InstanceGeneralSettings, InstanceSettings } from "./instance.js";
|
||||
export type {
|
||||
CompanySkillSourceType,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import type { FeedbackDataSharingPreference } from "./feedback.js";
|
||||
|
||||
export interface InstanceGeneralSettings {
|
||||
censorUsernameInLogs: boolean;
|
||||
feedbackDataSharingPreference: FeedbackDataSharingPreference;
|
||||
}
|
||||
|
||||
export interface InstanceExperimentalSettings {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ export const portabilityCompanyManifestEntrySchema = z.object({
|
|||
brandColor: z.string().nullable(),
|
||||
logoPath: z.string().nullable(),
|
||||
requireBoardApprovalForNewAgents: z.boolean(),
|
||||
feedbackDataSharingEnabled: z.boolean().default(false),
|
||||
feedbackDataSharingConsentAt: z.string().datetime().nullable().default(null),
|
||||
feedbackDataSharingConsentByUserId: z.string().nullable().default(null),
|
||||
feedbackDataSharingTermsVersion: z.string().nullable().default(null),
|
||||
});
|
||||
|
||||
export const portabilitySidebarOrderSchema = z.object({
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { COMPANY_STATUSES } from "../constants.js";
|
|||
|
||||
const logoAssetIdSchema = z.string().uuid().nullable().optional();
|
||||
const brandColorSchema = z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
|
||||
const feedbackDataSharingTermsVersionSchema = z.string().min(1).nullable().optional();
|
||||
|
||||
export const createCompanySchema = z.object({
|
||||
name: z.string().min(1),
|
||||
|
|
@ -18,6 +19,10 @@ export const updateCompanySchema = createCompanySchema
|
|||
status: z.enum(COMPANY_STATUSES).optional(),
|
||||
spentMonthlyCents: z.number().int().nonnegative().optional(),
|
||||
requireBoardApprovalForNewAgents: z.boolean().optional(),
|
||||
feedbackDataSharingEnabled: z.boolean().optional(),
|
||||
feedbackDataSharingConsentAt: z.coerce.date().nullable().optional(),
|
||||
feedbackDataSharingConsentByUserId: z.string().min(1).nullable().optional(),
|
||||
feedbackDataSharingTermsVersion: feedbackDataSharingTermsVersionSchema,
|
||||
brandColor: brandColorSchema,
|
||||
logoAssetId: logoAssetIdSchema,
|
||||
});
|
||||
|
|
|
|||
22
packages/shared/src/validators/feedback.ts
Normal file
22
packages/shared/src/validators/feedback.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { z } from "zod";
|
||||
import {
|
||||
FEEDBACK_DATA_SHARING_PREFERENCES,
|
||||
FEEDBACK_TARGET_TYPES,
|
||||
FEEDBACK_TRACE_STATUSES,
|
||||
FEEDBACK_VOTE_VALUES,
|
||||
} from "../types/feedback.js";
|
||||
|
||||
export const feedbackTargetTypeSchema = z.enum(FEEDBACK_TARGET_TYPES);
|
||||
export const feedbackTraceStatusSchema = z.enum(FEEDBACK_TRACE_STATUSES);
|
||||
export const feedbackVoteValueSchema = z.enum(FEEDBACK_VOTE_VALUES);
|
||||
export const feedbackDataSharingPreferenceSchema = z.enum(FEEDBACK_DATA_SHARING_PREFERENCES);
|
||||
|
||||
export const upsertIssueFeedbackVoteSchema = z.object({
|
||||
targetType: feedbackTargetTypeSchema,
|
||||
targetId: z.string().uuid(),
|
||||
vote: feedbackVoteValueSchema,
|
||||
reason: z.string().trim().max(1000).optional(),
|
||||
allowSharing: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export type UpsertIssueFeedbackVote = z.infer<typeof upsertIssueFeedbackVoteSchema>;
|
||||
|
|
@ -24,6 +24,14 @@ export {
|
|||
type UpdateCompany,
|
||||
type UpdateCompanyBranding,
|
||||
} from "./company.js";
|
||||
export {
|
||||
feedbackDataSharingPreferenceSchema,
|
||||
feedbackTargetTypeSchema,
|
||||
feedbackTraceStatusSchema,
|
||||
feedbackVoteValueSchema,
|
||||
upsertIssueFeedbackVoteSchema,
|
||||
type UpsertIssueFeedbackVote,
|
||||
} from "./feedback.js";
|
||||
export {
|
||||
companySkillSourceTypeSchema,
|
||||
companySkillTrustLevelSchema,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { z } from "zod";
|
||||
import { DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE } from "../types/feedback.js";
|
||||
import { feedbackDataSharingPreferenceSchema } from "./feedback.js";
|
||||
|
||||
export const instanceGeneralSettingsSchema = z.object({
|
||||
censorUsernameInLogs: z.boolean().default(false),
|
||||
feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(
|
||||
DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE,
|
||||
),
|
||||
}).strict();
|
||||
|
||||
export const patchInstanceGeneralSettingsSchema = instanceGeneralSettingsSchema.partial();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue